bcacheadm: add capacity command

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>
This commit is contained in:
Jacob Malevich 2014-12-15 18:10:25 -08:00
parent 6401e32229
commit 91ba18738e
3 changed files with 160 additions and 18 deletions

129
bcache.c
View File

@ -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));
if(print_val)
printf("%s\n", buf);
else
printf("%s\n", stat_name);
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;
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
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;
}

View File

@ -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) \
({ \

View 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},
@ -595,6 +604,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] = "/";
@ -631,6 +658,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);
@ -650,17 +678,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);
@ -714,6 +746,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"),