Add bcachefs fs usage

This commit is contained in:
Kent Overstreet 2017-12-23 00:50:55 -05:00
parent 14117dcdfb
commit 30caf69540
5 changed files with 185 additions and 48 deletions

View File

@ -42,8 +42,7 @@ static void usage(void)
" stop Stop a running filesystem\n"
"\n"
"Commands for managing a running filesystem:\n"
" fs show Show various information about a filesystem\n"
" fs set Modify filesystem options\n"
" fs usage Show disk usage\n"
"\n"
"Commands for managing devices within a running filesystem:\n"
" device add Add a new device to an existing filesystem\n"
@ -90,10 +89,8 @@ static int fs_cmds(int argc, char *argv[])
{
char *cmd = pop_cmd(&argc, argv);
if (!strcmp(cmd, "show"))
return cmd_fs_show(argc, argv);
if (!strcmp(cmd, "set"))
return cmd_fs_set(argc, argv);
if (!strcmp(cmd, "usage"))
return cmd_fs_usage(argc, argv);
usage();
return 0;

146
cmd_fs.c
View File

@ -1,43 +1,125 @@
#include <stdio.h>
#include <sys/ioctl.h>
#include <uuid/uuid.h>
#include "libbcachefs/bcachefs_ioctl.h"
#include "libbcachefs/opts.h"
#include "cmds.h"
struct bcache_fs {
/* options... */
u64 capacity;
/* XXX: dirty != used, it doesn't count metadata */
u64 bytes_dirty;
};
#if 0
static struct bcache_fs fill_fs(struct bcache_handle fs)
static inline int printf_pad(unsigned pad, const char * fmt, ...)
{
return (struct bcache_fs) {
};
va_list args;
int ret;
va_start(args, fmt);
ret = vprintf(fmt, args);
va_end(args);
while (ret++ < pad)
putchar(' ');
return ret;
}
#endif
int cmd_fs_show(int argc, char *argv[])
static void print_fs_usage(const char *path, enum units units)
{
if (argc != 2)
die("Please supply a filesystem");
unsigned i, j, nr_devices = 4;
struct bcache_handle fs = bcache_fs_open(path);
struct bch_ioctl_usage *u = NULL;
char uuid[40];
#if 0
struct bcache_handle fs = bcache_fs_open(argv[1]);
#endif
return 0;
}
int cmd_fs_set(int argc, char *argv[])
{
if (argc != 2)
die("Please supply a filesystem");
#if 0
struct bcache_handle fs = bcache_fs_open(argv[1]);
#endif
while (1) {
u = xrealloc(u, sizeof(*u) + sizeof(u->devs[0]) * nr_devices);
u->nr_devices = nr_devices;
if (!ioctl(fs.ioctl_fd, BCH_IOCTL_USAGE, u))
break;
if (errno != ENOSPC)
die("BCH_IOCTL_USAGE error: %m");
nr_devices *= 2;
}
uuid_unparse(fs.uuid.b, uuid);
printf("Filesystem %s:\n", uuid);
printf("%-20s%12s\n", "Size:", pr_units(u->fs.capacity, units));
printf("%-20s%12s\n", "Used:", pr_units(u->fs.used, units));
printf("%-20s%12s%12s%12s%12s\n",
"By replicas:", "1x", "2x", "3x", "4x");
for (j = BCH_DATA_BTREE; j < BCH_DATA_NR; j++) {
printf_pad(20, " %s:", bch2_data_types[j]);
for (i = 0; i < BCH_REPLICAS_MAX; i++)
printf("%12s", pr_units(u->fs.sectors[j][i], units));
printf("\n");
}
printf_pad(20, " %s:", "reserved");
for (i = 0; i < BCH_REPLICAS_MAX; i++)
printf("%12s", pr_units(u->fs.persistent_reserved[i], units));
printf("\n");
printf("%-20s%12s\n", " online reserved:", pr_units(u->fs.online_reserved, units));
for (i = 0; i < u->nr_devices; i++) {
struct bch_ioctl_dev_usage *d = u->devs + i;
char *name = NULL;
if (!d->alive)
continue;
printf("\n");
printf_pad(20, "Device %u usage:", i);
name = !d->dev ? strdup("(offline)")
: dev_to_path(d->dev)
?: strdup("(device not found)");
printf("%24s%12s\n", name, bch2_dev_state[d->state]);
free(name);
printf("%-20s%12s%12s%12s\n",
"", "data", "buckets", "fragmented");
for (j = BCH_DATA_SB; j < BCH_DATA_NR; j++) {
u64 frag = max((s64) d->buckets[j] * d->bucket_size -
(s64) d->sectors[j], 0LL);
printf_pad(20, " %s:", bch2_data_types[j]);
printf("%12s%12llu%12s\n",
pr_units(d->sectors[j], units),
d->buckets[j],
pr_units(frag, units));
}
}
free(u);
bcache_fs_close(fs);
}
int cmd_fs_usage(int argc, char *argv[])
{
enum units units = BYTES;
unsigned i;
int opt;
while ((opt = getopt(argc, argv, "h")) != -1)
switch (opt) {
case 'h':
units = HUMAN_READABLE;
break;
}
if (argc - optind < 1) {
print_fs_usage(".", units);
} else {
for (i = optind; i < argc; i++)
print_fs_usage(argv[i], units);
}
return 0;
}

3
cmds.h
View File

@ -17,8 +17,7 @@ int cmd_incremental(int argc, char *argv[]);
int cmd_run(int argc, char *argv[]);
int cmd_stop(int argc, char *argv[]);
int cmd_fs_show(int argc, char *argv[]);
int cmd_fs_set(int argc, char *argv[]);
int cmd_fs_usage(int argc, char *argv[]);
int cmd_device_add(int argc, char *argv[]);
int cmd_device_remove(int argc, char *argv[]);

View File

@ -10,6 +10,7 @@
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <unistd.h>
@ -70,6 +71,15 @@ void *xmalloc(size_t size)
return p;
}
void *xrealloc(void *p, size_t size)
{
p = realloc(p, size);
if (!p)
die("insufficient memory");
return p;
}
void xpread(int fd, void *buf, size_t count, off_t offset)
{
ssize_t r = pread(fd, buf, count, offset);
@ -104,27 +114,34 @@ struct stat xfstat(int fd)
/* Integer stuff: */
struct units_buf __pr_units(u64 v, enum units units)
struct units_buf __pr_units(s64 _v, enum units units)
{
struct units_buf ret;
char *out = ret.b, *end = out + sizeof(ret.b);
u64 v = _v;
if (_v < 0) {
out += scnprintf(out, end - out, "-");
v = -_v;
}
switch (units) {
case BYTES:
snprintf(ret.b, sizeof(ret.b), "%llu", v << 9);
snprintf(out, end - out, "%llu", v << 9);
break;
case SECTORS:
snprintf(ret.b, sizeof(ret.b), "%llu", v);
snprintf(out, end - out, "%llu", v);
break;
case HUMAN_READABLE:
v <<= 9;
if (v >= 1024) {
int exp = log(v) / log(1024);
snprintf(ret.b, sizeof(ret.b), "%.1f%c",
snprintf(out, end - out, "%.1f%c",
v / pow(1024, exp),
"KMGTPE"[exp-1]);
} else {
snprintf(ret.b, sizeof(ret.b), "%llu", v);
snprintf(out, end - out, "%llu", v);
}
break;
@ -255,12 +272,17 @@ int bcachectl_open(void)
#define SYSFS_BASE "/sys/fs/bcachefs/"
void bcache_fs_close(struct bcache_handle fs)
{
close(fs.ioctl_fd);
close(fs.sysfs_fd);
}
struct bcache_handle bcache_fs_open(const char *path)
{
struct bcache_handle ret;
uuid_t tmp;
if (!uuid_parse(path, tmp)) {
if (!uuid_parse(path, ret.uuid.b)) {
/* It's a UUID, look it up in sysfs: */
char *sysfs = mprintf("%s%s", SYSFS_BASE, path);
ret.sysfs_fd = xopen(sysfs, O_RDONLY);
@ -279,6 +301,8 @@ struct bcache_handle bcache_fs_open(const char *path)
struct bch_ioctl_query_uuid uuid;
xioctl(ret.ioctl_fd, BCH_IOCTL_QUERY_UUID, &uuid);
ret.uuid = uuid.uuid;
char uuid_str[40];
uuid_unparse(uuid.uuid.b, uuid_str);
@ -562,4 +586,33 @@ u32 crc32c(u32 crc, const void *buf, size_t size)
#endif /* HAVE_WORKING_IFUNC */
char *dev_to_path(dev_t dev)
{
char *line = NULL, *name = NULL, *path = NULL;
size_t n = 0;
FILE *f = fopen("/proc/partitions", "r");
if (!f)
die("error opening /proc/partitions: %m");
while (getline(&line, &n, f) != -1) {
unsigned ma, mi;
u64 sectors;
name = realloc(name, n + 1);
if (sscanf(line, " %u %u %llu %s", &ma, &mi, &sectors, name) == 4 &&
ma == major(dev) && mi == minor(dev)) {
path = mprintf("/dev/%s", name);
break;
}
}
fclose(f);
free(line);
free(name);
return path;
}
#endif

View File

@ -15,12 +15,14 @@
#include <linux/log2.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/uuid.h>
#include "ccan/darray/darray.h"
void die(const char *, ...);
char *mprintf(const char *, ...);
void *xcalloc(size_t, size_t);
void *xmalloc(size_t);
void *xrealloc(void *, size_t);
void xpread(int, void *, size_t, off_t);
void xpwrite(int, const void *, size_t, off_t);
struct stat xfstatat(int, const char *, int);
@ -48,7 +50,7 @@ enum units {
HUMAN_READABLE,
};
struct units_buf __pr_units(u64, enum units);
struct units_buf __pr_units(s64, enum units);
struct units_buf {
char b[20];
@ -69,10 +71,12 @@ int open_for_format(const char *, bool);
int bcachectl_open(void);
struct bcache_handle {
uuid_le uuid;
int ioctl_fd;
int sysfs_fd;
};
void bcache_fs_close(struct bcache_handle);
struct bcache_handle bcache_fs_open(const char *);
bool ask_yn(void);
@ -151,4 +155,6 @@ unsigned hatoi_validate(const char *, const char *);
u32 crc32c(u32, const void *, size_t);
char *dev_to_path(dev_t);
#endif /* _TOOLS_UTIL_H */