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
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)
--- /dev/null
+/*
+ * 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;
+}
+
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);
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];
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;
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);
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;
}
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;
+}
+
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
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);
}
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)
*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:
*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));
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);
return ret;
}
+struct list_head *btrfs_scanned_uuids(void)
+{
+ return &fs_uuids;
+}
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;
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