* [PATCH 0/1 not for integration] btrfs-devlist @ 2014-05-16 14:03 Anand Jain 2014-05-16 14:03 ` [PATCH 1/1] btrfs: introduce BTRFS_IOC_GET_DEVS Anand Jain 2014-05-16 14:03 ` [PATCH 1/1] btrfs-progs: introduce btrfs-devlist Anand Jain 0 siblings, 2 replies; 4+ messages in thread From: Anand Jain @ 2014-05-16 14:03 UTC (permalink / raw) To: linux-btrfs btrfs-devlist: Dumps kernel fs_devices for debug purpose (This is not for integration, use it until we have a replacement tool) Anand Jain (1): btrfs: introduce BTRFS_IOC_GET_DEVS fs/btrfs/super.c | 86 ++++++++++++++++++++++++++ fs/btrfs/volumes.c | 142 ++++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/volumes.h | 2 + include/uapi/linux/btrfs.h | 51 ++++++++++++++++ 4 files changed, 281 insertions(+), 0 deletions(-) Anand Jain (1): btrfs-progs: introduce btrfs-devlist .gitignore | 1 + Makefile | 4 +- btrfs-devlist.c | 266 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ ioctl.h | 51 +++++++++++ 4 files changed, 320 insertions(+), 2 deletions(-) create mode 100644 btrfs-devlist.c ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/1] btrfs: introduce BTRFS_IOC_GET_DEVS 2014-05-16 14:03 [PATCH 0/1 not for integration] btrfs-devlist Anand Jain @ 2014-05-16 14:03 ` Anand Jain 2014-05-16 14:03 ` [PATCH 1/1] btrfs-progs: introduce btrfs-devlist Anand Jain 1 sibling, 0 replies; 4+ messages in thread From: Anand Jain @ 2014-05-16 14:03 UTC (permalink / raw) To: linux-btrfs The user land progs needs a simple way to see the raw list of disks and its parameters as seen by the btrfs kernel. As of now btrfs-devlist uses this ioctl. Signed-off-by: Anand Jain <anand.jain@oracle.com> --- fs/btrfs/super.c | 86 ++++++++++++++++++++++++++ fs/btrfs/volumes.c | 142 ++++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/volumes.h | 2 + include/uapi/linux/btrfs.h | 51 ++++++++++++++++ 4 files changed, 281 insertions(+), 0 deletions(-) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index ac5886b..f43327d 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1717,6 +1717,89 @@ static struct file_system_type btrfs_fs_type = { }; MODULE_ALIAS_FS("btrfs"); +static int btrfs_ioc_get_devlist(void __user *arg) +{ + int ret = 0; + u64 sz_devlist_arg; + u64 sz_devlist; + u64 u_sz_devlist_arg; + u64 u_sz_devlist; + u64 sz_out; + + struct btrfs_ioctl_devlist_args *devlist_arg; + struct btrfs_ioctl_devlist_args *tmp_devlist_arg; + struct btrfs_ioctl_devlist *devlist; + + u64 cnt = 0, ucnt; + + sz_devlist_arg = sizeof(*devlist_arg); + sz_devlist = sizeof(*devlist); + + /* Check if the user land and kernel ioctl struct match */ + if (copy_from_user(&u_sz_devlist_arg, + (struct btrfs_ioctl_devlist_args __user *)(arg + + offsetof(struct btrfs_ioctl_devlist_args, sz_self)), + sizeof(u_sz_devlist_arg))) + return -EFAULT; + + if (copy_from_user(&u_sz_devlist, + (struct btrfs_ioctl_devlist_args __user *)(arg + + sz_devlist_arg + + offsetof(struct btrfs_ioctl_devlist, sz_self)), + sizeof(u_sz_devlist))) + return -EFAULT; + + if (u_sz_devlist_arg != sz_devlist_arg || + u_sz_devlist != sz_devlist) { + if (copy_to_user(arg + + offsetof(struct btrfs_ioctl_devlist_args, sz_self), + &sz_devlist_arg, sizeof(sz_devlist_arg))) + return -EFAULT; + if (copy_to_user(arg + + sz_devlist_arg + + offsetof(struct btrfs_ioctl_devlist, sz_self), + &sz_devlist, sizeof(sz_devlist))) + return -EFAULT; + return 2; + } + + if (copy_from_user(&ucnt, + (struct btrfs_ioctl_devlist_args __user *)(arg + + offsetof(struct btrfs_ioctl_devlist_args, count)), + sizeof(ucnt))) + return -EFAULT; + + cnt = btrfs_get_devlist_cnt(); + + if (cnt > ucnt) { + if (copy_to_user(arg + + offsetof(struct btrfs_ioctl_devlist_args, count), + &cnt, sizeof(cnt))) + return -EFAULT; + return 1; + } + + sz_out = sz_devlist_arg + sz_devlist * cnt; + + tmp_devlist_arg = devlist_arg = memdup_user(arg, sz_out); + if (IS_ERR(devlist_arg)) + return PTR_ERR(devlist_arg); + + devlist = (struct btrfs_ioctl_devlist *) (++tmp_devlist_arg); + cnt = btrfs_get_devlist(devlist, cnt); + devlist_arg->count = cnt; + + if (copy_to_user(arg, devlist_arg, sz_out)) { + ret = -EFAULT; + goto out; + } + ret = 0; +out: + kfree(devlist_arg); + return ret; + +} + static int btrfs_ioc_get_fslist(void __user *arg) { int ret = 0; @@ -1801,6 +1884,9 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd, case BTRFS_IOC_GET_FSLIST: ret = btrfs_ioc_get_fslist(argp); break; + case BTRFS_IOC_GET_DEVS: + ret = btrfs_ioc_get_devlist(argp); + break; } return ret; diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index e22ac22..012aed7 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -6380,3 +6380,145 @@ u64 btrfs_get_fslist(struct btrfs_ioctl_fslist *fslist, u64 ucnt) return cnt; } + +int btrfs_get_devlist_cnt(void) +{ + int cnt = 0; + struct btrfs_device *device; + struct btrfs_fs_devices *fs_devices; + struct btrfs_fs_devices *cur_fs_devices; + + mutex_lock(&uuid_mutex); + list_for_each_entry(cur_fs_devices, &fs_uuids, list) { + + fs_devices = cur_fs_devices; +again_dev_cnt: + list_for_each_entry(device, &fs_devices->devices, dev_list) + cnt++; + + fs_devices = fs_devices->seed; + if (fs_devices) + goto again_dev_cnt; + } + + mutex_unlock(&uuid_mutex); + + return cnt; +} + +u64 btrfs_get_devlist(struct btrfs_ioctl_devlist *dev, u64 alloc_cnt) +{ + u64 cnt = 0; + + struct btrfs_device *device; + struct btrfs_fs_devices *fs_devices; + struct btrfs_fs_devices *cur_fs_devices; + struct btrfs_fs_devices *sprout_fs_devices; + + mutex_lock(&uuid_mutex); + /* Todo: there must be better way of doing this */ + list_for_each_entry(cur_fs_devices, &fs_uuids, list) { + + mutex_lock(&cur_fs_devices->device_list_mutex); + + fs_devices = cur_fs_devices; + sprout_fs_devices = NULL; + +again_dev: + list_for_each_entry(device, &fs_devices->devices, dev_list) { + + if (!(cnt < alloc_cnt)) + break; + + dev->fs_addr = (u64)fs_devices; + dev->dev_addr = (u64)device; + memcpy(dev->fsid, fs_devices->fsid, BTRFS_FSID_SIZE); + + if (fs_devices->seed) + memcpy(dev->seed_fsid, fs_devices->seed->fsid, + BTRFS_FSID_SIZE); + else + memset(dev->seed_fsid, 0, BTRFS_FSID_SIZE); + + if (sprout_fs_devices) + memcpy(dev->sprout_fsid, sprout_fs_devices->fsid, + BTRFS_FSID_SIZE); + else + memset(dev->sprout_fsid, 0, BTRFS_FSID_SIZE); + + dev->fs_latest_devid = fs_devices->latest_devid; + dev->fs_latest_trans = fs_devices->latest_trans; + dev->fs_num_devices = fs_devices->num_devices; + dev->fs_open_devices = fs_devices->open_devices; + dev->fs_rw_devices = fs_devices->rw_devices; + dev->fs_missing_devices = fs_devices->missing_devices; + dev->fs_total_rw_bytes = fs_devices->total_rw_bytes; + dev->fs_num_can_discard = fs_devices->num_can_discard; + dev->fs_total_devices = fs_devices->total_devices; + + dev->flags = 0; + + if (fs_devices->opened) + dev->flags |= BTRFS_FS_MOUNTED; + if (fs_devices->seeding) + dev->flags |= BTRFS_FS_SEEDING; + if (fs_devices->rotating) + dev->flags |= BTRFS_FS_ROTATING; + + dev->gen = device->generation; + dev->devid = device->devid; + dev->total_bytes = device->total_bytes; + dev->disk_total_bytes = device->disk_total_bytes; + dev->bytes_used = device->bytes_used; + dev->type = device->type; + dev->io_align = device->io_align; + dev->io_width = device->io_width; + dev->sector_size = device->sector_size; + dev->fmode = device->mode; + + if (device->writeable) + dev->flags |= BTRFS_DEV_WRITEABLE; + if (device->in_fs_metadata) + dev->flags |= BTRFS_DEV_IN_FS_MD; + if (device->missing) + dev->flags |= BTRFS_DEV_MISSING; + if (device->can_discard) + dev->flags |= BTRFS_DEV_CAN_DISCARD; + if (device->is_tgtdev_for_dev_replace) + dev->flags |= BTRFS_DEV_REPLACE_TGT; + if (device->running_pending) + dev->flags |= BTRFS_DEV_RUN_PENDING; + if (device->nobarriers) + dev->flags |= BTRFS_DEV_NOBARRIERS; + if (device->dev_stats_valid) + dev->flags |= BTRFS_DEV_STATS_VALID; + if (device->dev_stats_dirty) + dev->flags |= BTRFS_DEV_STATS_DIRTY; + if (device->bdev) + dev->flags |= BTRFS_DEV_BDEV; + + memcpy(dev->uuid, device->uuid, BTRFS_UUID_SIZE); + if (device->name) { + rcu_read_lock(); + memcpy(dev->name, rcu_str_deref(device->name), + BTRFS_PATH_NAME_MAX); + rcu_read_unlock(); + } else { + memset(dev->name, 0, BTRFS_PATH_NAME_MAX); + } + dev++; + cnt++; + } + + if (fs_devices->seed) { + sprout_fs_devices = fs_devices; + fs_devices = fs_devices->seed; + goto again_dev; + } + + mutex_unlock(&cur_fs_devices->device_list_mutex); + } + mutex_unlock(&uuid_mutex); + + return cnt; +} diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 0b97fcf..91b7596 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -393,4 +393,6 @@ static inline void btrfs_dev_stat_reset(struct btrfs_device *dev, } int btrfs_get_fslist_cnt(void); u64 btrfs_get_fslist(struct btrfs_ioctl_fslist *fslist, u64 ucnt); +int btrfs_get_devlist_cnt(void); +u64 btrfs_get_devlist(struct btrfs_ioctl_devlist *devlist, u64 ucnt); #endif diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index 76b91d6..1c12b7f 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -520,6 +520,8 @@ static inline char *btrfs_err_str(enum btrfs_err_code err_code) /* fs flags */ #define BTRFS_FS_MOUNTED (1LLU << 0) +#define BTRFS_FS_SEEDING (1LLU << 1) +#define BTRFS_FS_ROTATING (1LLU << 2) struct btrfs_ioctl_fslist { __u64 self_sz; /* in/out */ @@ -535,6 +537,53 @@ struct btrfs_ioctl_fslist_args { __u64 count; /* out */ }; +#define BTRFS_DEV_WRITEABLE (1LLU << 8) +#define BTRFS_DEV_IN_FS_MD (1LLU << 9) +#define BTRFS_DEV_MISSING (1LLU << 10) +#define BTRFS_DEV_CAN_DISCARD (1LLU << 11) +#define BTRFS_DEV_REPLACE_TGT (1LLU << 12) +#define BTRFS_DEV_RUN_PENDING (1LLU << 13) +#define BTRFS_DEV_NOBARRIERS (1LLU << 14) +#define BTRFS_DEV_STATS_VALID (1LLU << 15) +#define BTRFS_DEV_STATS_DIRTY (1LLU << 16) +#define BTRFS_DEV_BDEV (1LLU << 17) + +struct btrfs_ioctl_devlist { + __u64 sz_self; + __u64 fs_addr; + __u64 dev_addr; + __u64 fs_latest_devid; + __u64 fs_latest_trans; + __u64 fs_num_devices; + __u64 fs_open_devices; + __u64 fs_rw_devices; + __u64 fs_missing_devices; + __u64 fs_total_rw_bytes; + __u64 fs_num_can_discard; + __u64 fs_total_devices; + __u64 gen; + __u64 flags; + __u64 devid; + __u64 total_bytes; + __u64 disk_total_bytes; + __u64 bytes_used; + __u64 type; + __u64 fmode; + __u32 io_align; + __u32 io_width; + __u32 sector_size; + __u8 fsid[BTRFS_FSID_SIZE]; + __u8 uuid[BTRFS_UUID_SIZE]; + __u8 seed_fsid[BTRFS_FSID_SIZE]; + __u8 sprout_fsid[BTRFS_UUID_SIZE]; + __u8 name[BTRFS_PATH_NAME_MAX]; +}__attribute__ ((__packed__)); + +struct btrfs_ioctl_devlist_args { + __u64 sz_self; /* in/out */ + __u64 count; /* in/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, \ @@ -637,5 +686,7 @@ struct btrfs_ioctl_fslist_args { struct btrfs_ioctl_feature_flags[2]) #define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ struct btrfs_ioctl_feature_flags[3]) +#define BTRFS_IOC_GET_DEVS _IOWR(BTRFS_IOCTL_MAGIC, 58, \ + struct btrfs_ioctl_devlist_args) #endif /* _UAPI_LINUX_BTRFS_H */ -- 1.7.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 1/1] btrfs-progs: introduce btrfs-devlist 2014-05-16 14:03 [PATCH 0/1 not for integration] btrfs-devlist Anand Jain 2014-05-16 14:03 ` [PATCH 1/1] btrfs: introduce BTRFS_IOC_GET_DEVS Anand Jain @ 2014-05-16 14:03 ` Anand Jain 1 sibling, 0 replies; 4+ messages in thread From: Anand Jain @ 2014-05-16 14:03 UTC (permalink / raw) To: linux-btrfs This is a small (debug) program to dump the device list in the raw format from the btrfs kernel. here I use ioctl which was introduced in the below kernel patch btrfs: introduce BTRFS_IOC_GET_DEVS Signed-off-by: Anand Jain <anand.jain@oracle.com> --- .gitignore | 1 + Makefile | 4 +- btrfs-devlist.c | 266 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ ioctl.h | 51 +++++++++++ 4 files changed, 320 insertions(+), 2 deletions(-) create mode 100644 btrfs-devlist.c diff --git a/.gitignore b/.gitignore index fc8c07a..760eaeb 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ libbtrfs.a libbtrfs.so libbtrfs.so.0 libbtrfs.so.0.1 +btrfs-devlist diff --git a/Makefile b/Makefile index c861d61..a91cf8b 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ MAKEOPTS = --no-print-directory Q=$(Q) progs = mkfs.btrfs btrfs-debug-tree btrfsck \ btrfs btrfs-map-logical btrfs-image btrfs-zero-log btrfs-convert \ - btrfs-find-root btrfstune btrfs-show-super + btrfs-find-root btrfstune btrfs-show-super btrfs-devlist # external libs required by various binaries; for btrfs-foo, # specify btrfs_foo_libs = <list of libs>; see $($(subst...)) rules below @@ -229,7 +229,7 @@ clean: $(CLEANDIRS) @echo "Cleaning" $(Q)rm -f $(progs) cscope.out *.o *.o.d btrfs-convert btrfs-image btrfs-select-super \ btrfs-zero-log btrfstune dir-test ioctl-test quick-test send-test btrfsck \ - btrfs.static mkfs.btrfs.static btrfs-calc-size \ + btrfs.static mkfs.btrfs.static btrfs-calc-size btrfs-devlist\ version.h $(check_defs) \ $(libs) $(lib_links) diff --git a/btrfs-devlist.c b/btrfs-devlist.c new file mode 100644 index 0000000..332a171 --- /dev/null +++ b/btrfs-devlist.c @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2014 Oracle. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#include <unistd.h> +#include <getopt.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <uuid/uuid.h> + +#include "ctree.h" +#include "ioctl.h" +#include "commands.h" +#include "utils.h" + +void print_header(void) +{ + printf( + "fs_address dev_address\n"\ + "fsid "\ + "name "\ + "uuid "\ + "(seed_fsid "\ + "sprout_fsid) \n"\ + "\t(fs_latest_devid "\ + "fs_num_devices "\ + "fs_open_devices "\ + "fs_rw_devices "\ + "fs_missing_devices "\ + "fs_total_devices) "\ + "fs_total_rw_bytes "\ + "fs_num_can_discard "\ + "fs_latest_trans \n"\ + "\tdevid "\ + "gen "\ + "total_bytes "\ + "disk_total_bytes "\ + "bytes_used "\ + "type "\ + "io_align "\ + "io_width "\ + "sector_size "\ + "fmode \n"\ + "\tfs_flags\n"\ + "\tdev_flags\n"); +} + +void print_dev(struct btrfs_ioctl_devlist *dev) +{ + char uuid[BTRFS_UUID_UNPARSED_SIZE]; + char fsid[BTRFS_UUID_UNPARSED_SIZE]; + char seed_fsid[BTRFS_UUID_UNPARSED_SIZE]; + char sprout_fsid[BTRFS_UUID_UNPARSED_SIZE]; + + memset(seed_fsid, '0', BTRFS_UUID_UNPARSED_SIZE); + strcpy(seed_fsid, "null"); + memset(sprout_fsid, '0', BTRFS_UUID_UNPARSED_SIZE); + strcpy(sprout_fsid, "null"); + + uuid_unparse(dev->uuid, uuid); + uuid_unparse(dev->fsid, fsid); + if (! uuid_is_null(dev->seed_fsid)) + uuid_unparse(dev->seed_fsid, seed_fsid); + if (! uuid_is_null(dev->sprout_fsid)) + uuid_unparse(dev->sprout_fsid, sprout_fsid); + + printf("\n%llX %llX\n"\ + "%s %s %s (%s %s)\n"\ + "\t(%llu %llu %llu %llu %llu %llu) %llu %llu %llu\n"\ + "\t%llu %llu %llu %llu %llu %llu %u %u %u 0x%llX\n"\ + "\t%s|%s|%s\n"\ + "\t%s|%s|%s|%s|%s|%s|%s|%s|%s|%s\n", + dev->fs_addr, + dev->dev_addr, + fsid, + dev->name, + uuid, + seed_fsid, + sprout_fsid, + dev->fs_latest_devid, + dev->fs_num_devices, + dev->fs_open_devices, + dev->fs_rw_devices, + dev->fs_missing_devices, + dev->fs_total_devices, + dev->fs_total_rw_bytes, + dev->fs_num_can_discard, + dev->fs_latest_trans, + dev->devid, + dev->gen, + dev->total_bytes, + dev->disk_total_bytes, + dev->bytes_used, + dev->type, + dev->io_align, + dev->io_width, + dev->sector_size, + dev->fmode, + dev->flags & BTRFS_FS_MOUNTED ? "fs_Mounted":"not_fs_Mounted", + dev->flags & BTRFS_FS_SEEDING ? "fs_Seeding":"not_fs_Seeding", + dev->flags & BTRFS_FS_ROTATING ? "fs_Rotating":"not_fs_Rotating", + dev->flags & BTRFS_DEV_WRITEABLE ? "Writable":"not_Writable", + dev->flags & BTRFS_DEV_IN_FS_MD ? "MD":"not_MD", + dev->flags & BTRFS_DEV_MISSING ? "Missing":"not_Missing", + dev->flags & BTRFS_DEV_CAN_DISCARD ? "Discard":"not_Discard", + dev->flags & BTRFS_DEV_REPLACE_TGT ? "Replace_tgt":"not_Replace_tgt", + dev->flags & BTRFS_DEV_RUN_PENDING ? "Run_pending":"not_Run_pending", + dev->flags & BTRFS_DEV_NOBARRIERS ? "Nobarriers":"not_Nobarriers", + dev->flags & BTRFS_DEV_STATS_VALID ? "Stat_valid":"not_Stat_valid", + dev->flags & BTRFS_DEV_STATS_DIRTY ? "Stat_dirty":"not_Stat_dirty", + dev->flags & BTRFS_DEV_BDEV ? "Bdev":"not_Bdev"); +} + +int get_devlist(struct btrfs_ioctl_devlist **out_devlist, u64 *out_count) +{ + int ret, fd, e; + struct btrfs_ioctl_devlist_args *devargs; + struct btrfs_ioctl_devlist_args *devargs_saved = NULL; + struct btrfs_ioctl_devlist *devlist; + 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(*devargs) + sizeof(*devlist) * count; + + devargs_saved = devargs = malloc(sz); + if (!devargs) { + close(fd); + return -ENOMEM; + } + + memset(devargs, 0, sz); + devlist = (struct btrfs_ioctl_devlist *) (++devargs); + devargs = devargs_saved; + + devargs->count = count; + devargs->sz_self = (u64) sizeof(*devargs); + devlist->sz_self = (u64) sizeof(*devlist); + + ret = ioctl(fd, BTRFS_IOC_GET_DEVS, devargs); + e = errno; + if (ret == 1) { + /* out of size so reallocate */ + count = devargs->count; + free(devargs); + goto again; + } else if (ret < 0) { + printf("ERROR: scan_fsid ioctl failed - %s\n", + strerror(e)); + ret = -e; + goto out; + } + + /* Check if the kernel has the same struct as this */ + if (devargs->sz_self != sizeof(*devargs) || + devlist->sz_self != sizeof(*devlist)) { + fprintf(stderr, + "ERROR: version mismatch udevarg %lu udevlist %lu kdevarg %llu kdevlist %llu\n", + sizeof(*devargs), sizeof(*devlist), devargs->sz_self, devlist->sz_self); + goto out; + } + + /* ioctl returns devs count in count parameter*/ + + *out_count = devargs->count; + if (*out_count == 0) { + *out_devlist = NULL; + ret = 0; + goto out; + } + + + sz = sizeof(*devlist) * *out_count; + *out_devlist = malloc(sz); + if (*out_devlist == NULL) { + ret = -ENOMEM; + goto out; + } + + memcpy(*out_devlist, devlist, sz); + ret = 0; + +out: + free(devargs_saved); + close(fd); + return ret; +} + +static void local_usage(void) +{ + printf("btrfs_devlist [options]\n"\ + " Dumps the device list from the btrfs kernel "\ + "without altering at the user level\n"\ + " options:\n"\ + " -h|--help prints this usage\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + int ret; + u64 cnt; + struct btrfs_ioctl_devlist *devlist; + struct btrfs_ioctl_devlist *tmp_devlist; + + while(1) { + int long_index; + static struct option long_options[] = { + {"help", no_argument, NULL, 'h'}, + { NULL, no_argument, NULL, 0 } + }; + + int c = getopt_long(argc, argv, "h", long_options, + &long_index); + + if(c < 0) + break; + + switch(c) { + case 'h': + default: + local_usage(); + } + } + + ret = get_devlist(&devlist, &cnt); + if (ret) { + fprintf(stderr, "get devlist failed %d\n", ret); + return 1; + } + + tmp_devlist = devlist; + + print_header(); + while (cnt--) { + print_dev(devlist); + devlist++; + } + kfree(tmp_devlist); + return ret; +} diff --git a/ioctl.h b/ioctl.h index d4e54f9..a2320fc 100644 --- a/ioctl.h +++ b/ioctl.h @@ -528,6 +528,8 @@ static inline char *btrfs_err_str(enum btrfs_err_code err_code) /* fs flags */ #define BTRFS_FS_MOUNTED (1LLU << 0) +#define BTRFS_FS_SEEDING (1LLU << 1) +#define BTRFS_FS_ROTATING (1LLU << 2) struct btrfs_ioctl_fslist { __u64 self_sz; /* in/out */ @@ -543,6 +545,53 @@ struct btrfs_ioctl_fslist_args { __u64 count; /* out */ }; +#define BTRFS_DEV_WRITEABLE (1LLU << 8) +#define BTRFS_DEV_IN_FS_MD (1LLU << 9) +#define BTRFS_DEV_MISSING (1LLU << 10) +#define BTRFS_DEV_CAN_DISCARD (1LLU << 11) +#define BTRFS_DEV_REPLACE_TGT (1LLU << 12) +#define BTRFS_DEV_RUN_PENDING (1LLU << 13) +#define BTRFS_DEV_NOBARRIERS (1LLU << 14) +#define BTRFS_DEV_STATS_VALID (1LLU << 15) +#define BTRFS_DEV_STATS_DIRTY (1LLU << 16) +#define BTRFS_DEV_BDEV (1LLU << 17) + +struct btrfs_ioctl_devlist { + __u64 sz_self; + __u64 fs_addr; + __u64 dev_addr; + __u64 fs_latest_devid; + __u64 fs_latest_trans; + __u64 fs_num_devices; + __u64 fs_open_devices; + __u64 fs_rw_devices; + __u64 fs_missing_devices; + __u64 fs_total_rw_bytes; + __u64 fs_num_can_discard; + __u64 fs_total_devices; + __u64 gen; + __u64 flags; + __u64 devid; + __u64 total_bytes; + __u64 disk_total_bytes; + __u64 bytes_used; + __u64 type; + __u64 fmode; + __u32 io_align; + __u32 io_width; + __u32 sector_size; + __u8 fsid[BTRFS_FSID_SIZE]; + __u8 uuid[BTRFS_UUID_SIZE]; + __u8 seed_fsid[BTRFS_FSID_SIZE]; + __u8 sprout_fsid[BTRFS_UUID_SIZE]; + __u8 name[BTRFS_PATH_NAME_MAX]; +}__attribute__ ((__packed__)); + +struct btrfs_ioctl_devlist_args { + __u64 sz_self; /* in/out */ + __u64 count; /* in/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, \ @@ -652,6 +701,8 @@ struct btrfs_ioctl_clone_range_args { struct btrfs_ioctl_feature_flags[2]) #define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ struct btrfs_ioctl_feature_flags[3]) +#define BTRFS_IOC_GET_DEVS _IOWR(BTRFS_IOCTL_MAGIC, 58, \ + struct btrfs_ioctl_devlist_args) #ifdef __cplusplus } #endif -- 1.7.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH not for integration] btrfs-devlist: dumps btrfs_device and btrfs_fs_devices from kernel @ 2014-07-25 12:33 Anand Jain 2014-07-25 12:33 ` [PATCH 1/1] btrfs-progs: introduce btrfs-devlist Anand Jain 0 siblings, 1 reply; 4+ messages in thread From: Anand Jain @ 2014-07-25 12:33 UTC (permalink / raw) To: linux-btrfs This would dump the following info: fs_address dev_address dev_root_addr root_fsid fsid name uuid (seed_fsid@seed_addr sprout_fsid@sprout_addr) (fs_num_devices fs_open_devices fs_rw_devices fs_missing_devices fs_total_devices) fs_total_rw_bytes fs_num_can_discard devid gen total_bytes disk_total_bytes bytes_used type io_align io_width sector_size fmode not_fs_Mounted|not_fs_Seeding|not_fs_Rotating not_Writable|not_MD|not_Missing|not_Discard|not_Replace_tgt|not_Run_pending|not_Nobarriers|not_Stat_valid|not_Bdev Applies on Chris integration branch now Anand Jain (1): btrfs: introduce BTRFS_IOC_GET_DEVS fs/btrfs/super.c | 86 +++++++++++++++++++++++++++ fs/btrfs/volumes.c | 145 +++++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/volumes.h | 3 + include/uapi/linux/btrfs.h | 53 ++++++++++++++++- 4 files changed, 286 insertions(+), 1 deletion(-) Anand Jain (1): btrfs-progs: introduce btrfs-devlist .gitignore | 1 + Makefile | 4 +- btrfs-devlist.c | 268 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ioctl.h | 52 +++++++++++ 4 files changed, 323 insertions(+), 2 deletions(-) create mode 100644 btrfs-devlist.c -- 2.0.0.153.g79dcccc ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/1] btrfs-progs: introduce btrfs-devlist 2014-07-25 12:33 [PATCH not for integration] btrfs-devlist: dumps btrfs_device and btrfs_fs_devices from kernel Anand Jain @ 2014-07-25 12:33 ` Anand Jain 0 siblings, 0 replies; 4+ messages in thread From: Anand Jain @ 2014-07-25 12:33 UTC (permalink / raw) To: linux-btrfs This is a small (debug) program to dump the device list in the raw format from the btrfs kernel. here I use ioctl which was introduced in the below kernel patch btrfs: introduce BTRFS_IOC_GET_DEVS Signed-off-by: Anand Jain <anand.jain@oracle.com> --- .gitignore | 1 + Makefile | 4 +- btrfs-devlist.c | 268 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ioctl.h | 52 +++++++++++ 4 files changed, 323 insertions(+), 2 deletions(-) create mode 100644 btrfs-devlist.c diff --git a/.gitignore b/.gitignore index fc8c07a..760eaeb 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ libbtrfs.a libbtrfs.so libbtrfs.so.0 libbtrfs.so.0.1 +btrfs-devlist diff --git a/Makefile b/Makefile index 9f805ac..ec6011c 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ MAKEOPTS = --no-print-directory Q=$(Q) progs = mkfs.btrfs btrfs-debug-tree btrfsck \ btrfs btrfs-map-logical btrfs-image btrfs-zero-log btrfs-convert \ - btrfs-find-root btrfstune btrfs-show-super + btrfs-find-root btrfstune btrfs-show-super btrfs-devlist # external libs required by various binaries; for btrfs-foo, # specify btrfs_foo_libs = <list of libs>; see $($(subst...)) rules below @@ -229,7 +229,7 @@ clean: $(CLEANDIRS) @echo "Cleaning" $(Q)rm -f $(progs) cscope.out *.o *.o.d btrfs-convert btrfs-image btrfs-select-super \ btrfs-zero-log btrfstune dir-test ioctl-test quick-test send-test btrfsck \ - btrfs.static mkfs.btrfs.static btrfs-calc-size \ + btrfs.static mkfs.btrfs.static btrfs-calc-size btrfs-devlist\ version.h $(check_defs) \ $(libs) $(lib_links) diff --git a/btrfs-devlist.c b/btrfs-devlist.c new file mode 100644 index 0000000..740957a --- /dev/null +++ b/btrfs-devlist.c @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2014 Oracle. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#include <unistd.h> +#include <getopt.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <uuid/uuid.h> + +#include "ctree.h" +#include "ioctl.h" +#include "commands.h" +#include "utils.h" + +void print_header(void) +{ + printf( + "fs_address dev_address dev_root_addr root_fsid\n"\ + "fsid "\ + "name "\ + "uuid "\ + "(seed_fsid@seed_addr "\ + "sprout_fsid@sprout_addr) \n"\ + "\t(fs_num_devices "\ + "fs_open_devices "\ + "fs_rw_devices "\ + "fs_missing_devices "\ + "fs_total_devices) "\ + "fs_total_rw_bytes "\ + "fs_num_can_discard\n"\ + "\tdevid "\ + "gen "\ + "total_bytes "\ + "disk_total_bytes "\ + "bytes_used "\ + "type "\ + "io_align "\ + "io_width "\ + "sector_size "\ + "fmode \n"\ + "\tfs_flags\n"\ + "\tdev_flags\n"); +} + +void print_dev(struct btrfs_ioctl_devlist *dev) +{ + char uuid[BTRFS_UUID_UNPARSED_SIZE]; + char fsid[BTRFS_UUID_UNPARSED_SIZE]; + char seed_fsid[BTRFS_UUID_UNPARSED_SIZE]; + char sprout_fsid[BTRFS_UUID_UNPARSED_SIZE]; + char root_fsid[BTRFS_UUID_UNPARSED_SIZE]; + + memset(seed_fsid, '0', BTRFS_UUID_UNPARSED_SIZE); + strcpy(seed_fsid, "null"); + memset(sprout_fsid, '0', BTRFS_UUID_UNPARSED_SIZE); + strcpy(sprout_fsid, "null"); + memset(root_fsid, '0', BTRFS_UUID_UNPARSED_SIZE); + strcpy(root_fsid, "null"); + + uuid_unparse(dev->uuid, uuid); + uuid_unparse(dev->fsid, fsid); + if (! uuid_is_null(dev->seed_fsid)) + uuid_unparse(dev->seed_fsid, seed_fsid); + if (! uuid_is_null(dev->sprout_fsid)) + uuid_unparse(dev->sprout_fsid, sprout_fsid); + if (! uuid_is_null(dev->root_fsid)) + uuid_unparse(dev->root_fsid, root_fsid); + + printf("\n%llX %llX %llX %s\n"\ + "%s %s %s (%s@%llX %s@%llX)\n"\ + "\t(%llu %llu %llu %llu %llu) %llu %llu\n"\ + "\t%llu %llu %llu %llu %llu %llu %u %u %u 0x%llX\n"\ + "\t%s|%s|%s\n"\ + "\t%s|%s|%s|%s|%s|%s|%s|%s|%s\n", + dev->fs_addr, + dev->dev_addr, + dev->dev_root_addr, + root_fsid, + fsid, + dev->name, + uuid, + seed_fsid, dev->seed_fs_addr, + sprout_fsid, dev->sprout_fs_addr, + dev->fs_num_devices, + dev->fs_open_devices, + dev->fs_rw_devices, + dev->fs_missing_devices, + dev->fs_total_devices, + dev->fs_total_rw_bytes, + dev->fs_num_can_discard, + dev->devid, + dev->gen, + dev->total_bytes, + dev->disk_total_bytes, + dev->bytes_used, + dev->type, + dev->io_align, + dev->io_width, + dev->sector_size, + dev->fmode, + dev->flags & BTRFS_FS_MOUNTED ? "fs_Mounted":"not_fs_Mounted", + dev->flags & BTRFS_FS_SEEDING ? "fs_Seeding":"not_fs_Seeding", + dev->flags & BTRFS_FS_ROTATING ? "fs_Rotating":"not_fs_Rotating", + dev->flags & BTRFS_DEV_WRITEABLE ? "Writable":"not_Writable", + dev->flags & BTRFS_DEV_IN_FS_MD ? "MD":"not_MD", + dev->flags & BTRFS_DEV_MISSING ? "Missing":"not_Missing", + dev->flags & BTRFS_DEV_CAN_DISCARD ? "Discard":"not_Discard", + dev->flags & BTRFS_DEV_REPLACE_TGT ? "Replace_tgt":"not_Replace_tgt", + dev->flags & BTRFS_DEV_RUN_PENDING ? "Run_pending":"not_Run_pending", + dev->flags & BTRFS_DEV_NOBARRIERS ? "Nobarriers":"not_Nobarriers", + dev->flags & BTRFS_DEV_STATS_VALID ? "Stat_valid":"not_Stat_valid", + dev->flags & BTRFS_DEV_BDEV ? "Bdev":"not_Bdev"); +} + +int get_devlist(struct btrfs_ioctl_devlist **out_devlist, u64 *out_count) +{ + int ret, fd, e; + struct btrfs_ioctl_devlist_args *devargs; + struct btrfs_ioctl_devlist_args *devargs_saved = NULL; + struct btrfs_ioctl_devlist *devlist; + 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(*devargs) + sizeof(*devlist) * count; + + devargs_saved = devargs = malloc(sz); + if (!devargs) { + close(fd); + return -ENOMEM; + } + + memset(devargs, 0, sz); + devlist = (struct btrfs_ioctl_devlist *) (++devargs); + devargs = devargs_saved; + + devargs->count = count; + devargs->sz_self = (u64) sizeof(*devargs); + devlist->sz_self = (u64) sizeof(*devlist); + + ret = ioctl(fd, BTRFS_IOC_GET_DEVS, devargs); + e = errno; + if (ret == 1) { + /* out of size so reallocate */ + count = devargs->count; + free(devargs); + goto again; + } else if (ret < 0) { + printf("ERROR: scan_fsid ioctl failed - %s\n", + strerror(e)); + ret = -e; + goto out; + } + + /* Check if the kernel has the same struct as this */ + if (devargs->sz_self != sizeof(*devargs) || + devlist->sz_self != sizeof(*devlist)) { + fprintf(stderr, + "ERROR: version mismatch udevarg %lu udevlist %lu kdevarg %llu kdevlist %llu\n", + sizeof(*devargs), sizeof(*devlist), devargs->sz_self, devlist->sz_self); + goto out; + } + + /* ioctl returns devs count in count parameter*/ + + *out_count = devargs->count; + if (*out_count == 0) { + *out_devlist = NULL; + ret = 0; + goto out; + } + + + sz = sizeof(*devlist) * *out_count; + *out_devlist = malloc(sz); + if (*out_devlist == NULL) { + ret = -ENOMEM; + goto out; + } + + memcpy(*out_devlist, devlist, sz); + ret = 0; + +out: + free(devargs_saved); + close(fd); + return ret; +} + +static void local_usage(void) +{ + printf("btrfs_devlist [options]\n"\ + " Dumps the device list from the btrfs kernel "\ + "without altering at the user level\n"\ + " options:\n"\ + " -h|--help prints this usage\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + int ret; + u64 cnt; + struct btrfs_ioctl_devlist *devlist; + struct btrfs_ioctl_devlist *tmp_devlist; + + while(1) { + int long_index; + static struct option long_options[] = { + {"help", no_argument, NULL, 'h'}, + { NULL, no_argument, NULL, 0 } + }; + + int c = getopt_long(argc, argv, "h", long_options, + &long_index); + + if(c < 0) + break; + + switch(c) { + case 'h': + default: + local_usage(); + } + } + + ret = get_devlist(&devlist, &cnt); + if (ret) { + fprintf(stderr, "get devlist failed %d\n", ret); + return 1; + } + + tmp_devlist = devlist; + + print_header(); + while (cnt--) { + print_dev(devlist); + devlist++; + } + kfree(tmp_devlist); + return ret; +} diff --git a/ioctl.h b/ioctl.h index 4ea74ba..b8a1348 100644 --- a/ioctl.h +++ b/ioctl.h @@ -533,6 +533,8 @@ static inline char *btrfs_err_str(enum btrfs_err_code err_code) /* fs flags */ #define BTRFS_FS_MOUNTED (1LLU << 0) +#define BTRFS_FS_SEEDING (1LLU << 1) +#define BTRFS_FS_ROTATING (1LLU << 2) struct btrfs_ioctl_fslist { __u64 self_sz; /* in/out */ @@ -548,6 +550,54 @@ struct btrfs_ioctl_fslist_args { __u64 count; /* out */ }; +#define BTRFS_DEV_WRITEABLE (1LLU << 8) +#define BTRFS_DEV_IN_FS_MD (1LLU << 9) +#define BTRFS_DEV_MISSING (1LLU << 10) +#define BTRFS_DEV_CAN_DISCARD (1LLU << 11) +#define BTRFS_DEV_REPLACE_TGT (1LLU << 12) +#define BTRFS_DEV_RUN_PENDING (1LLU << 13) +#define BTRFS_DEV_NOBARRIERS (1LLU << 14) +#define BTRFS_DEV_STATS_VALID (1LLU << 15) +#define BTRFS_DEV_BDEV (1LLU << 16) + +struct btrfs_ioctl_devlist { + __u64 sz_self; + __u64 dev_root_addr; + __u64 fs_addr; + __u64 dev_addr; + __u64 seed_fs_addr; + __u64 sprout_fs_addr; + __u64 fs_num_devices; + __u64 fs_open_devices; + __u64 fs_rw_devices; + __u64 fs_missing_devices; + __u64 fs_total_rw_bytes; + __u64 fs_num_can_discard; + __u64 fs_total_devices; + __u64 gen; + __u64 flags; + __u64 devid; + __u64 total_bytes; + __u64 disk_total_bytes; + __u64 bytes_used; + __u64 type; + __u64 fmode; + __u32 io_align; + __u32 io_width; + __u32 sector_size; + __u8 fsid[BTRFS_FSID_SIZE]; + __u8 uuid[BTRFS_UUID_SIZE]; + __u8 seed_fsid[BTRFS_FSID_SIZE]; + __u8 sprout_fsid[BTRFS_UUID_SIZE]; + __u8 root_fsid[BTRFS_FSID_SIZE]; + __u8 name[BTRFS_PATH_NAME_MAX]; +}__attribute__ ((__packed__)); + +struct btrfs_ioctl_devlist_args { + __u64 sz_self; /* in/out */ + __u64 count; /* in/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, \ @@ -657,6 +707,8 @@ struct btrfs_ioctl_clone_range_args { struct btrfs_ioctl_feature_flags[2]) #define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ struct btrfs_ioctl_feature_flags[3]) +#define BTRFS_IOC_GET_DEVS _IOWR(BTRFS_IOCTL_MAGIC, 59, \ + struct btrfs_ioctl_devlist_args) #ifdef __cplusplus } #endif -- 2.0.0.153.g79dcccc ^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-07-25 12:30 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-05-16 14:03 [PATCH 0/1 not for integration] btrfs-devlist Anand Jain 2014-05-16 14:03 ` [PATCH 1/1] btrfs: introduce BTRFS_IOC_GET_DEVS Anand Jain 2014-05-16 14:03 ` [PATCH 1/1] btrfs-progs: introduce btrfs-devlist Anand Jain -- strict thread matches above, loose matches on Subject: below -- 2014-07-25 12:33 [PATCH not for integration] btrfs-devlist: dumps btrfs_device and btrfs_fs_devices from kernel Anand Jain 2014-07-25 12:33 ` [PATCH 1/1] btrfs-progs: introduce btrfs-devlist Anand Jain
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).