Anand Jain
2013-Nov-15 11:25 UTC
[PATCH v4 1/3] btrfs-progs: mechanism to fetch fsinfo from btrfs-control
need fsinfo from btrfs-control that is when mount path is not known. current method of going through each mount points isn''t efficient, and multiple subvol of a fsid could be mounted means extra logic to handle that. Further this will help to revamp check_mounted() (planned) check_mounted is heavily used in the btrfs-progs, it does full scan of all the disks in the system to confirm if a multi-disk btrfs is mounted it doesn''t scalable well with few hundreds luns, check_mounted for sure needs a revamp. using this it can be done easily. which is planned. This patch depends on the btrfs kernel patch btrfs: add framework to read fs info from btrfs-control Signed-off-by: Anand Jain <anand.jain@oracle.com> --- v5: edits commit message v4: bug fix and accepts Stefan suggested v3: accepts Josef suggested v2: commit reword ioctl.h | 19 ++++++++++++++++ utils.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ utils.h | 1 + 3 files changed, 95 insertions(+), 0 deletions(-) diff --git a/ioctl.h b/ioctl.h index d21413f..29575d8 100644 --- a/ioctl.h +++ b/ioctl.h @@ -506,6 +506,23 @@ static inline char *btrfs_err_str(enum btrfs_err_code err_code) } } +/* fs flags */ +#define BTRFS_FS_MOUNTED (1LLU << 0) + +struct btrfs_ioctl_fslist { + __u64 self_sz; /* in/out */ + __u8 fsid[BTRFS_FSID_SIZE]; /* out */ + __u64 num_devices; + __u64 missing_devices; + __u64 total_devices; + __u64 flags; +}; + +struct btrfs_ioctl_fslist_args { + __u64 self_sz; /* in/out */ + __u64 count; /* out */ +}; + #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ @@ -604,6 +621,8 @@ struct btrfs_ioctl_clone_range_args { struct btrfs_ioctl_dev_replace_args) #define BTRFS_IOC_DEDUP_CTL _IOWR(BTRFS_IOCTL_MAGIC, 55, \ struct btrfs_ioctl_dedup_args) +#define BTRFS_IOC_GET_FSLIST _IOWR(BTRFS_IOCTL_MAGIC, 56, \ + struct btrfs_ioctl_fslist_args) #ifdef __cplusplus } #endif diff --git a/utils.c b/utils.c index c1c55db..1ed7cde 100644 --- a/utils.c +++ b/utils.c @@ -47,6 +47,7 @@ #include "utils.h" #include "volumes.h" #include "ioctl.h" +#include "btrfs-list.h" #ifndef BLKDISCARD #define BLKDISCARD _IO(0x12,119) @@ -2111,3 +2112,77 @@ int lookup_ino_rootid(int fd, u64 *rootid) return 0; } + +/* scans for fsid(s) in the kernel using the btrfs-control + * interface. + */ +int get_fslist(struct btrfs_ioctl_fslist **out_fslist, u64 *out_count) +{ + int ret, fd, e; + struct btrfs_ioctl_fslist_args *fsargs; + struct btrfs_ioctl_fslist_args *fsargs_saved = NULL; + struct btrfs_ioctl_fslist *fslist; + u64 sz; + int count; + + fd = open("/dev/btrfs-control", O_RDWR); + e = errno; + if (fd < 0) { + perror("failed to open /dev/btrfs-control"); + return -e; + } + + /* space to hold 512 fsids, doesn''t matter if small + * it would fail and return count so then we try again + */ + count = 512; +again: + sz = sizeof(*fsargs) + sizeof(*fslist) * count; + + fsargs_saved = fsargs = malloc(sz); + if (!fsargs) { + close(fd); + return -ENOMEM; + } + + memset(fsargs, 0, sz); + fsargs->count = count; + + ret = ioctl(fd, BTRFS_IOC_GET_FSLIST, fsargs); + e = errno; + if (ret == 1) { + /* out of size so reallocate */ + count = fsargs->count; + free(fsargs); + goto again; + } else if (ret < 0) { + printf("ERROR: scan_fsid ioctl failed - %s\n", + strerror(e)); + ret = -e; + goto out; + } + + /* ioctl returns fsid count in count parameter*/ + + *out_count = fsargs->count; + if (*out_count == 0) { + *out_fslist = NULL; + ret = 0; + goto out; + } + + fslist = (struct btrfs_ioctl_fslist *) (++fsargs); + + sz = sizeof(*fslist) * *out_count; + *out_fslist = malloc(sz); + if (*out_fslist == NULL) { + ret = -ENOMEM; + goto out; + } + memcpy(*out_fslist, fslist, sz); + ret = 0; +out: + free(fsargs_saved); + close(fd); + return ret; +} diff --git a/utils.h b/utils.h index 512c51b..2fc230b 100644 --- a/utils.h +++ b/utils.h @@ -96,5 +96,6 @@ int ask_user(char *question); int lookup_ino_rootid(int fd, u64 *rootid); int btrfs_scan_lblkid(int update_kernel); int get_btrfs_mount(const char *dev, char *mp, size_t mp_size); +int get_fslist(struct btrfs_ioctl_fslist **out_fslist, u64 *out_count); #endif -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Anand Jain
2013-Nov-15 11:25 UTC
[PATCH v4 2/3] btrfs-progs: fs show should handle if subvol(s) mounted
as of now with out this patch user would see fsinfo per btrfs mount path but which mean multiple entry if more than one subvol is mounted of the same fsid. so this patch will handle that nicely. Signed-off-by: Anand Jain <anand.jain@oracle.com> --- v4: rebase on integration-20131114 v3: accepts Josef suggested v2: accepts Zach suggested cmds-filesystem.c | 90 +++++++++++++++++++++++++++++++++-------------------- utils.c | 60 +++++++++++++++++++++++++++++++++++ utils.h | 1 + 3 files changed, 117 insertions(+), 34 deletions(-) diff --git a/cmds-filesystem.c b/cmds-filesystem.c index c747193..b23d337 100644 --- a/cmds-filesystem.c +++ b/cmds-filesystem.c @@ -318,6 +318,29 @@ static int print_one_fs(struct btrfs_ioctl_fs_info_args *fs_info, return 0; } +static void handle_print(char *mnt, char *label) +{ + int fd; + struct btrfs_ioctl_fs_info_args fs_info_arg; + struct btrfs_ioctl_dev_info_args *dev_info_arg = NULL; + struct btrfs_ioctl_space_args *space_info_arg; + + if (get_fs_info(mnt, &fs_info_arg, &dev_info_arg)) { + fprintf(stdout, "ERROR: get_fs_info failed\n"); + return; + } + + fd = open(mnt, O_RDONLY); + if (fd != -1 && !get_df(fd, &space_info_arg)) { + print_one_fs(&fs_info_arg, dev_info_arg, + space_info_arg, label, mnt); + kfree(space_info_arg); + } + if (fd != -1) + close(fd); + kfree(dev_info_arg); +} + /* This function checks if the given input parameter is * an uuid or a path * return -1: some error in the given input @@ -352,47 +375,39 @@ static int check_arg_type(char *input) static int btrfs_scan_kernel(void *search) { - int ret = 0, fd; - FILE *f; - struct mntent *mnt; - struct btrfs_ioctl_fs_info_args fs_info_arg; - struct btrfs_ioctl_dev_info_args *dev_info_arg = NULL; - struct btrfs_ioctl_space_args *space_info_arg; + int ret = 0; char label[BTRFS_LABEL_SIZE]; - - f = setmntent("/proc/self/mounts", "r"); - if (f == NULL) - return 1; - - memset(label, 0, sizeof(label)); - while ((mnt = getmntent(f)) != NULL) { - if (strcmp(mnt->mnt_type, "btrfs")) + char mnt[BTRFS_PATH_NAME_MAX + 1]; + struct btrfs_ioctl_fslist *fslist; + struct btrfs_ioctl_fslist *fslist_saved; + u64 cnt_fs; + int cnt_mnt; + __u8 *fsid; + __u64 flags; + + ret = get_fslist(&fslist, &cnt_fs); + if (ret) + return ret; + fslist_saved = fslist; + while (cnt_fs--) { + fsid = fslist->fsid; + flags = fslist->flags; + fslist++; + if (!(flags & BTRFS_FS_MOUNTED)) continue; - ret = get_fs_info(mnt->mnt_dir, &fs_info_arg, - &dev_info_arg); + memset(mnt, 0, BTRFS_PATH_NAME_MAX + 1); + memset(label, 0, sizeof(label)); + ret = fsid_to_mntpt(fsid, mnt, &cnt_mnt); if (ret) return ret; - - if (get_label_mounted(mnt->mnt_dir, label)) { - kfree(dev_info_arg); + if (get_label_mounted(mnt, label)) return 1; - } - if (search && !match_search_item_kernel(fs_info_arg.fsid, - mnt->mnt_dir, label, search)) { - kfree(dev_info_arg); + + if (search && !match_search_item_kernel(fsid, + mnt, label, search)) continue; - } - fd = open(mnt->mnt_dir, O_RDONLY); - if ((fd != -1) && !get_df(fd, &space_info_arg)) { - print_one_fs(&fs_info_arg, dev_info_arg, - space_info_arg, label, mnt->mnt_dir); - kfree(space_info_arg); - memset(label, 0, sizeof(label)); - } - if (fd != -1) - close(fd); - kfree(dev_info_arg); + handle_print(mnt, label); if (search) return 0; } @@ -470,7 +485,14 @@ static int cmd_show(int argc, char **argv) else goto devs_only; } + } else if (type == BTRFS_ARG_MNTPOINT) { + char label[BTRFS_LABEL_SIZE]; + if (get_label_mounted(search, label)) + return 1; + handle_print(search, label); + return 0; } + } if (where == BTRFS_SCAN_DEV) diff --git a/utils.c b/utils.c index 1ed7cde..ddbd623 100644 --- a/utils.c +++ b/utils.c @@ -2186,3 +2186,63 @@ out: close(fd); return ret; } + +/* This finds the mount point for a given fsid, + * subvols of the same fs/fsid can be mounted + * so here this picks and lowest subvol id + * and returns the mount point +*/ +int fsid_to_mntpt(__u8 *fsid, char *mntpt, int *mnt_cnt) +{ + int fd = -1, ret = 0; + DIR *dirstream = NULL; + FILE *f; + struct btrfs_ioctl_fs_info_args fi_args; + u64 svid, saved_svid = (u64)-1; + struct mntent *mnt; + int mcnt = 0; + + *mnt_cnt = 0; + f = setmntent("/proc/self/mounts", "r"); + if (f == NULL) + return 1; + + while ((mnt = getmntent(f)) != NULL) { + if (strcmp(mnt->mnt_type, "btrfs")) + continue; + fd = open_file_or_dir(mnt->mnt_dir, &dirstream); + if (fd < 0) { + ret = -errno; + return ret; + } + ret = ioctl(fd, BTRFS_IOC_FS_INFO, &fi_args); + if (ret < 0) { + ret = -errno; + close_file_or_dir(fd, dirstream); + break; + } + if (uuid_compare(fsid, fi_args.fsid)) { + close_file_or_dir(fd, dirstream); + continue; + } + + /* found */ + mcnt++; + ret = btrfs_list_get_path_rootid(fd, &svid); + if (ret) { + /* error so just copy and return*/ + strcpy(mntpt, mnt->mnt_dir); + close_file_or_dir(fd, dirstream); + break; + } + if (svid < saved_svid) { + strcpy(mntpt, mnt->mnt_dir); + saved_svid = svid; + } + } + endmntent(f); + if (mcnt) + *mnt_cnt = mcnt; + + return ret; +} diff --git a/utils.h b/utils.h index 2fc230b..00f1c18 100644 --- a/utils.h +++ b/utils.h @@ -97,5 +97,6 @@ int lookup_ino_rootid(int fd, u64 *rootid); int btrfs_scan_lblkid(int update_kernel); int get_btrfs_mount(const char *dev, char *mp, size_t mp_size); int get_fslist(struct btrfs_ioctl_fslist **out_fslist, u64 *out_count); +int fsid_to_mntpt(__u8 *fsid, char *mntpt, int *mnt_cnt); #endif -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Anand Jain
2013-Nov-15 11:25 UTC
[PATCH v4 3/3] btrfs-progs: lblkid wouldn''t find non mapper path input
A new test case when disk is unmounted and if the non mapper disk path is given as the argument to the btrfs filesystem show <arg> we still need this to work but lblkid will pull only mapper disks, it won''t match. So this will normalize the input to find btrfs by fsid and pass it to the search. Signed-off-by: Anand Jain <anand.jain@oracle.com> --- v4: rebased on integration-20131114 v3: accepts Josef suggested again v2: accepts Josef suggested cmds-filesystem.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 55 insertions(+), 2 deletions(-) diff --git a/cmds-filesystem.c b/cmds-filesystem.c index b23d337..c98425f 100644 --- a/cmds-filesystem.c +++ b/cmds-filesystem.c @@ -37,6 +37,7 @@ #include "version.h" #include "commands.h" #include "list_sort.h" +#include "disk-io.h" static const char * const filesystem_cmd_group_usage[] = { "btrfs filesystem [<group>] <command> [<args>]", @@ -416,6 +417,39 @@ static int btrfs_scan_kernel(void *search) return 0; } +static int dev_to_fsid(char *dev, __u8 *fsid) +{ + struct btrfs_super_block *disk_super; + char *buf; + int ret; + int fd; + + buf = malloc(4096); + if (!buf) + return -ENOMEM; + + fd = open(dev, O_RDONLY); + if (fd < 0) { + ret = -errno; + free(buf); + return ret; + } + + disk_super = (struct btrfs_super_block *)buf; + ret = btrfs_read_dev_super(fd, disk_super, + BTRFS_SUPER_INFO_OFFSET); + if (ret) + goto out; + + memcpy(fsid, disk_super->fsid, BTRFS_FSID_SIZE); + ret = 0; + +out: + close(fd); + free(buf); + return ret; +} + static const char * const cmd_show_usage[] = { "btrfs filesystem show [options] [<path>|<uuid>|<device>|label]", "Show the structure of a filesystem", @@ -436,6 +470,8 @@ static int cmd_show(int argc, char **argv) int type = 0; char mp[BTRFS_PATH_NAME_MAX + 1]; char path[PATH_MAX]; + __u8 fsid[BTRFS_FSID_SIZE]; + char uuid_buf[37]; while (1) { int long_index; @@ -468,6 +504,11 @@ static int cmd_show(int argc, char **argv) if (strlen(search) == 0) usage(cmd_show_usage); type = check_arg_type(search); + /* + * needs spl handling if input arg is block dev + * And if input arg is mount-point just print it + * right away + */ if (type == BTRFS_ARG_BLKDEV) { if (where == BTRFS_SCAN_DEV) { /* we need to do this because @@ -479,11 +520,23 @@ static int cmd_show(int argc, char **argv) } else { ret = get_btrfs_mount(search, mp, sizeof(mp)); - if (!ret) + if (!ret) { /* given block dev is mounted*/ search = mp; - else + type = BTRFS_ARG_MNTPOINT; + } else { + ret = dev_to_fsid(search, fsid); + if (ret) { + fprintf(stderr, + "ERROR: No btrfs on %s\n", + search); + return 1; + } + uuid_unparse(fsid, uuid_buf); + search = uuid_buf; + type = BTRFS_ARG_UUID; goto devs_only; + } } } else if (type == BTRFS_ARG_MNTPOINT) { char label[BTRFS_LABEL_SIZE]; -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
David Sterba
2013-Nov-15 15:07 UTC
Re: [PATCH v4 1/3] btrfs-progs: mechanism to fetch fsinfo from btrfs-control
On Fri, Nov 15, 2013 at 07:25:33PM +0800, Anand Jain wrote:> need fsinfo from btrfs-control that is when mount path is > not known. > current method of going through each mount points isn''t > efficient, and multiple subvol of a fsid could be mounted > means extra logic to handle that. Further this will help > to revamp check_mounted() (planned) > > check_mounted is heavily used in the btrfs-progs, it > does full scan of all the disks in the system to confirm > if a multi-disk btrfs is mounted it doesn''t scalable well > with few hundreds luns, check_mounted for sure needs a > revamp. using this it can be done easily. which is planned. > > This patch depends on the btrfs kernel patch > btrfs: add framework to read fs info from btrfs-control > > Signed-off-by: Anand Jain <anand.jain@oracle.com>Added patches 1-3 to integration-next due to pending kernel support (like dedup and properties). -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
David Sterba
2013-Nov-20 14:18 UTC
Re: [PATCH v4 2/3] btrfs-progs: fs show should handle if subvol(s) mounted
On Fri, Nov 15, 2013 at 07:25:34PM +0800, Anand Jain wrote:> static int btrfs_scan_kernel(void *search) > { > - int ret = 0, fd; > - FILE *f; > - struct mntent *mnt; > - struct btrfs_ioctl_fs_info_args fs_info_arg; > - struct btrfs_ioctl_dev_info_args *dev_info_arg = NULL; > - struct btrfs_ioctl_space_args *space_info_arg; > + int ret = 0; > char label[BTRFS_LABEL_SIZE]; > - > - f = setmntent("/proc/self/mounts", "r"); > - if (f == NULL) > - return 1; > - > - memset(label, 0, sizeof(label)); > - while ((mnt = getmntent(f)) != NULL) { > - if (strcmp(mnt->mnt_type, "btrfs")) > + char mnt[BTRFS_PATH_NAME_MAX + 1]; > + struct btrfs_ioctl_fslist *fslist; > + struct btrfs_ioctl_fslist *fslist_saved;[CC] cmds-send.o cmds-filesystem.c: In function ‘btrfs_scan_kernel’: cmds-filesystem.c:461:29: warning: variable ‘fslist_saved’ set but not used [-Wunused-but-set-variable]> + u64 cnt_fs; > + int cnt_mnt; > + __u8 *fsid; > + __u64 flags; > + > + ret = get_fslist(&fslist, &cnt_fs); > + if (ret) > + return ret; > + fslist_saved = fslist; > + while (cnt_fs--) { > + fsid = fslist->fsid; > + flags = fslist->flags; > + fslist++; > + if (!(flags & BTRFS_FS_MOUNTED)) > continue; > - ret = get_fs_info(mnt->mnt_dir, &fs_info_arg, > - &dev_info_arg); > + memset(mnt, 0, BTRFS_PATH_NAME_MAX + 1); > + memset(label, 0, sizeof(label)); > + ret = fsid_to_mntpt(fsid, mnt, &cnt_mnt); > if (ret) > return ret; > - > - if (get_label_mounted(mnt->mnt_dir, label)) { > - kfree(dev_info_arg); > + if (get_label_mounted(mnt, label)) > return 1; > - } > - if (search && !match_search_item_kernel(fs_info_arg.fsid, > - mnt->mnt_dir, label, search)) { > - kfree(dev_info_arg); > + > + if (search && !match_search_item_kernel(fsid, > + mnt, label, search)) > continue; > - } > > - fd = open(mnt->mnt_dir, O_RDONLY); > - if ((fd != -1) && !get_df(fd, &space_info_arg)) { > - print_one_fs(&fs_info_arg, dev_info_arg, > - space_info_arg, label, mnt->mnt_dir); > - kfree(space_info_arg); > - memset(label, 0, sizeof(label)); > - } > - if (fd != -1) > - close(fd); > - kfree(dev_info_arg); > + handle_print(mnt, label); > if (search) > return 0; > }-- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Anand Jain
2013-Nov-21 03:28 UTC
[PATCH v5 2/3] btrfs-progs: fs show should handle if subvol(s) mounted
as of now with out this patch user would see fsinfo per btrfs mount path but which mean multiple entry if more than one subvol is mounted of the same fsid. so this patch will handle that nicely. Signed-off-by: Anand Jain <anand.jain@oracle.com> --- v5: fixup missed mem free, thanks David v4: rebase on integration-20131114 v3: accepts Josef suggested v2: accepts Zach suggested cmds-filesystem.c | 104 +++++++++++++++++++++++++++++++++------------------- utils.c | 60 ++++++++++++++++++++++++++++++ utils.h | 1 + 3 files changed, 127 insertions(+), 38 deletions(-) diff --git a/cmds-filesystem.c b/cmds-filesystem.c index c747193..bb827e1 100644 --- a/cmds-filesystem.c +++ b/cmds-filesystem.c @@ -318,6 +318,29 @@ static int print_one_fs(struct btrfs_ioctl_fs_info_args *fs_info, return 0; } +static void handle_print(char *mnt, char *label) +{ + int fd; + struct btrfs_ioctl_fs_info_args fs_info_arg; + struct btrfs_ioctl_dev_info_args *dev_info_arg = NULL; + struct btrfs_ioctl_space_args *space_info_arg; + + if (get_fs_info(mnt, &fs_info_arg, &dev_info_arg)) { + fprintf(stdout, "ERROR: get_fs_info failed\n"); + return; + } + + fd = open(mnt, O_RDONLY); + if (fd != -1 && !get_df(fd, &space_info_arg)) { + print_one_fs(&fs_info_arg, dev_info_arg, + space_info_arg, label, mnt); + kfree(space_info_arg); + } + if (fd != -1) + close(fd); + kfree(dev_info_arg); +} + /* This function checks if the given input parameter is * an uuid or a path * return -1: some error in the given input @@ -352,53 +375,52 @@ static int check_arg_type(char *input) static int btrfs_scan_kernel(void *search) { - int ret = 0, fd; - FILE *f; - struct mntent *mnt; - struct btrfs_ioctl_fs_info_args fs_info_arg; - struct btrfs_ioctl_dev_info_args *dev_info_arg = NULL; - struct btrfs_ioctl_space_args *space_info_arg; + int ret = 0; char label[BTRFS_LABEL_SIZE]; - - f = setmntent("/proc/self/mounts", "r"); - if (f == NULL) - return 1; - - memset(label, 0, sizeof(label)); - while ((mnt = getmntent(f)) != NULL) { - if (strcmp(mnt->mnt_type, "btrfs")) + char mnt[BTRFS_PATH_NAME_MAX + 1]; + struct btrfs_ioctl_fslist *fslist; + struct btrfs_ioctl_fslist *fslist_saved; + u64 cnt_fs; + int cnt_mnt; + __u8 *fsid; + __u64 flags; + int found = 0; + + ret = get_fslist(&fslist, &cnt_fs); + if (ret) + return ret; + fslist_saved = fslist; + while (cnt_fs--) { + fsid = fslist->fsid; + flags = fslist->flags; + fslist++; + if (!(flags & BTRFS_FS_MOUNTED)) continue; - ret = get_fs_info(mnt->mnt_dir, &fs_info_arg, - &dev_info_arg); + memset(mnt, 0, BTRFS_PATH_NAME_MAX + 1); + memset(label, 0, sizeof(label)); + ret = fsid_to_mntpt(fsid, mnt, &cnt_mnt); if (ret) - return ret; - - if (get_label_mounted(mnt->mnt_dir, label)) { - kfree(dev_info_arg); - return 1; + break; + if (get_label_mounted(mnt, label)) { + ret = 1; + break; } - if (search && !match_search_item_kernel(fs_info_arg.fsid, - mnt->mnt_dir, label, search)) { - kfree(dev_info_arg); + + if (search && !match_search_item_kernel(fsid, + mnt, label, search)) continue; - } - fd = open(mnt->mnt_dir, O_RDONLY); - if ((fd != -1) && !get_df(fd, &space_info_arg)) { - print_one_fs(&fs_info_arg, dev_info_arg, - space_info_arg, label, mnt->mnt_dir); - kfree(space_info_arg); - memset(label, 0, sizeof(label)); + handle_print(mnt, label); + if (search) { + found = 1; + break; } - if (fd != -1) - close(fd); - kfree(dev_info_arg); - if (search) - return 0; } - if (search) + if (fslist_saved) + kfree(fslist_saved); + if (search && !found) return 1; - return 0; + return ret; } static const char * const cmd_show_usage[] = { @@ -470,6 +492,12 @@ static int cmd_show(int argc, char **argv) else goto devs_only; } + } else if (type == BTRFS_ARG_MNTPOINT) { + char label[BTRFS_LABEL_SIZE]; + if (get_label_mounted(search, label)) + return 1; + handle_print(search, label); + return 0; } } diff --git a/utils.c b/utils.c index 1ed7cde..ddbd623 100644 --- a/utils.c +++ b/utils.c @@ -2186,3 +2186,63 @@ out: close(fd); return ret; } + +/* This finds the mount point for a given fsid, + * subvols of the same fs/fsid can be mounted + * so here this picks and lowest subvol id + * and returns the mount point +*/ +int fsid_to_mntpt(__u8 *fsid, char *mntpt, int *mnt_cnt) +{ + int fd = -1, ret = 0; + DIR *dirstream = NULL; + FILE *f; + struct btrfs_ioctl_fs_info_args fi_args; + u64 svid, saved_svid = (u64)-1; + struct mntent *mnt; + int mcnt = 0; + + *mnt_cnt = 0; + f = setmntent("/proc/self/mounts", "r"); + if (f == NULL) + return 1; + + while ((mnt = getmntent(f)) != NULL) { + if (strcmp(mnt->mnt_type, "btrfs")) + continue; + fd = open_file_or_dir(mnt->mnt_dir, &dirstream); + if (fd < 0) { + ret = -errno; + return ret; + } + ret = ioctl(fd, BTRFS_IOC_FS_INFO, &fi_args); + if (ret < 0) { + ret = -errno; + close_file_or_dir(fd, dirstream); + break; + } + if (uuid_compare(fsid, fi_args.fsid)) { + close_file_or_dir(fd, dirstream); + continue; + } + + /* found */ + mcnt++; + ret = btrfs_list_get_path_rootid(fd, &svid); + if (ret) { + /* error so just copy and return*/ + strcpy(mntpt, mnt->mnt_dir); + close_file_or_dir(fd, dirstream); + break; + } + if (svid < saved_svid) { + strcpy(mntpt, mnt->mnt_dir); + saved_svid = svid; + } + } + endmntent(f); + if (mcnt) + *mnt_cnt = mcnt; + + return ret; +} diff --git a/utils.h b/utils.h index 2fc230b..00f1c18 100644 --- a/utils.h +++ b/utils.h @@ -97,5 +97,6 @@ int lookup_ino_rootid(int fd, u64 *rootid); int btrfs_scan_lblkid(int update_kernel); int get_btrfs_mount(const char *dev, char *mp, size_t mp_size); int get_fslist(struct btrfs_ioctl_fslist **out_fslist, u64 *out_count); +int fsid_to_mntpt(__u8 *fsid, char *mntpt, int *mnt_cnt); #endif -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Anand Jain
2013-Nov-21 03:32 UTC
Re: [PATCH v4 2/3] btrfs-progs: fs show should handle if subvol(s) mounted
On 11/20/2013 10:18 PM, David Sterba wrote:> On Fri, Nov 15, 2013 at 07:25:34PM +0800, Anand Jain wrote: >> static int btrfs_scan_kernel(void *search) >> { >> - int ret = 0, fd; >> - FILE *f; >> - struct mntent *mnt; >> - struct btrfs_ioctl_fs_info_args fs_info_arg; >> - struct btrfs_ioctl_dev_info_args *dev_info_arg = NULL; >> - struct btrfs_ioctl_space_args *space_info_arg; >> + int ret = 0; >> char label[BTRFS_LABEL_SIZE]; >> - >> - f = setmntent("/proc/self/mounts", "r"); >> - if (f == NULL) >> - return 1; >> - >> - memset(label, 0, sizeof(label)); >> - while ((mnt = getmntent(f)) != NULL) { >> - if (strcmp(mnt->mnt_type, "btrfs")) >> + char mnt[BTRFS_PATH_NAME_MAX + 1]; >> + struct btrfs_ioctl_fslist *fslist; >> + struct btrfs_ioctl_fslist *fslist_saved; > > [CC] cmds-send.o > cmds-filesystem.c: In function ‘btrfs_scan_kernel’: > cmds-filesystem.c:461:29: warning: variable ‘fslist_saved’ set but not used [-Wunused-but-set-variable]Thanks David. That was something for later todo which I missed. sorry my mistake. Sent out v5.>> + u64 cnt_fs; >> + int cnt_mnt; >> + __u8 *fsid; >> + __u64 flags; >> + >> + ret = get_fslist(&fslist, &cnt_fs); >> + if (ret) >> + return ret; >> + fslist_saved = fslist; >> + while (cnt_fs--) { >> + fsid = fslist->fsid; >> + flags = fslist->flags; >> + fslist++; >> + if (!(flags & BTRFS_FS_MOUNTED)) >> continue; >> - ret = get_fs_info(mnt->mnt_dir, &fs_info_arg, >> - &dev_info_arg); >> + memset(mnt, 0, BTRFS_PATH_NAME_MAX + 1); >> + memset(label, 0, sizeof(label)); >> + ret = fsid_to_mntpt(fsid, mnt, &cnt_mnt); >> if (ret) >> return ret; >> - >> - if (get_label_mounted(mnt->mnt_dir, label)) { >> - kfree(dev_info_arg); >> + if (get_label_mounted(mnt, label)) >> return 1; >> - } >> - if (search && !match_search_item_kernel(fs_info_arg.fsid, >> - mnt->mnt_dir, label, search)) { >> - kfree(dev_info_arg); >> + >> + if (search && !match_search_item_kernel(fsid, >> + mnt, label, search)) >> continue; >> - } >> >> - fd = open(mnt->mnt_dir, O_RDONLY); >> - if ((fd != -1) && !get_df(fd, &space_info_arg)) { >> - print_one_fs(&fs_info_arg, dev_info_arg, >> - space_info_arg, label, mnt->mnt_dir); >> - kfree(space_info_arg); >> - memset(label, 0, sizeof(label)); >> - } >> - if (fd != -1) >> - close(fd); >> - kfree(dev_info_arg); >> + handle_print(mnt, label); >> if (search) >> return 0; >> } > -- > To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html >-- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
David Sterba
2013-Nov-22 07:56 UTC
Re: [PATCH v4 2/3] btrfs-progs: fs show should handle if subvol(s) mounted
On Thu, Nov 21, 2013 at 11:32:36AM +0800, Anand Jain wrote:> On 11/20/2013 10:18 PM, David Sterba wrote: > >On Fri, Nov 15, 2013 at 07:25:34PM +0800, Anand Jain wrote: > >> static int btrfs_scan_kernel(void *search) > >> { > >>- int ret = 0, fd; > >>- FILE *f; > >>- struct mntent *mnt; > >>- struct btrfs_ioctl_fs_info_args fs_info_arg; > >>- struct btrfs_ioctl_dev_info_args *dev_info_arg = NULL; > >>- struct btrfs_ioctl_space_args *space_info_arg; > >>+ int ret = 0; > >> char label[BTRFS_LABEL_SIZE]; > >>- > >>- f = setmntent("/proc/self/mounts", "r"); > >>- if (f == NULL) > >>- return 1; > >>- > >>- memset(label, 0, sizeof(label)); > >>- while ((mnt = getmntent(f)) != NULL) { > >>- if (strcmp(mnt->mnt_type, "btrfs")) > >>+ char mnt[BTRFS_PATH_NAME_MAX + 1]; > >>+ struct btrfs_ioctl_fslist *fslist; > >>+ struct btrfs_ioctl_fslist *fslist_saved; > > > > [CC] cmds-send.o > >cmds-filesystem.c: In function ‘btrfs_scan_kernel’: > >cmds-filesystem.c:461:29: warning: variable ‘fslist_saved’ set but not used [-Wunused-but-set-variable] > > Thanks David. That was something for later todo which I missed. > sorry my mistake. Sent out v5.Thanks, patch replaced. -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html