diff --git a/bcache.c b/bcache.c index 7e061649..bcc8f738 100644 --- a/bcache.c +++ b/bcache.c @@ -15,12 +15,17 @@ #include #include #include +#include #include #include #include #include "bcache.h" +#define __KERNEL__ +#include +#undef __KERNEL__ + const char * const cache_state[] = { "active", "ro", @@ -802,7 +807,7 @@ void show_super_backingdev(struct cache_sb *sb, bool force_csum) bdev_state[BDEV_STATE(sb)]); } -void show_cache_member(struct cache_sb *sb, unsigned i) +static void show_cache_member(struct cache_sb *sb, unsigned i) { struct cache_member *m = ((struct cache_member *) sb->d) + i; @@ -845,3 +850,151 @@ void show_super_cache(struct cache_sb *sb, bool force_csum) show_cache_member(sb, sb->nr_this_dev); } + +void query_dev(char *dev, bool force_csum) +{ + struct cache_sb sb_stack, *sb = &sb_stack; + size_t bytes = sizeof(*sb); + + int fd = open(dev, O_RDONLY); + if (fd < 0) { + printf("Can't open dev %s: %s\n", dev, strerror(errno)); + exit(2); + } + + if (pread(fd, sb, bytes, SB_START) != bytes) { + fprintf(stderr, "Couldn't read\n"); + exit(2); + } + + if (sb->keys) { + bytes = sizeof(*sb) + sb->keys * sizeof(uint64_t); + sb = malloc(bytes); + + if (pread(fd, sb, bytes, SB_START) != bytes) { + fprintf(stderr, "Couldn't read\n"); + exit(2); + } + } + + if (!SB_IS_BDEV(sb)) + show_super_cache(sb, force_csum); + else + show_super_backingdev(sb, force_csum); +} + +int list_cachesets(char *cset_dir) +{ + struct dirent *ent; + DIR *dir = opendir(cset_dir); + if (!dir) { + fprintf(stderr, "Failed to open dir %s\n", cset_dir); + return 1; + } + + while ((ent = readdir(dir)) != NULL) { + struct stat statbuf; + char entry[100]; + + if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) + continue; + + strcpy(entry, cset_dir); + strcat(entry, "/"); + strcat(entry, ent->d_name); + if(stat(entry, &statbuf) == -1) { + fprintf(stderr, "Failed to stat %s\n", entry); + return 1; + } + if (S_ISDIR(statbuf.st_mode)) { + printf("%s\n", ent->d_name); + } + } + + closedir(dir); + + return 0; +} + +char *parse_array_to_list(char *const *args) +{ + int i, len = 0; + char *space = " "; + for(i=0; args[i] != NULL; i++) { + len+=strlen(args[i]) + 1; + } + + char *arg_list = (char*)malloc(sizeof(char)*len); + strcpy(arg_list, args[0]); + strcat(arg_list, space); + + for(i=1; args[i] != NULL; i++) { + strcat(arg_list, args[i]); + strcat(arg_list, space); + } + + return arg_list; +} + +int register_bcache(char *devs) +{ + int ret, bcachefd; + + bcachefd = open("/dev/bcache", O_RDWR); + if (bcachefd < 0) { + perror("Can't open bcache device"); + exit(EXIT_FAILURE); + } + + ret = ioctl(bcachefd, BCH_IOCTL_REGISTER, devs); + if (ret < 0) { + fprintf(stderr, "ioctl error %d", ret); + exit(EXIT_FAILURE); + } + return 0; + +} + +int probe(char *dev, int udev) +{ + struct cache_sb sb; + char uuid[40]; + blkid_probe pr; + + int fd = open(dev, O_RDONLY); + if (fd == -1) + return -1; + + if (!(pr = blkid_new_probe())) + return -1; + if (blkid_probe_set_device(pr, fd, 0, 0)) + return -1; + /* probe partitions too */ + if (blkid_probe_enable_partitions(pr, true)) + return -1; + /* bail if anything was found + * probe-bcache isn't needed once blkid recognizes bcache */ + if (!blkid_do_probe(pr)) { + return -1; + } + + if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) + return -1; + + if (memcmp(&sb.magic, &BCACHE_MAGIC, sizeof(sb.magic))) + return -1; + + uuid_unparse(sb.uuid.b, uuid); + + if (udev) + printf("ID_FS_UUID=%s\n" + "ID_FS_UUID_ENC=%s\n" + "ID_FS_TYPE=bcache\n", + uuid, uuid); + else + printf("%s: UUID=\"\" TYPE=\"bcache\"\n", uuid); + + return 0; +} + + diff --git a/bcache.h b/bcache.h index 7f61a0e7..05c0989f 100644 --- a/bcache.h +++ b/bcache.h @@ -54,9 +54,16 @@ unsigned get_blocksize(const char *); long strtoul_or_die(const char *, size_t, const char *); void show_super_backingdev(struct cache_sb *, bool); -void show_cache_member(struct cache_sb *, unsigned); void show_super_cache(struct cache_sb *, bool); +void query_dev(char *dev, bool force_csum); +int list_cachesets(char *cset_dir); +char *parse_array_to_list(char *const *args); +int register_bcache(); +int probe(char *dev, int udev); + + + #define csum_set(i, type) \ ({ \ void *start = ((void *) (i)) + sizeof(uint64_t); \ diff --git a/bcacheadm.c b/bcacheadm.c index ecfc650c..ed65c6e7 100644 --- a/bcacheadm.c +++ b/bcacheadm.c @@ -28,9 +28,6 @@ #include #include #include //libbcache -#define __KERNEL__ -#include -#undef __KERNEL__ #define PACKAGE_NAME "bcacheadm" #define PACKAGE_VERSION "1.0" @@ -77,14 +74,12 @@ enum long_opts { /* super-show globals */ bool force_csum = false; -char *show_dev = NULL; - /* probe globals */ bool udev = false; -/* register globals */ -int bcachefd; +/* list globals */ +char *cset_dir = "/sys/fs/bcache"; /* make-bcache option setters */ static int set_CACHE_SET_UUID(NihOption *option, const char *arg) @@ -178,7 +173,6 @@ static NihOption make_bcache_options[] = { {'t', "tier", N_("tier of subsequent devices"), NULL,NULL, &tier, NULL}, {'p', "cache_replacement_policy", N_("one of (lru|fifo|random)"), NULL,NULL, &replacement_policy, NULL}, {'o', "data_offset", N_("data offset in sectors"), NULL,NULL, &data_offset, NULL}, - {'h', "help", N_("display this help and exit"), NULL,NULL, NULL, NULL}, {0, "cset-uuid", N_("UUID for the cache set"), NULL, NULL, NULL, set_CACHE_SET_UUID }, {0, "csum-type", N_("One of (none|crc32c|crc64)"), NULL, NULL, NULL, set_CSUM_TYPE }, @@ -193,13 +187,6 @@ static NihOption make_bcache_options[] = { NIH_OPTION_LAST }; -static NihOption super_show_options[] = { - {'f', "force_csum", N_("force_csum"), NULL, NULL, &force_csum, NULL}, - {0, "dev", N_("dev"), NULL, NULL, &show_dev, NULL}, - NIH_OPTION_LAST - -}; - static NihOption probe_bcache_options[] = { {'o', "udev", N_("udev"), NULL, NULL, NULL, set_udev}, NIH_OPTION_LAST @@ -209,6 +196,16 @@ static NihOption bcache_register_options[] = { NIH_OPTION_LAST }; +static NihOption query_devs_options[] = { + {'f', "force_csum", N_("force_csum"), NULL, NULL, &force_csum, NULL}, + NIH_OPTION_LAST +}; + +static NihOption list_cachesets_options[] = { + {'d', "dir", N_("directory"), NULL, NULL, &cset_dir, NULL}, + NIH_OPTION_LAST +}; + static NihOption options[] = { NIH_OPTION_LAST }; @@ -280,80 +277,12 @@ int make_bcache (NihCommand *command, char *const *args) return 0; } -int super_show (NihCommand *command, char *const *args) -{ - struct cache_sb sb_stack, *sb = &sb_stack; - size_t bytes = sizeof(*sb); - - int fd = open(show_dev, O_RDONLY); - if (fd < 0) { - printf("Can't open dev %s: %s\n", show_dev, strerror(errno)); - exit(2); - } - - if (pread(fd, sb, bytes, SB_START) != bytes) { - fprintf(stderr, "Couldn't read\n"); - exit(2); - } - - if (sb->keys) { - bytes = sizeof(*sb) + sb->keys * sizeof(uint64_t); - sb = malloc(bytes); - - if (pread(fd, sb, bytes, SB_START) != bytes) { - fprintf(stderr, "Couldn't read\n"); - exit(2); - } - } - - if (!SB_IS_BDEV(sb)) - show_super_cache(sb, force_csum); - else - show_super_backingdev(sb, force_csum); - - return 0; -} - int probe_bcache (NihCommand *command, char *const *args) { int i; - struct cache_sb sb; - char uuid[40]; - blkid_probe pr; - for (i = 0; args[i]!=NULL; i++) { - int fd = open(args[i], O_RDONLY); - if (fd == -1) - continue; - - if (!(pr = blkid_new_probe())) - continue; - if (blkid_probe_set_device(pr, fd, 0, 0)) - continue; - /* probe partitions too */ - if (blkid_probe_enable_partitions(pr, true)) - continue; - /* bail if anything was found - * probe-bcache isn't needed once blkid recognizes bcache */ - if (!blkid_do_probe(pr)) { - continue; - } - - if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) - continue; - - if (memcmp(&sb.magic, &BCACHE_MAGIC, sizeof(sb.magic))) - continue; - - uuid_unparse(sb.uuid.b, uuid); - - if (udev) - printf("ID_FS_UUID=%s\n" - "ID_FS_UUID_ENC=%s\n" - "ID_FS_TYPE=bcache\n", - uuid, uuid); - else - printf("%s: UUID=\"\" TYPE=\"bcache\"\n", uuid); + for (i = 0; args[i] != NULL; i++) { + probe(args[i], udev); } return 0; @@ -362,26 +291,36 @@ int probe_bcache (NihCommand *command, char *const *args) int bcache_register (NihCommand *command, char *const *args) { int ret; + char *arg_list = parse_array_to_list(args); - bcachefd = open("/dev/bcache", O_RDWR); - if (bcachefd < 0) { - perror("Can't open bcache device"); - exit(EXIT_FAILURE); + if(arg_list) { + ret = register_bcache(arg_list); + free(arg_list); } - ret = ioctl(bcachefd, BCH_IOCTL_REGISTER, args); - if (ret < 0) { - fprintf(stderr, "ioctl error %d", ret); - exit(EXIT_FAILURE); + return ret; +} + +int bcache_list_cachesets (NihCommand *command, char *const *args) +{ + return list_cachesets(cset_dir); +} + +int bcache_query_devs (NihCommand *command, char *const *args) +{ + int i; + + for (i = 0; args[i]!=NULL; i++) { + query_dev(args[i], false); } - return 0; } static NihCommand commands[] = { {"format", N_("format "), "Format one or a list of devices with bcache datastructures. You need to do this before you create a volume", N_("format drive[s] with bcache"), NULL, make_bcache_options, make_bcache}, - {"show-sb", N_("show-sb "), "View a superblock on one or a list of bcache formated devices", N_("show superblock on each of the listed drive"), NULL, super_show_options, super_show}, - {"probe", N_("probe "), NULL, NULL, NULL, probe_bcache_options, probe_bcache}, - {"register", N_("register "), NULL, NULL, NULL, bcache_register_options, bcache_register}, + {"probe", N_("probe "), "Does a blkid_probe on a device", N_("Does a blkid_probe on a device"), NULL, probe_bcache_options, probe_bcache}, + {"register", N_("register "), "Registers a list of devices", N_("Registers a list of devices"), NULL, bcache_register_options, bcache_register}, + {"list-cachesets", N_("list-cachesets"), "Lists cachesets in /sys/fs/bcache", N_("Lists cachesets in /sys/fs/bcache"), NULL, list_cachesets_options, bcache_list_cachesets}, + {"query-devs", N_("query "), "Gives info about the superblock of a list of devices", N_("show superblock on each of the listed drive"), NULL, query_devs_options, bcache_query_devs}, NIH_COMMAND_LAST };