Anand Jain
2013-Nov-04 03:45 UTC
[PATCH 1/4] btrfs-progs: make filesystem show by label work
with design revamp around filesystem show the fsid filter by label wasn''t planned. but apparently that seemed to be necessary. this patch will fix it. Signed-off-by: Anand Jain <anand.jain@oracle.com> --- cmds-filesystem.c | 120 ++++++++++++++++++++++++++++++++--------------------- 1 files changed, 73 insertions(+), 47 deletions(-) diff --git a/cmds-filesystem.c b/cmds-filesystem.c index d08007e..d2cad81 100644 --- a/cmds-filesystem.c +++ b/cmds-filesystem.c @@ -179,6 +179,26 @@ static int cmd_df(int argc, char **argv) return !!ret; } +static int match_search_item_kernel(__u8 *fsid, char *mnt, char *label, + char *search) +{ + char uuidbuf[37]; + int search_len = strlen(search); + + search_len = min(search_len, 37); + uuid_unparse(fsid, uuidbuf); + if (!strncmp(uuidbuf, search, search_len)) + return 1; + + if (strlen(label) && strcmp(label, search) == 0) + return 1; + + if (strcmp(mnt, search) == 0) + return 1; + + return 0; +} + static int uuid_search(struct btrfs_fs_devices *fs_devices, char *search) { char uuidbuf[37]; @@ -275,16 +295,18 @@ static int print_one_fs(struct btrfs_ioctl_fs_info_args *fs_info, struct btrfs_ioctl_dev_info_args *tmp_dev_info; uuid_unparse(fs_info->fsid, uuidbuf); - printf("Label: %s uuid: %s\n", - strlen(label) ? label : "none", uuidbuf); + if (label && strlen(label)) + printf("Label: ''%s'' ", label); + else + printf("Label: none "); - printf("\tTotal devices %llu FS bytes used %s\n", - fs_info->num_devices, + printf(" uuid: %s\n\tTotal devices %llu FS bytes used %s\n", uuidbuf, + fs_info->num_devices, pretty_size(calc_used_bytes(space_info))); for (i = 0; i < fs_info->num_devices; i++) { tmp_dev_info = (struct btrfs_ioctl_dev_info_args *)&dev_info[i]; - printf("\tdevid %llu size %s used %s path %s\n", + printf("\tdevid %4llu size %s used %s path %s\n", tmp_dev_info->devid, pretty_size(tmp_dev_info->total_bytes), pretty_size(tmp_dev_info->bytes_used), @@ -308,7 +330,7 @@ static int check_arg_type(char *input) char path[PATH_MAX]; if (!input) - return BTRFS_ARG_UNKNOWN; + return -EINVAL; if (realpath(input, path)) { if (is_block_device(input) == 1) @@ -320,7 +342,7 @@ static int check_arg_type(char *input) return BTRFS_ARG_UNKNOWN; } - if (!uuid_parse(input, out)) + if (strlen(input) == 36 && !uuid_parse(input, out)) return BTRFS_ARG_UUID; return BTRFS_ARG_UNKNOWN; @@ -328,23 +350,19 @@ static int check_arg_type(char *input) static int btrfs_scan_kernel(void *search) { - int ret = 0, fd, type; + 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; char label[BTRFS_LABEL_SIZE]; - uuid_t uuid; f = setmntent("/proc/self/mounts", "r"); if (f == NULL) return 1; - type = check_arg_type(search); - if (type == BTRFS_ARG_BLKDEV) - return 1; - + memset(label, 0, sizeof(label)); while ((mnt = getmntent(f)) != NULL) { if (strcmp(mnt->mnt_type, "btrfs")) continue; @@ -353,38 +371,36 @@ static int btrfs_scan_kernel(void *search) if (ret) return ret; - switch (type) { - case BTRFS_ARG_UUID: - ret = uuid_parse(search, uuid); - if (ret) - return 1; - if (uuid_compare(fs_info_arg.fsid, uuid)) - continue; - break; - case BTRFS_ARG_MNTPOINT: - if (strcmp(search, mnt->mnt_dir)) - continue; - break; - case BTRFS_ARG_UNKNOWN: - break; + if (get_label_mounted(mnt->mnt_dir, label)) { + kfree(dev_info_arg); + return 1; + } + if (search && !match_search_item_kernel(fs_info_arg.fsid, + mnt->mnt_dir, label, search)) { + kfree(dev_info_arg); + continue; } fd = open(mnt->mnt_dir, O_RDONLY); if (fd > 0 && !get_df(fd, &space_info_arg)) { - get_label_mounted(mnt->mnt_dir, label); print_one_fs(&fs_info_arg, dev_info_arg, space_info_arg, label, mnt->mnt_dir); - free(space_info_arg); + kfree(space_info_arg); + memset(label, 0, sizeof(label)); } if (fd > 0) close(fd); - free(dev_info_arg); + kfree(dev_info_arg); + if (search) + return 0; } - return ret; + if (search) + return 1; + return 0; } static const char * const cmd_show_usage[] = { - "btrfs filesystem show [options] [<path>|<uuid>|<device>]", + "btrfs filesystem show [options] [<path>|<uuid>|<device>|label]", "Show the structure of a filesystem", "-d|--all-devices show only disks under /dev containing btrfs filesystem", "-m|--mounted show only mounted btrfs", @@ -402,6 +418,7 @@ static int cmd_show(int argc, char **argv) int where = BTRFS_SCAN_LBLKID; int type = 0; char mp[BTRFS_PATH_NAME_MAX + 1]; + char path[PATH_MAX]; while (1) { int long_index; @@ -426,24 +443,31 @@ static int cmd_show(int argc, char **argv) } } - if (where == BTRFS_SCAN_LBLKID) { - if (check_argc_max(argc, optind + 1)) - usage(cmd_show_usage); - } else { - if (check_argc_max(argc, optind)) - usage(cmd_show_usage); - } + if (check_argc_max(argc, optind + 1)) + usage(cmd_show_usage); + if (argc > optind) { search = argv[optind]; - type = check_arg_type(search); - if (type == BTRFS_ARG_UNKNOWN) { - fprintf(stderr, "ERROR: arg type unknown\n"); + if (strlen(search) == 0) usage(cmd_show_usage); - } + type = check_arg_type(search); if (type == BTRFS_ARG_BLKDEV) { - ret = get_btrfs_mount(search, mp, sizeof(mp)); - if (ret == 0) - search = mp; + if (where == BTRFS_SCAN_DEV) { + /* we need to do this because + * legacy BTRFS_SCAN_DEV + * provides /dev/dm-x paths + */ + if (realpath(search, path)) + search = path; + } else { + ret = get_btrfs_mount(search, + mp, sizeof(mp)); + if (!ret) + /* given block dev is mounted*/ + search = mp; + else + goto devs_only; + } } } @@ -451,7 +475,9 @@ static int cmd_show(int argc, char **argv) goto devs_only; /* show mounted btrfs */ - btrfs_scan_kernel(search); + ret = btrfs_scan_kernel(search); + if (search && !ret) + return 0; /* shows mounted only */ if (where == BTRFS_SCAN_MOUNTED) -- 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-04 03:45 UTC
[PATCH 2/4 v2] 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. v2: commit reword Signed-off-by: Anand Jain <anand.jain@oracle.com> --- ioctl.h | 19 +++++++++++++++ utils.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ utils.h | 1 + 3 files changed, 100 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 5bedd97..1798a7c 100644 --- a/utils.c +++ b/utils.c @@ -2087,3 +2087,83 @@ 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, int *out_count) +{ + int ret, fd, e; + struct btrfs_ioctl_fslist_args *fsargs; + struct btrfs_ioctl_fslist *fslist; + struct btrfs_ioctl_fslist *fslist_tmp; + 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 = (struct btrfs_ioctl_fslist_args *) malloc(sz); + memset(fsargs, 0, sz); + + if (!fsargs) { + close(fd); + return -ENOMEM; + } + 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 = count = fsargs->count; + if (count == 0) { + *out_fslist = NULL; + ret = 0; + goto out; + } + + fslist = (struct btrfs_ioctl_fslist *) (fsargs + + sizeof(*fsargs)); + + fslist_tmp = *out_fslist = (struct btrfs_ioctl_fslist *) + malloc(sizeof(*fslist) * count); + if (!fslist_tmp) { + ret = -ENOMEM; + goto out; + } + + while (count--) { + memcpy(fslist_tmp, fslist, sizeof(*fslist)); + fslist_tmp = fslist_tmp + sizeof(*fslist_tmp); + fslist = fslist + sizeof(*fslist); + } + ret = 0; +out: + free(fsargs); + close(fd); + return 0; +} diff --git a/utils.h b/utils.h index 6f4b10c..e20ad74 100644 --- a/utils.h +++ b/utils.h @@ -94,5 +94,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, int *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-04 03:45 UTC
[PATCH 3/4 v2] 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. v2: accepts Zach suggested Signed-off-by: Anand Jain <anand.jain@oracle.com> --- cmds-filesystem.c | 90 +++++++++++++++++++++++++++++++++-------------------- utils.c | 88 ++++++++++++++++++++++++++++++++++++++++++--------- utils.h | 3 +- 3 files changed, 130 insertions(+), 51 deletions(-) diff --git a/cmds-filesystem.c b/cmds-filesystem.c index d2cad81..f8e8475 100644 --- a/cmds-filesystem.c +++ b/cmds-filesystem.c @@ -317,6 +317,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 > 0 && !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 > 0) + 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 @@ -350,47 +373,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 > 0 && !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 > 0) - close(fd); - kfree(dev_info_arg); + handle_print(mnt, label); if (search) return 0; } @@ -469,6 +484,13 @@ static int cmd_show(int argc, char **argv) goto devs_only; } } + 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 1798a7c..d466ffa 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) @@ -2091,12 +2092,12 @@ int lookup_ino_rootid(int fd, u64 *rootid) /* scans for fsid(s) in the kernel using the btrfs-control * interface. */ -int get_fslist(struct btrfs_ioctl_fslist **out_fslist, int *out_count) +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; - struct btrfs_ioctl_fslist *fslist_tmp; u64 sz; int count; @@ -2139,31 +2140,86 @@ again: /* ioctl returns fsid count in count parameter*/ - *out_count = count = fsargs->count; - if (count == 0) { + *out_count = fsargs->count; + if (*out_count == 0) { *out_fslist = NULL; ret = 0; goto out; } - fslist = (struct btrfs_ioctl_fslist *) (fsargs + - sizeof(*fsargs)); + fsargs_saved = fsargs; + fslist = (struct btrfs_ioctl_fslist *) (++fsargs); - fslist_tmp = *out_fslist = (struct btrfs_ioctl_fslist *) - malloc(sizeof(*fslist) * count); - if (!fslist_tmp) { + sz = sizeof(*fslist) * *out_count; + *out_fslist = (struct btrfs_ioctl_fslist *) malloc(sz); + if (*out_fslist == NULL) { ret = -ENOMEM; goto out; } - - while (count--) { - memcpy(fslist_tmp, fslist, sizeof(*fslist)); - fslist_tmp = fslist_tmp + sizeof(*fslist_tmp); - fslist = fslist + sizeof(*fslist); - } + memcpy(*out_fslist, fslist, sz); ret = 0; out: - free(fsargs); + free(fsargs_saved); close(fd); return 0; } + +/* 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 e20ad74..8c64575 100644 --- a/utils.h +++ b/utils.h @@ -94,6 +94,7 @@ 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, int *out_count); +int get_fslist(struct btrfs_ioctl_fslist **out_fslist, u64 *out_count); +int fsid_to_mntpt(__u8 *fsid, char *mnt, 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-04 03:45 UTC
[PATCH 4/4] 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. v2: accepts Josef suggested Signed-off-by: Anand Jain <anand.jain@oracle.com> --- cmds-filesystem.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 55 insertions(+), 4 deletions(-) diff --git a/cmds-filesystem.c b/cmds-filesystem.c index f8e8475..f40178a 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>]", @@ -414,6 +415,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", @@ -434,6 +468,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; @@ -466,6 +502,10 @@ 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 @@ -477,14 +517,25 @@ 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; + } } - } - if (type == BTRFS_ARG_MNTPOINT) { + } else if (type == BTRFS_ARG_MNTPOINT) { char label[BTRFS_LABEL_SIZE]; if (get_label_mounted(search, label)) return 1; -- 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-04 04:36 UTC
[PATCH 4/4 v2] 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. v2: accepts Josef suggested Signed-off-by: Anand Jain <anand.jain@oracle.com> --- cmds-filesystem.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 55 insertions(+), 4 deletions(-) diff --git a/cmds-filesystem.c b/cmds-filesystem.c index f8e8475..f40178a 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>]", @@ -414,6 +415,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", @@ -434,6 +468,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; @@ -466,6 +502,10 @@ 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 @@ -477,14 +517,25 @@ 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; + } } - } - if (type == BTRFS_ARG_MNTPOINT) { + } else if (type == BTRFS_ARG_MNTPOINT) { char label[BTRFS_LABEL_SIZE]; if (get_label_mounted(search, label)) return 1; -- 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
Josef Bacik
2013-Nov-06 20:13 UTC
Re: [PATCH 2/4 v2] btrfs-progs: mechanism to fetch fsinfo from btrfs-control
On Mon, Nov 04, 2013 at 11:45:43AM +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. > > v2: commit reword > > Signed-off-by: Anand Jain <anand.jain@oracle.com> > --- > ioctl.h | 19 +++++++++++++++ > utils.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > utils.h | 1 + > 3 files changed, 100 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 5bedd97..1798a7c 100644 > --- a/utils.c > +++ b/utils.c > @@ -2087,3 +2087,83 @@ 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, int *out_count) > +{ > + int ret, fd, e; > + struct btrfs_ioctl_fslist_args *fsargs; > + struct btrfs_ioctl_fslist *fslist; > + struct btrfs_ioctl_fslist *fslist_tmp; > + 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 = (struct btrfs_ioctl_fslist_args *) malloc(sz);No need to cast the return value of malloc.> + memset(fsargs, 0, sz); > + > + if (!fsargs) { > + close(fd); > + return -ENOMEM; > + }Should check !fsargs before memsetting it.> + 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 = count = fsargs->count; > + if (count == 0) { > + *out_fslist = NULL; > + ret = 0; > + goto out; > + } > + > + fslist = (struct btrfs_ioctl_fslist *) (fsargs + > + sizeof(*fsargs)); > + > + fslist_tmp = *out_fslist = (struct btrfs_ioctl_fslist *) > + malloc(sizeof(*fslist) * count);No need to cast. Thanks, Josef -- 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
Josef Bacik
2013-Nov-06 20:19 UTC
Re: [PATCH 3/4 v2] btrfs-progs: fs show should handle if subvol(s) mounted
On Mon, Nov 04, 2013 at 11:45:44AM +0800, Anand Jain wrote:> 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. > > v2: accepts Zach suggested > > Signed-off-by: Anand Jain <anand.jain@oracle.com> > --- > cmds-filesystem.c | 90 +++++++++++++++++++++++++++++++++-------------------- > utils.c | 88 ++++++++++++++++++++++++++++++++++++++++++--------- > utils.h | 3 +- > 3 files changed, 130 insertions(+), 51 deletions(-) > > diff --git a/cmds-filesystem.c b/cmds-filesystem.c > index d2cad81..f8e8475 100644 > --- a/cmds-filesystem.c > +++ b/cmds-filesystem.c > @@ -317,6 +317,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 > 0 && !get_df(fd, &space_info_arg)) {0 is a valid fd. Thanks, Josef -- 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
Josef Bacik
2013-Nov-06 20:20 UTC
Re: [PATCH 4/4] btrfs-progs: lblkid wouldn''t find non mapper path input
On Mon, Nov 04, 2013 at 11:45:45AM +0800, Anand Jain wrote:> 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. > > v2: accepts Josef suggested > > Signed-off-by: Anand Jain <anand.jain@oracle.com> > --- > cmds-filesystem.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++--- > 1 files changed, 55 insertions(+), 4 deletions(-) > > diff --git a/cmds-filesystem.c b/cmds-filesystem.c > index f8e8475..f40178a 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>]", > @@ -414,6 +415,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", > @@ -434,6 +468,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; > @@ -466,6 +502,10 @@ 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 > + */Format screwup. Thanks, Josef -- 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-07 09:53 UTC
Re: [PATCH 2/4 v2] btrfs-progs: mechanism to fetch fsinfo from btrfs-control
Thanks sent out v3. On 11/07/13 04:13 AM, Josef Bacik wrote:> On Mon, Nov 04, 2013 at 11:45:43AM +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. >> >> v2: commit reword >> >> Signed-off-by: Anand Jain<anand.jain@oracle.com> >> --- >> ioctl.h | 19 +++++++++++++++ >> utils.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >> utils.h | 1 + >> 3 files changed, 100 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 5bedd97..1798a7c 100644 >> --- a/utils.c >> +++ b/utils.c >> @@ -2087,3 +2087,83 @@ 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, int *out_count) >> +{ >> + int ret, fd, e; >> + struct btrfs_ioctl_fslist_args *fsargs; >> + struct btrfs_ioctl_fslist *fslist; >> + struct btrfs_ioctl_fslist *fslist_tmp; >> + 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 = (struct btrfs_ioctl_fslist_args *) malloc(sz); > > No need to cast the return value of malloc. > >> + memset(fsargs, 0, sz); >> + >> + if (!fsargs) { >> + close(fd); >> + return -ENOMEM; >> + } > > Should check !fsargs before memsetting it. > >> + 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 = count = fsargs->count; >> + if (count == 0) { >> + *out_fslist = NULL; >> + ret = 0; >> + goto out; >> + } >> + >> + fslist = (struct btrfs_ioctl_fslist *) (fsargs + >> + sizeof(*fsargs)); >> + >> + fslist_tmp = *out_fslist = (struct btrfs_ioctl_fslist *) >> + malloc(sizeof(*fslist) * count); > > No need to cast. Thanks, > > Josef > -- > 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
Anand Jain
2013-Nov-07 09:54 UTC
Re: [PATCH 3/4 v2] btrfs-progs: fs show should handle if subvol(s) mounted
Thanks sent out v3 On 11/07/13 04:19 AM, Josef Bacik wrote:> On Mon, Nov 04, 2013 at 11:45:44AM +0800, Anand Jain wrote: >> 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. >> >> v2: accepts Zach suggested >> >> Signed-off-by: Anand Jain<anand.jain@oracle.com> >> --- >> cmds-filesystem.c | 90 +++++++++++++++++++++++++++++++++-------------------- >> utils.c | 88 ++++++++++++++++++++++++++++++++++++++++++--------- >> utils.h | 3 +- >> 3 files changed, 130 insertions(+), 51 deletions(-) >> >> diff --git a/cmds-filesystem.c b/cmds-filesystem.c >> index d2cad81..f8e8475 100644 >> --- a/cmds-filesystem.c >> +++ b/cmds-filesystem.c >> @@ -317,6 +317,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> 0&& !get_df(fd,&space_info_arg)) { > > 0 is a valid fd. Thanks, > > Josef > -- > 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
Anand Jain
2013-Nov-07 09:54 UTC
Re: [PATCH 4/4] btrfs-progs: lblkid wouldn''t find non mapper path input
Done. On 11/07/13 04:20 AM, Josef Bacik wrote:> On Mon, Nov 04, 2013 at 11:45:45AM +0800, Anand Jain wrote: >> 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. >> >> v2: accepts Josef suggested >> >> Signed-off-by: Anand Jain<anand.jain@oracle.com> >> --- >> cmds-filesystem.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++--- >> 1 files changed, 55 insertions(+), 4 deletions(-) >> >> diff --git a/cmds-filesystem.c b/cmds-filesystem.c >> index f8e8475..f40178a 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>]", >> @@ -414,6 +415,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", >> @@ -434,6 +468,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; >> @@ -466,6 +502,10 @@ 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 >> + */ > > Format screwup. Thanks, > > Josef > -- > 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
Anand Jain
2013-Nov-07 10:01 UTC
[PATCH 1/3] btrfs-progs: mechanism to fetch fsinfo from btrfs-control v3
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. v3: accepts Josef suggested and fix git screwup v2: commit reword Signed-off-by: Anand Jain <anand.jain@oracle.com> --- ioctl.h | 19 +++++++++++++++ utils.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ utils.h | 1 + 3 files changed, 96 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 60d2c3a..4b90026 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) @@ -2087,3 +2088,78 @@ 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 = 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; + } + + fsargs_saved = fsargs; + 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 0; +} diff --git a/utils.h b/utils.h index 6f4b10c..a14a887 100644 --- a/utils.h +++ b/utils.h @@ -94,5 +94,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-07 10:01 UTC
[PATCH 2/3] btrfs-progs: fs show should handle if subvol(s) mounted v3
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. v3: accepts Josef suggested and fix git screwup v2: accepts Zach suggested Signed-off-by: Anand Jain <anand.jain@oracle.com> --- 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 d2cad81..d237989 100644 --- a/cmds-filesystem.c +++ b/cmds-filesystem.c @@ -317,6 +317,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 @@ -350,47 +373,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 > 0 && !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 > 0) - close(fd); - kfree(dev_info_arg); + handle_print(mnt, label); if (search) return 0; } @@ -469,6 +484,13 @@ static int cmd_show(int argc, char **argv) goto devs_only; } } + 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 4b90026..6126af4 100644 --- a/utils.c +++ b/utils.c @@ -2163,3 +2163,63 @@ out: close(fd); return 0; } + +/* 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 a14a887..81fa603 100644 --- a/utils.h +++ b/utils.h @@ -95,5 +95,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-07 10:01 UTC
[PATCH 3/3] btrfs-progs: lblkid wouldn''t find non mapper path input v3
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. v2: accepts Josef suggested v2: accepts Josef suggested Signed-off-by: Anand Jain <anand.jain@oracle.com> --- cmds-filesystem.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 55 insertions(+), 4 deletions(-) diff --git a/cmds-filesystem.c b/cmds-filesystem.c index d237989..72ffe46 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>]", @@ -414,6 +415,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", @@ -434,6 +468,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; @@ -466,6 +502,10 @@ 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 @@ -477,14 +517,25 @@ 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; + } } - } - if (type == BTRFS_ARG_MNTPOINT) { + } else if (type == BTRFS_ARG_MNTPOINT) { char label[BTRFS_LABEL_SIZE]; if (get_label_mounted(search, label)) return 1; -- 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
Stefan Behrens
2013-Nov-07 10:04 UTC
Re: [PATCH 1/3] btrfs-progs: mechanism to fetch fsinfo from btrfs-control v3
On Thu, 7 Nov 2013 18:01:41 +0800, Anand Jain wrote:> + *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 0; > +}return ret; -- 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-07 10:05 UTC
[PATCH 3/3] btrfs-progs: lblkid wouldn''t find non mapper path input v3
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. v3: accepts Josef suggested v2: accepts Josef suggested Signed-off-by: Anand Jain <anand.jain@oracle.com> --- cmds-filesystem.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 55 insertions(+), 4 deletions(-) diff --git a/cmds-filesystem.c b/cmds-filesystem.c index d237989..72ffe46 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>]", @@ -414,6 +415,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", @@ -434,6 +468,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; @@ -466,6 +502,10 @@ 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 @@ -477,14 +517,25 @@ 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; + } } - } - if (type == BTRFS_ARG_MNTPOINT) { + } else if (type == BTRFS_ARG_MNTPOINT) { char label[BTRFS_LABEL_SIZE]; if (get_label_mounted(search, label)) return 1; -- 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-07 10:06 UTC
[PATCH 1/3] btrfs-progs: mechanism to fetch fsinfo from btrfs-control v3
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. v3: accepts Josef suggested and fix git screwup v2: commit reword Signed-off-by: Anand Jain <anand.jain@oracle.com> --- ioctl.h | 19 +++++++++++++++ utils.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ utils.h | 1 + 3 files changed, 96 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 60d2c3a..4b90026 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) @@ -2087,3 +2088,78 @@ 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 = 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; + } + + fsargs_saved = fsargs; + 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 0; +} diff --git a/utils.h b/utils.h index 6f4b10c..a14a887 100644 --- a/utils.h +++ b/utils.h @@ -94,5 +94,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-07 11:18 UTC
[PATCH 1/3] btrfs-progs: mechanism to fetch fsinfo from btrfs-control v4
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. Signed-off-by: Anand Jain <anand.jain@oracle.com> 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 60d2c3a..9983db2 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) @@ -2087,3 +2088,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 6f4b10c..a14a887 100644 --- a/utils.h +++ b/utils.h @@ -94,5 +94,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-07 11:21 UTC
Re: [PATCH 1/3] btrfs-progs: mechanism to fetch fsinfo from btrfs-control v3
On 11/07/2013 06:04 PM, Stefan Behrens wrote:> On Thu, 7 Nov 2013 18:01:41 +0800, Anand Jain wrote: >> + *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 0; >> +} > > return ret;nice catch. Thanks. Also fsargs_saved wasn''t initialized along with one of early goto out. I have fixed it as well in v4 which was sent out. Thanks, Anand -- 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