From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from aserp1040.oracle.com ([141.146.126.69]:17258 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751830AbaBXLt3 (ORCPT ); Mon, 24 Feb 2014 06:49:29 -0500 Received: from ucsinet22.oracle.com (ucsinet22.oracle.com [156.151.31.94]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id s1OBnSYK005905 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 24 Feb 2014 11:49:29 GMT Received: from userz7022.oracle.com (userz7022.oracle.com [156.151.31.86]) by ucsinet22.oracle.com (8.14.5+Sun/8.14.5) with ESMTP id s1OBnSNF010714 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 24 Feb 2014 11:49:28 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by userz7022.oracle.com (8.14.5+Sun/8.14.4) with ESMTP id s1OBnRep010700 for ; Mon, 24 Feb 2014 11:49:27 GMT From: Anand Jain To: linux-btrfs@vger.kernel.org Subject: [PATCH v2] btrfs-progs: introduce btrfs-devlist Date: Mon, 24 Feb 2014 19:48:44 +0800 Message-Id: <1393242525-18587-1-git-send-email-Anand.Jain@oracle.com> Sender: linux-btrfs-owner@vger.kernel.org List-ID: From: Anand Jain 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 --- v2: add more parameter to get from the kernel .gitignore | 1 + Makefile | 4 +- btrfs-devlist.c | 249 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ioctl.h | 49 +++++++++++ 4 files changed, 301 insertions(+), 2 deletions(-) create mode 100644 btrfs-devlist.c diff --git a/.gitignore b/.gitignore index ab8b81c..0928374 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,4 @@ libbtrfs.a libbtrfs.so libbtrfs.so.0 libbtrfs.so.0.1 +btrfs-devlist diff --git a/Makefile b/Makefile index f99ca7c..2a52c17 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,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 = ; see $($(subst...)) rules below @@ -226,7 +226,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..baaca17 --- /dev/null +++ b/btrfs-devlist.c @@ -0,0 +1,249 @@ +/* + * 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 +#include +#include +#include +#include + +#include "ctree.h" +#include "ioctl.h" +#include "commands.h" +#include "utils.h" + +void print_header(void) +{ + printf( + "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%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", + 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); + devargs->count = count; + + 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; + } + + /* ioctl returns devs count in count parameter*/ + + *out_count = devargs->count; + if (*out_count == 0) { + *out_devlist = NULL; + ret = 0; + goto out; + } + + devlist = (struct btrfs_ioctl_devlist *) (++devargs); + + 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 d8186d8..92909cf 100644 --- a/ioctl.h +++ b/ioctl.h @@ -508,6 +508,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 */ @@ -523,6 +525,51 @@ 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_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 self_sz; /* 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, \ @@ -625,6 +672,8 @@ struct btrfs_ioctl_clone_range_args { struct btrfs_ioctl_dedup_args) #define BTRFS_IOC_GET_FSLIST _IOWR(BTRFS_IOCTL_MAGIC, 56, \ struct btrfs_ioctl_fslist_args) +#define BTRFS_IOC_GET_DEVS _IOWR(BTRFS_IOCTL_MAGIC, 58, \ + struct btrfs_ioctl_devlist_args) #ifdef __cplusplus } #endif -- 1.8.4.2