summaryrefslogtreecommitdiff
path: root/libbcachefs.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs.c')
-rw-r--r--libbcachefs.c90
1 files changed, 88 insertions, 2 deletions
diff --git a/libbcachefs.c b/libbcachefs.c
index 238cca99..bdf2924f 100644
--- a/libbcachefs.c
+++ b/libbcachefs.c
@@ -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;
+}