diff options
authorMisono, Tomohiro <>2017-10-23 13:45:48 +0900
committerDavid Sterba <>2017-11-14 15:59:00 +0100
commitb1dac5996bdfa0ba58ea2e545ce1f1af25b99a7d (patch)
parent94afa11d832901cd63766ec38b60752058722a7b (diff)
btrfs-progs: fi: enable fi usage for filesystem on top of seed device
Currently "fi usage" (and "dev usage") cannot run for the filesystem using the seed device. This is because FS_INFO ioctl returns the number of devices excluding seeds, but load_device_info() tries to access valid device from devid 0 to max_id, and results in accessing seeds too (thus causing mismatching number of devices). Since only the size of non-seed devices matters, fix this by just skipping seed device by checking device's fsid and comparing it to the fsid obtained by FS_INFO ioctl. Anand Jain: %fi_args.num_devices provides number of devices excluding the seed device. So when looping through the device list for a given fsid, determine if the given device is a seed device by reading its superblock and then skip it if its a seed device. Reading of the superblock is done by the function dev_to_fsid() which can fail if the user is not root OR if the device has media errors as well. So skip the seed check altogether if we fail to know the device superblock and thus the fsid. With this now we are able to view the btrfs fi usage when the device is bad. Signed-off-by: Anand Jain <> Signed-off-by: Tomohiro Misono <> Reviewed-by: Anand Jain <> Signed-off-by: David Sterba <>
1 files changed, 14 insertions, 0 deletions
diff --git a/cmds-fi-usage.c b/cmds-fi-usage.c
index a72fb4e3..83d0c589 100644
--- a/cmds-fi-usage.c
+++ b/cmds-fi-usage.c
@@ -545,6 +545,7 @@ static int load_device_info(int fd, struct device_info **device_info_ptr,
struct btrfs_ioctl_fs_info_args fi_args;
struct btrfs_ioctl_dev_info_args dev_info;
struct device_info *info;
+ u8 fsid[BTRFS_UUID_SIZE];
*device_info_count = 0;
*device_info_ptr = NULL;
@@ -568,6 +569,8 @@ static int load_device_info(int fd, struct device_info **device_info_ptr,
if (ndevs >= fi_args.num_devices) {
error("unexpected number of devices: %d >= %llu", ndevs,
(unsigned long long)fi_args.num_devices);
+ error(
+ "if seed device is used, try running this command as root");
goto out;
memset(&dev_info, 0, sizeof(dev_info));
@@ -580,6 +583,17 @@ static int load_device_info(int fd, struct device_info **device_info_ptr,
goto out;
+ /*
+ * Skip seed device by checking device's fsid (requires root).
+ * And we will skip only if dev_to_fsid is successful and dev
+ * is a seed device.
+ * Ignore any other error including -EACCES, which is seen when
+ * a non-root process calls dev_to_fsid(path)->open(path).
+ */
+ ret = dev_to_fsid((const char *)dev_info.path, fsid);
+ if (!ret && memcmp(fi_args.fsid, fsid, BTRFS_FSID_SIZE) != 0)
+ continue;
info[ndevs].devid = dev_info.devid;
if (!dev_info.path[0]) {
strcpy(info[ndevs].path, "missing");