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.j...@oracle.com>
---
 .gitignore      |    1 +
 Makefile        |    4 +-
 btrfs-devlist.c |  230 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ioctl.h         |   45 +++++++++++
 4 files changed, 278 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 = <list of 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..7d9ef73
--- /dev/null
+++ b/btrfs-devlist.c
@@ -0,0 +1,230 @@
+/*
+ * 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(
+               "fsid "\
+               "uuid "\
+               "name \n"\
+               "\tfs_latest_devid "\
+               "fs_latest_trans "\
+               "fs_num_devices "\
+               "fs_open_devices "\
+               "fs_rw_devices "\
+               "fs_missing_devices "\
+               "fs_total_rw_bytes "\
+               "fs_num_can_discard "\
+               "fs_total_devices \n"\
+               "\tgen "\
+               "devid "\
+               "total_bytes "\
+               "disk_total_bytes "\
+               "bytes_used "\
+               "type "\
+               "io_align "\
+               "io_width "\
+               "sector_size \n"\
+               "\tflags\n");
+}
+
+void print_dev(struct btrfs_ioctl_devlist *dev)
+{
+       char uuid[BTRFS_UUID_UNPARSED_SIZE];
+       char fsid[BTRFS_UUID_UNPARSED_SIZE];
+
+       uuid_unparse(dev->uuid, uuid);
+       uuid_unparse(dev->fsid, fsid);
+
+       printf("\n%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\n"\
+               "\t%s|%s|%s\n"\
+               "\t%s|%s|%s|%s|%s|%s|%s|%s|%s\n",
+               fsid,
+               uuid,
+               dev->name,
+               dev->fs_latest_devid,
+               dev->fs_latest_trans,
+               dev->fs_num_devices,
+               dev->fs_open_devices,
+               dev->fs_rw_devices,
+               dev->fs_missing_devices,
+               dev->fs_total_rw_bytes,
+               dev->fs_num_can_discard,
+               dev->fs_total_devices,
+               dev->gen,
+               dev->devid,
+               dev->total_bytes,
+               dev->disk_total_bytes,
+               dev->bytes_used,
+               dev->type,
+               dev->io_align,
+               dev->io_width,
+               dev->sector_size,
+               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_SUBSTITUTED ? 
"Substituted":"not_Substituted",
+               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");
+}
+
+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 f84300b..7343a33 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,47 @@ 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_SUBSTITUTED  (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)
+
+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;
+       __u32 io_align;
+       __u32 io_width;
+       __u32 sector_size;
+       __u8 fsid[BTRFS_FSID_SIZE];
+       __u8 uuid[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, \
@@ -631,6 +674,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

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to