]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
rewrite
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 9 May 2015 01:13:38 +0000 (18:13 -0700)
committerKent Overstreet <kent.overstreet@gmail.com>
Mon, 11 May 2015 04:36:46 +0000 (21:36 -0700)
13 files changed:
Makefile
bcache.c
bcache.h
bcacheadm-assemble.c [new file with mode: 0644]
bcacheadm-assemble.h [new file with mode: 0644]
bcacheadm-format.c
bcacheadm-format.h [new file with mode: 0644]
bcacheadm-query.c [new file with mode: 0644]
bcacheadm-query.h [new file with mode: 0644]
bcacheadm-run.c [new file with mode: 0644]
bcacheadm-run.h [new file with mode: 0644]
bcacheadm.c
bcacheadm.h [deleted file]

index 7d022cb55247a281a4b08dc5840b3a4a1a8f5b2a..696d355597bbc9f1d30ce0b4dc14037f15baa378 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,8 @@ bcache.o: CFLAGS += `pkg-config --cflags uuid blkid`
 
 bcacheadm.o: CFLAGS += `pkg-config --cflags uuid blkid libnih`
 bcacheadm: LDLIBS += `pkg-config --libs uuid blkid libnih`
-bcacheadm: bcacheadm.o bcacheadm-format.o bcache.o
+bcacheadm: bcacheadm.o bcacheadm-format.o bcacheadm-assemble.o bcacheadm-run.o\
+       bcacheadm-query.o bcache.o
 
 probe-bcache.o: CFLAGS += `pkg-config --cflags uuid blkid`
 probe-bcache: LDLIBS += `pkg-config --libs uuid blkid`
index e2de70b96608c06f44addd770214e58cdd2d493b..cd2ea1abd65ac733dbf2451e80258a4ca813c8fc 100644 (file)
--- a/bcache.c
+++ b/bcache.c
@@ -852,55 +852,6 @@ char *dev_name(const char *ugly_path) {
        return strdup(buf);
 }
 
-static void list_cacheset_devs(char *cset_dir, char *cset_name, bool parse_dev_name)
-{
-       DIR *cachedir, *dir;
-       struct stat cache_stat;
-       char entry[MAX_PATH];
-       struct dirent *ent;
-       snprintf(entry, MAX_PATH, "%s/%s", cset_dir, cset_name);
-
-       if((dir = opendir(entry)) != NULL) {
-               while((ent = readdir(dir)) != NULL) {
-                       char buf[MAX_PATH];
-                       int len;
-                       char *tmp;
-
-                       /*
-                        * We are looking for all cache# directories
-                        * do a strlen < 9 to skip over other entries
-                        * that also start with "cache"
-                        */
-                       if(strncmp(ent->d_name, "cache", 5) ||
-                                       !(strlen(ent->d_name) < 9))
-                               continue;
-
-                       snprintf(entry, MAX_PATH, "%s/%s/%s",
-                                       cset_dir,
-                                       cset_name,
-                                       ent->d_name);
-
-                       if((cachedir = opendir(entry)) == NULL)
-                               continue;
-
-                       if(stat(entry, &cache_stat))
-                               continue;
-
-                       if((len = readlink(entry, buf, sizeof(buf) - 1)) !=
-                                       -1) {
-                               buf[len] = '\0';
-                               if(parse_dev_name) {
-                                       tmp = dev_name(buf);
-                                       printf("/dev%s\n", tmp);
-                                       free(tmp);
-                               } else {
-                                       printf("\t%s\n", buf);
-                               }
-                       }
-               }
-       }
-}
-
 char *find_matching_uuid(char *stats_dir, char *subdir, const char *stats_dev_uuid)
 {
        /* Do a query-dev --uuid only to get the uuid
@@ -973,360 +924,21 @@ char *find_matching_uuid(char *stats_dir, char *subdir, const char *stats_dev_uu
        return err;
 }
 
-char *list_cachesets(char *cset_dir, bool list_devs)
-{
-       struct dirent *ent;
-       DIR *dir;
-       char *err = NULL;
-
-       dir = opendir(cset_dir);
-       if (!dir) {
-               err = "Failed to open cacheset dir";
-               goto err;
-       }
-
-       while ((ent = readdir(dir)) != NULL) {
-               struct stat statbuf;
-               char entry[MAX_PATH];
-
-               if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
-                       continue;
-
-               snprintf(entry, MAX_PATH, "%s/%s", cset_dir, ent->d_name);
-               if(stat(entry, &statbuf) == -1) {
-                       err = "Failed to stat cacheset subdir";
-                       goto err;
-               }
-
-               if (S_ISDIR(statbuf.st_mode)) {
-                       printf("%s\n", ent->d_name);
-
-                       if(list_devs) {
-                               list_cacheset_devs(cset_dir, ent->d_name, true);
-                       }
-               }
-       }
-
-err:
-       closedir(dir);
-       return err;
-}
-
-char *register_bcache(char *const *devs)
-{
-       int ret, bcachefd;
-       char *err = NULL;
-
-       bcachefd = open("/dev/bcache", O_RDWR);
-       if (bcachefd < 0) {
-               err = "Can't open bcache device";
-               goto err;
-       }
-
-       ret = ioctl(bcachefd, BCH_IOCTL_REGISTER, devs);
-       if (ret < 0) {
-               char tmp[64];
-               snprintf(tmp, 64, "ioctl register error: %s\n",
-                               strerror(ret));
-               err = strdup(tmp);
-               goto err;
-       }
-
-err:
-       if (bcachefd)
-               close(bcachefd);
-       return err;
-}
-
-char *unregister_bcache(char *const *devs)
-{
-       int ret, bcachefd;
-       char *err = NULL;
-
-       bcachefd = open("/dev/bcache_extent0", O_RDWR);
-       if (bcachefd < 0) {
-               err = "Can't open bcache device";
-               goto err;
-       }
-
-       ret = ioctl(bcachefd, BCH_IOCTL_STOP);
-       if (ret < 0) {
-               char tmp[64];
-               snprintf(tmp, 64, "ioctl unregister error: %s\n",
-                               strerror(ret));
-               err = strdup(tmp);
-               goto err;
-       }
-
-err:
-       close(bcachefd);
-       return err;
-}
-
-char *add_devices(char *const *devs)
-{
-       int ret, bcachefd;
-       char *err = NULL;
-
-       bcachefd = open("/dev/bcache_extent0", O_RDWR);
-       if (bcachefd < 0) {
-               err = "Can't open bcache device";
-               goto err;
-       }
-
-       struct bch_ioctl_add_disks ia;
-       ia.devs = devs;
-
-       ret = ioctl(bcachefd, BCH_IOCTL_ADD_DISKS, &ia);
-       if (ret < 0) {
-               char tmp[128];
-               snprintf(tmp, 128, "ioctl add disk error: %s\n",
-                               strerror(ret));
-               err = strdup(tmp);
-       }
-
-err:
-       close(bcachefd);
-       return err;
-}
-
-char *remove_device(const char *dev, bool force)
-{
-       int ret, bcachefd;
-       char *err = NULL;
-
-       bcachefd = open("/dev/bcache_extent0", O_RDWR);
-       if (bcachefd < 0) {
-               err = "Can't open bcache device";
-               goto err;
-       }
-
-       struct bch_ioctl_rm_disk ir;
-       ir.dev = dev;
-       ir.force = force ? 1 : 0;
-
-       ret = ioctl(bcachefd, BCH_IOCTL_RM_DISK, &ir);
-       if (ret < 0) {
-               char tmp[128];
-               snprintf(tmp, 128, "ioctl add disk error: %s\n",
-                               strerror(ret));
-               err = strdup(tmp);
-       }
-
-err:
-       close(bcachefd);
-       return err;
-}
-
-char *device_set_failed(const char *dev_uuid) {
-       int ret, bcachefd;
-       char *err = NULL;
-       uuid_le dev;
-       struct bch_ioctl_disk_failed df;
-
-       bcachefd = open("/dev/bcache_extent0", O_RDWR);
-       if (bcachefd < 0) {
-               err = "Can't open bcache device";
-               goto err;
-       }
-
-       uuid_parse(dev_uuid, dev.b);
-       df.dev_uuid = dev;
-
-       ret = ioctl(bcachefd, BCH_IOCTL_SET_DISK_FAILED, &df);
-       if (ret < 0) {
-               char tmp[128];
-               snprintf(tmp, 128, "ioctl set disk failed error %s\n",
-                               strerror(ret));
-               err = strdup(tmp);
-       }
-
-err:
-       close(bcachefd);
-       return err;
-}
-
-char *probe(char *dev, int udev)
+int bcachectl_open(void)
 {
-       struct cache_sb sb;
-       char uuid[40];
-       blkid_probe pr;
-       char *err = NULL;
-
-       int fd = open(dev, O_RDONLY);
-       if (fd == -1) {
-               err = "Got file descriptor -1 trying to open dev";
-               goto err;
-       }
-
-       if (!(pr = blkid_new_probe())) {
-               err = "Failed trying to get a blkid for new probe";
-               goto err;
-       }
-
-       if (blkid_probe_set_device(pr, fd, 0, 0)) {
-               err = "Failed blkid probe set device";
-               goto err;
-       }
-
-       /* probe partitions too */
-       if (blkid_probe_enable_partitions(pr, true)) {
-               err = "Enable probe partitions";
-               goto err;
-       }
-
-       /* bail if anything was found
-        * probe-bcache isn't needed once blkid recognizes bcache */
-       if (!blkid_do_probe(pr)) {
-               err = "blkid recognizes bcache";
-               goto err;
-       }
+       int fd = open("/dev/bcache-ctl", O_RDWR);
+       if (fd < 0)
+               die("Can't open bcache device: %s", strerror(errno));
 
-       if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) {
-               err = "Failed to read superblock";
-               goto err;
-       }
-
-       if (memcmp(&sb.magic, &BCACHE_MAGIC, sizeof(sb.magic))) {
-               err = "Bcache magic incorrect";
-               goto err;
-       }
-
-       uuid_unparse(sb.disk_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;
-
-err:
-       return err;
-}
-
-char *read_stat_dir(DIR *dir, char *stats_dir, char *stat_name, char *ret)
-{
-       struct stat statbuf;
-       char entry[MAX_PATH];
-       char *err = NULL;
-
-       snprintf(entry, MAX_PATH, "%s/%s", stats_dir, stat_name);
-       if(stat(entry, &statbuf) == -1) {
-               char tmp[MAX_PATH];
-               snprintf(tmp, MAX_PATH, "Failed to stat %s\n", entry);
-               err = strdup(tmp);
-               goto err;
-       }
-
-       if (S_ISREG(statbuf.st_mode)) {
-               FILE *fp = NULL;
-
-               fp = fopen(entry, "r");
-               if(!fp) {
-                       /* If we can't open the file, this is probably because
-                        * of permissions, just move to the next file */
-                       return NULL;
-               }
-
-               while(fgets(ret, MAX_PATH, fp));
-               fclose(fp);
-       }
-err:
-       return err;
+       return fd;
 }
 
-char *bcache_get_capacity(const char *cset_dir, const char *capacity_uuid,
-                         bool show_devs)
+unsigned nr_args(char *const *args)
 {
-       char *err = NULL;
-       char bucket_size_path[MAX_PATH];
-       char nbuckets_path[MAX_PATH];
-       char avail_buckets_path[MAX_PATH];
-       char cache_path[MAX_PATH];
-
-       double bucket_sizes[MAX_DEVS];
-       double nbuckets[MAX_DEVS];
-       double avail_buckets[MAX_DEVS];
-       char *dev_names[MAX_DEVS];
-       int dev_count = 0, i;
-       double total_cap = 0, total_free = 0;
-       int precision = 2;
-
-
-       while (true) {
-               char buf[MAX_PATH];
-               int len;
-               DIR *cache_dir;
-
-               snprintf(bucket_size_path, sizeof(bucket_size_path), "%s/%s/%s%d/%s", cset_dir,
-                               capacity_uuid, "cache", dev_count, "bucket_size_bytes");
-               snprintf(nbuckets_path, sizeof(nbuckets_path), "%s/%s/%s%d/%s", cset_dir,
-                               capacity_uuid, "cache", dev_count, "nbuckets");
-               snprintf(avail_buckets_path, sizeof(avail_buckets_path), "%s/%s/%s%d/%s", cset_dir,
-                               capacity_uuid, "cache", dev_count, "available_buckets");
-               snprintf(cache_path, sizeof(cache_path), "%s/%s/%s%d", cset_dir, capacity_uuid,
-                               "cache", dev_count);
-
-               if((cache_dir = opendir(cache_path)) == NULL)
-                       break;
-
-               err = read_stat_dir(cache_dir, cache_path,
-                               "bucket_size_bytes", buf);
-               if (err)
-                       goto err;
-               else
-                       bucket_sizes[dev_count] = atof(buf);
+       unsigned i;
 
-               err = read_stat_dir(cache_dir, cache_path,
-                               "nbuckets", buf);
-               if (err)
-                       goto err;
-               else
-                       nbuckets[dev_count] = atof(buf);
-
-               err = read_stat_dir(cache_dir, cache_path,
-                               "available_buckets", buf);
-               if (err)
-                       goto err;
-               else
-                       avail_buckets[dev_count] = atof(buf);
-
-               if((len = readlink(cache_path, buf, sizeof(buf) - 1)) != -1) {
-                       buf[len] = '\0';
-                       dev_names[dev_count] = dev_name(buf);
-               }
-
-               dev_count++;
-       }
-
-       printf("%-15s%-25s%-25s\n", "Device Name", "Capacity (512 Blocks)", "Free (512 Blocks)");
+       for (i = 0; args[i]; i++)
+               ;
 
-       if (show_devs) {
-               for (i = 0; i < dev_count; i++) {
-                       printf("%s%-11s%-25.*f%-25.*f\n", "/dev", dev_names[i],
-                               precision,
-                               (bucket_sizes[i] * nbuckets[i]) / 512,
-                               precision,
-                               (bucket_sizes[i] * avail_buckets[i]) / 512);
-               }
-       }
-
-       for (i = 0; i < dev_count; i++) {
-               total_cap += (bucket_sizes[i] * nbuckets[i]) / 512;
-               total_free += (bucket_sizes[i] * avail_buckets[i]) / 512;
-
-       }
-
-       printf("%-15s%-25.*f%-25.*f\n", "Total", precision, total_cap,
-                       precision, total_free);
-
-err:
-       for (i = 0; i < dev_count; i++)
-               if (dev_names[i])
-                       free(dev_names[i]);
-       return err;
+       return i;
 }
index e5ab8ae86b822605eda7a30cde8f20cc663f5e51..16d0929598a154d44c646cf30aca123315ecfada 100644 (file)
--- a/bcache.h
+++ b/bcache.h
@@ -7,6 +7,7 @@
 #ifndef _BCACHE_H
 #define _BCACHE_H
 
+#include <stdint.h>
 #include <linux/bcache.h>
 #include <dirent.h>
 
@@ -87,18 +88,13 @@ enum sysfs_attr sysfs_attr_type(const char *attr);
 void sysfs_attr_list();
 
 struct cache_sb *query_dev(char *, bool, bool, bool, char *dev_uuid);
-char *list_cachesets(char *, bool);
 char *parse_array_to_list(char *const *);
 char *register_bcache(char *const *);
-char *unregister_bcache(char *const *);
-char *probe(char *, int);
-char *read_stat_dir(DIR *, char *, char *, char *);
 char *find_matching_uuid(char *, char *, const char*);
-char *add_devices(char *const *);
-char *remove_device(const char *, bool);
-char *bcache_get_capacity(const char *, const char *, bool);
 char *dev_name(const char *);
-char *device_set_failed(const char *dev_uuid);
+
+int bcachectl_open(void);
+unsigned nr_args(char * const *);
 
 #define csum_set(i, type)                                              \
 ({                                                                     \
diff --git a/bcacheadm-assemble.c b/bcacheadm-assemble.c
new file mode 100644 (file)
index 0000000..976caad
--- /dev/null
@@ -0,0 +1,61 @@
+
+#include <alloca.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/ioctl.h>
+
+#include <nih/command.h>
+#include <nih/option.h>
+
+#include <linux/bcache-ioctl.h>
+
+#include "bcache.h"
+#include "bcacheadm-assemble.h"
+
+NihOption opts_assemble[] = {
+       NIH_OPTION_LAST
+};
+
+int cmd_assemble(NihCommand *command, char *const *args)
+{
+       unsigned nr_devs = nr_args(args);
+
+       struct bch_ioctl_assemble *assemble =
+               alloca(sizeof(*assemble) + sizeof(__u64) * nr_devs);
+
+       memset(assemble, 0, sizeof(*assemble));
+       assemble->nr_devs = nr_devs;
+
+       for (unsigned i = 0; i < nr_devs; i++)
+            assemble->devs[i] = (__u64) args[i];
+
+       int ret = ioctl(bcachectl_open(), BCH_IOCTL_ASSEMBLE, assemble);
+       if (ret < 0)
+               die("BCH_IOCTL_ASSEMBLE error: %s", strerror(errno));
+
+       return 0;
+}
+
+NihOption opts_incremental[] = {
+       NIH_OPTION_LAST
+};
+
+int cmd_incremental(NihCommand *command, char *const *args)
+{
+       if (nr_args(args) != 1)
+               die("Please supply exactly one device");
+
+       struct bch_ioctl_incremental incremental = {
+               .dev = (__u64) args[0],
+       };
+
+       int ret = ioctl(bcachectl_open(), BCH_IOCTL_INCREMENTAL, &incremental);
+       if (ret < 0)
+               die("BCH_IOCTL_INCREMENTAL error: %s", strerror(errno));
+
+       return 0;
+}
diff --git a/bcacheadm-assemble.h b/bcacheadm-assemble.h
new file mode 100644 (file)
index 0000000..49ccf9a
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _BCACHEADM_ASSEMBLE_H
+#define _BCACHEADM_ASSEMBLE_H
+
+extern NihOption opts_assemble[];
+int cmd_assemble(NihCommand *, char * const *);
+
+extern NihOption opts_incremental[];
+int cmd_incremental(NihCommand *, char * const *);
+
+#endif /* _BCACHEADM_ASSEMBLE_H */
index 5121fd150e1eb28c4be48e57dc8d3c3d1e7b7e4c..52acc097b1a0c807c6835da8b9d86f9c0a63825a 100644 (file)
@@ -35,7 +35,7 @@
 #include <nih/option.h>
 
 #include "bcache.h"
-#include "bcacheadm.h"
+#include "bcacheadm-format.h"
 
 static struct cache_opts {
        int             fd;
@@ -180,7 +180,7 @@ static int set_cache_mode(NihOption *option, const char *arg)
        return 0;
 }
 
-NihOption bcacheadm_format_options[] = {
+NihOption opts_format[] = {
 //     { int shortoption, char *longoption, char *help, NihOptionGroup, char *argname, void *value, NihOptionSetter}
 
        { 'C',  "cache",                N_("Format a cache device"),
@@ -259,12 +259,14 @@ static unsigned ilog2(uint64_t n)
        return ret;
 }
 
-int bcacheadm_format(NihCommand *command, char *const *args)
+static int format_v0(void)
 {
-       struct cache_sb *cache_set_sb;
+       return 0;
+}
 
-       if (!nr_cache_devices && !nr_backing_devices)
-               die("Please supply a device");
+static int format_v1(void)
+{
+       struct cache_sb *cache_set_sb;
 
        if (!block_size) {
                for (struct cache_opts *i = cache_devices;
@@ -403,3 +405,11 @@ int bcacheadm_format(NihCommand *command, char *const *args)
 
        return 0;
 }
+
+int cmd_format(NihCommand *command, char *const *args)
+{
+       if (!nr_cache_devices && !nr_backing_devices)
+               die("Please supply a device");
+
+       return format_v1();
+}
diff --git a/bcacheadm-format.h b/bcacheadm-format.h
new file mode 100644 (file)
index 0000000..301e9a4
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _BCACHEADM_FORMAT_H
+#define _BCACHEADM_FORMAT_H
+
+extern NihOption opts_format[];
+int cmd_format(NihCommand *, char * const *);
+
+#endif /* _BCACHEADM_FORMAT_H */
diff --git a/bcacheadm-query.c b/bcacheadm-query.c
new file mode 100644 (file)
index 0000000..b3f5e39
--- /dev/null
@@ -0,0 +1,361 @@
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <nih/command.h>
+#include <nih/option.h>
+
+#include <linux/bcache-ioctl.h>
+
+#include <uuid/uuid.h>
+
+#include "bcache.h"
+#include "bcacheadm-query.h"
+
+static char *cset_dir = "/sys/fs/bcache";
+static bool list_devs = false;
+static const char *internal_uuid = NULL;
+
+NihOption opts_list[] = {
+       {'d', "dir", N_("directory"), NULL, NULL, &cset_dir, NULL},
+       {0, "list-devs", N_("list all devices in the cache sets as well"), NULL, NULL, &list_devs, NULL},
+       {0, "internal_uuid", N_("Show the internal UUID for the given cacheset UUID"), NULL, "UUID", &internal_uuid, NULL},
+       NIH_OPTION_LAST
+};
+
+static void list_cacheset_devs(char *cset_dir, char *cset_name, bool parse_dev_name)
+{
+       DIR *cachedir, *dir;
+       struct stat cache_stat;
+       char entry[MAX_PATH];
+       struct dirent *ent;
+       snprintf(entry, MAX_PATH, "%s/%s", cset_dir, cset_name);
+
+       if((dir = opendir(entry)) != NULL) {
+               while((ent = readdir(dir)) != NULL) {
+                       char buf[MAX_PATH];
+                       int len;
+                       char *tmp;
+
+                       /*
+                        * We are looking for all cache# directories
+                        * do a strlen < 9 to skip over other entries
+                        * that also start with "cache"
+                        */
+                       if(strncmp(ent->d_name, "cache", 5) ||
+                                       !(strlen(ent->d_name) < 9))
+                               continue;
+
+                       snprintf(entry, MAX_PATH, "%s/%s/%s",
+                                       cset_dir,
+                                       cset_name,
+                                       ent->d_name);
+
+                       if((cachedir = opendir(entry)) == NULL)
+                               continue;
+
+                       if(stat(entry, &cache_stat))
+                               continue;
+
+                       if((len = readlink(entry, buf, sizeof(buf) - 1)) !=
+                                       -1) {
+                               buf[len] = '\0';
+                               if(parse_dev_name) {
+                                       tmp = dev_name(buf);
+                                       printf("/dev%s\n", tmp);
+                                       free(tmp);
+                               } else {
+                                       printf("\t%s\n", buf);
+                               }
+                       }
+               }
+       }
+}
+
+static char *list_cachesets(char *cset_dir, bool list_devs)
+{
+       struct dirent *ent;
+       DIR *dir;
+       char *err = NULL;
+
+       dir = opendir(cset_dir);
+       if (!dir) {
+               err = "Failed to open cacheset dir";
+               goto err;
+       }
+
+       while ((ent = readdir(dir)) != NULL) {
+               struct stat statbuf;
+               char entry[MAX_PATH];
+
+               if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
+                       continue;
+
+               snprintf(entry, MAX_PATH, "%s/%s", cset_dir, ent->d_name);
+               if(stat(entry, &statbuf) == -1) {
+                       err = "Failed to stat cacheset subdir";
+                       goto err;
+               }
+
+               if (S_ISDIR(statbuf.st_mode)) {
+                       printf("%s\n", ent->d_name);
+
+                       if(list_devs) {
+                               list_cacheset_devs(cset_dir, ent->d_name, true);
+                       }
+               }
+       }
+
+err:
+       closedir(dir);
+       return err;
+}
+
+static char *read_stat_dir(DIR *dir, char *stats_dir, char *stat_name, char *ret)
+{
+       struct stat statbuf;
+       char entry[MAX_PATH];
+       char *err = NULL;
+
+       snprintf(entry, MAX_PATH, "%s/%s", stats_dir, stat_name);
+       if(stat(entry, &statbuf) == -1) {
+               char tmp[MAX_PATH];
+               snprintf(tmp, MAX_PATH, "Failed to stat %s\n", entry);
+               err = strdup(tmp);
+               goto err;
+       }
+
+       if (S_ISREG(statbuf.st_mode)) {
+               FILE *fp = NULL;
+
+               fp = fopen(entry, "r");
+               if(!fp) {
+                       /* If we can't open the file, this is probably because
+                        * of permissions, just move to the next file */
+                       return NULL;
+               }
+
+               while(fgets(ret, MAX_PATH, fp));
+               fclose(fp);
+       }
+err:
+       return err;
+}
+
+int cmd_list(NihCommand *command, char *const *args)
+{
+       char *err = NULL;
+
+       if (internal_uuid) {
+               char uuid_path[MAX_PATH];
+               DIR *uuid_dir;
+               char buf[MAX_PATH];
+
+               snprintf(uuid_path, MAX_PATH, "%s/%s", cset_dir, internal_uuid);
+
+               err = "uuid does not exist";
+               if((uuid_dir = opendir(uuid_path)) == NULL)
+                       goto err;
+
+               err = read_stat_dir(uuid_dir, uuid_path, "/internal/internal_uuid", buf);
+               if (err)
+                       goto err;
+               printf("%s", buf);
+               return 0;
+       }
+
+       err = list_cachesets(cset_dir, list_devs);
+       if (err)
+               goto err;
+
+       return 0;
+
+err:
+       printf("bcache_list_cachesets error :%s\n", err);
+       return -1;
+}
+
+static bool force_csum = false;
+static bool uuid_only = false;
+static bool query_brief = false;
+
+NihOption opts_query[] = {
+       {'f', "force_csum", N_("force_csum"), NULL, NULL, &force_csum, NULL},
+       {'u', "uuid-only", N_("only print out the uuid for the devices, not the whole superblock"), NULL, NULL, &uuid_only, NULL},
+       {'b', "brief", N_("only print out the cluster,server,and disk uuids"), NULL, NULL, &query_brief, NULL},
+       NIH_OPTION_LAST
+};
+
+int cmd_query(NihCommand *command, char *const *args)
+{
+       int i;
+
+       if (query_brief)
+               printf("%-10s%-40s%-40s%-40s\n", "dev name", "disk uuid",
+                               "server uuid", "cluster uuid");
+
+       for (i = 0; args[i] != NULL; i++) {
+               char dev_uuid[40];
+               struct cache_sb *sb = query_dev(args[i], force_csum,
+                               !query_brief, uuid_only, dev_uuid);
+
+               if (!sb) {
+                       printf("error opening the superblock for %s\n",
+                                       args[i]);
+                       return -1;
+               }
+
+               if (uuid_only) {
+                       printf("%s\n", dev_uuid);
+               } else if (query_brief) {
+                       char set_uuid_str[40], dev_uuid_str[40];
+                       char *clus_uuid = (char *)sb->label;
+
+                       uuid_unparse(sb->user_uuid.b, set_uuid_str);
+                       uuid_unparse(sb->disk_uuid.b, dev_uuid_str);
+                       if (!strcmp(clus_uuid, ""))
+                               clus_uuid = "None";
+
+                       printf("%-10s%-40s%-40s%-40s\n", args[i],
+                                       dev_uuid_str,
+                                       set_uuid_str,
+                                       clus_uuid);
+               }
+               free(sb);
+       }
+
+       return 0;
+}
+
+static bool status_all = false;
+
+NihOption opts_status[] = {
+       {'a', "all", N_("all"), NULL, NULL, &status_all, NULL},
+       NIH_OPTION_LAST
+};
+
+int cmd_status(NihCommand *command, char *const *args)
+{
+       int i, dev_count = 0, seq, cache_count = 0;
+       struct cache_sb *seq_sb = NULL;
+       char cache_path[MAX_PATH];
+       char *dev_names[MAX_DEVS];
+       char *dev_uuids[MAX_DEVS];
+       char intbuf[4];
+       char set_uuid[40];
+
+       for (i = 0; args[i] != NULL; i++) {
+               struct cache_sb *sb = query_dev(args[i], false, false,
+                               false, NULL);
+
+               if (!sb) {
+                       printf("Unable to open superblock, bad path\n");
+                       return -1;
+               }
+
+               if (!seq_sb || sb->seq > seq) {
+                       seq = sb->seq;
+                       seq_sb = sb;
+               } else
+                       free(sb);
+       }
+
+       if (!seq_sb) {
+               printf("Unable to find a superblock\n");
+               return -1;
+       } else {
+               uuid_unparse(seq_sb->user_uuid.b, set_uuid);
+               printf("%-50s%-15s%-4s\n", "uuid", "state", "tier");
+       }
+
+       snprintf(intbuf, 4, "%d", i);
+       snprintf(cache_path, MAX_PATH, "%s/%s/%s", cset_dir, set_uuid,
+                       "cache0");
+
+       /*
+        * Get a list of all the devices from sysfs first, then
+        * compare it to the list we get back from the most up
+        * to date superblock. If there are any devices in the superblock
+        * that are not in sysfs, print out 'missing'
+        */
+       while (true) {
+               char buf[MAX_PATH];
+               int len;
+               DIR *cache_dir;
+
+               if(((cache_dir = opendir(cache_path)) == NULL) &&
+                   cache_count > MAX_DEVS)
+                       break;
+
+               if (cache_dir)
+                       closedir(cache_dir);
+
+               if((len = readlink(cache_path, buf, sizeof(buf) - 1)) != -1) {
+                       struct cache_sb *sb;
+                       char dev_uuid[40];
+                       char dev_path[32];
+
+                       buf[len] = '\0';
+                       dev_names[dev_count] = dev_name(buf);
+                       snprintf(dev_path, MAX_PATH, "%s/%s", "/dev",
+                                       dev_names[dev_count]);
+                       sb = query_dev(dev_path, false, false,
+                                       true, dev_uuid);
+                       if (!sb) {
+                               printf("error reading %s\n", dev_path);
+                               return -1;
+                       } else
+                               free(sb);
+
+                       dev_uuids[dev_count] = strdup(dev_uuid);
+                       dev_count++;
+               }
+
+               cache_path[strlen(cache_path) - strlen(intbuf)] = 0;
+               cache_count++;
+
+               snprintf(intbuf, 4, "%d", cache_count);
+               strcat(cache_path, intbuf);
+       }
+
+       for (i = 0; i < seq_sb->nr_in_set; i++) {
+               char uuid_str[40];
+               struct cache_member *m = seq_sb->members + i;
+               char dev_state[32];
+               int j;
+
+               uuid_unparse(m->uuid.b, uuid_str);
+               snprintf(dev_state, MAX_PATH, "%s",
+                         cache_state[CACHE_STATE(m)]);
+
+               for (j = 0; j < dev_count; j++) {
+                       if (!strcmp(uuid_str, dev_uuids[j])) {
+                               break;
+                       } else if (j == dev_count - 1) {
+                               if (!strcmp(cache_state[CACHE_STATE(m)], "active"))
+                                       snprintf(dev_state, MAX_PATH, "%s", "missing");
+                               break;
+                       }
+               }
+
+               printf("%-50s%-15s%-4llu\n", uuid_str, dev_state,
+                               CACHE_TIER(m));
+       }
+
+       if (seq_sb)
+               free(seq_sb);
+       for (i = 0; i < dev_count; i++) {
+               free(dev_names[i]);
+               free(dev_uuids[i]);
+       }
+
+       return 0;
+}
diff --git a/bcacheadm-query.h b/bcacheadm-query.h
new file mode 100644 (file)
index 0000000..c7c7d93
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _BCACHEADM_QUERY_H
+#define _BCACHEADM_QUERY_H
+
+extern NihOption opts_list[];
+int cmd_list(NihCommand *, char * const *);
+
+extern NihOption opts_query[];
+int cmd_query(NihCommand *, char * const *);
+
+extern NihOption opts_status[];
+int cmd_status(NihCommand *, char * const *);
+
+#endif /* _BCACHEADM_QUERY_H */
diff --git a/bcacheadm-run.c b/bcacheadm-run.c
new file mode 100644 (file)
index 0000000..8f995a1
--- /dev/null
@@ -0,0 +1,153 @@
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <nih/command.h>
+#include <nih/option.h>
+
+#include <linux/bcache-ioctl.h>
+
+#include <uuid/uuid.h>
+
+#include "bcache.h"
+#include "bcacheadm-run.h"
+
+static bool force_data = false;
+static bool force_metadata = false;
+
+NihOption opts_run[] = {
+       NIH_OPTION_LAST
+};
+
+int cmd_run(NihCommand *command, char *const *args)
+{
+       return 0;
+}
+
+NihOption opts_stop[] = {
+       NIH_OPTION_LAST
+};
+
+int cmd_stop(NihCommand *command, char *const *args)
+{
+       int bcachefd = open("/dev/bcache_extent0", O_RDWR);
+       if (bcachefd < 0)
+               die("Can't open bcache device");
+
+       int ret = ioctl(bcachefd, BCH_IOCTL_STOP);
+       if (ret < 0)
+               die("BCH_IOCTL_STOP error: %s", strerror(errno));
+
+       close(bcachefd);
+       return 0;
+}
+
+NihOption opts_add[] = {
+       NIH_OPTION_LAST
+};
+
+int cmd_add(NihCommand *command, char *const *args)
+{
+       if (nr_args(args) != 1)
+               die("Please supply exactly one device");
+
+       int ret, bcachefd;
+
+       bcachefd = open("/dev/bcache_extent0", O_RDWR);
+       if (bcachefd < 0)
+               die("Can't open bcache device: %s", strerror(errno));
+
+       struct bch_ioctl_disk_add ia = {
+               .dev = (__u64) args[0],
+       };
+
+       ret = ioctl(bcachefd, BCH_IOCTL_DISK_ADD, &ia);
+       if (ret < 0)
+               die("BCH_IOCTL_DISK_ADD error: %s", strerror(ret));
+
+       close(bcachefd);
+       return 0;
+}
+
+NihOption opts_readd[] = {
+       NIH_OPTION_LAST
+};
+
+int cmd_readd(NihCommand *command, char *const *args)
+{
+       if (nr_args(args) != 1)
+               die("Please supply exactly one device");
+
+       return 0;
+}
+
+NihOption opts_remove[] = {
+       {
+               'f', "force", N_("force if data present"),
+               NULL, NULL, &force_data, NULL
+       },
+       {
+               '\0', "force-metadata", N_("force if metadata present"),
+               NULL, NULL, &force_metadata, NULL},
+       NIH_OPTION_LAST
+};
+
+int cmd_remove(NihCommand *command, char *const *args)
+{
+       if (nr_args(args) != 1)
+               die("Please supply exactly one device");
+
+       int bcachefd = open("/dev/bcache_extent0", O_RDWR);
+       if (bcachefd < 0)
+               die("Can't open bcache device");
+
+       struct bch_ioctl_disk_remove ir = {
+               .dev = (__u64) args[0],
+       };
+
+       if (force_data)
+               ir.flags |= BCH_FORCE_IF_DATA_MISSING;
+       if (force_metadata)
+               ir.flags |= BCH_FORCE_IF_METADATA_MISSING;
+
+       int ret = ioctl(bcachefd, BCH_IOCTL_DISK_REMOVE, &ir);
+       if (ret < 0)
+               die("BCH_IOCTL_DISK_REMOVE error: %s\n", strerror(errno));
+
+       close(bcachefd);
+       return 0;
+}
+
+static const char *dev_failed_uuid = NULL;
+
+NihOption opts_fail[] = {
+       {'d', "dev", N_("dev UUID"), NULL, "UUID", &dev_failed_uuid, NULL},
+       NIH_OPTION_LAST
+};
+
+int cmd_fail(NihCommand *command, char *const *args)
+{
+       if (nr_args(args) != 1)
+               die("Please supply exactly one device");
+
+       int bcachefd = open("/dev/bcache_extent0", O_RDWR);
+       if (bcachefd < 0)
+               die("Can't open bcache device");
+
+       struct bch_ioctl_disk_fail df = {
+               .dev = (__u64) args[0],
+       };
+
+       int ret = ioctl(bcachefd, BCH_IOCTL_DISK_FAIL, &df);
+       if (ret < 0)
+               die("BCH_IOCTL_DISK_FAIL error: %s\n", strerror(errno));
+
+       return 0;
+}
diff --git a/bcacheadm-run.h b/bcacheadm-run.h
new file mode 100644 (file)
index 0000000..ad7c153
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _BCACHEADM_RUN_H
+#define _BCACHEADM_RUN_H
+
+extern NihOption opts_run[];
+int cmd_run(NihCommand *, char * const *);
+
+extern NihOption opts_stop[];
+int cmd_stop(NihCommand *, char * const *);
+
+extern NihOption opts_add[];
+int cmd_add(NihCommand *, char * const *);
+
+extern NihOption opts_readd[];
+int cmd_readd(NihCommand *, char * const *);
+
+extern NihOption opts_remove[];
+int cmd_remove(NihCommand *, char * const *);
+
+extern NihOption opts_fail[];
+int cmd_fail(NihCommand *, char * const *);
+
+#endif /* _BCACHEADM_RUN_H */
index 6fd317350e3690ffbc4ee8bcd25e8f4c292f834f..efe9065b265ca154557cd29b1bf4f458295673bb 100644 (file)
 #include <dirent.h>
 
 #include "bcache.h"
-#include "bcacheadm.h"
+#include "bcacheadm-format.h"
+#include "bcacheadm-assemble.h"
+#include "bcacheadm-run.h"
+#include "bcacheadm-query.h"
 
 #define PACKAGE_NAME "bcacheadm"
 #define PACKAGE_VERSION "1.0"
-#define PACKAGE_BUGREPORT "bugreport"
+#define PACKAGE_BUGREPORT "linux-bcache@vger.kernel.org"
 
-/* rm-dev globals */
-bool force_remove = false;
-
-/* Modify globals */
-bool modify_list_attrs = false;
+#if 0
+static bool modify_list_attrs = false;
 static const char *modify_set_uuid = NULL;
 static const char *modify_dev_uuid = NULL;
 
-/* query-dev globals */
-bool force_csum = false;
-bool uuid_only = false;
-bool query_brief = false;
-
-/* probe globals */
-bool udev = false;
-
-/* list globals */
-char *cset_dir = "/sys/fs/bcache";
-bool list_devs = false;
-static const char *internal_uuid = NULL;
-
-/* status globals */
-bool status_all = false;
-
-/* capacity globals */
-static const char *capacity_uuid = NULL;
-bool capacity_devs = false;
-
-/* stats globals */
-bool stats_all = false;
-bool stats_list = false;
-static const char *stats_uuid = NULL;
-static const char *stats_dev_uuid = NULL;
-static const char *stats_cache_num = NULL;
-bool stats_five_min = false;
-bool stats_hour = false;
-bool stats_day = false;
-bool stats_total = false;
-
-/* set_failed globals */
-static const char *dev_failed_uuid = NULL;
-
-/* probe setters */
-static int set_udev(NihOption *option, const char *arg)
-{
-       if (strcmp("udev", arg)) {
-               printf("Invalid output format %s\n", arg);
-               exit(EXIT_FAILURE);
-       }
-       udev = true;
-       return 0;
-}
-
-/* options */
-static NihOption probe_bcache_options[] = {
-       {'o', "udev", N_("udev"), NULL, NULL, NULL, set_udev},
-       NIH_OPTION_LAST
-};
-
-static NihOption bcache_register_options[] = {
-       NIH_OPTION_LAST
-};
-
-static NihOption bcache_unregister_options[] = {
-       NIH_OPTION_LAST
-};
-
-static NihOption bcache_add_device_options[] = {
-       NIH_OPTION_LAST
-};
-
-static NihOption bcache_rm_device_options[] = {
-       {'f', "force", N_("force cache removal"), NULL, NULL, &force_remove, NULL},
-       NIH_OPTION_LAST
-};
-
 static NihOption bcache_modify_options[] = {
        {'l', "list", N_("list attributes"), NULL, NULL, &modify_list_attrs, NULL},
        {'u', "set", N_("cacheset uuid"), NULL, "UUID", &modify_set_uuid, NULL},
@@ -118,127 +50,6 @@ static NihOption bcache_modify_options[] = {
        NIH_OPTION_LAST
 };
 
-static NihOption query_devs_options[] = {
-       {'f', "force_csum", N_("force_csum"), NULL, NULL, &force_csum, NULL},
-       {'u', "uuid-only", N_("only print out the uuid for the devices, not the whole superblock"), NULL, NULL, &uuid_only, NULL},
-       {'b', "brief", N_("only print out the cluster,server,and disk uuids"), NULL, NULL, &query_brief, NULL},
-       NIH_OPTION_LAST
-};
-
-static NihOption list_cachesets_options[] = {
-       {'d', "dir", N_("directory"), NULL, NULL, &cset_dir, NULL},
-       {0, "list-devs", N_("list all devices in the cache sets as well"), NULL, NULL, &list_devs, NULL},
-       {0, "internal_uuid", N_("Show the internal UUID for the given cacheset UUID"), NULL, "UUID", &internal_uuid, NULL},
-       NIH_OPTION_LAST
-};
-
-static NihOption status_options[] = {
-       {'a', "all", N_("all"), NULL, NULL, &status_all, NULL},
-       NIH_OPTION_LAST
-};
-
-static NihOption capacity_options[] = {
-       {'u', "set", N_("cache_set UUID"), NULL, "UUID", &capacity_uuid, NULL},
-       {'d', "devs", N_("Individual device capacities"), NULL, NULL, &capacity_devs, NULL},
-       NIH_OPTION_LAST
-};
-
-static NihOption stats_options[] = {
-       {'a', "all", N_("all"), NULL, NULL, &stats_all, NULL},
-       {'l', "list", N_("list"), NULL, NULL, &stats_list, NULL},
-       {'u', "set", N_("cache_set UUID"), NULL, "UUID", &stats_uuid, NULL},
-       {'d', "dev", N_("dev UUID"), NULL, "UUID", &stats_dev_uuid, NULL},
-       {'c', "cache", N_("cache number (starts from 0)"), NULL, "CACHE#", &stats_cache_num, NULL},
-       {0, "five-min-stats", N_("stats accumulated in last 5 minutes"), NULL, NULL, &stats_five_min, NULL},
-       {0, "hour-stats", N_("stats accumulated in last hour"), NULL, NULL, &stats_hour, NULL},
-       {0, "day-stats", N_("stats accumulated in last day"), NULL, NULL, &stats_day, NULL},
-       {0, "total-stats", N_("stats accumulated in total"), NULL, NULL, &stats_total, NULL},
-       NIH_OPTION_LAST
-};
-
-static NihOption set_failed_options[] = {
-       {'d', "dev", N_("dev UUID"), NULL, "UUID", &dev_failed_uuid, NULL},
-       NIH_OPTION_LAST
-};
-
-static NihOption options[] = {
-       NIH_OPTION_LAST
-};
-
-/* commands */
-int probe_bcache(NihCommand *command, char *const *args)
-{
-       int i;
-       char *err = NULL;
-
-       for (i = 0; args[i] != NULL; i++) {
-               err = probe(args[i], udev);
-               if(err) {
-                       printf("probe_bcache error: %s\n", err);
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-int bcache_register(NihCommand *command, char *const *args)
-{
-       char *err = NULL;
-
-       err = register_bcache(args);
-       if (err) {
-               printf("bcache_register error: %s\n", err);
-               return -1;
-       }
-
-       return 0;
-}
-
-int bcache_unregister(NihCommand *command, char *const *args)
-{
-       char *err = NULL;
-
-       err = unregister_bcache(args);
-       if (err) {
-               printf("bcache_unregister error: %s\n", err);
-               return -1;
-       }
-
-       return 0;
-}
-
-int bcache_add_devices(NihCommand *command, char *const *args)
-{
-       char *err;
-
-       err = add_devices(args);
-       if (err) {
-               printf("bcache_add_devices error: %s\n", err);
-               return -1;
-       }
-
-       return 0;
-}
-
-int bcache_rm_device(NihCommand *command, char *const *args)
-{
-       char *err;
-
-       if (!args[0]) {
-               printf("Must provide a device name\n");
-               return -1;
-       }
-
-       err = remove_device(args[0], force_remove);
-       if (err) {
-               printf("bcache_rm_devices error: %s\n", err);
-               return -1;
-       }
-
-       return 0;
-}
-
 int bcache_modify(NihCommand *command, char *const *args)
 {
        char *err;
@@ -312,386 +123,80 @@ err:
                close(fd);
        return 0;
 }
-
-int bcache_list_cachesets(NihCommand *command, char *const *args)
-{
-       char *err = NULL;
-
-       if (internal_uuid) {
-               char uuid_path[MAX_PATH];
-               DIR *uuid_dir;
-               char buf[MAX_PATH];
-
-               snprintf(uuid_path, MAX_PATH, "%s/%s", cset_dir, internal_uuid);
-
-               err = "uuid does not exist";
-               if((uuid_dir = opendir(uuid_path)) == NULL)
-                       goto err;
-
-               err = read_stat_dir(uuid_dir, uuid_path, "/internal/internal_uuid", buf);
-               if (err)
-                       goto err;
-               printf("%s", buf);
-               return 0;
-       }
-
-       err = list_cachesets(cset_dir, list_devs);
-       if (err)
-               goto err;
-
-       return 0;
-
-err:
-       printf("bcache_list_cachesets error :%s\n", err);
-       return -1;
-}
-
-int bcache_query_devs(NihCommand *command, char *const *args)
-{
-       int i;
-
-       if (query_brief)
-               printf("%-10s%-40s%-40s%-40s\n", "dev name", "disk uuid",
-                               "server uuid", "cluster uuid");
-
-       for (i = 0; args[i] != NULL; i++) {
-               char dev_uuid[40];
-               struct cache_sb *sb = query_dev(args[i], force_csum,
-                               !query_brief, uuid_only, dev_uuid);
-
-               if (!sb) {
-                       printf("error opening the superblock for %s\n",
-                                       args[i]);
-                       return -1;
-               }
-
-               if (uuid_only) {
-                       printf("%s\n", dev_uuid);
-               } else if (query_brief) {
-                       char set_uuid_str[40], dev_uuid_str[40];
-                       char *clus_uuid = (char *)sb->label;
-
-                       uuid_unparse(sb->user_uuid.b, set_uuid_str);
-                       uuid_unparse(sb->disk_uuid.b, dev_uuid_str);
-                       if (!strcmp(clus_uuid, ""))
-                               clus_uuid = "None";
-
-                       printf("%-10s%-40s%-40s%-40s\n", args[i],
-                                       dev_uuid_str,
-                                       set_uuid_str,
-                                       clus_uuid);
-               }
-               free(sb);
-       }
-
-       return 0;
-}
-
-int bcache_status(NihCommand *command, char *const *args)
-{
-       int i, dev_count = 0, seq, cache_count = 0;
-       struct cache_sb *seq_sb = NULL;
-       char cache_path[MAX_PATH];
-       char *dev_names[MAX_DEVS];
-       char *dev_uuids[MAX_DEVS];
-       char intbuf[4];
-       char set_uuid[40];
-
-       for (i = 0; args[i] != NULL; i++) {
-               struct cache_sb *sb = query_dev(args[i], false, false,
-                               false, NULL);
-
-               if (!sb) {
-                       printf("Unable to open superblock, bad path\n");
-                       return -1;
-               }
-
-               if (!seq_sb || sb->seq > seq) {
-                       seq = sb->seq;
-                       seq_sb = sb;
-               } else
-                       free(sb);
-       }
-
-       if (!seq_sb) {
-               printf("Unable to find a superblock\n");
-               return -1;
-       } else {
-               uuid_unparse(seq_sb->user_uuid.b, set_uuid);
-               printf("%-50s%-15s%-4s\n", "uuid", "state", "tier");
-       }
-
-       snprintf(intbuf, 4, "%d", i);
-       snprintf(cache_path, MAX_PATH, "%s/%s/%s", cset_dir, set_uuid,
-                       "cache0");
-
-       /*
-        * Get a list of all the devices from sysfs first, then
-        * compare it to the list we get back from the most up
-        * to date superblock. If there are any devices in the superblock
-        * that are not in sysfs, print out 'missing'
-        */
-       while (true) {
-               char buf[MAX_PATH];
-               int len;
-               DIR *cache_dir;
-
-               if(((cache_dir = opendir(cache_path)) == NULL) &&
-                   cache_count > MAX_DEVS)
-                       break;
-
-               if (cache_dir)
-                       closedir(cache_dir);
-
-               if((len = readlink(cache_path, buf, sizeof(buf) - 1)) != -1) {
-                       struct cache_sb *sb;
-                       char dev_uuid[40];
-                       char dev_path[32];
-
-                       buf[len] = '\0';
-                       dev_names[dev_count] = dev_name(buf);
-                       snprintf(dev_path, MAX_PATH, "%s/%s", "/dev",
-                                       dev_names[dev_count]);
-                       sb = query_dev(dev_path, false, false,
-                                       true, dev_uuid);
-                       if (!sb) {
-                               printf("error reading %s\n", dev_path);
-                               return -1;
-                       } else
-                               free(sb);
-
-                       dev_uuids[dev_count] = strdup(dev_uuid);
-                       dev_count++;
-               }
-
-               cache_path[strlen(cache_path) - strlen(intbuf)] = 0;
-               cache_count++;
-
-               snprintf(intbuf, 4, "%d", cache_count);
-               strcat(cache_path, intbuf);
-       }
-
-       for (i = 0; i < seq_sb->nr_in_set; i++) {
-               char uuid_str[40];
-               struct cache_member *m = seq_sb->members + i;
-               char dev_state[32];
-               int j;
-
-               uuid_unparse(m->uuid.b, uuid_str);
-               snprintf(dev_state, MAX_PATH, "%s",
-                         cache_state[CACHE_STATE(m)]);
-
-               for (j = 0; j < dev_count; j++) {
-                       if (!strcmp(uuid_str, dev_uuids[j])) {
-                               break;
-                       } else if (j == dev_count - 1) {
-                               if (!strcmp(cache_state[CACHE_STATE(m)], "active"))
-                                       snprintf(dev_state, MAX_PATH, "%s", "missing");
-                               break;
-                       }
-               }
-
-               printf("%-50s%-15s%-4llu\n", uuid_str, dev_state,
-                               CACHE_TIER(m));
-       }
-
-       if (seq_sb)
-               free(seq_sb);
-       for (i = 0; i < dev_count; i++) {
-               free(dev_names[i]);
-               free(dev_uuids[i]);
-       }
-
-       return 0;
-}
-
-int bcache_capacity(NihCommand *command, char *const *args)
-{
-       char *err = "Must provide a cacheset uuid";
-       if(!capacity_uuid)
-               goto err;
-
-       err = bcache_get_capacity(cset_dir, capacity_uuid, capacity_devs);
-       if (err)
-               goto err;
-
-       return 0;
-
-err:
-       printf("bcache_capacity failed with error: %s\n", err);
-       return -1;
-
-}
-
-static char *stats_subdir(char* stats_dir)
-{
-       char tmp[50] = "/";
-       char *err = NULL;
-       if(stats_dev_uuid) {
-               strcat(tmp, "cache");
-               err = find_matching_uuid(stats_dir, tmp, stats_dev_uuid);
-               if(err)
-                       goto err;
-       } else if(stats_cache_num) {
-               strcat(tmp, "cache");
-               strcat(tmp, stats_cache_num);
-       } else if (stats_five_min)
-               strcat(tmp, "stats_five_minute");
-       else if (stats_hour)
-               strcat(tmp, "stats_hour");
-       else if (stats_day)
-               strcat(tmp, "stats_day");
-       else if (stats_total)
-               strcat(tmp, "stats_total");
-       else
-               return err;
-
-       strcat(stats_dir, tmp);
-
-err:
-       return err;
-}
-
-int bcache_stats(NihCommand *command, char *const *args)
-{
-       int i;
-       char stats_dir[MAX_PATH];
-       DIR *dir = NULL;
-       struct dirent *ent = NULL;
-       char *err = NULL;
-       char buf[MAX_PATH];
-
-       if (stats_uuid) {
-               snprintf(stats_dir, MAX_PATH, "%s/%s", cset_dir, stats_uuid);
-               err = stats_subdir(stats_dir);
-               if(err)
-                       goto err;
-
-               dir = opendir(stats_dir);
-               if (!dir) {
-                       err = "Failed to open dir";
-                       goto err;
-               }
-       } else {
-               err = "Must provide a cacheset uuid";
-               goto err;
-       }
-
-       if(stats_list || stats_all) {
-               while ((ent = readdir(dir)) != NULL) {
-                       err = read_stat_dir(dir, stats_dir, ent->d_name, buf);
-                       if (err)
-                               goto err;
-                       if(stats_list)
-                               printf("%s\n", ent->d_name);
-                       if(stats_all)
-                               printf("\t%s\n", buf);
-               }
-       }
-
-       for (i = 0; args[i] != NULL; i++) {
-               err = read_stat_dir(dir, stats_dir, args[i], buf);
-               if (err)
-                       goto err;
-               printf("%s\n", buf);
-       }
-
-       closedir(dir);
-       return 0;
-
-err:
-       closedir(dir);
-       printf("bcache_stats error: %s\n", err);
-       return -1;
-}
-
-int bcache_set_failed(NihCommand *command, char *const *args)
-{
-       char *err = NULL;
-
-       if (!dev_failed_uuid) {
-               printf("Pass in a dev uuid\n");
-               return -1;
-       }
-
-       err = device_set_failed(dev_failed_uuid);
-       if (err) {
-               printf("bcache_set_failed_ioctl error: %s\n", err);
-               return -1;
-       }
-
-       return 0;
+#endif
+
+#define CMD(_command, _usage, _synopsis, _help)                                \
+{                                                                      \
+       .command        = #_command,                                    \
+       .usage          = _usage,                                       \
+       .synopsis       = _synopsis,                                    \
+       .help           = _help,                                        \
+       .group          = NULL,                                         \
+       .options        = opts_##_command,                              \
+       .action         = cmd_##_command,                               \
 }
 
 static NihCommand commands[] = {
-       {"format", N_("format <list of drives>"),
-                 "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, bcacheadm_format_options, bcacheadm_format},
-       {"probe", N_("probe <list of devices>"),
-                 "Does a blkid_probe on a device",
-                 N_("Does a blkid_probe on a device"),
-                 NULL, probe_bcache_options, probe_bcache},
-       {"register", N_("register <list of devices>"),
-                    "Registers a list of devices",
-                    N_("Registers a list of devices"),
-                    NULL, bcache_register_options, bcache_register},
-       {"unregister", N_("unregister <list of devices>"),
-                    "Unregisters a list of devices",
-                    N_("Unregisters a list of devices"),
-                    NULL, bcache_unregister_options, bcache_unregister},
-       {"add-devs", N_("add-devs --tier=# <list of devices>"),
-               "Adds a list of devices to a cacheset",
-               N_("Adds a list of devices to a cacheset"),
-               NULL, bcache_add_device_options, bcache_add_devices},
-       {"rm-dev", N_("rm-dev <dev>"),
-               "Removes a device from its cacheset",
-               N_("Removes a device from its cacheset"),
-               NULL, bcache_rm_device_options, bcache_rm_device},
-       {"modify", N_("modify --set=UUID (dev=UUID) name value"),
-               "Modifies attributes related to the cacheset",
-               N_("Modifies attributes related to the cacheset"),
-               NULL, bcache_modify_options, bcache_modify},
-       {"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 <list of devices>"),
-                      "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},
-       {"status", N_("status <list of devices>"),
-                  "Finds the status of the most up to date superblock",
-                  N_("Finds the status of the most up to date superblock"),
-                  NULL, status_options, bcache_status},
-       {"capacity", N_("capacity --set=UUID"),
-               "Shows the capacity of the cacheset",
-               N_("Shows the capacity of the cacheset"),
-               NULL, capacity_options, bcache_capacity},
-       {"stats", N_("stats <list of devices>"),
-                 "List various bcache statistics",
-                 N_("List various bcache statistics"),
-                 NULL, stats_options, bcache_stats},
-       {"set-failed", N_("set-failed --dev=UUID"),
-               "Sets a device to the FAILED state",
-               N_("Sets a device to the FAILED state"),
-               NULL, set_failed_options, bcache_set_failed},
+       CMD(format, N_("<list of devices>"),
+           "Create a new bcache volume from one or more devices",
+           N_("format drive[s] for bcache")),
+
+       CMD(assemble, N_("<devices>"),
+           "Assembles one or more devices into a bcache volume",
+           N_("Registers a list of devices")),
+       CMD(incremental, N_("<device"),
+           "Incremental assemble bcache volumes",
+           N_("Incrementally registers a single device")),
+
+       CMD(run, N_("<volume>"),
+           "Start a partially assembled volume",
+           N_("Registers a list of devices")),
+       CMD(stop, N_("<volume>"),
+           "Stops a running bcache volume",
+           N_("Unregisters a list of devices")),
+       CMD(add, N_("<volume> <devices>"),
+           "Adds a list of devices to a volume",
+           N_("Adds a list of devices to a volume")),
+       CMD(readd, N_("<volume> <devices>"),
+           "Adds previously used members of a volume",
+           N_("Adds a list of devices to a volume")),
+       CMD(remove, N_("<volume> <devices>"),
+           "Removes a device from its volume",
+           N_("Removes a device from its volume")),
+       CMD(fail, N_("<volume> <devices>"),
+           "Sets a device to the FAILED state",
+           N_("Sets a device to the FAILED state")),
+
+#if 0
+       CMD(modify, N_("<options>"),
+           "Modifies attributes related to the volume",
+           N_("Modifies attributes related to the volume")),
+#endif
+       CMD(list, N_("list-cachesets"),
+           "Lists cachesets in /sys/fs/bcache",
+           N_("Lists cachesets in /sys/fs/bcache")),
+       CMD(query, N_("query <list of devices>"),
+           "Gives info about the superblock of a list of devices",
+           N_("show superblock on each of the listed drive")),
+       CMD(status, N_("status <list of devices>"),
+           "Finds the status of the most up to date superblock",
+           N_("Finds the status of the most up to date superblock")),
        NIH_COMMAND_LAST
 };
 
+static NihOption options[] = {
+       NIH_OPTION_LAST
+};
+
 int main(int argc, char *argv[])
 {
-       int ret = 0;
-       nih_main_init (argv[0]);
-
-       nih_option_set_synopsis (_("Manage bcache devices"));
-       nih_option_set_help (
-                       _("Helps you manage bcache devices"));
+       nih_main_init(argv[0]);
+       nih_option_set_synopsis(_("Manage bcache devices"));
+       nih_option_set_help( _("Helps you manage bcache devices"));
 
-       ret = nih_command_parser (NULL, argc, argv, options, commands);
+       int ret = nih_command_parser(NULL, argc, argv, options, commands);
        if (ret < 0)
-               exit (1);
+               exit(EXIT_FAILURE);
 
        nih_signal_reset();
 
diff --git a/bcacheadm.h b/bcacheadm.h
deleted file mode 100644 (file)
index 7a31ee9..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _BCACHEADM_H
-#define _BCACHEADM_H
-
-extern NihOption bcacheadm_format_options[];
-int bcacheadm_format(NihCommand *, char * const *);
-
-#endif /* _BCACHEADM_H */