mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-23 00:00:02 +03:00
Resizing
This commit is contained in:
parent
9d2dfea54b
commit
aca9f96dcc
@ -51,6 +51,7 @@ static void usage(void)
|
|||||||
" device offline Take a device offline, without removing it\n"
|
" device offline Take a device offline, without removing it\n"
|
||||||
" device evacuate Migrate data off of a specific device\n"
|
" device evacuate Migrate data off of a specific device\n"
|
||||||
" device set-state Mark a device as failed\n"
|
" device set-state Mark a device as failed\n"
|
||||||
|
" device resize Resize filesystem on a device\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Encryption:\n"
|
"Encryption:\n"
|
||||||
" unlock Unlock an encrypted filesystem prior to running/mounting\n"
|
" unlock Unlock an encrypted filesystem prior to running/mounting\n"
|
||||||
@ -112,6 +113,8 @@ static int device_cmds(int argc, char *argv[])
|
|||||||
return cmd_device_offline(argc, argv);
|
return cmd_device_offline(argc, argv);
|
||||||
if (!strcmp(cmd, "set-state"))
|
if (!strcmp(cmd, "set-state"))
|
||||||
return cmd_device_set_state(argc, argv);
|
return cmd_device_set_state(argc, argv);
|
||||||
|
if (!strcmp(cmd, "resize"))
|
||||||
|
return cmd_device_resize(argc, argv);
|
||||||
|
|
||||||
usage();
|
usage();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "libbcachefs/bcachefs_ioctl.h"
|
#include "libbcachefs/bcachefs_ioctl.h"
|
||||||
#include "cmds.h"
|
#include "cmds.h"
|
||||||
|
#include "libbcachefs.h"
|
||||||
|
|
||||||
int cmd_assemble(int argc, char *argv[])
|
int cmd_assemble(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
130
cmd_device.c
130
cmd_device.c
@ -13,6 +13,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "libbcachefs/bcachefs_ioctl.h"
|
#include "libbcachefs/bcachefs_ioctl.h"
|
||||||
|
#include "libbcachefs/super-io.h"
|
||||||
#include "cmds.h"
|
#include "cmds.h"
|
||||||
#include "libbcachefs.h"
|
#include "libbcachefs.h"
|
||||||
#include "libbcachefs/opts.h"
|
#include "libbcachefs/opts.h"
|
||||||
@ -99,7 +100,7 @@ int cmd_device_show(int argc, char *argv[])
|
|||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
die("Please supply a single device");
|
die("Please supply a single device");
|
||||||
|
|
||||||
struct bcache_handle fs = bcache_fs_open(argv[1]);
|
struct bchfs_handle fs = bcache_fs_open(argv[1]);
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
|
|
||||||
struct bcache_dev devices[256];
|
struct bcache_dev devices[256];
|
||||||
@ -240,7 +241,7 @@ int cmd_device_add(int argc, char *argv[])
|
|||||||
if (argc - optind != 2)
|
if (argc - optind != 2)
|
||||||
die("Please supply a filesystem and a device to add");
|
die("Please supply a filesystem and a device to add");
|
||||||
|
|
||||||
struct bcache_handle fs = bcache_fs_open(argv[optind]);
|
struct bchfs_handle fs = bcache_fs_open(argv[optind]);
|
||||||
|
|
||||||
dev_opts.path = argv[optind + 1];
|
dev_opts.path = argv[optind + 1];
|
||||||
dev_opts.fd = open_for_format(dev_opts.path, force);
|
dev_opts.fd = open_for_format(dev_opts.path, force);
|
||||||
@ -255,9 +256,7 @@ int cmd_device_add(int argc, char *argv[])
|
|||||||
fsync(dev_opts.fd);
|
fsync(dev_opts.fd);
|
||||||
close(dev_opts.fd);
|
close(dev_opts.fd);
|
||||||
|
|
||||||
struct bch_ioctl_disk i = { .dev = (__u64) dev_opts.path, };
|
bchu_disk_add(fs, dev_opts.path);
|
||||||
|
|
||||||
xioctl(fs.ioctl_fd, BCH_IOCTL_DISK_ADD, &i);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,20 +435,113 @@ int cmd_device_set_state(int argc, char *argv[])
|
|||||||
if (argc - optind != 3)
|
if (argc - optind != 3)
|
||||||
die("Please supply a filesystem, device and state");
|
die("Please supply a filesystem, device and state");
|
||||||
|
|
||||||
struct bcache_handle fs = bcache_fs_open(argv[optind]);
|
struct bchfs_handle fs = bcache_fs_open(argv[optind]);
|
||||||
|
|
||||||
struct bch_ioctl_disk_set_state i = {
|
bchu_disk_set_state(fs, argv[optind + 1],
|
||||||
.flags = flags,
|
read_string_list_or_die(argv[optind + 2],
|
||||||
.new_state = read_string_list_or_die(argv[optind + 2],
|
bch2_dev_state, "device state"),
|
||||||
bch2_dev_state, "device state"),
|
flags);
|
||||||
};
|
return 0;
|
||||||
|
}
|
||||||
const char *dev = argv[optind + 1];
|
|
||||||
if (!kstrtoull(dev, 10, &i.dev))
|
static void device_resize_usage(void)
|
||||||
i.flags |= BCH_BY_INDEX;
|
{
|
||||||
else
|
puts("bcachefs device resize \n"
|
||||||
i.dev = (u64) dev;
|
"Usage: bcachefs device resize device [ size ]\n"
|
||||||
|
"\n"
|
||||||
xioctl(fs.ioctl_fd, BCH_IOCTL_DISK_SET_STATE, &i);
|
"Options:\n"
|
||||||
|
" -h, --help display this help and exit\n"
|
||||||
|
"Report bugs to <linux-bcache@vger.kernel.org>");
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_device_resize(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
static const struct option longopts[] = {
|
||||||
|
{ "help", 0, NULL, 'h' },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
u64 size;
|
||||||
|
int opt;
|
||||||
|
|
||||||
|
while ((opt = getopt_long(argc, argv, "h", longopts, NULL)) != -1)
|
||||||
|
switch (opt) {
|
||||||
|
case 'h':
|
||||||
|
device_resize_usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc < optind + 1)
|
||||||
|
die("Please supply a device to resize");
|
||||||
|
|
||||||
|
char *dev = argv[optind];
|
||||||
|
int dev_fd = xopen(dev, O_RDONLY);
|
||||||
|
|
||||||
|
if (argc == optind + 1)
|
||||||
|
size = get_size(dev, dev_fd);
|
||||||
|
else if (bch2_strtoull_h(argv[optind + 1], &size))
|
||||||
|
die("invalid size");
|
||||||
|
|
||||||
|
size >>= 9;
|
||||||
|
|
||||||
|
if (argc > optind + 2)
|
||||||
|
die("Too many arguments");
|
||||||
|
|
||||||
|
struct stat dev_stat = xfstat(dev_fd);
|
||||||
|
|
||||||
|
char *mount = dev_to_mount(dev);
|
||||||
|
if (mount) {
|
||||||
|
if (!S_ISBLK(dev_stat.st_mode))
|
||||||
|
die("%s is mounted but isn't a block device?!", dev);
|
||||||
|
|
||||||
|
printf("Doing online resize of %s\n", dev);
|
||||||
|
|
||||||
|
struct bchfs_handle fs = bcache_fs_open(mount);
|
||||||
|
|
||||||
|
unsigned idx = bchu_disk_get_idx(fs, dev_stat.st_rdev);
|
||||||
|
|
||||||
|
struct bch_sb *sb = bchu_read_super(fs, -1);
|
||||||
|
if (idx >= sb->nr_devices)
|
||||||
|
die("error reading superblock: dev idx >= sb->nr_devices");
|
||||||
|
|
||||||
|
struct bch_sb_field_members *mi = bch2_sb_get_members(sb);
|
||||||
|
if (!mi)
|
||||||
|
die("error reading superblock: no member info");
|
||||||
|
|
||||||
|
/* could also just read this out of sysfs... meh */
|
||||||
|
struct bch_member *m = mi->members + idx;
|
||||||
|
|
||||||
|
u64 nbuckets = size / le16_to_cpu(m->bucket_size);
|
||||||
|
|
||||||
|
printf("resizing %s to %llu buckets\n", dev, nbuckets);
|
||||||
|
bchu_disk_resize(fs, idx, nbuckets);
|
||||||
|
} else {
|
||||||
|
printf("Doing offline resize of %s\n", dev);
|
||||||
|
|
||||||
|
struct bch_fs *c = NULL;
|
||||||
|
struct bch_opts opts = bch2_opts_empty();
|
||||||
|
const char *err = bch2_fs_open(&dev, 1, opts, &c);
|
||||||
|
if (err)
|
||||||
|
die("error opening %s: %s", argv[optind], err);
|
||||||
|
|
||||||
|
struct bch_dev *ca, *resize = NULL;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for_each_online_member(ca, c, i) {
|
||||||
|
if (resize)
|
||||||
|
die("confused: more than one online device?");
|
||||||
|
resize = ca;
|
||||||
|
percpu_ref_get(&resize->io_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 nbuckets = size / le16_to_cpu(resize->mi.bucket_size);
|
||||||
|
|
||||||
|
printf("resizing %s to %llu buckets\n", dev, nbuckets);
|
||||||
|
int ret = bch2_dev_resize(c, resize, nbuckets);
|
||||||
|
if (ret)
|
||||||
|
fprintf(stderr, "resize error: %s\n", strerror(-ret));
|
||||||
|
|
||||||
|
percpu_ref_put(&resize->io_ref);
|
||||||
|
bch2_fs_stop(c);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
17
cmd_fs.c
17
cmd_fs.c
@ -8,6 +8,7 @@
|
|||||||
#include "libbcachefs/opts.h"
|
#include "libbcachefs/opts.h"
|
||||||
|
|
||||||
#include "cmds.h"
|
#include "cmds.h"
|
||||||
|
#include "libbcachefs.h"
|
||||||
|
|
||||||
static inline int printf_pad(unsigned pad, const char * fmt, ...)
|
static inline int printf_pad(unsigned pad, const char * fmt, ...)
|
||||||
{
|
{
|
||||||
@ -26,21 +27,11 @@ static inline int printf_pad(unsigned pad, const char * fmt, ...)
|
|||||||
|
|
||||||
static void print_fs_usage(const char *path, enum units units)
|
static void print_fs_usage(const char *path, enum units units)
|
||||||
{
|
{
|
||||||
unsigned i, j, nr_devices = 4;
|
unsigned i, j;
|
||||||
struct bcache_handle fs = bcache_fs_open(path);
|
|
||||||
struct bch_ioctl_usage *u = NULL;
|
|
||||||
char uuid[40];
|
char uuid[40];
|
||||||
|
|
||||||
while (1) {
|
struct bchfs_handle fs = bcache_fs_open(path);
|
||||||
u = xrealloc(u, sizeof(*u) + sizeof(u->devs[0]) * nr_devices);
|
struct bch_ioctl_usage *u = bchu_usage(fs);
|
||||||
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);
|
uuid_unparse(fs.uuid.b, uuid);
|
||||||
printf("Filesystem %s:\n", uuid);
|
printf("Filesystem %s:\n", uuid);
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "libbcachefs/bcachefs_ioctl.h"
|
#include "libbcachefs/bcachefs_ioctl.h"
|
||||||
#include "cmds.h"
|
#include "cmds.h"
|
||||||
|
#include "libbcachefs.h"
|
||||||
|
|
||||||
int cmd_run(int argc, char *argv[])
|
int cmd_run(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -24,7 +25,7 @@ int cmd_stop(int argc, char *argv[])
|
|||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
die("Please supply a filesystem");
|
die("Please supply a filesystem");
|
||||||
|
|
||||||
struct bcache_handle fs = bcache_fs_open(argv[1]);
|
struct bchfs_handle fs = bcache_fs_open(argv[1]);
|
||||||
xioctl(fs.ioctl_fd, BCH_IOCTL_STOP);
|
xioctl(fs.ioctl_fd, BCH_IOCTL_STOP);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
1
cmds.h
1
cmds.h
@ -25,6 +25,7 @@ int cmd_device_online(int argc, char *argv[]);
|
|||||||
int cmd_device_offline(int argc, char *argv[]);
|
int cmd_device_offline(int argc, char *argv[]);
|
||||||
int cmd_device_evacuate(int argc, char *argv[]);
|
int cmd_device_evacuate(int argc, char *argv[]);
|
||||||
int cmd_device_set_state(int argc, char *argv[]);
|
int cmd_device_set_state(int argc, char *argv[]);
|
||||||
|
int cmd_device_resize(int argc, char *argv[]);
|
||||||
|
|
||||||
int cmd_unlock(int argc, char *argv[]);
|
int cmd_unlock(int argc, char *argv[]);
|
||||||
int cmd_set_passphrase(int argc, char *argv[]);
|
int cmd_set_passphrase(int argc, char *argv[]);
|
||||||
|
@ -455,3 +455,57 @@ void bch2_super_print(struct bch_sb *sb, int units)
|
|||||||
BCH_MEMBER_DISCARD(m));
|
BCH_MEMBER_DISCARD(m));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ioctl interface: */
|
||||||
|
|
||||||
|
/* Global control device: */
|
||||||
|
int bcachectl_open(void)
|
||||||
|
{
|
||||||
|
return xopen("/dev/bcachefs-ctl", O_RDWR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Filesystem handles (ioctl, sysfs dir): */
|
||||||
|
|
||||||
|
#define SYSFS_BASE "/sys/fs/bcachefs/"
|
||||||
|
|
||||||
|
void bcache_fs_close(struct bchfs_handle fs)
|
||||||
|
{
|
||||||
|
close(fs.ioctl_fd);
|
||||||
|
close(fs.sysfs_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bchfs_handle bcache_fs_open(const char *path)
|
||||||
|
{
|
||||||
|
struct bchfs_handle ret;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
char *minor = read_file_str(ret.sysfs_fd, "minor");
|
||||||
|
char *ctl = mprintf("/dev/bcachefs%s-ctl", minor);
|
||||||
|
ret.ioctl_fd = xopen(ctl, O_RDWR);
|
||||||
|
|
||||||
|
free(sysfs);
|
||||||
|
free(minor);
|
||||||
|
free(ctl);
|
||||||
|
} else {
|
||||||
|
/* It's a path: */
|
||||||
|
ret.ioctl_fd = xopen(path, O_RDONLY);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
char *sysfs = mprintf("%s%s", SYSFS_BASE, uuid_str);
|
||||||
|
ret.sysfs_fd = xopen(sysfs, O_RDONLY);
|
||||||
|
free(sysfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
100
libbcachefs.h
100
libbcachefs.h
@ -5,6 +5,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "libbcachefs/bcachefs_format.h"
|
#include "libbcachefs/bcachefs_format.h"
|
||||||
|
#include "libbcachefs/bcachefs_ioctl.h"
|
||||||
#include "tools-util.h"
|
#include "tools-util.h"
|
||||||
#include "libbcachefs/vstructs.h"
|
#include "libbcachefs/vstructs.h"
|
||||||
|
|
||||||
@ -76,4 +77,103 @@ struct bch_sb *__bch2_super_read(int, u64);
|
|||||||
|
|
||||||
void bch2_super_print(struct bch_sb *, int);
|
void bch2_super_print(struct bch_sb *, int);
|
||||||
|
|
||||||
|
/* ioctl interface: */
|
||||||
|
|
||||||
|
int bcachectl_open(void);
|
||||||
|
|
||||||
|
struct bchfs_handle {
|
||||||
|
uuid_le uuid;
|
||||||
|
int ioctl_fd;
|
||||||
|
int sysfs_fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
void bcache_fs_close(struct bchfs_handle);
|
||||||
|
struct bchfs_handle bcache_fs_open(const char *);
|
||||||
|
|
||||||
|
static inline void bchu_disk_add(struct bchfs_handle fs, char *dev)
|
||||||
|
{
|
||||||
|
struct bch_ioctl_disk i = { .dev = (__u64) dev, };
|
||||||
|
|
||||||
|
xioctl(fs.ioctl_fd, BCH_IOCTL_DISK_ADD, &i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bchu_disk_set_state(struct bchfs_handle fs, const char *dev,
|
||||||
|
unsigned new_state, unsigned flags)
|
||||||
|
{
|
||||||
|
struct bch_ioctl_disk_set_state i = {
|
||||||
|
.flags = flags,
|
||||||
|
.new_state = new_state,
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct bch_ioctl_usage *bchu_usage(struct bchfs_handle fs)
|
||||||
|
{
|
||||||
|
struct bch_ioctl_usage *u = NULL;
|
||||||
|
unsigned nr_devices = 4;
|
||||||
|
|
||||||
|
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))
|
||||||
|
return u;
|
||||||
|
|
||||||
|
if (errno != ENOSPC)
|
||||||
|
die("BCH_IOCTL_USAGE error: %m");
|
||||||
|
nr_devices *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct bch_sb *bchu_read_super(struct bchfs_handle fs, unsigned idx)
|
||||||
|
{
|
||||||
|
size_t size = 4096;
|
||||||
|
struct bch_sb *sb = NULL;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
sb = xrealloc(sb, size);
|
||||||
|
struct bch_ioctl_read_super i = {
|
||||||
|
.size = size,
|
||||||
|
.sb = (u64) sb,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (idx != -1) {
|
||||||
|
i.flags |= BCH_READ_DEV|BCH_BY_INDEX;
|
||||||
|
i.dev = idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ioctl(fs.ioctl_fd, BCH_IOCTL_READ_SUPER, &i))
|
||||||
|
return sb;
|
||||||
|
if (errno != ERANGE)
|
||||||
|
die("BCH_IOCTL_READ_SUPER error: %m");
|
||||||
|
size *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned bchu_disk_get_idx(struct bchfs_handle fs, dev_t dev)
|
||||||
|
{
|
||||||
|
struct bch_ioctl_disk_get_idx i = { .dev = dev };
|
||||||
|
|
||||||
|
return xioctl(fs.ioctl_fd, BCH_IOCTL_DISK_GET_IDX, &i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bchu_disk_resize(struct bchfs_handle fs,
|
||||||
|
unsigned idx,
|
||||||
|
u64 nbuckets)
|
||||||
|
{
|
||||||
|
struct bch_ioctl_disk_resize i = {
|
||||||
|
.flags = BCH_BY_INDEX,
|
||||||
|
.dev = idx,
|
||||||
|
.nbuckets = nbuckets,
|
||||||
|
};
|
||||||
|
|
||||||
|
xioctl(fs.ioctl_fd, BCH_IOCTL_DISK_RESIZE, &i);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _LIBBCACHE_H */
|
#endif /* _LIBBCACHE_H */
|
||||||
|
107
tools-util.c
107
tools-util.c
@ -262,58 +262,6 @@ int open_for_format(const char *dev, bool force)
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Global control device: */
|
|
||||||
int bcachectl_open(void)
|
|
||||||
{
|
|
||||||
return xopen("/dev/bcachefs-ctl", O_RDWR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Filesystem handles (ioctl, sysfs dir): */
|
|
||||||
|
|
||||||
#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;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
char *minor = read_file_str(ret.sysfs_fd, "minor");
|
|
||||||
char *ctl = mprintf("/dev/bcachefs%s-ctl", minor);
|
|
||||||
ret.ioctl_fd = xopen(ctl, O_RDWR);
|
|
||||||
|
|
||||||
free(sysfs);
|
|
||||||
free(minor);
|
|
||||||
free(ctl);
|
|
||||||
} else {
|
|
||||||
/* It's a path: */
|
|
||||||
ret.ioctl_fd = xopen(path, O_RDONLY);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
char *sysfs = mprintf("%s%s", SYSFS_BASE, uuid_str);
|
|
||||||
ret.sysfs_fd = xopen(sysfs, O_RDONLY);
|
|
||||||
free(sysfs);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ask_yn(void)
|
bool ask_yn(void)
|
||||||
{
|
{
|
||||||
const char *short_yes = "yY";
|
const char *short_yes = "yY";
|
||||||
@ -586,9 +534,9 @@ u32 crc32c(u32 crc, const void *buf, size_t size)
|
|||||||
|
|
||||||
#endif /* HAVE_WORKING_IFUNC */
|
#endif /* HAVE_WORKING_IFUNC */
|
||||||
|
|
||||||
char *dev_to_path(dev_t dev)
|
char *dev_to_name(dev_t dev)
|
||||||
{
|
{
|
||||||
char *line = NULL, *name = NULL, *path = NULL;
|
char *line = NULL, *name = NULL;
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
|
|
||||||
FILE *f = fopen("/proc/partitions", "r");
|
FILE *f = fopen("/proc/partitions", "r");
|
||||||
@ -602,17 +550,58 @@ char *dev_to_path(dev_t dev)
|
|||||||
name = realloc(name, n + 1);
|
name = realloc(name, n + 1);
|
||||||
|
|
||||||
if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
|
if (sscanf(line, " %u %u %llu %s", &ma, &mi, §ors, name) == 4 &&
|
||||||
ma == major(dev) && mi == minor(dev)) {
|
ma == major(dev) && mi == minor(dev))
|
||||||
path = mprintf("/dev/%s", name);
|
goto found;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(name);
|
||||||
|
name = NULL;
|
||||||
|
found:
|
||||||
fclose(f);
|
fclose(f);
|
||||||
free(line);
|
free(line);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *dev_to_path(dev_t dev)
|
||||||
|
{
|
||||||
|
char *name = dev_to_name(dev);
|
||||||
|
if (!name)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char *path = mprintf("/dev/%s", name);
|
||||||
|
|
||||||
free(name);
|
free(name);
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *dev_to_mount(char *dev)
|
||||||
|
{
|
||||||
|
char *line = NULL, *ret = NULL;
|
||||||
|
size_t n = 0;
|
||||||
|
|
||||||
|
FILE *f = fopen("/proc/mounts", "r");
|
||||||
|
if (!f)
|
||||||
|
die("error opening /proc/mounts: %m");
|
||||||
|
|
||||||
|
while (getline(&line, &n, f) != -1) {
|
||||||
|
char *d, *p = line;
|
||||||
|
char *devs = strsep(&p, " ");
|
||||||
|
char *mount = strsep(&p, " ");
|
||||||
|
|
||||||
|
if (!devs || !mount)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
p = devs;
|
||||||
|
while ((d = strsep(&p, ":")))
|
||||||
|
if (!strcmp(d, dev)) {
|
||||||
|
ret = strdup(mount);
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
found:
|
||||||
|
fclose(f);
|
||||||
|
free(line);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
22
tools-util.h
22
tools-util.h
@ -5,6 +5,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -39,10 +40,12 @@ struct stat xfstat(int);
|
|||||||
#define xopen(...) xopenat(AT_FDCWD, __VA_ARGS__)
|
#define xopen(...) xopenat(AT_FDCWD, __VA_ARGS__)
|
||||||
|
|
||||||
#define xioctl(_fd, _nr, ...) \
|
#define xioctl(_fd, _nr, ...) \
|
||||||
do { \
|
({ \
|
||||||
if (ioctl((_fd), (_nr), ##__VA_ARGS__)) \
|
int _ret = ioctl((_fd), (_nr), ##__VA_ARGS__); \
|
||||||
|
if (_ret < 0) \
|
||||||
die(#_nr " ioctl error: %m"); \
|
die(#_nr " ioctl error: %m"); \
|
||||||
} while (0)
|
_ret; \
|
||||||
|
})
|
||||||
|
|
||||||
enum units {
|
enum units {
|
||||||
BYTES,
|
BYTES,
|
||||||
@ -68,17 +71,6 @@ u64 get_size(const char *, int);
|
|||||||
unsigned get_blocksize(const char *, int);
|
unsigned get_blocksize(const char *, int);
|
||||||
int open_for_format(const char *, bool);
|
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);
|
bool ask_yn(void);
|
||||||
|
|
||||||
struct range {
|
struct range {
|
||||||
@ -155,6 +147,8 @@ unsigned hatoi_validate(const char *, const char *);
|
|||||||
|
|
||||||
u32 crc32c(u32, const void *, size_t);
|
u32 crc32c(u32, const void *, size_t);
|
||||||
|
|
||||||
|
char *dev_to_name(dev_t);
|
||||||
char *dev_to_path(dev_t);
|
char *dev_to_path(dev_t);
|
||||||
|
char *dev_to_mount(char *);
|
||||||
|
|
||||||
#endif /* _TOOLS_UTIL_H */
|
#endif /* _TOOLS_UTIL_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user