summaryrefslogtreecommitdiff
path: root/utils.c
diff options
context:
space:
mode:
authorStefan Behrens <sbehrens@giantdisaster.de>2012-05-15 12:05:44 +0200
committerDavid Sterba <dsterba@suse.cz>2013-01-30 00:40:35 +0100
commit7a69dc4eecfd52841b11e0f9312f62d17e3479f5 (patch)
treebc833b0d2699568054fe6d3b352f255e6d35f069 /utils.c
parent46e3b8087b86ef555b13be6807c34c555171fc4a (diff)
Btrfs-progs: make two utility functions globally available
Two convenient utility functions that have so far been local to scrub are moved to utils.c. They will be used in the device stats code in a following commit. Signed-off-by: Stefan Behrens <sbehrens@giantdisaster.de>
Diffstat (limited to 'utils.c')
-rw-r--r--utils.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/utils.c b/utils.c
index 87051359..d92f3178 100644
--- a/utils.c
+++ b/utils.c
@@ -1302,3 +1302,70 @@ int open_file_or_dir(const char *fname)
}
return fd;
}
+
+int get_device_info(int fd, u64 devid,
+ struct btrfs_ioctl_dev_info_args *di_args)
+{
+ int ret;
+
+ di_args->devid = devid;
+ memset(&di_args->uuid, '\0', sizeof(di_args->uuid));
+
+ ret = ioctl(fd, BTRFS_IOC_DEV_INFO, di_args);
+ return ret ? -errno : 0;
+}
+
+int get_fs_info(int fd, char *path, struct btrfs_ioctl_fs_info_args *fi_args,
+ struct btrfs_ioctl_dev_info_args **di_ret)
+{
+ int ret = 0;
+ int ndevs = 0;
+ int i = 1;
+ struct btrfs_fs_devices *fs_devices_mnt = NULL;
+ struct btrfs_ioctl_dev_info_args *di_args;
+ char mp[BTRFS_PATH_NAME_MAX + 1];
+
+ memset(fi_args, 0, sizeof(*fi_args));
+
+ ret = ioctl(fd, BTRFS_IOC_FS_INFO, fi_args);
+ if (ret && (errno == EINVAL || errno == ENOTTY)) {
+ /* path is not a mounted btrfs. Try if it's a device */
+ ret = check_mounted_where(fd, path, mp, sizeof(mp),
+ &fs_devices_mnt);
+ if (!ret)
+ return -EINVAL;
+ if (ret < 0)
+ return ret;
+ fi_args->num_devices = 1;
+ fi_args->max_id = fs_devices_mnt->latest_devid;
+ i = fs_devices_mnt->latest_devid;
+ memcpy(fi_args->fsid, fs_devices_mnt->fsid, BTRFS_FSID_SIZE);
+ close(fd);
+ fd = open_file_or_dir(mp);
+ if (fd < 0)
+ return -errno;
+ } else if (ret) {
+ return -errno;
+ }
+
+ if (!fi_args->num_devices)
+ return 0;
+
+ di_args = *di_ret = malloc(fi_args->num_devices * sizeof(*di_args));
+ if (!di_args)
+ return -errno;
+
+ for (; i <= fi_args->max_id; ++i) {
+ BUG_ON(ndevs >= fi_args->num_devices);
+ ret = get_device_info(fd, i, &di_args[ndevs]);
+ if (ret == -ENODEV)
+ continue;
+ if (ret)
+ return ret;
+ ndevs++;
+ }
+
+ BUG_ON(ndevs == 0);
+
+ return 0;
+}