Add a command to show all of the btrfs filesystems on the box (btrfs-show)
authorChris Mason <chris.mason@oracle.com>
Tue, 22 Apr 2008 18:06:31 +0000 (14:06 -0400)
committerDavid Woodhouse <dwmw2@hera.kernel.org>
Tue, 22 Apr 2008 18:06:31 +0000 (14:06 -0400)
Makefile
btrfs-show.c [new file with mode: 0644]
disk-io.c
mkfs.c
utils.c
utils.h
volumes.c
volumes.h

index 63fddcf..e6fbf62 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@ prefix ?= /usr/local
 bindir = $(prefix)/bin
 LIBS=-luuid
 
-progs = btrfsctl btrfsck mkfs.btrfs debug-tree quick-test
+progs = btrfsctl btrfsck mkfs.btrfs debug-tree quick-test btrfs-show
 
 # make C=1 to enable sparse
 ifdef C
@@ -34,6 +34,9 @@ all: $(progs)
 btrfsctl: $(objects) btrfsctl.o
        gcc $(CFLAGS) -o btrfsctl btrfsctl.o $(objects) $(LDFLAGS) $(LIBS)
 
+btrfs-show: $(objects) btrfs-show.o
+       gcc $(CFLAGS) -o btrfs-show btrfs-show.o $(objects) $(LDFLAGS) $(LIBS)
+
 btrfsck: $(objects) btrfsck.o bit-radix.o
        gcc $(CFLAGS) -o btrfsck btrfsck.o $(objects) bit-radix.o $(LDFLAGS) $(LIBS)
 
diff --git a/btrfs-show.c b/btrfs-show.c
new file mode 100644 (file)
index 0000000..5c370f1
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#define _GNU_SOURCE
+#ifndef __CHECKER__
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include "ioctl.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <uuid/uuid.h>
+#include "kerncompat.h"
+#include "ctree.h"
+#include "transaction.h"
+#include "utils.h"
+#include "volumes.h"
+
+static int uuid_search(struct btrfs_fs_devices *fs_devices, char *search)
+{
+       struct list_head *cur;
+       struct btrfs_device *device;
+
+       list_for_each(cur, &fs_devices->devices) {
+               device = list_entry(cur, struct btrfs_device, dev_list);
+               if ((device->label && strcmp(device->label, search) == 0) ||
+                   strcmp(device->name, search) == 0)
+                       return 1;
+       }
+       return 0;
+}
+
+static void print_one_uuid(struct btrfs_fs_devices *fs_devices)
+{
+       char uuidbuf[37];
+       struct list_head *cur;
+       struct btrfs_device *device;
+       char *super_bytes_used;
+       u64 devs_found = 0;
+       u64 total;
+
+       uuid_unparse(fs_devices->fsid, uuidbuf);
+       device = list_entry(fs_devices->devices.next, struct btrfs_device,
+                           dev_list);
+       if (device->label && device->label[0])
+               printf("Label: %s ", device->label);
+       else
+               printf("Label: none ");
+
+       super_bytes_used = pretty_sizes(device->super_bytes_used);
+
+       total = device->total_devs;
+       printf(" uuid: %s\n\tTotal devices %llu FS bytes used %s\n", uuidbuf,
+              (unsigned long long)total, super_bytes_used);
+
+       free(super_bytes_used);
+
+       list_for_each(cur, &fs_devices->devices) {
+               char *total_bytes;
+               char *bytes_used;
+               device = list_entry(cur, struct btrfs_device, dev_list);
+               total_bytes = pretty_sizes(device->total_bytes);
+               bytes_used = pretty_sizes(device->bytes_used);
+               printf("\tdevid %4llu size %s used %s path %s\n",
+                      (unsigned long long)device->devid,
+                      total_bytes, bytes_used, device->name);
+               free(total_bytes);
+               free(bytes_used);
+               devs_found++;
+       }
+       if (devs_found < total) {
+               printf("\t*** Some devices missing\n");
+       }
+       printf("\n");
+}
+
+static void print_usage(void)
+{
+       fprintf(stderr, "usage: btrfs-show [search label or device]\n");
+       exit(1);
+}
+
+static struct option long_options[] = {
+       /* { "byte-count", 1, NULL, 'b' }, */
+       { 0, 0, 0, 0}
+};
+
+int main(int ac, char **av)
+{
+       struct list_head *all_uuids;
+       struct btrfs_fs_devices *fs_devices;
+       struct list_head *cur_uuid;
+       char *search = NULL;
+       int ret;
+       int option_index = 0;
+
+       while(1) {
+               int c;
+               c = getopt_long(ac, av, "", long_options,
+                               &option_index);
+               if (c < 0)
+                       break;
+               switch(c) {
+                       default:
+                               print_usage();
+               }
+       }
+       ac = ac - optind;
+       if (ac != 0) {
+               search = av[optind];
+       }
+
+       ret = btrfs_scan_one_dir("/dev", 0);
+       if (ret)
+               fprintf(stderr, "error %d while scanning\n", ret);
+
+       all_uuids = btrfs_scanned_uuids();
+       list_for_each(cur_uuid, all_uuids) {
+               fs_devices = list_entry(cur_uuid, struct btrfs_fs_devices,
+                                       list);
+               if (search && uuid_search(fs_devices, search) == 0)
+                       continue;
+               print_one_uuid(fs_devices);
+       }
+       return 0;
+}
+
index 3080e62..dc82a96 100644 (file)
--- a/disk-io.c
+++ b/disk-io.c
@@ -493,8 +493,6 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr)
                fprintf(stderr, "No valid Btrfs found on %s\n", path);
                return NULL;
        }
-       fprintf(stderr, "found Btrfs on %s with %lu devices\n", path,
-               (unsigned long)total_devs);
 
        if (total_devs != 1) {
                ret = btrfs_scan_for_fsid(fs_devices, total_devs, 1);
diff --git a/mkfs.c b/mkfs.c
index bb2c58e..a629e49 100644 (file)
--- a/mkfs.c
+++ b/mkfs.c
@@ -296,6 +296,7 @@ int main(int ac, char **av)
        struct btrfs_root *root;
        struct btrfs_trans_handle *trans;
        char *label = NULL;
+       char *first_file;
        u64 block_count = 0;
        u64 dev_block_count = 0;
        u64 blocks[6];
@@ -375,6 +376,7 @@ int main(int ac, char **av)
                exit(1);
        }
        first_fd = fd;
+       first_file = file;
        ret = btrfs_prepare_device(fd, file, zero_end, &dev_block_count);
        if (block_count == 0)
                block_count = dev_block_count;
@@ -394,12 +396,6 @@ int main(int ac, char **av)
                fprintf(stderr, "failed to setup the root directory\n");
                exit(1);
        }
-       printf("fs created label %s on %s\n\tnodesize %u leafsize %u "
-              "sectorsize %u bytes %llu\n",
-              label, file, nodesize, leafsize, sectorsize,
-              (unsigned long long)block_count);
-
-       free(label);
        root = open_ctree(file, 0);
        trans = btrfs_start_transaction(root, 1);
 
@@ -452,9 +448,17 @@ int main(int ac, char **av)
 raid_groups:
        ret = create_raid_groups(trans, root, data_profile,
                                 metadata_profile);
+
+       printf("fs created label %s on %s\n\tnodesize %u leafsize %u "
+           "sectorsize %u size %s\n",
+           label, first_file, nodesize, leafsize, sectorsize,
+           pretty_sizes(btrfs_super_total_bytes(&root->fs_info->super_copy)));
+
        btrfs_commit_transaction(trans, root);
        ret = close_ctree(root);
        BUG_ON(ret);
+
+       free(label);
        return 0;
 }
 
diff --git a/utils.c b/utils.c
index b9d85ac..5845903 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -774,3 +774,29 @@ brelse:
 out:
        return ret;
 }
+
+static char *size_strs[] = { "", "KB", "MB", "GB", "TB",
+                           "PB", "EB", "ZB", "YB"};
+char *pretty_sizes(u64 size)
+{
+       int num_divs = 0;
+       u64 last_size = size;
+       u64 fract_size = size;
+       float fraction;
+       char *pretty;
+
+       while(size > 0) {
+               fract_size = last_size;
+               last_size = size;
+               size /= 1024;
+               num_divs++;
+       }
+       if (num_divs > ARRAY_SIZE(size_strs))
+               return NULL;
+
+       fraction = (float)fract_size / 1024;
+       pretty = malloc(16);
+       sprintf(pretty, "%.2f%s", fraction, size_strs[num_divs-1]);
+       return pretty;
+}
+
diff --git a/utils.h b/utils.h
index f93f8b3..18707d0 100644 (file)
--- a/utils.h
+++ b/utils.h
@@ -39,4 +39,5 @@ int btrfs_scan_one_dir(char *dirname, int run_ioctl);
 int check_mounted(char *devicename);
 int btrfs_device_already_in_root(struct btrfs_root *root, int fd,
                                 int super_offset);
+char *pretty_sizes(u64 size);
 #endif
index 97aa57a..d3eeaf9 100644 (file)
--- a/volumes.c
+++ b/volumes.c
@@ -119,6 +119,13 @@ static int device_list_add(const char *path,
                        kfree(device);
                        return -ENOMEM;
                }
+               device->label = kstrdup(disk_super->label, GFP_NOFS);
+               device->total_devs = btrfs_super_num_devices(disk_super);
+               device->super_bytes_used = btrfs_super_bytes_used(disk_super);
+               device->total_bytes =
+                       btrfs_stack_device_total_bytes(&disk_super->dev_item);
+               device->bytes_used =
+                       btrfs_stack_device_bytes_used(&disk_super->dev_item);
                list_add(&device->dev_list, &fs_devices->devices);
        }
 
@@ -156,13 +163,13 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices, int flags)
 
        list_for_each(cur, head) {
                device = list_entry(cur, struct btrfs_device, dev_list);
+
                fd = open(device->name, flags);
-printk("opening %s devid %llu fd %d\n", device->name,
-       (unsigned long long)device->devid, fd);
                if (fd < 0) {
                        ret = -errno;
                        goto fail;
                }
+
                if (device->devid == fs_devices->latest_devid)
                        fs_devices->latest_bdev = fd;
                if (device->devid == fs_devices->lowest_devid)
@@ -205,12 +212,6 @@ int btrfs_scan_one_device(int fd, const char *path,
        *total_devs = btrfs_super_num_devices(disk_super);
        uuid_unparse(disk_super->fsid, uuidbuf);
 
-       printf("device ");
-       if (disk_super->label[0])
-               printf("label %s ", disk_super->label);
-       else
-               printf("fsuuid %s ", uuidbuf);
-       printf("devid %llu %s\n", (unsigned long long)devid, path);
        ret = device_list_add(path, disk_super, devid, fs_devices_ret);
 
 error_brelse:
@@ -764,7 +765,6 @@ again:
        *num_bytes = chunk_bytes_by_type(type, calc_size,
                                         num_stripes, sub_stripes);
        index = 0;
-printk("new chunk type %Lu start %Lu size %Lu\n", type, key.offset, *num_bytes);
        while(index < num_stripes) {
                struct btrfs_stripe *stripe;
                BUG_ON(list_empty(&private_devs));
@@ -781,10 +781,7 @@ printk("new chunk type %Lu start %Lu size %Lu\n", type, key.offset, *num_bytes);
                             BTRFS_FIRST_CHUNK_TREE_OBJECTID, key.offset,
                             calc_size, &dev_offset);
                BUG_ON(ret);
-printk("\talloc chunk size %llu from dev %llu phys %llu\n",
-       (unsigned long long)calc_size,
-       (unsigned long long)device->devid,
-       (unsigned long long)dev_offset);
+
                device->bytes_used += calc_size;
                ret = btrfs_update_device(trans, device);
                BUG_ON(ret);
@@ -1297,3 +1294,7 @@ error:
        return ret;
 }
 
+struct list_head *btrfs_scanned_uuids(void)
+{
+       return &fs_uuids;
+}
index 07d1c0a..9aec0e3 100644 (file)
--- a/volumes.h
+++ b/volumes.h
@@ -28,6 +28,11 @@ struct btrfs_device {
 
        char *name;
 
+       /* these are read off the super block, only in the progs */
+       char *label;
+       u64 total_devs;
+       u64 super_bytes_used;
+
        /* the internal btrfs device id */
        u64 devid;
 
@@ -109,4 +114,5 @@ int btrfs_scan_one_device(int fd, const char *path,
 int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len);
 int btrfs_bootstrap_super_map(struct btrfs_mapping_tree *map_tree,
                              struct btrfs_fs_devices *fs_devices);
+struct list_head *btrfs_scanned_uuids(void);
 #endif