]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
bcacheadm: add capacity command
authorJacob Malevich <jam@daterainc.com>
Tue, 16 Dec 2014 02:10:25 +0000 (18:10 -0800)
committerRaghu Krishnamurthy <rk@daterainc.com>
Wed, 31 Dec 2014 23:17:12 +0000 (15:17 -0800)
prints the device capacity, and free space for a cacheset

example:
bcacheadm capacity -u UUID --devs

Device Name    Capacity (512 Blocks)    Free (512 Blocks)
/dev/sdb       1048576.00               1024128.00
/dev/sdc       1048576.00               1024128.00
/dev/sdd       1048576.00               1024128.00
Total          3145728.00               3072384.00

Also did some bcacheadm stats refactoring.

Change-Id: Iff5562191478c5fd9f03399a9479d3d75740904d
Signed-off-by: Jacob Malevich <jam@daterainc.com>
bcache.c
bcache.h
bcacheadm.c

index 5274551992e2c1120a14fa57b09048306ef6c47e..f6fcb24c1f1e4fa52a7ac343048c00e41f5632ac 100644 (file)
--- a/bcache.c
+++ b/bcache.c
@@ -829,6 +829,7 @@ static void show_cache_member(struct cache_sb *sb, unsigned i)
        struct cache_member *m = ((struct cache_member *) sb->d) + i;
 
        printf("cache.state\t%s\n",             cache_state[CACHE_STATE(m)]);
+
        printf("cache.tier\t%llu\n",            CACHE_TIER(m));
 
        printf("cache.replication_set\t%llu\n", CACHE_REPLICATION_SET(m));
@@ -944,7 +945,7 @@ struct cache_sb *query_dev(char *dev, bool force_csum,
        return sb;
 }
 
-static void dev_name(const char *ugly_path) {
+static char *dev_name(const char *ugly_path) {
        char buf[32];
        int i, end = strlen(ugly_path);
 
@@ -958,7 +959,7 @@ static void dev_name(const char *ugly_path) {
 
        // Is the dev guaranteed to be in /dev?
        // This is needed for finding the superblock with a query-dev
-       printf("/dev%s\n", buf);
+       return strdup(buf);
 }
 
 static void list_cacheset_devs(char *cset_dir, char *cset_name, bool parse_dev_name) {
@@ -974,6 +975,7 @@ static void list_cacheset_devs(char *cset_dir, char *cset_name, bool parse_dev_n
        while(true) {
                char buf[MAX_PATH];
                int len;
+               char *tmp;
 
                if((cachedir = opendir(entry)) == NULL)
                        break;
@@ -983,10 +985,13 @@ static void list_cacheset_devs(char *cset_dir, char *cset_name, bool parse_dev_n
 
                if((len = readlink(entry, buf, sizeof(buf) - 1)) != -1) {
                        buf[len] = '\0';
-                       if(parse_dev_name)
-                               dev_name(buf);
-                       else
+                       if(parse_dev_name) {
+                               tmp = dev_name(buf);
+                               printf("/dev%s\n", tmp);
+                               free(tmp);
+                       } else {
                                printf("\t%s\n", buf);
+                       }
                }
 
                /* remove i from end and append i++ */
@@ -1274,7 +1279,7 @@ err:
        return err;
 }
 
-char *read_stat_dir(DIR *dir, char *stats_dir, char *stat_name, bool print_val)
+char *read_stat_dir(DIR *dir, char *stats_dir, char *stat_name, char *ret)
 {
        struct stat statbuf;
        char entry[MAX_PATH];
@@ -1299,14 +1304,114 @@ char *read_stat_dir(DIR *dir, char *stats_dir, char *stat_name, bool print_val)
                        return NULL;
                }
 
-               while(fgets(buf, MAX_PATH, fp));
+               while(fgets(ret, MAX_PATH, fp));
+               fclose(fp);
+       }
+err:
+       return err;
+}
+
+char *bcache_get_capacity(const char *cset_dir, const char *capacity_uuid,
+               bool show_devs)
+{
+       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;
+       char intbuf[4];
+       double total_cap = 0, total_free = 0;
+       int precision = 2;
 
-               if(print_val)
-                       printf("%s\n", buf);
+       snprintf(intbuf, 4, "%d", i);
+       snprintf(bucket_size_path, MAX_PATH, "%s/%s/%s/%s", cset_dir,
+                       capacity_uuid, "cache0", "bucket_size_bytes");
+       snprintf(nbuckets_path, MAX_PATH, "%s/%s/%s/%s", cset_dir,
+                       capacity_uuid, "cache0", "nbuckets");
+       snprintf(avail_buckets_path, MAX_PATH, "%s/%s/%s/%s", cset_dir,
+                       capacity_uuid, "cache0", "available_buckets");
+       snprintf(cache_path, MAX_PATH, "%s/%s/%s", cset_dir, capacity_uuid,
+                       "cache0");
+
+       while(true) {
+               char buf[MAX_PATH];
+               int len;
+               DIR *cache_dir;
+
+               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
-                       printf("%s\n", stat_name);
-               fclose(fp);
+                       bucket_sizes[dev_count] = atof(buf);
+
+               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);
+               }
+
+               /* remove i/stat and append i++/stat */
+               bucket_size_path[strlen(cache_path) - strlen(intbuf)] = 0;
+               nbuckets_path[strlen(cache_path) - strlen(intbuf)] = 0;
+               avail_buckets_path[strlen(cache_path) - strlen(intbuf)] = 0;
+               cache_path[strlen(cache_path) - strlen(intbuf)] = 0;
+
+               dev_count++;
+
+               snprintf(intbuf, 4, "%d", dev_count);
+               strcat(cache_path, intbuf);
+               strcat(bucket_size_path, intbuf);
+               strcat(nbuckets_path, intbuf);
+               strcat(avail_buckets_path, intbuf);
+       }
+
+       printf("%-15s%-25s%-25s\n", "Device Name", "Capacity (512 Blocks)", "Free (512 Blocks)");
+
+       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;
 }
index dc79d066521460284f3716b41e371cb42201d38e..4cfac71f191ba82a7e91c4b08ad3919fd065864d 100644 (file)
--- a/bcache.h
+++ b/bcache.h
@@ -22,7 +22,7 @@ typedef __s64 s64;
 
 #define SB_START               (SB_SECTOR * 512)
 #define MAX_PATH               256
-
+#define MAX_DEVS               MAX_CACHES_PER_SET
 
 #define max(x, y) ({                           \
        typeof(x) _max1 = (x);                  \
@@ -104,10 +104,11 @@ 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 *, bool);
+char *read_stat_dir(DIR *, char *, char *, char *);
 char *find_matching_uuid(char *, char *, const char*);
 char *add_devices(char *const *, char *);
 char *remove_device(const char *, bool);
+char *bcache_get_capacity(const char *, const char *, bool);
 
 #define csum_set(i, type)                                              \
 ({                                                                     \
index 10ffb3fa8d07ebf86a0e1314a5e9d3403b976383..ea9fc7516942d6dad9efe29acd0f9d6988516fb0 100644 (file)
@@ -34,7 +34,6 @@
 #define PACKAGE_VERSION "1.0"
 #define PACKAGE_BUGREPORT "bugreport"
 
-#define MAX_DEVS MAX_CACHES_PER_SET
 
 
 /* make-bcache globals */
@@ -85,6 +84,10 @@ bool list_devs = false;
 /* 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;
@@ -232,6 +235,12 @@ static NihOption status_options[] = {
        NIH_OPTION_LAST
 };
 
+static NihOption capacity_options[] = {
+       {'u', "set", N_("cache_set UUID"), NULL, "UUID", &capacity_uuid, NULL},
+       {'d', "devs", N_("dev UUID"), 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},
@@ -598,6 +607,24 @@ int bcache_status(NihCommand *command, char *const *args)
        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] = "/";
@@ -634,6 +661,7 @@ int bcache_stats(NihCommand *command, char *const *args)
        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);
@@ -653,17 +681,21 @@ int bcache_stats(NihCommand *command, char *const *args)
 
        if(stats_list || stats_all) {
                while ((ent = readdir(dir)) != NULL) {
-                       err = read_stat_dir(dir, stats_dir, ent->d_name, stats_all);
+                       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], true);
+               err = read_stat_dir(dir, stats_dir, args[i], buf);
                if (err)
                        goto err;
+               printf("%s\n", buf);
        }
 
        closedir(dir);
@@ -717,6 +749,10 @@ static NihCommand commands[] = {
                   "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"),