// SPDX-License-Identifier: GPL-2.0 #define _FILE_OFFSET_BITS 64 #define __USE_FILE_OFFSET64 #define _XOPEN_SOURCE 600 #define _DEFAULT_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "bcache.h" #include "lib.h" #include "bitwise.h" #include "zoned.h" #include "features.h" #include "list.h" int show_bdevs_detail(void) { struct list_head head; struct dev *devs, *n; INIT_LIST_HEAD(&head); int ret; ret = list_bdevs(&head); if (ret != 0) { fprintf(stderr, "Failed to list devices\n"); return ret; } printf("Name\t\tUuid\t\t\t\t\tCset_Uuid\t\t\t\tType\t\t\tState"); printf("\t\t\tBname\t\tAttachToDev\tAttachToCset\n"); list_for_each_entry_safe(devs, n, &head, dev_list) { printf("%s\t%s\t%s\t%lu", devs->name, devs->uuid, devs->cset, devs->version); switch (devs->version) { // These are handled the same by the kernel case BCACHE_SB_VERSION_CDEV: case BCACHE_SB_VERSION_CDEV_WITH_UUID: case BCACHE_SB_VERSION_CDEV_WITH_FEATURES: printf(" (cache)"); break; // The second adds data offset supporet case BCACHE_SB_VERSION_BDEV: case BCACHE_SB_VERSION_BDEV_WITH_OFFSET: case BCACHE_SB_VERSION_BDEV_WITH_FEATURES: printf(" (data)"); break; default: printf(" (unknown)"); break; } printf("\t\t%-16s", devs->state); printf("\t%-16s", devs->bname); char attachdev[30]; if (strlen(devs->attachuuid) == 36) { cset_to_devname(&head, devs->cset, attachdev); } else if (devs->version == BCACHE_SB_VERSION_CDEV || devs->version == BCACHE_SB_VERSION_CDEV_WITH_UUID || devs->version == BCACHE_SB_VERSION_CDEV_WITH_FEATURES) { strcpy(attachdev, BCACHE_NO_SUPPORT); } else { strcpy(attachdev, BCACHE_ATTACH_ALONE); } printf("%-16s", attachdev); printf("%s", devs->attachuuid); putchar('\n'); } free_dev(&head); return 0; } int show_bdevs(void) { struct list_head head; struct dev *devs, *n; INIT_LIST_HEAD(&head); int ret; ret = list_bdevs(&head); if (ret != 0) { fprintf(stderr, "Failed to list devices\n"); return ret; } printf("Name\t\tType\t\tState\t\t\tBname\t\tAttachToDev\n"); list_for_each_entry_safe(devs, n, &head, dev_list) { printf("%s\t%lu", devs->name, devs->version); switch (devs->version) { // These are handled the same by the kernel case BCACHE_SB_VERSION_CDEV: case BCACHE_SB_VERSION_CDEV_WITH_UUID: case BCACHE_SB_VERSION_CDEV_WITH_FEATURES: printf(" (cache)"); break; // The second adds data offset supporet case BCACHE_SB_VERSION_BDEV: case BCACHE_SB_VERSION_BDEV_WITH_OFFSET: case BCACHE_SB_VERSION_BDEV_WITH_FEATURES: printf(" (data)"); break; default: printf(" (unknown)"); break; } printf("\t%-16s", devs->state); printf("\t%-16s", devs->bname); char attachdev[30]; if (strlen(devs->attachuuid) == 36) { cset_to_devname(&head, devs->cset, attachdev); } else if (devs->version == BCACHE_SB_VERSION_CDEV || devs->version == BCACHE_SB_VERSION_CDEV_WITH_UUID || devs->version == BCACHE_SB_VERSION_CDEV_WITH_FEATURES) { strcpy(attachdev, BCACHE_NO_SUPPORT); } else { strcpy(attachdev, BCACHE_ATTACH_ALONE); } printf("%s", attachdev); putchar('\n'); } free_dev(&head); return 0; } int detail_single(char *devname) { struct bdev bd; struct cdev cd; int type = 1; int ret; ret = detail_dev(devname, &bd, &cd, &type); if (ret != 0) { fprintf(stderr, "Failed to detail device\n"); return ret; } if (type == BCACHE_SB_VERSION_BDEV || type == BCACHE_SB_VERSION_BDEV_WITH_OFFSET || type == BCACHE_SB_VERSION_BDEV_WITH_FEATURES) { printf("sb.magic\t\t%s\n", bd.base.magic); printf("sb.first_sector\t\t%" PRIu64 "\n", bd.base.first_sector); printf("sb.csum\t\t\t%" PRIX64 "\n", bd.base.csum); printf("sb.version\t\t%" PRIu64, bd.base.version); printf(" [backing device]\n"); putchar('\n'); printf("dev.label\t\t"); if (*bd.base.label) print_encode(bd.base.label); else printf("(empty)"); putchar('\n'); printf("dev.uuid\t\t%s\n", bd.base.uuid); printf("dev.sectors_per_block\t%u\n" "dev.sectors_per_bucket\t%u\n", bd.base.sectors_per_block, bd.base.sectors_per_bucket); printf("dev.data.first_sector\t%u\n" "dev.data.cache_mode\t%d", bd.first_sector, bd.cache_mode); switch (bd.cache_mode) { case CACHE_MODE_WRITETHROUGH: printf(" [writethrough]\n"); break; case CACHE_MODE_WRITEBACK: printf(" [writeback]\n"); break; case CACHE_MODE_WRITEAROUND: printf(" [writearound]\n"); break; case CACHE_MODE_NONE: printf(" [no caching]\n"); break; default: putchar('\n'); } printf("dev.data.cache_state\t%u", bd.cache_state); switch (bd.cache_state) { case BDEV_STATE_NONE: printf(" [detached]\n"); break; case BDEV_STATE_CLEAN: printf(" [clean]\n"); break; case BDEV_STATE_DIRTY: printf(" [dirty]\n"); break; case BDEV_STATE_STALE: printf(" [inconsistent]\n"); break; default: putchar('\n'); } putchar('\n'); printf("cset.uuid\t\t%s\n", bd.base.cset); } else if (type == BCACHE_SB_VERSION_CDEV || type == BCACHE_SB_VERSION_CDEV_WITH_UUID || type == BCACHE_SB_VERSION_CDEV_WITH_FEATURES) { printf("sb.magic\t\t%s\n", cd.base.magic); printf("sb.first_sector\t\t%" PRIu64 "\n", cd.base.first_sector); printf("sb.csum\t\t\t%" PRIX64 "\n", cd.base.csum); printf("sb.version\t\t%" PRIu64, cd.base.version); printf(" [cache device]\n"); print_cache_set_supported_feature_sets(&cd.base.sb); putchar('\n'); printf("dev.label\t\t"); if (*cd.base.label) print_encode(cd.base.label); else printf("(empty)"); putchar('\n'); printf("dev.uuid\t\t%s\n", cd.base.uuid); printf("dev.sectors_per_block\t%u\n" "dev.sectors_per_bucket\t%u\n", cd.base.sectors_per_block, cd.base.sectors_per_bucket); printf("dev.cache.first_sector\t%u\n" "dev.cache.cache_sectors\t%ju\n" "dev.cache.total_sectors\t%ju\n" "dev.cache.ordered\t%s\n" "dev.cache.discard\t%s\n" "dev.cache.pos\t\t%u\n" "dev.cache.replacement\t%d", cd.first_sector, cd.cache_sectors, cd.total_sectors, cd.ordered ? "yes" : "no", cd.discard ? "yes" : "no", cd.pos, cd.replacement); switch (cd.replacement) { case CACHE_REPLACEMENT_LRU: printf(" [lru]\n"); break; case CACHE_REPLACEMENT_FIFO: printf(" [fifo]\n"); break; case CACHE_REPLACEMENT_RANDOM: printf(" [random]\n"); break; default: putchar('\n'); } putchar('\n'); printf("cset.uuid\t\t%s\n", cd.base.cset); } else { return 1; } return 0; }