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));
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);
// 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) {
while(true) {
char buf[MAX_PATH];
int len;
+ char *tmp;
if((cachedir = opendir(entry)) == NULL)
break;
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++ */
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];
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;
}
#define PACKAGE_VERSION "1.0"
#define PACKAGE_BUGREPORT "bugreport"
-#define MAX_DEVS MAX_CACHES_PER_SET
/* make-bcache globals */
/* 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;
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},
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] = "/";
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);
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);
"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"),