mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-23 00:00:02 +03:00
New data rereplicate command
This commit is contained in:
parent
6976570d67
commit
7875b82630
17
bcachefs.c
17
bcachefs.c
@ -53,6 +53,9 @@ static void usage(void)
|
||||
" device set-state Mark a device as failed\n"
|
||||
" device resize Resize filesystem on a device\n"
|
||||
"\n"
|
||||
"Commands for managing filesystem data:\n"
|
||||
" data rereplicate Rereplicate degraded data\n"
|
||||
"\n"
|
||||
"Encryption:\n"
|
||||
" unlock Unlock an encrypted filesystem prior to running/mounting\n"
|
||||
" set-passphrase Change passphrase on an existing (unmounted) filesystem\n"
|
||||
@ -120,6 +123,17 @@ static int device_cmds(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int data_cmds(int argc, char *argv[])
|
||||
{
|
||||
char *cmd = pop_cmd(&argc, argv);
|
||||
|
||||
if (!strcmp(cmd, "rereplicate"))
|
||||
return cmd_data_rereplicate(argc, argv);
|
||||
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
full_cmd = argv[0];
|
||||
@ -151,6 +165,9 @@ int main(int argc, char *argv[])
|
||||
if (!strcmp(cmd, "device"))
|
||||
return device_cmds(argc, argv);
|
||||
|
||||
if (!strcmp(cmd, "data"))
|
||||
return data_cmds(argc, argv);
|
||||
|
||||
if (!strcmp(cmd, "unlock"))
|
||||
return cmd_unlock(argc, argv);
|
||||
if (!strcmp(cmd, "set-passphrase"))
|
||||
|
48
cmd_data.c
Normal file
48
cmd_data.c
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "libbcachefs/bcachefs_ioctl.h"
|
||||
|
||||
#include "cmds.h"
|
||||
#include "libbcachefs.h"
|
||||
|
||||
static void data_rereplicate_usage(void)
|
||||
{
|
||||
puts("bcachefs data rereplicate\n"
|
||||
"Usage: bcachefs data rereplicate filesystem\n"
|
||||
"\n"
|
||||
"Walks existing data in a filesystem, writing additional copies\n"
|
||||
"of any degraded data\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -h, --help display this help and exit\n"
|
||||
"Report bugs to <linux-bcache@vger.kernel.org>");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
int cmd_data_rereplicate(int argc, char *argv[])
|
||||
{
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "h")) != -1)
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
data_rereplicate_usage();
|
||||
}
|
||||
args_shift(optind);
|
||||
|
||||
char *fs_path = arg_pop();
|
||||
if (!fs_path)
|
||||
die("Please supply a filesystem");
|
||||
|
||||
if (argc)
|
||||
die("too many arguments");
|
||||
|
||||
return bchu_data(bcache_fs_open(fs_path), (struct bch_ioctl_data) {
|
||||
.op = BCH_DATA_OP_REREPLICATE,
|
||||
.start = POS_MIN,
|
||||
.end = POS_MAX,
|
||||
});
|
||||
}
|
20
cmd_debug.c
20
cmd_debug.c
@ -103,16 +103,17 @@ int cmd_dump(int argc, char *argv[])
|
||||
dump_usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (optind >= argc)
|
||||
die("Please supply device(s) to check");
|
||||
args_shift(optind);
|
||||
|
||||
if (!out)
|
||||
die("Please supply output filename");
|
||||
|
||||
struct bch_fs *c = bch2_fs_open(argv + optind, argc - optind, opts);
|
||||
if (!argc)
|
||||
die("Please supply device(s) to check");
|
||||
|
||||
struct bch_fs *c = bch2_fs_open(argv, argc, opts);
|
||||
if (IS_ERR(c))
|
||||
die("error opening %s: %s", argv[optind], strerror(-PTR_ERR(c)));
|
||||
die("error opening %s: %s", argv[0], strerror(-PTR_ERR(c)));
|
||||
|
||||
down_read(&c->gc_lock);
|
||||
|
||||
@ -299,13 +300,14 @@ int cmd_list(int argc, char *argv[])
|
||||
list_keys_usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
args_shift(optind);
|
||||
|
||||
if (optind >= argc)
|
||||
die("Please supply device(s) to check");
|
||||
if (!argc)
|
||||
die("Please supply device(s)");
|
||||
|
||||
struct bch_fs *c = bch2_fs_open(argv + optind, argc - optind, opts);
|
||||
struct bch_fs *c = bch2_fs_open(argv, argc, opts);
|
||||
if (IS_ERR(c))
|
||||
die("error opening %s: %s", argv[optind], strerror(-PTR_ERR(c)));
|
||||
die("error opening %s: %s", argv[0], strerror(-PTR_ERR(c)));
|
||||
|
||||
switch (mode) {
|
||||
case 0:
|
||||
|
261
cmd_device.c
261
cmd_device.c
@ -19,165 +19,6 @@
|
||||
#include "libbcachefs/opts.h"
|
||||
#include "tools-util.h"
|
||||
|
||||
/* This code belongs under show_fs */
|
||||
#if 0
|
||||
|
||||
struct bcache_dev {
|
||||
unsigned nr;
|
||||
const char *name;
|
||||
|
||||
unsigned has_metadata;
|
||||
unsigned has_data;
|
||||
const char *state;
|
||||
unsigned tier;
|
||||
|
||||
u64 bucket_size;
|
||||
u64 first_bucket;
|
||||
u64 nbuckets;
|
||||
|
||||
/* XXX: dirty != used, it doesn't count metadata */
|
||||
u64 bytes_dirty;
|
||||
};
|
||||
|
||||
static struct bcache_dev fill_dev(const char *dev_name, unsigned nr, int dir)
|
||||
{
|
||||
return (struct bcache_dev) {
|
||||
.nr = nr,
|
||||
.name = dev_name,
|
||||
|
||||
.has_metadata = read_file_u64(dir, "has_metadata"),
|
||||
.has_data = read_file_u64(dir, "has_data"),
|
||||
.state = read_file_str(dir, "state"),
|
||||
.tier = read_file_u64(dir, "tier"),
|
||||
|
||||
.bucket_size = read_file_u64(dir, "bucket_size_bytes"),
|
||||
.first_bucket = read_file_u64(dir, "first_bucket"),
|
||||
.nbuckets = read_file_u64(dir, "nbuckets"),
|
||||
.bytes_dirty = read_file_u64(dir, "dirty_bytes"),
|
||||
};
|
||||
}
|
||||
|
||||
static void show_dev(struct bcache_dev *dev)
|
||||
{
|
||||
u64 capacity = (dev->nbuckets - dev->first_bucket) *
|
||||
dev->bucket_size;
|
||||
/*
|
||||
* XXX: show fragmentation information, cached/dirty information
|
||||
*/
|
||||
|
||||
printf("Device %u (/dev/%s):\n"
|
||||
" Has metadata:\t%u\n"
|
||||
" Has dirty data:\t%u\n"
|
||||
" State:\t\t%s\n"
|
||||
" Tier:\t\t%u\n"
|
||||
" Size:\t\t%llu\n"
|
||||
" Used:\t\t%llu\n"
|
||||
" Free:\t\t%llu\n"
|
||||
" Use%%:\t\t%llu\n",
|
||||
dev->nr, dev->name,
|
||||
dev->has_metadata,
|
||||
dev->has_data,
|
||||
dev->state,
|
||||
dev->tier,
|
||||
capacity,
|
||||
dev->bytes_dirty,
|
||||
capacity - dev->bytes_dirty,
|
||||
(dev->bytes_dirty * 100) / capacity);
|
||||
}
|
||||
|
||||
int cmd_device_show(int argc, char *argv[])
|
||||
{
|
||||
int human_readable = 0;
|
||||
NihOption opts[] = {
|
||||
// { int shortoption, char *longoption, char *help, NihOptionGroup, char *argname, void *value, NihOptionSetter}
|
||||
|
||||
{ 'h', "human-readable", N_("print sizes in powers of 1024 (e.g., 1023M)"),
|
||||
NULL, NULL, &human_readable, NULL},
|
||||
NIH_OPTION_LAST
|
||||
};
|
||||
char **args = bch_nih_init(argc, argv, opts);
|
||||
|
||||
if (argc != 2)
|
||||
die("Please supply a single device");
|
||||
|
||||
struct bchfs_handle fs = bcache_fs_open(argv[1]);
|
||||
struct dirent *entry;
|
||||
|
||||
struct bcache_dev devices[256];
|
||||
unsigned i, j, nr_devices = 0, nr_active_tiers = 0;
|
||||
|
||||
unsigned tiers[BCH_TIER_MAX]; /* number of devices in each tier */
|
||||
memset(tiers, 0, sizeof(tiers));
|
||||
|
||||
while ((entry = readdir(fs.sysfs))) {
|
||||
unsigned nr;
|
||||
int pos = 0;
|
||||
|
||||
sscanf(entry->d_name, "cache%u%n", &nr, &pos);
|
||||
if (pos != strlen(entry->d_name))
|
||||
continue;
|
||||
|
||||
char link[PATH_MAX];
|
||||
if (readlinkat(dirfd(fs.sysfs), entry->d_name,
|
||||
link, sizeof(link)) < 0)
|
||||
die("readlink error: %m\n");
|
||||
|
||||
char *dev_name = basename(dirname(link));
|
||||
|
||||
int fd = xopenat(dirfd(fs.sysfs), entry->d_name, O_RDONLY);
|
||||
|
||||
devices[nr_devices] = fill_dev(strdup(dev_name), nr, fd);
|
||||
tiers[devices[nr_devices].tier]++;
|
||||
nr_devices++;
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
for (i = 0; i < BCH_TIER_MAX; i++)
|
||||
if (tiers[i])
|
||||
nr_active_tiers++;
|
||||
|
||||
/* Print out devices sorted by tier: */
|
||||
bool first = true;
|
||||
|
||||
for (i = 0; i < BCH_TIER_MAX; i++) {
|
||||
if (!tiers[i])
|
||||
continue;
|
||||
|
||||
if (nr_active_tiers > 1) {
|
||||
if (!first)
|
||||
printf("\n");
|
||||
first = false;
|
||||
printf("Tier %u:\n\n", i);
|
||||
}
|
||||
|
||||
for (j = 0; j < nr_devices; j++) {
|
||||
if (devices[j].tier != i)
|
||||
continue;
|
||||
|
||||
if (!first)
|
||||
printf("\n");
|
||||
first = false;
|
||||
show_dev(&devices[j]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void disk_ioctl(const char *fs, const char *dev, int cmd, int flags)
|
||||
{
|
||||
struct bch_ioctl_disk i = { .flags = flags, };
|
||||
|
||||
if (!kstrtoull(dev, 10, &i.dev))
|
||||
i.flags |= BCH_BY_INDEX;
|
||||
else
|
||||
i.dev = (u64) dev;
|
||||
|
||||
xioctl(bcache_fs_open(fs).ioctl_fd, cmd, &i);
|
||||
}
|
||||
|
||||
static void device_add_usage(void)
|
||||
{
|
||||
puts("bcachefs device add - add a device to an existing filesystem\n"
|
||||
@ -239,12 +80,20 @@ int cmd_device_add(int argc, char *argv[])
|
||||
}
|
||||
args_shift(optind);
|
||||
|
||||
if (argc != 2)
|
||||
die("Please supply a filesystem and a device to add");
|
||||
char *fs_path = arg_pop();
|
||||
if (!fs_path)
|
||||
die("Please supply a filesystem");
|
||||
|
||||
struct bchfs_handle fs = bcache_fs_open(arg_pop());
|
||||
char *dev_path = arg_pop();
|
||||
if (!dev_path)
|
||||
die("Please supply a device");
|
||||
|
||||
dev_opts.path = arg_pop();
|
||||
if (argc)
|
||||
die("too many arguments");
|
||||
|
||||
struct bchfs_handle fs = bcache_fs_open(fs_path);
|
||||
|
||||
dev_opts.path = dev_path;
|
||||
dev_opts.fd = open_for_format(dev_opts.path, force);
|
||||
|
||||
format_opts.block_size =
|
||||
@ -264,7 +113,7 @@ int cmd_device_add(int argc, char *argv[])
|
||||
static void device_remove_usage(void)
|
||||
{
|
||||
puts("bcachefs device_remove - remove a device from a filesystem\n"
|
||||
"Usage: bcachefs device remove filesystem device\n"
|
||||
"Usage: bcachefs device remove device\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -f, --force Force removal, even if some data\n"
|
||||
@ -299,10 +148,6 @@ int cmd_device_remove(int argc, char *argv[])
|
||||
}
|
||||
args_shift(optind);
|
||||
|
||||
char *fs = arg_pop();
|
||||
if (!fs)
|
||||
die("Please supply a filesystem");
|
||||
|
||||
char *dev = arg_pop();
|
||||
if (!dev)
|
||||
die("Please supply a device to remove");
|
||||
@ -310,14 +155,16 @@ int cmd_device_remove(int argc, char *argv[])
|
||||
if (argc)
|
||||
die("too many arguments");
|
||||
|
||||
disk_ioctl(fs, dev, BCH_IOCTL_DISK_REMOVE, flags);
|
||||
unsigned dev_idx;
|
||||
struct bchfs_handle fs = bchu_fs_open_by_dev(dev, &dev_idx);
|
||||
bchu_disk_remove(fs, dev_idx, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void device_online_usage(void)
|
||||
{
|
||||
puts("bcachefs device online - readd a device to a running filesystem\n"
|
||||
"Usage: bcachefs device online [OPTION]... filesystem device\n"
|
||||
"Usage: bcachefs device online [OPTION]... device\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -h, --help Display this help and exit\n"
|
||||
@ -335,18 +182,25 @@ int cmd_device_online(int argc, char *argv[])
|
||||
device_online_usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
args_shift(optind);
|
||||
|
||||
if (argc - optind != 2)
|
||||
die("Please supply a filesystem and a device");
|
||||
char *dev = arg_pop();
|
||||
if (!dev)
|
||||
die("Please supply a device");
|
||||
|
||||
disk_ioctl(argv[optind], argv[optind + 1], BCH_IOCTL_DISK_ONLINE, 0);
|
||||
if (argc)
|
||||
die("too many arguments");
|
||||
|
||||
unsigned dev_idx;
|
||||
struct bchfs_handle fs = bchu_fs_open_by_dev(dev, &dev_idx);
|
||||
bchu_disk_online(fs, dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void device_offline_usage(void)
|
||||
{
|
||||
puts("bcachefs device offline - take a device offline, without removing it\n"
|
||||
"Usage: bcachefs device offline [OPTION]... filesystem device\n"
|
||||
"Usage: bcachefs device offline [OPTION]... device\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -f, --force Force, if data redundancy will be degraded\n"
|
||||
@ -373,19 +227,25 @@ int cmd_device_offline(int argc, char *argv[])
|
||||
device_offline_usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
args_shift(optind);
|
||||
|
||||
if (argc - optind != 2)
|
||||
die("Please supply a filesystem and a device");
|
||||
char *dev = arg_pop();
|
||||
if (!dev)
|
||||
die("Please supply a device");
|
||||
|
||||
disk_ioctl(argv[optind], argv[optind + 1],
|
||||
BCH_IOCTL_DISK_OFFLINE, flags);
|
||||
if (argc)
|
||||
die("too many arguments");
|
||||
|
||||
unsigned dev_idx;
|
||||
struct bchfs_handle fs = bchu_fs_open_by_dev(dev, &dev_idx);
|
||||
bchu_disk_offline(fs, dev_idx, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void device_evacuate_usage(void)
|
||||
{
|
||||
puts("bcachefs device evacuate - move data off of a given device\n"
|
||||
"Usage: bcachefs device evacuate [OPTION]... filesystem device\n"
|
||||
"Usage: bcachefs device evacuate [OPTION]... device\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -h, --help Display this help and exit\n"
|
||||
@ -403,18 +263,30 @@ int cmd_device_evacuate(int argc, char *argv[])
|
||||
device_evacuate_usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
args_shift(optind);
|
||||
|
||||
if (argc - optind != 2)
|
||||
die("Please supply a filesystem and a device");
|
||||
char *dev_path = arg_pop();
|
||||
if (!dev_path)
|
||||
die("Please supply a device");
|
||||
|
||||
disk_ioctl(argv[optind], argv[optind + 1], BCH_IOCTL_DISK_EVACUATE, 0);
|
||||
return 0;
|
||||
if (argc)
|
||||
die("too many arguments");
|
||||
|
||||
unsigned dev_idx;
|
||||
struct bchfs_handle fs = bchu_fs_open_by_dev(dev_path, &dev_idx);
|
||||
|
||||
return bchu_data(fs, (struct bch_ioctl_data) {
|
||||
.op = BCH_DATA_OP_MIGRATE,
|
||||
.start = POS_MIN,
|
||||
.end = POS_MAX,
|
||||
.migrate.dev = dev_idx,
|
||||
});
|
||||
}
|
||||
|
||||
static void device_set_state_usage(void)
|
||||
{
|
||||
puts("bcachefs device set-state\n"
|
||||
"Usage: bcachefs device set-state filesystem device new-state\n"
|
||||
"Usage: bcachefs device set-state device new-state\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -f, --force Force, if data redundancy will be degraded\n"
|
||||
@ -440,16 +312,23 @@ int cmd_device_set_state(int argc, char *argv[])
|
||||
case 'h':
|
||||
device_set_state_usage();
|
||||
}
|
||||
args_shift(optind);
|
||||
|
||||
if (argc - optind != 3)
|
||||
die("Please supply a filesystem, device and state");
|
||||
char *dev_path = arg_pop();
|
||||
if (!dev_path)
|
||||
die("Please supply a device");
|
||||
|
||||
struct bchfs_handle fs = bcache_fs_open(argv[optind]);
|
||||
char *new_state_str = arg_pop();
|
||||
if (!new_state_str)
|
||||
die("Please supply a device state");
|
||||
|
||||
bchu_disk_set_state(fs, argv[optind + 1],
|
||||
read_string_list_or_die(argv[optind + 2],
|
||||
bch2_dev_state, "device state"),
|
||||
flags);
|
||||
unsigned new_state = read_string_list_or_die(new_state_str,
|
||||
bch2_dev_state, "device state");
|
||||
|
||||
unsigned dev_idx;
|
||||
struct bchfs_handle fs = bchu_fs_open_by_dev(dev_path, &dev_idx);
|
||||
|
||||
bchu_disk_set_state(fs, dev_idx, new_state, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -329,6 +329,10 @@ int cmd_show_super(int argc, char *argv[])
|
||||
die("too many arguments");
|
||||
|
||||
struct bch_opts opts = bch2_opts_empty();
|
||||
|
||||
opt_set(opts, noexcl, true);
|
||||
opt_set(opts, nochanges, true);
|
||||
|
||||
struct bch_sb_handle sb;
|
||||
int ret = bch2_read_super(dev, &opts, &sb);
|
||||
if (ret)
|
||||
|
9
cmd_fs.c
9
cmd_fs.c
@ -80,7 +80,7 @@ static void print_fs_usage(const char *path, enum units units)
|
||||
int cmd_fs_usage(int argc, char *argv[])
|
||||
{
|
||||
enum units units = BYTES;
|
||||
unsigned i;
|
||||
char *fs;
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "h")) != -1)
|
||||
@ -89,12 +89,13 @@ int cmd_fs_usage(int argc, char *argv[])
|
||||
units = HUMAN_READABLE;
|
||||
break;
|
||||
}
|
||||
args_shift(optind);
|
||||
|
||||
if (argc - optind < 1) {
|
||||
if (!argc) {
|
||||
print_fs_usage(".", units);
|
||||
} else {
|
||||
for (i = optind; i < argc; i++)
|
||||
print_fs_usage(argv[i], units);
|
||||
while ((fs = arg_pop()))
|
||||
print_fs_usage(fs, units);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -50,13 +50,14 @@ int cmd_fsck(int argc, char *argv[])
|
||||
usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
args_shift(optind);
|
||||
|
||||
if (optind >= argc)
|
||||
if (!argc)
|
||||
die("Please supply device(s) to check");
|
||||
|
||||
struct bch_fs *c = bch2_fs_open(argv + optind, argc - optind, opts);
|
||||
struct bch_fs *c = bch2_fs_open(argv, argc, opts);
|
||||
if (IS_ERR(c))
|
||||
die("error opening %s: %s", argv[optind], strerror(-PTR_ERR(c)));
|
||||
die("error opening %s: %s", argv[0], strerror(-PTR_ERR(c)));
|
||||
|
||||
bch2_fs_stop(c);
|
||||
return 0;
|
||||
|
2
cmds.h
2
cmds.h
@ -27,6 +27,8 @@ int cmd_device_evacuate(int argc, char *argv[]);
|
||||
int cmd_device_set_state(int argc, char *argv[]);
|
||||
int cmd_device_resize(int argc, char *argv[]);
|
||||
|
||||
int cmd_data_rereplicate(int argc, char *argv[]);
|
||||
|
||||
int cmd_unlock(int argc, char *argv[]);
|
||||
int cmd_set_passphrase(int argc, char *argv[]);
|
||||
int cmd_remove_passphrase(int argc, char *argv[]);
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
@ -17,6 +18,7 @@
|
||||
#include "libbcachefs/checksum.h"
|
||||
#include "crypto.h"
|
||||
#include "libbcachefs.h"
|
||||
#include "libbcachefs/btree_cache.h"
|
||||
#include "libbcachefs/opts.h"
|
||||
#include "libbcachefs/super-io.h"
|
||||
|
||||
@ -640,7 +642,7 @@ struct bchfs_handle bcache_fs_open(const char *path)
|
||||
|
||||
if (!uuid_parse(path, ret.uuid.b)) {
|
||||
/* It's a UUID, look it up in sysfs: */
|
||||
char *sysfs = mprintf("%s%s", SYSFS_BASE, path);
|
||||
char *sysfs = mprintf(SYSFS_BASE "%s", path);
|
||||
ret.sysfs_fd = xopen(sysfs, O_RDONLY);
|
||||
|
||||
char *minor = read_file_str(ret.sysfs_fd, "minor");
|
||||
@ -662,10 +664,94 @@ struct bchfs_handle bcache_fs_open(const char *path)
|
||||
char uuid_str[40];
|
||||
uuid_unparse(uuid.uuid.b, uuid_str);
|
||||
|
||||
char *sysfs = mprintf("%s%s", SYSFS_BASE, uuid_str);
|
||||
char *sysfs = mprintf(SYSFS_BASE "%s", uuid_str);
|
||||
ret.sysfs_fd = xopen(sysfs, O_RDONLY);
|
||||
free(sysfs);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a path to a block device, open the filesystem it belongs to; also
|
||||
* return the device's idx:
|
||||
*/
|
||||
struct bchfs_handle bchu_fs_open_by_dev(const char *path, unsigned *idx)
|
||||
{
|
||||
char buf[1024], *uuid_str;
|
||||
|
||||
struct stat stat = xstat(path);
|
||||
|
||||
if (!S_ISBLK(stat.st_mode))
|
||||
die("%s is not a block device", path);
|
||||
|
||||
char *sysfs = mprintf("/sys/dev/block/%u:%u/bcachefs",
|
||||
major(stat.st_dev),
|
||||
minor(stat.st_dev));
|
||||
ssize_t len = readlink(sysfs, buf, sizeof(buf));
|
||||
free(sysfs);
|
||||
|
||||
if (len > 0) {
|
||||
char *p = strrchr(buf, '/');
|
||||
if (!p || sscanf(p + 1, "dev-%u", idx) != 1)
|
||||
die("error parsing sysfs");
|
||||
|
||||
*p = '\0';
|
||||
p = strrchr(buf, '/');
|
||||
uuid_str = p + 1;
|
||||
} else {
|
||||
struct bch_opts opts = bch2_opts_empty();
|
||||
|
||||
opt_set(opts, noexcl, true);
|
||||
opt_set(opts, nochanges, true);
|
||||
|
||||
struct bch_sb_handle sb;
|
||||
int ret = bch2_read_super(path, &opts, &sb);
|
||||
if (ret)
|
||||
die("Error opening %s: %s", path, strerror(-ret));
|
||||
|
||||
*idx = sb.sb->dev_idx;
|
||||
uuid_str = buf;
|
||||
uuid_unparse(sb.sb->user_uuid.b, uuid_str);
|
||||
|
||||
bch2_free_super(&sb);
|
||||
}
|
||||
|
||||
return bcache_fs_open(uuid_str);
|
||||
}
|
||||
|
||||
int bchu_data(struct bchfs_handle fs, struct bch_ioctl_data cmd)
|
||||
{
|
||||
int progress_fd = xioctl(fs.ioctl_fd, BCH_IOCTL_DATA, &cmd);
|
||||
|
||||
while (1) {
|
||||
struct bch_ioctl_data_progress p;
|
||||
|
||||
if (read(progress_fd, &p, sizeof(p)) != sizeof(p))
|
||||
die("error reading from progress fd");
|
||||
|
||||
if (p.data_type == U8_MAX)
|
||||
break;
|
||||
|
||||
printf("\33[2K\r");
|
||||
|
||||
printf("%llu%% complete: current position %s",
|
||||
p.sectors_done * 100 / p.sectors_total,
|
||||
bch2_data_types[p.data_type]);
|
||||
|
||||
switch (p.data_type) {
|
||||
case BCH_DATA_BTREE:
|
||||
case BCH_DATA_USER:
|
||||
printf(" %s:%llu:%llu",
|
||||
bch2_btree_ids[p.btree_id],
|
||||
p.pos.inode,
|
||||
p.pos.offset);
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
printf("\nDone\n");
|
||||
|
||||
close(progress_fd);
|
||||
return 0;
|
||||
}
|
||||
|
@ -89,6 +89,7 @@ struct bchfs_handle {
|
||||
|
||||
void bcache_fs_close(struct bchfs_handle);
|
||||
struct bchfs_handle bcache_fs_open(const char *);
|
||||
struct bchfs_handle bchu_fs_open_by_dev(const char *, unsigned *);
|
||||
|
||||
static inline void bchu_disk_add(struct bchfs_handle fs, char *dev)
|
||||
{
|
||||
@ -97,19 +98,44 @@ static inline void bchu_disk_add(struct bchfs_handle fs, char *dev)
|
||||
xioctl(fs.ioctl_fd, BCH_IOCTL_DISK_ADD, &i);
|
||||
}
|
||||
|
||||
static inline void bchu_disk_set_state(struct bchfs_handle fs, const char *dev,
|
||||
static inline void bchu_disk_remove(struct bchfs_handle fs, unsigned dev_idx,
|
||||
unsigned flags)
|
||||
{
|
||||
struct bch_ioctl_disk i = {
|
||||
.flags = flags|BCH_BY_INDEX,
|
||||
.dev = dev_idx,
|
||||
};
|
||||
|
||||
xioctl(fs.ioctl_fd, BCH_IOCTL_DISK_REMOVE, &i);
|
||||
}
|
||||
|
||||
static inline void bchu_disk_online(struct bchfs_handle fs, char *dev)
|
||||
{
|
||||
struct bch_ioctl_disk i = { .dev = (__u64) dev, };
|
||||
|
||||
xioctl(fs.ioctl_fd, BCH_IOCTL_DISK_ONLINE, &i);
|
||||
}
|
||||
|
||||
static inline void bchu_disk_offline(struct bchfs_handle fs, unsigned dev_idx,
|
||||
unsigned flags)
|
||||
{
|
||||
struct bch_ioctl_disk i = {
|
||||
.flags = flags|BCH_BY_INDEX,
|
||||
.dev = dev_idx,
|
||||
};
|
||||
|
||||
xioctl(fs.ioctl_fd, BCH_IOCTL_DISK_OFFLINE, &i);
|
||||
}
|
||||
|
||||
static inline void bchu_disk_set_state(struct bchfs_handle fs, unsigned dev,
|
||||
unsigned new_state, unsigned flags)
|
||||
{
|
||||
struct bch_ioctl_disk_set_state i = {
|
||||
.flags = flags,
|
||||
.flags = flags|BCH_BY_INDEX,
|
||||
.new_state = new_state,
|
||||
.dev = dev,
|
||||
};
|
||||
|
||||
if (!kstrtoull(dev, 10, &i.dev))
|
||||
i.flags |= BCH_BY_INDEX;
|
||||
else
|
||||
i.dev = (u64) dev;
|
||||
|
||||
xioctl(fs.ioctl_fd, BCH_IOCTL_DISK_SET_STATE, &i);
|
||||
}
|
||||
|
||||
@ -176,4 +202,6 @@ static inline void bchu_disk_resize(struct bchfs_handle fs,
|
||||
xioctl(fs.ioctl_fd, BCH_IOCTL_DISK_RESIZE, &i);
|
||||
}
|
||||
|
||||
int bchu_data(struct bchfs_handle, struct bch_ioctl_data);
|
||||
|
||||
#endif /* _LIBBCACHE_H */
|
||||
|
@ -118,6 +118,14 @@ struct stat xfstat(int fd)
|
||||
return stat;
|
||||
}
|
||||
|
||||
struct stat xstat(const char *path)
|
||||
{
|
||||
struct stat statbuf;
|
||||
if (stat(path, &statbuf))
|
||||
die("stat error: %m");
|
||||
return statbuf;
|
||||
}
|
||||
|
||||
/* Formatting: */
|
||||
|
||||
int printf_pad(unsigned pad, const char * fmt, ...)
|
||||
|
@ -28,6 +28,7 @@ void xpread(int, void *, size_t, off_t);
|
||||
void xpwrite(int, const void *, size_t, off_t);
|
||||
struct stat xfstatat(int, const char *, int);
|
||||
struct stat xfstat(int);
|
||||
struct stat xstat(const char *);
|
||||
|
||||
#define xopenat(_dirfd, _path, ...) \
|
||||
({ \
|
||||
@ -155,8 +156,9 @@ char *dev_to_mount(char *);
|
||||
|
||||
#define args_shift(_nr) \
|
||||
do { \
|
||||
argc -= (_nr); \
|
||||
argv += (_nr); \
|
||||
unsigned _n = min((_nr), argc); \
|
||||
argc -= _n; \
|
||||
argv += _n; \
|
||||
} while (0)
|
||||
|
||||
#define arg_pop() \
|
||||
|
Loading…
Reference in New Issue
Block a user