Accepting request 232437 from filesystems

- update to upstream 3.14.1
- mkfs:
  - fix TRIM detection
  - do not zero-out end of device unconditionally
  - no crash with --features option
- fsck:
  - clear log tree in repair mode
  - check reloc roots
- btrfs - reworked space reporting (bnc#873106)
  - btrfs fi usage - new command
  - btrfs dev usage - new command
  - btrfs fi df - enhanced output with GlobalReserve
- Removed patches:
  * 0001-btrfs-progs-move-arg_strtou64-to-a-separate-file-for.patch
- Added patches:
  * 0001-Btrfs-progs-fix-check-to-test-trim-support.patch
  * 0002-Btrfs-progs-fsck-fix-double-free-memory-crash.patch
  * 0003-Btrfs-progs-mkfs-Remove-zero_end-1-since-it-has-been.patch
  * 0004-btrfs-progs-fix-wrong-max-system-array-size-check-in.patch
  * 0005-btrfs-progs-move-arg_strtou64-to-a-separate-file-for.patch
  * 0006-Btrfs-progs-fsck-clear-out-log-tree-in-repair-mode.patch
  * 0007-Btrfs-progs-fsck-avoid-pinning-same-block-several-ti.patch
  * 0008-Btrfs-progs-fsck-add-ability-to-check-reloc-roots.patch
  * 0009-btrfs-progs-prevent-close_root-if-the-root-to-close-.patch
  * 0010-btrfs-progs-fix-mkfs.btrfs-segfault-with-features-op.patch
  * 0011-btrfs-progs-Enhance-the-command-btrfs-filesystem-df.patch
  * 0012-btrfs-progs-Add-helpers-functions-to-handle-the-prin.patch
  * 0013-btrfs-progs-Add-command-btrfs-filesystem-disk-usage.patch
  * 0014-btrfs-progs-Add-btrfs-device-disk-usage-command.patch
  * 0015-btrfs-progs-cleanup-dead-return-after-usage-for-fi-d.patch
  * 0016-btrfs-progs-Fix-memleak-in-get_raid56_used.patch
  * 0017-Btrfs-progs-fi-usage-free-memory-if-realloc-fails.patch
  * 0018-btrfs-progs-read-global-reserve-size-from-space-info.patch
  * 0019-btrfs-progs-add-original-df-and-rename-disk_usage-to.patch
  * 0020-btrfs-progs-move-device-usage-to-cmds-device-more-cl.patch
  * 0021-btrfs-progs-check-if-we-can-t-get-info-from-ioctls-d.patch
  * 0022-btrfs-progs-zero-out-structures-before-calling-ioctl.patch
  * 0023-btrfs-progs-print-B-for-bytes.patch
  * 0024-btrfs-progs-Print-more-info-about-device-sizes.patch
  * 0025-btrfs-progs-compare-unallocated-space-against-the-co.patch
  * 0026-btrfs-progs-add-section-of-overall-filesystem-usage.patch
  * 0027-btrfs-progs-cleanup-filesystem-device-usage-code.patch
  * 0028-btrfs-progs-extend-pretty-printers-with-unit-mode.patch
  * 0029-btrfs-progs-replace-df_pretty_sizes-with-pretty_size.patch
  * 0030-btrfs-progs-clean-up-return-codes-and-paths.patch
  * 0031-btrfs-progs-move-global-reserve-to-overall-summary.patch (forwarded request 232435 from dsterba)

OBS-URL: https://build.opensuse.org/request/show/232437
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/btrfsprogs?expand=0&rev=40
This commit is contained in:
Stephan Kulow 2014-05-06 11:39:23 +00:00 committed by Git OBS Bridge
commit 8188eb53c8
36 changed files with 5112 additions and 30 deletions

View File

@ -0,0 +1,30 @@
From f7025683c14debd0ca3ee21dc64699a185849b35 Mon Sep 17 00:00:00 2001
From: Rakesh Pandit <rakesh@tuxera.com>
Date: Tue, 22 Apr 2014 16:30:27 +0300
Subject: [PATCH 03/42] Btrfs-progs: fix check to test trim support
It was added in 25d82d22 but broke recently in 4724d7b0 while making
discard interruptible.
Signed-off-by: Rakesh Pandit <rakesh@tuxera.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
utils.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/utils.c b/utils.c
index 3e9c527a492c..187ad3b9b12b 100644
--- a/utils.c
+++ b/utils.c
@@ -626,7 +626,7 @@ int btrfs_prepare_device(int fd, char *file, int zero_end, u64 *block_count_ret,
* is not necessary for the mkfs functionality but just an
* optimization.
*/
- if (discard_blocks(fd, 0, 0) == 0) {
+ if (discard_range(fd, 0, 0) == 0) {
fprintf(stderr, "Performing full device TRIM (%s) ...\n",
pretty_size(block_count));
discard_blocks(fd, 0, block_count);
--
1.9.0

View File

@ -0,0 +1,35 @@
From 4c92a4a31b51950d8d0f167a0391586803802f4c Mon Sep 17 00:00:00 2001
From: Rakesh Pandit <rakesh@tuxera.com>
Date: Sun, 20 Apr 2014 16:17:53 +0300
Subject: [PATCH 08/42] Btrfs-progs: fsck: fix double free memory crash
Fix double free of memory if btrfs_open_devices fails:
*** Error in `btrfs': double free or corruption (fasttop): 0x000000000066e020 ***
Crash happened because when open failed on device inside
btrfs_open_devices it freed all memory by calling btrfs_close_devices but
inside disk-io.c we call btrfs_close_again it again.
Signed-off-by: Rakesh Pandit <rakesh@tuxera.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
disk-io.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/disk-io.c b/disk-io.c
index 19b95a724f1b..8db0335bc81b 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -1091,8 +1091,7 @@ static struct btrfs_fs_info *__open_ctree_fd(int fp, const char *path,
ret = btrfs_open_devices(fs_devices, oflags);
if (ret)
- goto out_devices;
-
+ goto out;
disk_super = fs_info->super_copy;
if (!(flags & OPEN_CTREE_RECOVER_SUPER))
--
1.9.0

View File

@ -0,0 +1,44 @@
From e7cd3d7fa55bb26d9b4579fececc863db6555d97 Mon Sep 17 00:00:00 2001
From: Li Yang <liyang.fnst@cn.fujitsu.com>
Date: Mon, 21 Apr 2014 05:38:08 -0400
Subject: [PATCH 09/42] Btrfs-progs: mkfs: Remove 'zero_end =1' since it has
been set to a value
In utils.c, zero_end is used as a parameter, should not force it to 1.
In mkfs.c, zero_end is set to 1 or 0(-b) at the beginning, should not
force it to 1 unconditionally.
Signed-off-by: Li Yang <liyang.fnst@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
mkfs.c | 1 -
utils.c | 1 -
2 files changed, 2 deletions(-)
diff --git a/mkfs.c b/mkfs.c
index dbd83f5ce168..f2b577922c9e 100644
--- a/mkfs.c
+++ b/mkfs.c
@@ -1543,7 +1543,6 @@ int main(int ac, char **av)
btrfs_register_one_device(file);
- zero_end = 1;
while (dev_cnt-- > 0) {
int old_mixed = mixed;
diff --git a/utils.c b/utils.c
index 44c0e4ab39f2..29953d9dd2a9 100644
--- a/utils.c
+++ b/utils.c
@@ -613,7 +613,6 @@ int btrfs_prepare_device(int fd, char *file, int zero_end, u64 *block_count_ret,
}
if (max_block_count)
block_count = min(block_count, max_block_count);
- zero_end = 1;
if (block_count < 1024 * 1024 * 1024 && !(*mixed)) {
printf("SMALL VOLUME: forcing mixed metadata/data groups\n");
--
1.9.0

View File

@ -0,0 +1,34 @@
From b014a6150ebaa97cee780fca184df626c173c30e Mon Sep 17 00:00:00 2001
From: Gui Hecheng <guihc.fnst@cn.fujitsu.com>
Date: Mon, 21 Apr 2014 20:13:31 +0800
Subject: [PATCH 10/42] btrfs-progs: fix wrong max system array size check in
user space
For system chunk array,
We copy a "disk_key" and an chunk item each time,
so there should be enough space to hold both of them,
not only the chunk item.
Signed-off-by: Gui Hecheng <guihc.fnst@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
volumes.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/volumes.c b/volumes.c
index 77ffd3252c38..b39f374305bc 100644
--- a/volumes.c
+++ b/volumes.c
@@ -630,7 +630,8 @@ int btrfs_add_system_chunk(struct btrfs_trans_handle *trans,
u8 *ptr;
array_size = btrfs_super_sys_array_size(super_copy);
- if (array_size + item_size > BTRFS_SYSTEM_CHUNK_ARRAY_SIZE)
+ if (array_size + item_size + sizeof(disk_key)
+ > BTRFS_SYSTEM_CHUNK_ARRAY_SIZE)
return -EFBIG;
ptr = super_copy->sys_chunk_array + array_size;
--
1.9.0

View File

@ -1,23 +1,25 @@
From f555e06e2d266f52cdeb12218f8175eba2a17020 Mon Sep 17 00:00:00 2001
From b5230eca8a9214c7290ed818ff9792eb5d3e142b Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Fri, 11 Apr 2014 13:22:50 +0200
Subject: [PATCH] btrfs-progs: move arg_strtou64 to a separate file for library
Subject: [PATCH 12/42] btrfs-progs: move arg_strtou64 to a separate file for
library
Linking with libbtrfs fails because arg_strtou64 is not defined and we
cannot just add utils.o to library objects because it's not
library-clean.
Reported-by: Arvin Schnell <aschnell@suse.com>
Reported-by: Anton Farygin <rider@altlinux.org>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
Makefile | 5 +++--
libutils.c | 43 +++++++++++++++++++++++++++++++++++++++++++
utils-lib.c | 42 ++++++++++++++++++++++++++++++++++++++++++
utils.c | 33 ---------------------------------
3 files changed, 46 insertions(+), 35 deletions(-)
create mode 100644 libutils.c
3 files changed, 45 insertions(+), 35 deletions(-)
create mode 100644 utils-lib.c
diff --git a/Makefile b/Makefile
index da0519766443..9ae7115d23a3 100644
index 51d53fadf5af..76565e8b2307 100644
--- a/Makefile
+++ b/Makefile
@@ -9,14 +9,15 @@ CFLAGS = -g -O1 -fno-strict-aliasing
@ -26,7 +28,7 @@ index da0519766443..9ae7115d23a3 100644
extent-cache.o extent_io.o volumes.o utils.o repair.o \
- qgroup.o raid6.o free-space-cache.o list_sort.o props.o
+ qgroup.o raid6.o free-space-cache.o list_sort.o props.o \
+ libutils.o
+ utils-lib.o
cmds_objects = cmds-subvolume.o cmds-filesystem.o cmds-device.o cmds-scrub.o \
cmds-inspect.o cmds-balance.o cmds-send.o cmds-receive.o \
cmds-quota.o cmds-qgroup.o cmds-replace.o cmds-check.o \
@ -34,16 +36,16 @@ index da0519766443..9ae7115d23a3 100644
cmds-property.o
libbtrfs_objects = send-stream.o send-utils.o rbtree.o btrfs-list.o crc32c.o \
- uuid-tree.o
+ uuid-tree.o libutils.o
+ uuid-tree.o utils-lib.o
libbtrfs_headers = send-stream.h send-utils.h send.h rbtree.h btrfs-list.h \
crc32c.h list.h kerncompat.h radix-tree.h extent-cache.h \
extent_io.h ioctl.h ctree.h btrfsck.h
diff --git a/libutils.c b/libutils.c
diff --git a/utils-lib.c b/utils-lib.c
new file mode 100644
index 000000000000..074f771e0b6e
index 000000000000..9d53c6e5c710
--- /dev/null
+++ b/libutils.c
@@ -0,0 +1,43 @@
+++ b/utils-lib.c
@@ -0,0 +1,42 @@
+#define _GNU_SOURCE
+
+#include "kerncompat.h"
@ -56,8 +58,8 @@ index 000000000000..074f771e0b6e
+#endif /* BTRFS_FLAT_INCLUDES */
+
+/*
+ * This function should be only used when parsing
+ * command arg, it won't return error to it's
+ * This function should be only used when parsing command arg, it won't return
+ * error to its caller and rather exit directly just like usage().
+ */
+u64 arg_strtou64(const char *str)
+{
@ -70,10 +72,10 @@ index 000000000000..074f771e0b6e
+ str);
+ exit(1);
+ }
+
+ /*
+ * if we pass a negative number to strtoull,
+ * it will return an unexpected number to us,
+ * so let's do the check ourselves.
+ * if we pass a negative number to strtoull, it will return an
+ * unexpected number to us, so let's do the check ourselves.
+ */
+ if (str[0] == '-') {
+ fprintf(stderr, "ERROR: %s: negative value is invalid.\n",
@ -86,12 +88,11 @@ index 000000000000..074f771e0b6e
+ }
+ return value;
+}
+
diff --git a/utils.c b/utils.c
index 3e9c527a492c..134f43a76fe9 100644
index 29953d9dd2a9..e130849c7bb5 100644
--- a/utils.c
+++ b/utils.c
@@ -1539,39 +1539,6 @@ scan_again:
@@ -1538,39 +1538,6 @@ scan_again:
return 0;
}

View File

@ -0,0 +1,71 @@
From 3ecff1d8f1eaa5e0d065c439cf72032dd01da751 Mon Sep 17 00:00:00 2001
From: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
Date: Thu, 24 Apr 2014 11:19:16 +0800
Subject: [PATCH 13/42] Btrfs-progs: fsck: clear out log tree in repair mode
Repair mode will commit transaction which will make us
fail to load log tree anymore.
Give a warning to common users, if they really want to
coninue, we will clear out log tree.
Signed-off-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-check.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/cmds-check.c b/cmds-check.c
index 1fe97b3a38c0..7457618fb702 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -6616,6 +6616,22 @@ out:
return ret;
}
+static int zero_log_tree(struct btrfs_root *root)
+{
+ struct btrfs_trans_handle *trans;
+ int ret;
+
+ trans = btrfs_start_transaction(root, 1);
+ if (IS_ERR(trans)) {
+ ret = PTR_ERR(trans);
+ return ret;
+ }
+ btrfs_set_super_log_root(root->fs_info->super_copy, 0);
+ btrfs_set_super_log_root_level(root->fs_info->super_copy, 0);
+ ret = btrfs_commit_transaction(trans, root);
+ return ret;
+}
+
static struct option long_options[] = {
{ "super", 1, NULL, 's' },
{ "repair", 0, NULL, 0 },
@@ -6720,6 +6736,23 @@ int cmd_check(int argc, char **argv)
}
root = info->fs_root;
+ /*
+ * repair mode will force us to commit transaction which
+ * will make us fail to load log tree when mounting.
+ */
+ if (repair && btrfs_super_log_root(info->super_copy)) {
+ ret = ask_user("repair mode will force to clear out log tree, Are you sure?");
+ if (!ret) {
+ ret = 1;
+ goto close_out;
+ }
+ ret = zero_log_tree(root);
+ if (ret) {
+ fprintf(stderr, "fail to zero log tree\n");
+ goto close_out;
+ }
+ }
+
uuid_unparse(info->super_copy->fsid, uuidbuf);
printf("Checking filesystem on %s\nUUID: %s\n", argv[optind], uuidbuf);
--
1.9.0

View File

@ -0,0 +1,38 @@
From 20e9fa6f969b3c6a4b3ff9941c351e90320aed61 Mon Sep 17 00:00:00 2001
From: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
Date: Thu, 24 Apr 2014 11:19:17 +0800
Subject: [PATCH 14/42] Btrfs-progs: fsck: avoid pinning same block several
times
This can not only give some speedups but also avoid forever loop
with a really broken filesystem.
Signed-off-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-check.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/cmds-check.c b/cmds-check.c
index 7457618fb702..57d3f36eea1f 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -6190,6 +6190,15 @@ static int pin_down_tree_blocks(struct btrfs_fs_info *fs_info,
int ret;
int i;
+ /*
+ * If we have pinned this block before, don't pin it again.
+ * This can not only avoid forever loop with broken filesystem
+ * but also give us some speedups.
+ */
+ if (test_range_bit(&fs_info->pinned_extents, eb->start,
+ eb->start + eb->len - 1, EXTENT_DIRTY, 0))
+ return 0;
+
btrfs_pin_extent(fs_info, eb->start, eb->len);
leafsize = btrfs_super_leafsize(fs_info->super_copy);
--
1.9.0

View File

@ -0,0 +1,92 @@
From 26bf4f0a10dd192e4dc5494d2cf9398c666eaab6 Mon Sep 17 00:00:00 2001
From: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
Date: Thu, 24 Apr 2014 18:51:10 +0800
Subject: [PATCH 15/42] Btrfs-progs: fsck: add ability to check reloc roots
When encountering system crash or balance enospc errors,
there maybe still some reloc roots left.
The way we store reloc root is different from fs root:
reloc root's root key(BTRFS_RELOC_TREE_OBJECTID, ROOT_ITEM, objectid)
fs root's root key(objectid, ROOT_ITEM, -1)
reloc data's root key(BTRFS_DATA_RELOC_TREE_OBJECTID, ROOT_ITEM, 0)
So this patch use right key to search corresponding root node, and
avoid using normal fs root cache for reloc roots.
Signed-off-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-check.c | 33 ++++++++++++++++++++++++++-------
1 file changed, 26 insertions(+), 7 deletions(-)
diff --git a/cmds-check.c b/cmds-check.c
index 57d3f36eea1f..103efc5718ec 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -299,8 +299,22 @@ static struct inode_record *clone_inode_rec(struct inode_record *orig_rec)
return rec;
}
-static void print_inode_error(int errors)
+static void print_inode_error(struct btrfs_root *root, struct inode_record *rec)
{
+ u64 root_objectid = root->root_key.objectid;
+ int errors = rec->errors;
+
+ if (!errors)
+ return;
+ /* reloc root errors, we print its corresponding fs root objectid*/
+ if (root_objectid == BTRFS_TREE_RELOC_OBJECTID) {
+ root_objectid = root->root_key.offset;
+ fprintf(stderr, "reloc");
+ }
+ fprintf(stderr, "root %llu inode %llu errors %x",
+ (unsigned long long) root_objectid,
+ (unsigned long long) rec->ino, rec->errors);
+
if (errors & I_ERR_NO_INODE_ITEM)
fprintf(stderr, ", no inode item");
if (errors & I_ERR_NO_ORPHAN_ITEM)
@@ -1598,10 +1612,7 @@ static int check_inode_recs(struct btrfs_root *root,
rec->errors |= I_ERR_NO_INODE_ITEM;
if (rec->found_link != rec->nlink)
rec->errors |= I_ERR_LINK_COUNT_WRONG;
- fprintf(stderr, "root %llu inode %llu errors %x",
- (unsigned long long) root->root_key.objectid,
- (unsigned long long) rec->ino, rec->errors);
- print_inode_error(rec->errors);
+ print_inode_error(root, rec);
list_for_each_entry(backref, &rec->backrefs, list) {
if (!backref->found_dir_item)
backref->errors |= REF_ERR_NO_DIR_ITEM;
@@ -2060,8 +2071,14 @@ static int check_fs_roots(struct btrfs_root *root,
btrfs_item_key_to_cpu(leaf, &key, path.slots[0]);
if (key.type == BTRFS_ROOT_ITEM_KEY &&
fs_root_objectid(key.objectid)) {
- key.offset = (u64)-1;
- tmp_root = btrfs_read_fs_root(root->fs_info, &key);
+ if (key.objectid == BTRFS_TREE_RELOC_OBJECTID) {
+ tmp_root = btrfs_read_fs_root_no_cache(
+ root->fs_info, &key);
+ } else {
+ key.offset = (u64)-1;
+ tmp_root = btrfs_read_fs_root(
+ root->fs_info, &key);
+ }
if (IS_ERR(tmp_root)) {
err = 1;
goto next;
@@ -2069,6 +2086,8 @@ static int check_fs_roots(struct btrfs_root *root,
ret = check_fs_root(tmp_root, root_cache, &wc);
if (ret)
err = 1;
+ if (key.objectid == BTRFS_TREE_RELOC_OBJECTID)
+ btrfs_free_fs_root(tmp_root);
} else if (key.type == BTRFS_ROOT_REF_KEY ||
key.type == BTRFS_ROOT_BACKREF_KEY) {
process_root_ref(leaf, path.slots[0], &key,
--
1.9.0

View File

@ -0,0 +1,43 @@
From 07bb42ca797d78333b0fd47189a6504cd25b28d5 Mon Sep 17 00:00:00 2001
From: Gui Hecheng <guihc.fnst@cn.fujitsu.com>
Date: Thu, 24 Apr 2014 11:39:28 +0800
Subject: [PATCH 16/42] btrfs-progs: prevent close_root if the root to close is
potentially NULL
Originally only if 'block_only' is specified, the 'fs_root == NULL'
will be checked. But if 'block_only' is not specified and close_root
will be called blindly without checking 'fs_root == NULL', which is
unsafe.
Signed-off-by: Gui Hecheng <guihc.fnst@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
btrfs-debug-tree.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/btrfs-debug-tree.c b/btrfs-debug-tree.c
index 8ae7270dc2fe..cb6c1061b329 100644
--- a/btrfs-debug-tree.c
+++ b/btrfs-debug-tree.c
@@ -177,13 +177,14 @@ int main(int ac, char **av)
fprintf(stderr, "unable to open %s\n", av[optind]);
exit(1);
}
+
root = info->fs_root;
+ if (!root) {
+ fprintf(stderr, "unable to open %s\n", av[optind]);
+ exit(1);
+ }
if (block_only) {
- if (!root) {
- fprintf(stderr, "unable to open %s\n", av[optind]);
- exit(1);
- }
leaf = read_tree_block(root,
block_only,
root->leafsize, 0);
--
1.9.0

View File

@ -0,0 +1,37 @@
From 61e0b6eaf4d98ddea540ebbf6b7ad7202ffc6786 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Holger=20Hoffst=C3=A4tte?=
<holger.hoffstaette@googlemail.com>
Date: Sat, 26 Apr 2014 09:41:04 +0000
Subject: [PATCH 19/42] btrfs-progs: fix mkfs.btrfs segfault with --features
option
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The mkfs.btrfs --features long option takes an argument but does not
declare it. Consequently getopt does not allocate an argument, which
makes an unconditional strdup() crash during options parsing.
Fix by declaring the argument in the options alias array.
Signed-off-by: Holger Hoffstätte <holger.hoffstaette@googlemail.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
mkfs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mkfs.c b/mkfs.c
index 4f5ee07e5ef9..16e92221a547 100644
--- a/mkfs.c
+++ b/mkfs.c
@@ -350,7 +350,7 @@ static struct option long_options[] = {
{ "version", 0, NULL, 'V' },
{ "rootdir", 1, NULL, 'r' },
{ "nodiscard", 0, NULL, 'K' },
- { "features", 0, NULL, 'O' },
+ { "features", 1, NULL, 'O' },
{ NULL, 0, NULL, 0}
};
--
1.9.0

View File

@ -0,0 +1,771 @@
From 04a9855f53cb7e4ad874cec28acfa537f00a28ba Mon Sep 17 00:00:00 2001
From: Goffredo Baroncelli <kreijack@libero.it>
Date: Thu, 13 Feb 2014 20:19:01 +0100
Subject: [PATCH 22/42] btrfs-progs: Enhance the command btrfs filesystem df
Enhance the command "btrfs filesystem df" to show space usage information
for a mount point(s). It shows also an estimation of the space available,
on the basis of the current one used.
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
Makefile | 2 +-
cmds-fi-disk_usage.c | 516 +++++++++++++++++++++++++++++++++++++++++++++++++++
cmds-fi-disk_usage.h | 25 +++
cmds-filesystem.c | 92 +--------
ctree.h | 5 +-
utils.c | 12 ++
utils.h | 1 +
7 files changed, 560 insertions(+), 93 deletions(-)
create mode 100644 cmds-fi-disk_usage.c
create mode 100644 cmds-fi-disk_usage.h
diff --git a/Makefile b/Makefile
index 76565e8b2307..50fb9b0ff2e3 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@ cmds_objects = cmds-subvolume.o cmds-filesystem.o cmds-device.o cmds-scrub.o \
cmds-inspect.o cmds-balance.o cmds-send.o cmds-receive.o \
cmds-quota.o cmds-qgroup.o cmds-replace.o cmds-check.o \
cmds-restore.o cmds-rescue.o chunk-recover.o super-recover.o \
- cmds-property.o
+ cmds-property.o cmds-fi-disk_usage.o
libbtrfs_objects = send-stream.o send-utils.o rbtree.o btrfs-list.o crc32c.o \
uuid-tree.o utils-lib.o
libbtrfs_headers = send-stream.h send-utils.h send.h rbtree.h btrfs-list.h \
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
new file mode 100644
index 000000000000..4012c781f20d
--- /dev/null
+++ b/cmds-fi-disk_usage.c
@@ -0,0 +1,516 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include "utils.h"
+#include "kerncompat.h"
+#include "ctree.h"
+
+#include "commands.h"
+
+#include "version.h"
+
+#define DF_HUMAN_UNIT (1<<0)
+
+/*
+ * To store the size information about the chunks:
+ * the chunks info are grouped by the tuple (type, devid, num_stripes),
+ * i.e. if two chunks are of the same type (RAID1, DUP...), are on the
+ * same disk, have the same stripes then their sizes are grouped
+ */
+struct chunk_info {
+ u64 type;
+ u64 size;
+ u64 devid;
+ u64 num_stripes;
+};
+
+/*
+ * Pretty print the size
+ * PAY ATTENTION: it return a statically buffer
+ */
+static char *df_pretty_sizes(u64 size, int mode)
+{
+ static char buf[30];
+
+ if (mode & DF_HUMAN_UNIT)
+ (void)pretty_size_snprintf(size, buf, sizeof(buf));
+ else
+ sprintf(buf, "%llu", size);
+
+ return buf;
+}
+
+/*
+ * Add the chunk info to the chunk_info list
+ */
+static int add_info_to_list(struct chunk_info **info_ptr,
+ int *info_count,
+ struct btrfs_chunk *chunk)
+{
+
+ u64 type = btrfs_stack_chunk_type(chunk);
+ u64 size = btrfs_stack_chunk_length(chunk);
+ int num_stripes = btrfs_stack_chunk_num_stripes(chunk);
+ int j;
+
+ for (j = 0 ; j < num_stripes ; j++) {
+ int i;
+ struct chunk_info *p = 0;
+ struct btrfs_stripe *stripe;
+ u64 devid;
+
+ stripe = btrfs_stripe_nr(chunk, j);
+ devid = btrfs_stack_stripe_devid(stripe);
+
+ for (i = 0 ; i < *info_count ; i++)
+ if ((*info_ptr)[i].type == type &&
+ (*info_ptr)[i].devid == devid &&
+ (*info_ptr)[i].num_stripes == num_stripes ) {
+ p = (*info_ptr) + i;
+ break;
+ }
+
+ if (!p) {
+ int size = sizeof(struct btrfs_chunk) * (*info_count+1);
+ struct chunk_info *res = realloc(*info_ptr, size);
+
+ if (!res) {
+ fprintf(stderr, "ERROR: not enough memory\n");
+ return -1;
+ }
+
+ *info_ptr = res;
+ p = res + *info_count;
+ (*info_count)++;
+
+ p->devid = devid;
+ p->type = type;
+ p->size = 0;
+ p->num_stripes = num_stripes;
+ }
+
+ p->size += size;
+
+ }
+
+ return 0;
+
+}
+
+/*
+ * Helper to sort the chunk type
+ */
+static int cmp_chunk_block_group(u64 f1, u64 f2)
+{
+
+ u64 mask;
+
+ if ((f1 & BTRFS_BLOCK_GROUP_TYPE_MASK) ==
+ (f2 & BTRFS_BLOCK_GROUP_TYPE_MASK))
+ mask = BTRFS_BLOCK_GROUP_PROFILE_MASK;
+ else if (f2 & BTRFS_BLOCK_GROUP_SYSTEM)
+ return -1;
+ else if (f1 & BTRFS_BLOCK_GROUP_SYSTEM)
+ return +1;
+ else
+ mask = BTRFS_BLOCK_GROUP_TYPE_MASK;
+
+ if ((f1 & mask) > (f2 & mask))
+ return +1;
+ else if ((f1 & mask) < (f2 & mask))
+ return -1;
+ else
+ return 0;
+}
+
+/*
+ * Helper to sort the chunk
+ */
+static int cmp_chunk_info(const void *a, const void *b)
+{
+ return cmp_chunk_block_group(
+ ((struct chunk_info *)a)->type,
+ ((struct chunk_info *)b)->type);
+}
+
+/*
+ * This function load all the chunk info from the 'fd' filesystem
+ */
+static int load_chunk_info(int fd,
+ struct chunk_info **info_ptr,
+ int *info_count)
+{
+
+ int ret;
+ struct btrfs_ioctl_search_args args;
+ struct btrfs_ioctl_search_key *sk = &args.key;
+ struct btrfs_ioctl_search_header *sh;
+ unsigned long off = 0;
+ int i, e;
+
+
+ memset(&args, 0, sizeof(args));
+
+ /*
+ * there may be more than one ROOT_ITEM key if there are
+ * snapshots pending deletion, we have to loop through
+ * them.
+ */
+
+
+ sk->tree_id = BTRFS_CHUNK_TREE_OBJECTID;
+
+ sk->min_objectid = 0;
+ sk->max_objectid = (u64)-1;
+ sk->max_type = 0;
+ sk->min_type = (u8)-1;
+ sk->min_offset = 0;
+ sk->max_offset = (u64)-1;
+ sk->min_transid = 0;
+ sk->max_transid = (u64)-1;
+ sk->nr_items = 4096;
+
+ while (1) {
+ ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
+ e = errno;
+ if (ret < 0) {
+ fprintf(stderr,
+ "ERROR: can't perform the search - %s\n",
+ strerror(e));
+ return -99;
+ }
+ /* the ioctl returns the number of item it found in nr_items */
+
+ if (sk->nr_items == 0)
+ break;
+
+ off = 0;
+ for (i = 0; i < sk->nr_items; i++) {
+ struct btrfs_chunk *item;
+ sh = (struct btrfs_ioctl_search_header *)(args.buf +
+ off);
+
+ off += sizeof(*sh);
+ item = (struct btrfs_chunk *)(args.buf + off);
+
+ if (add_info_to_list(info_ptr, info_count, item)) {
+ *info_ptr = 0;
+ free(*info_ptr);
+ return -100;
+ }
+
+ off += sh->len;
+
+ sk->min_objectid = sh->objectid;
+ sk->min_type = sh->type;
+ sk->min_offset = sh->offset+1;
+
+ }
+ if (!sk->min_offset) /* overflow */
+ sk->min_type++;
+ else
+ continue;
+
+ if (!sk->min_type)
+ sk->min_objectid++;
+ else
+ continue;
+
+ if (!sk->min_objectid)
+ break;
+ }
+
+ qsort(*info_ptr, *info_count, sizeof(struct chunk_info),
+ cmp_chunk_info);
+
+ return 0;
+
+}
+
+/*
+ * Helper to sort the struct btrfs_ioctl_space_info
+ */
+static int cmp_btrfs_ioctl_space_info(const void *a, const void *b)
+{
+ return cmp_chunk_block_group(
+ ((struct btrfs_ioctl_space_info *)a)->flags,
+ ((struct btrfs_ioctl_space_info *)b)->flags);
+}
+
+/*
+ * This function load all the information about the space usage
+ */
+static struct btrfs_ioctl_space_args *load_space_info(int fd, char *path)
+{
+ struct btrfs_ioctl_space_args *sargs = 0, *sargs_orig = 0;
+ int e, ret, count;
+
+ sargs_orig = sargs = malloc(sizeof(struct btrfs_ioctl_space_args));
+ if (!sargs) {
+ fprintf(stderr, "ERROR: not enough memory\n");
+ return NULL;
+ }
+
+ sargs->space_slots = 0;
+ sargs->total_spaces = 0;
+
+ ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, sargs);
+ e = errno;
+ if (ret) {
+ fprintf(stderr,
+ "ERROR: couldn't get space info on '%s' - %s\n",
+ path, strerror(e));
+ free(sargs);
+ return NULL;
+ }
+ if (!sargs->total_spaces) {
+ free(sargs);
+ printf("No chunks found\n");
+ return NULL;
+ }
+
+ count = sargs->total_spaces;
+
+ sargs = realloc(sargs, sizeof(struct btrfs_ioctl_space_args) +
+ (count * sizeof(struct btrfs_ioctl_space_info)));
+ if (!sargs) {
+ free(sargs_orig);
+ fprintf(stderr, "ERROR: not enough memory\n");
+ return NULL;
+ }
+
+ sargs->space_slots = count;
+ sargs->total_spaces = 0;
+
+ ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, sargs);
+ e = errno;
+
+ if (ret) {
+ fprintf(stderr,
+ "ERROR: couldn't get space info on '%s' - %s\n",
+ path, strerror(e));
+ free(sargs);
+ return NULL;
+ }
+
+ qsort(&(sargs->spaces), count, sizeof(struct btrfs_ioctl_space_info),
+ cmp_btrfs_ioctl_space_info);
+
+ return sargs;
+}
+
+/*
+ * This function computes the space occuped by a *single* RAID5/RAID6 chunk.
+ * The computation is performed on the basis of the number of stripes
+ * which compose the chunk, which could be different from the number of disks
+ * if a disk is added later.
+ */
+static int get_raid56_used(int fd, u64 *raid5_used, u64 *raid6_used)
+{
+ struct chunk_info *info_ptr=0, *p;
+ int info_count=0;
+ int ret;
+
+ *raid5_used = *raid6_used =0;
+
+ ret = load_chunk_info(fd, &info_ptr, &info_count);
+ if( ret < 0)
+ return ret;
+
+ for ( p = info_ptr; info_count ; info_count--, p++ ) {
+ if (p->type & BTRFS_BLOCK_GROUP_RAID5)
+ (*raid5_used) += p->size / (p->num_stripes -1);
+ if (p->type & BTRFS_BLOCK_GROUP_RAID6)
+ (*raid6_used) += p->size / (p->num_stripes -2);
+ }
+
+ return 0;
+
+}
+
+static int _cmd_disk_free(int fd, char *path, int mode)
+{
+ struct btrfs_ioctl_space_args *sargs = 0;
+ int i;
+ int ret = 0;
+ int e, width;
+ u64 total_disk; /* filesystem size == sum of
+ disks sizes */
+ u64 total_chunks; /* sum of chunks sizes on disk(s) */
+ u64 total_used; /* logical space used */
+ u64 total_free; /* logical space un-used */
+ double K;
+ u64 raid5_used, raid6_used;
+
+ if ((sargs = load_space_info(fd, path)) == NULL) {
+ ret = -1;
+ goto exit;
+ }
+
+ total_disk = disk_size(path);
+ e = errno;
+ if (total_disk == 0) {
+ fprintf(stderr,
+ "ERROR: couldn't get space info on '%s' - %s\n",
+ path, strerror(e));
+
+ ret = 19;
+ goto exit;
+ }
+ if (get_raid56_used(fd, &raid5_used, &raid6_used) < 0) {
+ fprintf(stderr,
+ "ERROR: couldn't get space info on '%s'\n",
+ path );
+ ret = 20;
+ goto exit;
+ }
+
+ total_chunks = total_used = total_free = 0;
+
+ for (i = 0; i < sargs->total_spaces; i++) {
+ float ratio = 1;
+ u64 allocated;
+ u64 flags = sargs->spaces[i].flags;
+
+ /*
+ * The raid5/raid6 ratio depends by the stripes number
+ * used by every chunk. It is computed separately
+ */
+ if (flags & BTRFS_BLOCK_GROUP_RAID0)
+ ratio = 1;
+ else if (flags & BTRFS_BLOCK_GROUP_RAID1)
+ ratio = 2;
+ else if (flags & BTRFS_BLOCK_GROUP_RAID5)
+ ratio = 0;
+ else if (flags & BTRFS_BLOCK_GROUP_RAID6)
+ ratio = 0;
+ else if (flags & BTRFS_BLOCK_GROUP_DUP)
+ ratio = 2;
+ else if (flags & BTRFS_BLOCK_GROUP_RAID10)
+ ratio = 2;
+ else
+ ratio = 1;
+
+ allocated = sargs->spaces[i].total_bytes * ratio;
+
+ total_chunks += allocated;
+ total_used += sargs->spaces[i].used_bytes;
+ total_free += (sargs->spaces[i].total_bytes -
+ sargs->spaces[i].used_bytes);
+
+ }
+
+ /* add the raid5/6 allocated space */
+ total_chunks += raid5_used + raid6_used;
+
+ K = ((double)total_used + (double)total_free) / (double)total_chunks;
+
+ if (mode & DF_HUMAN_UNIT)
+ width = 10;
+ else
+ width = 18;
+
+ printf("Disk size:\t\t%*s\n", width,
+ df_pretty_sizes(total_disk, mode));
+ printf("Disk allocated:\t\t%*s\n", width,
+ df_pretty_sizes(total_chunks, mode));
+ printf("Disk unallocated:\t%*s\n", width,
+ df_pretty_sizes(total_disk-total_chunks, mode));
+ printf("Used:\t\t\t%*s\n", width,
+ df_pretty_sizes(total_used, mode));
+ printf("Free (Estimated):\t%*s\t(",
+ width,
+ df_pretty_sizes((u64)(K*total_disk-total_used), mode));
+ printf("Max: %s, ",
+ df_pretty_sizes(total_disk-total_chunks+total_free, mode));
+ printf("min: %s)\n",
+ df_pretty_sizes((total_disk-total_chunks)/2+total_free, mode));
+ printf("Data to disk ratio:\t%*.0f %%\n",
+ width-2, K*100);
+
+exit:
+
+ if (sargs)
+ free(sargs);
+
+ return ret;
+}
+
+const char * const cmd_filesystem_df_usage[] = {
+ "btrfs filesystem df [-b] <path> [<path>..]",
+ "Show space usage information for a mount point(s).",
+ "",
+ "-b\tSet byte as unit",
+ NULL
+};
+
+int cmd_filesystem_df(int argc, char **argv)
+{
+
+ int flags = DF_HUMAN_UNIT;
+ int i, more_than_one = 0;
+
+ optind = 1;
+ while (1) {
+ char c = getopt(argc, argv, "b");
+ if (c < 0)
+ break;
+
+ switch (c) {
+ case 'b':
+ flags &= ~DF_HUMAN_UNIT;
+ break;
+ default:
+ usage(cmd_filesystem_df_usage);
+ }
+ }
+
+ if (check_argc_min(argc - optind, 1)) {
+ usage(cmd_filesystem_df_usage);
+ return 21;
+ }
+
+ for (i = optind; i < argc ; i++) {
+ int r, fd;
+ DIR *dirstream = NULL;
+ if (more_than_one)
+ printf("\n");
+
+ fd = open_file_or_dir(argv[i], &dirstream);
+ if (fd < 0) {
+ fprintf(stderr, "ERROR: can't access to '%s'\n",
+ argv[1]);
+ return 12;
+ }
+ r = _cmd_disk_free(fd, argv[i], flags);
+ close_file_or_dir(fd, dirstream);
+
+ if (r)
+ return r;
+ more_than_one = 1;
+
+ }
+
+ return 0;
+}
+
diff --git a/cmds-fi-disk_usage.h b/cmds-fi-disk_usage.h
new file mode 100644
index 000000000000..9f68bb342d52
--- /dev/null
+++ b/cmds-fi-disk_usage.h
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+#ifndef __CMDS_FI_DISK_USAGE__
+#define __CMDS_FI_DISK_USAGE__
+
+extern const char * const cmd_filesystem_df_usage[];
+int cmd_filesystem_df(int argc, char **argv);
+
+#endif
diff --git a/cmds-filesystem.c b/cmds-filesystem.c
index 306f715475ac..0edfb50daca2 100644
--- a/cmds-filesystem.c
+++ b/cmds-filesystem.c
@@ -36,6 +36,7 @@
#include "volumes.h"
#include "version.h"
#include "commands.h"
+#include "cmds-fi-disk_usage.h"
#include "list_sort.h"
#include "disk-io.h"
@@ -112,50 +113,6 @@ static const char * const filesystem_cmd_group_usage[] = {
NULL
};
-static const char * const cmd_df_usage[] = {
- "btrfs filesystem df <path>",
- "Show space usage information for a mount point",
- NULL
-};
-
-static char *group_type_str(u64 flag)
-{
- switch (flag & BTRFS_BLOCK_GROUP_TYPE_MASK) {
- case BTRFS_BLOCK_GROUP_DATA:
- return "Data";
- case BTRFS_BLOCK_GROUP_SYSTEM:
- return "System";
- case BTRFS_BLOCK_GROUP_METADATA:
- return "Metadata";
- case BTRFS_BLOCK_GROUP_DATA|BTRFS_BLOCK_GROUP_METADATA:
- return "Data+Metadata";
- default:
- return "unknown";
- }
-}
-
-static char *group_profile_str(u64 flag)
-{
- switch (flag & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
- case 0:
- return "single";
- case BTRFS_BLOCK_GROUP_RAID0:
- return "RAID0";
- case BTRFS_BLOCK_GROUP_RAID1:
- return "RAID1";
- case BTRFS_BLOCK_GROUP_RAID5:
- return "RAID5";
- case BTRFS_BLOCK_GROUP_RAID6:
- return "RAID6";
- case BTRFS_BLOCK_GROUP_DUP:
- return "DUP";
- case BTRFS_BLOCK_GROUP_RAID10:
- return "RAID10";
- default:
- return "unknown";
- }
-}
-
static int get_df(int fd, struct btrfs_ioctl_space_args **sargs_ret)
{
u64 count = 0;
@@ -204,51 +161,6 @@ static int get_df(int fd, struct btrfs_ioctl_space_args **sargs_ret)
return 0;
}
-static void print_df(struct btrfs_ioctl_space_args *sargs)
-{
- u64 i;
- struct btrfs_ioctl_space_info *sp = sargs->spaces;
-
- for (i = 0; i < sargs->total_spaces; i++, sp++) {
- printf("%s, %s: total=%s, used=%s\n",
- group_type_str(sp->flags),
- group_profile_str(sp->flags),
- pretty_size(sp->total_bytes),
- pretty_size(sp->used_bytes));
- }
-}
-
-static int cmd_df(int argc, char **argv)
-{
- struct btrfs_ioctl_space_args *sargs = NULL;
- int ret;
- int fd;
- char *path;
- DIR *dirstream = NULL;
-
- if (check_argc_exact(argc, 2))
- usage(cmd_df_usage);
-
- path = argv[1];
-
- fd = open_file_or_dir(path, &dirstream);
- if (fd < 0) {
- fprintf(stderr, "ERROR: can't access '%s'\n", path);
- return 1;
- }
- ret = get_df(fd, &sargs);
-
- if (!ret && sargs) {
- print_df(sargs);
- free(sargs);
- } else {
- fprintf(stderr, "ERROR: get_df failed %s\n", strerror(-ret));
- }
-
- close_file_or_dir(fd, dirstream);
- return !!ret;
-}
-
static int match_search_item_kernel(__u8 *fsid, char *mnt, char *label,
char *search)
{
@@ -999,7 +911,7 @@ static int cmd_label(int argc, char **argv)
const struct cmd_group filesystem_cmd_group = {
filesystem_cmd_group_usage, NULL, {
- { "df", cmd_df, cmd_df_usage, NULL, 0 },
+ { "df", cmd_filesystem_df, cmd_filesystem_df_usage, NULL, 0 },
{ "show", cmd_show, cmd_show_usage, NULL, 0 },
{ "sync", cmd_sync, cmd_sync_usage, NULL, 0 },
{ "defragment", cmd_defrag, cmd_defrag_usage, NULL, 0 },
diff --git a/ctree.h b/ctree.h
index a4d2cd114614..8ac17619b9dc 100644
--- a/ctree.h
+++ b/ctree.h
@@ -843,9 +843,10 @@ struct btrfs_csum_item {
#define BTRFS_BLOCK_GROUP_RAID1 (1ULL << 4)
#define BTRFS_BLOCK_GROUP_DUP (1ULL << 5)
#define BTRFS_BLOCK_GROUP_RAID10 (1ULL << 6)
-#define BTRFS_BLOCK_GROUP_RAID5 (1ULL << 7)
-#define BTRFS_BLOCK_GROUP_RAID6 (1ULL << 8)
+#define BTRFS_BLOCK_GROUP_RAID5 (1ULL << 7)
+#define BTRFS_BLOCK_GROUP_RAID6 (1ULL << 8)
#define BTRFS_BLOCK_GROUP_RESERVED BTRFS_AVAIL_ALLOC_BIT_SINGLE
+#define BTRFS_NR_RAID_TYPES 7
#define BTRFS_BLOCK_GROUP_TYPE_MASK (BTRFS_BLOCK_GROUP_DATA | \
BTRFS_BLOCK_GROUP_SYSTEM | \
diff --git a/utils.c b/utils.c
index e130849c7bb5..7731b071f353 100644
--- a/utils.c
+++ b/utils.c
@@ -38,6 +38,8 @@
#include <linux/kdev_t.h>
#include <limits.h>
#include <blkid/blkid.h>
+#include <sys/vfs.h>
+
#include "kerncompat.h"
#include "radix-tree.h"
#include "ctree.h"
@@ -2206,3 +2208,13 @@ int find_mount_root(const char *path, char **mount_root)
free(longest_match);
return ret;
}
+
+u64 disk_size(char *path)
+{
+ struct statfs sfs;
+
+ if (statfs(path, &sfs) < 0)
+ return 0;
+ else
+ return sfs.f_bsize * sfs.f_blocks;
+}
diff --git a/utils.h b/utils.h
index db8d63c396d5..581faa9f6972 100644
--- a/utils.h
+++ b/utils.h
@@ -101,5 +101,6 @@ int get_btrfs_mount(const char *dev, char *mp, size_t mp_size);
int find_mount_root(const char *path, char **mount_root);
int get_device_info(int fd, u64 devid,
struct btrfs_ioctl_dev_info_args *di_args);
+u64 disk_size(char *path);
#endif
--
1.9.0

View File

@ -0,0 +1,261 @@
From a79f61440afaa0b77dc67c896fa3367a171c2306 Mon Sep 17 00:00:00 2001
From: Goffredo Baroncelli <kreijack@libero.it>
Date: Thu, 13 Feb 2014 20:19:21 +0100
Subject: [PATCH 23/42] btrfs-progs: Add helpers functions to handle the
printing of data in tabular format
This patch adds some functions to manage the printing of the data in
tabular format.
The function
struct string_table *table_create(int columns, int rows)
creates an (empty) table.
The functions
char *table_printf(struct string_table *tab, int column,
int row, char *fmt, ...)
char *table_vprintf(struct string_table *tab, int column,
int row, char *fmt, va_list ap)
populate the table with text. To align the text to the left, the text
shall be prefixed with '<', otherwise the text shall be prefixed by a
'>'. If the first character is a '=', the the text is replace by a
sequence of '=' to fill the column width.
The function
void table_free(struct string_table *)
frees all the data associated to the table.
The function
void table_dump(struct string_table *tab)
prints the table on stdout.
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
Makefile | 2 +-
string_table.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
string_table.h | 36 +++++++++++++
3 files changed, 193 insertions(+), 1 deletion(-)
create mode 100644 string_table.c
create mode 100644 string_table.h
diff --git a/Makefile b/Makefile
index 50fb9b0ff2e3..bf6dc1c67d2c 100644
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ objects = ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \
root-tree.o dir-item.o file-item.o inode-item.o inode-map.o \
extent-cache.o extent_io.o volumes.o utils.o repair.o \
qgroup.o raid6.o free-space-cache.o list_sort.o props.o \
- utils-lib.o
+ utils-lib.o string_table.o
cmds_objects = cmds-subvolume.o cmds-filesystem.o cmds-device.o cmds-scrub.o \
cmds-inspect.o cmds-balance.o cmds-send.o cmds-receive.o \
cmds-quota.o cmds-qgroup.o cmds-replace.o cmds-check.o \
diff --git a/string_table.c b/string_table.c
new file mode 100644
index 000000000000..016356c50392
--- /dev/null
+++ b/string_table.c
@@ -0,0 +1,156 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "string_table.h"
+
+/*
+ * This function create an array of char * which will represent a table
+ */
+struct string_table *table_create(int columns, int rows)
+{
+ struct string_table *p;
+ int size;
+
+ size = sizeof( struct string_table ) +
+ rows * columns* sizeof(char *);
+ p = calloc(1, size);
+
+ if (!p) return NULL;
+
+ p->ncols = columns;
+ p->nrows = rows;
+
+ return p;
+}
+
+/*
+ * This function is like a vprintf, but store the results in a cell of
+ * the table.
+ * If fmt starts with '<', the text is left aligned; if fmt starts with
+ * '>' the text is right aligned. If fmt is equal to '=' the text will
+ * be replaced by a '=====' dimensioned on the basis of the column width
+ */
+char *table_vprintf(struct string_table *tab, int column, int row,
+ char *fmt, va_list ap)
+{
+ int idx = tab->ncols*row+column;
+ char *msg = calloc(100, sizeof(char));
+
+ if (!msg)
+ return NULL;
+
+ if (tab->cells[idx])
+ free(tab->cells[idx]);
+ tab->cells[idx] = msg;
+ vsnprintf(msg, 99, fmt, ap);
+
+ return msg;
+}
+
+
+/*
+ * This function is like a printf, but store the results in a cell of
+ * the table.
+ */
+char *table_printf(struct string_table *tab, int column, int row,
+ char *fmt, ...)
+{
+ va_list ap;
+ char *ret;
+
+ va_start(ap, fmt);
+ ret = table_vprintf(tab, column, row, fmt, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+/*
+ * This function dumps the table. Every "=" string will be replaced by
+ * a "=======" length as the column
+ */
+void table_dump(struct string_table *tab)
+{
+ int sizes[tab->ncols];
+ int i, j;
+
+ for (i = 0 ; i < tab->ncols ; i++) {
+ sizes[i] = 0;
+ for (j = 0 ; j < tab->nrows ; j++) {
+ int idx = i + j*tab->ncols;
+ int s;
+
+ if (!tab->cells[idx])
+ continue;
+
+ s = strlen(tab->cells[idx]) - 1;
+ if (s < 1 || tab->cells[idx][0] == '=')
+ continue;
+
+ if (s > sizes[i])
+ sizes[i] = s;
+ }
+ }
+
+
+ for (j = 0 ; j < tab->nrows ; j++) {
+ for (i = 0 ; i < tab->ncols ; i++) {
+
+ int idx = i + j*tab->ncols;
+ char *s = tab->cells[idx];
+
+ if (!s|| !strlen(s)) {
+ printf("%*s", sizes[i], "");
+ } else if (s && s[0] == '=') {
+ int k = sizes[i];
+ while(k--)
+ putchar('=');
+ } else {
+ printf("%*s",
+ s[0] == '<' ? -sizes[i] : sizes[i],
+ s+1);
+ }
+ if (i != (tab->ncols - 1))
+ putchar(' ');
+ }
+ putchar('\n');
+ }
+
+}
+
+/*
+ * Deallocate a tabular and all its content
+ */
+
+void table_free(struct string_table *tab)
+{
+
+ int i, count;
+
+ count = tab->ncols * tab->nrows;
+
+ for (i=0 ; i < count ; i++)
+ if (tab->cells[i])
+ free(tab->cells[i]);
+
+ free(tab);
+
+}
diff --git a/string_table.h b/string_table.h
new file mode 100644
index 000000000000..83c4425d5f76
--- /dev/null
+++ b/string_table.h
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#ifndef STRING_TABLE_H
+#define STRING_TABLE_H
+
+struct string_table {
+
+ int ncols, nrows;
+ char *cells[];
+
+};
+
+
+struct string_table *table_create(int columns, int rows);
+char *table_printf(struct string_table *tab, int column, int row,
+ char *fmt, ...);
+char *table_vprintf(struct string_table *tab, int column, int row,
+ char *fmt, va_list ap);
+void table_dump(struct string_table *tab);
+void table_free(struct string_table *);
+
+#endif
--
1.9.0

View File

@ -0,0 +1,581 @@
From bb2b9f64b992f166533cc0d06aeec9518795d24a Mon Sep 17 00:00:00 2001
From: Goffredo Baroncelli <kreijack@libero.it>
Date: Thu, 13 Feb 2014 20:19:50 +0100
Subject: [PATCH 24/42] btrfs-progs: Add command btrfs filesystem disk-usage
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-fi-disk_usage.c | 428 +++++++++++++++++++++++++++++++++++++++++++++++++++
cmds-fi-disk_usage.h | 3 +
cmds-filesystem.c | 3 +
utils.c | 60 ++++++++
utils.h | 5 +
5 files changed, 499 insertions(+)
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index 4012c781f20d..16b3ab250956 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -20,10 +20,12 @@
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
+#include <stdarg.h>
#include "utils.h"
#include "kerncompat.h"
#include "ctree.h"
+#include "string_table.h"
#include "commands.h"
@@ -44,6 +46,13 @@ struct chunk_info {
u64 num_stripes;
};
+/* to store information about the disks */
+struct disk_info {
+ u64 devid;
+ char path[BTRFS_DEVICE_PATH_NAME_MAX];
+ u64 size;
+};
+
/*
* Pretty print the size
* PAY ATTENTION: it return a statically buffer
@@ -514,3 +523,422 @@ int cmd_filesystem_df(int argc, char **argv)
return 0;
}
+/*
+ * Helper to sort the disk_info structure
+ */
+static int cmp_disk_info(const void *a, const void *b)
+{
+ return strcmp(((struct disk_info *)a)->path,
+ ((struct disk_info *)b)->path);
+}
+
+/*
+ * This function load the disk_info structure and put them in an array
+ */
+static int load_disks_info(int fd,
+ struct disk_info **disks_info_ptr,
+ int *disks_info_count)
+{
+
+ int ret, i, ndevs;
+ struct btrfs_ioctl_fs_info_args fi_args;
+ struct btrfs_ioctl_dev_info_args dev_info;
+ struct disk_info *info;
+
+ *disks_info_count = 0;
+ *disks_info_ptr = 0;
+
+ ret = ioctl(fd, BTRFS_IOC_FS_INFO, &fi_args);
+ if (ret < 0) {
+ fprintf(stderr, "ERROR: cannot get filesystem info\n");
+ return -1;
+ }
+
+ info = malloc(sizeof(struct disk_info) * fi_args.num_devices);
+ if (!info) {
+ fprintf(stderr, "ERROR: not enough memory\n");
+ return -1;
+ }
+
+ for (i = 0, ndevs = 0 ; i <= fi_args.max_id ; i++) {
+
+ BUG_ON(ndevs >= fi_args.num_devices);
+ ret = get_device_info(fd, i, &dev_info);
+
+ if (ret == -ENODEV)
+ continue;
+ if (ret) {
+ fprintf(stderr,
+ "ERROR: cannot get info about device devid=%d\n",
+ i);
+ free(info);
+ return -1;
+ }
+
+ info[ndevs].devid = dev_info.devid;
+ strcpy(info[ndevs].path, (char *)dev_info.path);
+ info[ndevs].size = get_partition_size((char *)dev_info.path);
+ ++ndevs;
+ }
+
+ BUG_ON(ndevs != fi_args.num_devices);
+ qsort(info, fi_args.num_devices,
+ sizeof(struct disk_info), cmp_disk_info);
+
+ *disks_info_count = fi_args.num_devices;
+ *disks_info_ptr = info;
+
+ return 0;
+
+}
+
+/*
+ * This function computes the size of a chunk in a disk
+ */
+static u64 calc_chunk_size(struct chunk_info *ci)
+{
+ if (ci->type & BTRFS_BLOCK_GROUP_RAID0)
+ return ci->size / ci->num_stripes;
+ else if (ci->type & BTRFS_BLOCK_GROUP_RAID1)
+ return ci->size ;
+ else if (ci->type & BTRFS_BLOCK_GROUP_DUP)
+ return ci->size ;
+ else if (ci->type & BTRFS_BLOCK_GROUP_RAID5)
+ return ci->size / (ci->num_stripes -1);
+ else if (ci->type & BTRFS_BLOCK_GROUP_RAID6)
+ return ci->size / (ci->num_stripes -2);
+ else if (ci->type & BTRFS_BLOCK_GROUP_RAID10)
+ return ci->size / ci->num_stripes;
+ return ci->size;
+}
+
+/*
+ * This function print the results of the command btrfs fi disk-usage
+ * in tabular format
+ */
+static void _cmd_filesystem_disk_usage_tabular(int mode,
+ struct btrfs_ioctl_space_args *sargs,
+ struct chunk_info *chunks_info_ptr,
+ int chunks_info_count,
+ struct disk_info *disks_info_ptr,
+ int disks_info_count)
+{
+ int i;
+ u64 total_unused = 0;
+ struct string_table *matrix = 0;
+ int ncols, nrows;
+
+ ncols = sargs->total_spaces + 2;
+ nrows = 2 + 1 + disks_info_count + 1 + 2;
+
+ matrix = table_create(ncols, nrows);
+ if (!matrix) {
+ fprintf(stderr, "ERROR: not enough memory\n");
+ return;
+ }
+
+ /* header */
+ for (i = 0; i < sargs->total_spaces; i++) {
+ const char *description;
+
+ u64 flags = sargs->spaces[i].flags;
+ description = group_type_str(flags);
+
+ table_printf(matrix, 1+i, 0, "<%s", description);
+ }
+
+ for (i = 0; i < sargs->total_spaces; i++) {
+ const char *r_mode;
+
+ u64 flags = sargs->spaces[i].flags;
+ r_mode = group_profile_str(flags);
+
+ table_printf(matrix, 1+i, 1, "<%s", r_mode);
+ }
+
+ table_printf(matrix, 1+sargs->total_spaces, 1, "<Unallocated");
+
+ /* body */
+ for (i = 0 ; i < disks_info_count ; i++) {
+ int k, col;
+ char *p;
+
+ u64 total_allocated = 0, unused;
+
+ p = strrchr(disks_info_ptr[i].path, '/');
+ if (!p)
+ p = disks_info_ptr[i].path;
+ else
+ p++;
+
+ table_printf(matrix, 0, i+3, "<%s",
+ disks_info_ptr[i].path);
+
+ for (col = 1, k = 0 ; k < sargs->total_spaces ; k++) {
+ u64 flags = sargs->spaces[k].flags;
+ u64 devid = disks_info_ptr[i].devid;
+ int j;
+ u64 size = 0;
+
+ for (j = 0 ; j < chunks_info_count ; j++) {
+ if (chunks_info_ptr[j].type != flags )
+ continue;
+ if (chunks_info_ptr[j].devid != devid)
+ continue;
+
+ size += calc_chunk_size(chunks_info_ptr+j);
+ }
+
+ if (size)
+ table_printf(matrix, col, i+3,
+ ">%s", df_pretty_sizes(size, mode));
+ else
+ table_printf(matrix, col, i+3, ">-");
+
+ total_allocated += size;
+ col++;
+ }
+
+ unused = get_partition_size(disks_info_ptr[i].path) -
+ total_allocated;
+
+ table_printf(matrix, sargs->total_spaces + 1, i + 3,
+ ">%s", df_pretty_sizes(unused, mode));
+ total_unused += unused;
+
+ }
+
+ for (i = 0; i <= sargs->total_spaces; i++)
+ table_printf(matrix, i + 1, disks_info_count + 3, "=");
+
+
+ /* footer */
+ table_printf(matrix, 0, disks_info_count + 4, "<Total");
+ for (i = 0; i < sargs->total_spaces; i++)
+ table_printf(matrix, 1 + i, disks_info_count + 4,
+ ">%s",
+ df_pretty_sizes(sargs->spaces[i].total_bytes, mode));
+
+ table_printf(matrix, sargs->total_spaces+1, disks_info_count+4,
+ ">%s", df_pretty_sizes(total_unused, mode));
+
+ table_printf(matrix, 0, disks_info_count+5, "<Used");
+ for (i = 0; i < sargs->total_spaces; i++)
+ table_printf(matrix, 1+i, disks_info_count+5, ">%s",
+ df_pretty_sizes(sargs->spaces[i].used_bytes, mode));
+
+
+ table_dump(matrix);
+ table_free(matrix);
+
+}
+
+/*
+ * This function prints the unused space per every disk
+ */
+static void print_unused(struct chunk_info *info_ptr,
+ int info_count,
+ struct disk_info *disks_info_ptr,
+ int disks_info_count,
+ int mode)
+{
+ int i;
+ for (i = 0 ; i < disks_info_count ; i++) {
+
+ int j;
+ u64 total = 0;
+
+ for (j = 0 ; j < info_count ; j++)
+ if (info_ptr[j].devid == disks_info_ptr[i].devid)
+ total += calc_chunk_size(info_ptr+j);
+
+ printf(" %s\t%10s\n",
+ disks_info_ptr[i].path,
+ df_pretty_sizes(disks_info_ptr[i].size - total, mode));
+
+ }
+
+}
+
+/*
+ * This function prints the allocated chunk per every disk
+ */
+static void print_chunk_disks(u64 chunk_type,
+ struct chunk_info *chunks_info_ptr,
+ int chunks_info_count,
+ struct disk_info *disks_info_ptr,
+ int disks_info_count,
+ int mode)
+{
+ int i;
+
+ for (i = 0 ; i < disks_info_count ; i++) {
+
+ int j;
+ u64 total = 0;
+
+ for (j = 0 ; j < chunks_info_count ; j++) {
+
+ if (chunks_info_ptr[j].type != chunk_type)
+ continue;
+ if (chunks_info_ptr[j].devid != disks_info_ptr[i].devid)
+ continue;
+
+ total += calc_chunk_size(&(chunks_info_ptr[j]));
+ //total += chunks_info_ptr[j].size;
+ }
+
+ if (total > 0)
+ printf(" %s\t%10s\n",
+ disks_info_ptr[i].path,
+ df_pretty_sizes(total, mode));
+ }
+}
+
+/*
+ * This function print the results of the command btrfs fi disk-usage
+ * in linear format
+ */
+static void _cmd_filesystem_disk_usage_linear(int mode,
+ struct btrfs_ioctl_space_args *sargs,
+ struct chunk_info *info_ptr,
+ int info_count,
+ struct disk_info *disks_info_ptr,
+ int disks_info_count)
+{
+ int i;
+
+ for (i = 0; i < sargs->total_spaces; i++) {
+ const char *description;
+ const char *r_mode;
+
+ u64 flags = sargs->spaces[i].flags;
+ description= group_type_str(flags);
+ r_mode = group_profile_str(flags);
+
+ printf("%s,%s: Size:%s, ",
+ description,
+ r_mode,
+ df_pretty_sizes(sargs->spaces[i].total_bytes ,
+ mode));
+ printf("Used:%s\n",
+ df_pretty_sizes(sargs->spaces[i].used_bytes,
+ mode));
+ print_chunk_disks(flags, info_ptr, info_count,
+ disks_info_ptr, disks_info_count,
+ mode);
+ printf("\n");
+
+ }
+
+ printf("Unallocated:\n");
+ print_unused(info_ptr, info_count,
+ disks_info_ptr, disks_info_count,
+ mode);
+
+
+
+}
+
+static int _cmd_filesystem_disk_usage(int fd, char *path, int mode, int tabular)
+{
+ struct btrfs_ioctl_space_args *sargs = 0;
+ int info_count = 0;
+ struct chunk_info *info_ptr = 0;
+ struct disk_info *disks_info_ptr = 0;
+ int disks_info_count = 0;
+ int ret = 0;
+
+ if (load_chunk_info(fd, &info_ptr, &info_count) ||
+ load_disks_info(fd, &disks_info_ptr, &disks_info_count)) {
+ ret = -1;
+ goto exit;
+ }
+
+ if ((sargs = load_space_info(fd, path)) == NULL) {
+ ret = -1;
+ goto exit;
+ }
+
+ if (tabular)
+ _cmd_filesystem_disk_usage_tabular(mode, sargs,
+ info_ptr, info_count,
+ disks_info_ptr, disks_info_count);
+ else
+ _cmd_filesystem_disk_usage_linear(mode, sargs,
+ info_ptr, info_count,
+ disks_info_ptr, disks_info_count);
+
+exit:
+
+ if (sargs)
+ free(sargs);
+ if (disks_info_ptr)
+ free(disks_info_ptr);
+ if (info_ptr)
+ free(info_ptr);
+
+ return ret;
+}
+
+const char * const cmd_filesystem_disk_usage_usage[] = {
+ "btrfs filesystem disk-usage [-b][-t] <path> [<path>..]",
+ "Show in which disk the chunks are allocated.",
+ "",
+ "-b\tSet byte as unit",
+ "-t\tShow data in tabular format",
+ NULL
+};
+
+int cmd_filesystem_disk_usage(int argc, char **argv)
+{
+
+ int flags = DF_HUMAN_UNIT;
+ int i, more_than_one = 0;
+ int tabular = 0;
+
+ optind = 1;
+ while (1) {
+ char c = getopt(argc, argv, "bt");
+ if (c < 0)
+ break;
+ switch (c) {
+ case 'b':
+ flags &= ~DF_HUMAN_UNIT;
+ break;
+ case 't':
+ tabular = 1;
+ break;
+ default:
+ usage(cmd_filesystem_disk_usage_usage);
+ }
+ }
+
+ if (check_argc_min(argc - optind, 1)) {
+ usage(cmd_filesystem_disk_usage_usage);
+ return 21;
+ }
+
+ for (i = optind; i < argc ; i++) {
+ int r, fd;
+ DIR *dirstream = NULL;
+ if (more_than_one)
+ printf("\n");
+
+ fd = open_file_or_dir(argv[i], &dirstream);
+ if (fd < 0) {
+ fprintf(stderr, "ERROR: can't access to '%s'\n",
+ argv[1]);
+ return 12;
+ }
+ r = _cmd_filesystem_disk_usage(fd, argv[i], flags, tabular);
+ close_file_or_dir(fd, dirstream);
+
+ if (r)
+ return r;
+ more_than_one = 1;
+
+ }
+
+ return 0;
+}
diff --git a/cmds-fi-disk_usage.h b/cmds-fi-disk_usage.h
index 9f68bb342d52..c7459b1521e4 100644
--- a/cmds-fi-disk_usage.h
+++ b/cmds-fi-disk_usage.h
@@ -22,4 +22,7 @@
extern const char * const cmd_filesystem_df_usage[];
int cmd_filesystem_df(int argc, char **argv);
+extern const char * const cmd_filesystem_disk_usage_usage[];
+int cmd_filesystem_disk_usage(int argc, char **argv);
+
#endif
diff --git a/cmds-filesystem.c b/cmds-filesystem.c
index 0edfb50daca2..214a0cda518c 100644
--- a/cmds-filesystem.c
+++ b/cmds-filesystem.c
@@ -918,6 +918,9 @@ const struct cmd_group filesystem_cmd_group = {
{ "balance", cmd_balance, NULL, &balance_cmd_group, 1 },
{ "resize", cmd_resize, cmd_resize_usage, NULL, 0 },
{ "label", cmd_label, cmd_label_usage, NULL, 0 },
+ { "disk-usage", cmd_filesystem_disk_usage,
+ cmd_filesystem_disk_usage_usage, NULL, 0 },
+
NULL_CMD_STRUCT
}
};
diff --git a/utils.c b/utils.c
index 7731b071f353..f2ab416c28b2 100644
--- a/utils.c
+++ b/utils.c
@@ -2218,3 +2218,63 @@ u64 disk_size(char *path)
else
return sfs.f_bsize * sfs.f_blocks;
}
+
+u64 get_partition_size(char *dev)
+{
+ u64 result;
+ int fd = open(dev, O_RDONLY);
+
+ if (fd < 0)
+ return 0;
+ if (ioctl(fd, BLKGETSIZE64, &result) < 0) {
+ close(fd);
+ return 0;
+ }
+ close(fd);
+
+ return result;
+}
+
+/*
+ * Convert a chunk type to a chunk description
+ */
+const char *group_type_str(u64 flag)
+{
+ switch (flag & BTRFS_BLOCK_GROUP_TYPE_MASK) {
+ case BTRFS_BLOCK_GROUP_DATA:
+ return "Data";
+ case BTRFS_BLOCK_GROUP_SYSTEM:
+ return "System";
+ case BTRFS_BLOCK_GROUP_METADATA:
+ return "Metadata";
+ case BTRFS_BLOCK_GROUP_DATA|BTRFS_BLOCK_GROUP_METADATA:
+ return "Data+Metadata";
+ default:
+ return "unknown";
+ }
+}
+
+/*
+ * Convert a chunk type to a chunk profile description
+ */
+const char *group_profile_str(u64 flag)
+{
+ switch (flag & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
+ case 0:
+ return "single";
+ case BTRFS_BLOCK_GROUP_RAID0:
+ return "RAID0";
+ case BTRFS_BLOCK_GROUP_RAID1:
+ return "RAID1";
+ case BTRFS_BLOCK_GROUP_RAID5:
+ return "RAID5";
+ case BTRFS_BLOCK_GROUP_RAID6:
+ return "RAID6";
+ case BTRFS_BLOCK_GROUP_DUP:
+ return "DUP";
+ case BTRFS_BLOCK_GROUP_RAID10:
+ return "RAID10";
+ default:
+ return "unknown";
+ }
+}
diff --git a/utils.h b/utils.h
index 581faa9f6972..2d08e0b2a3a4 100644
--- a/utils.h
+++ b/utils.h
@@ -102,5 +102,10 @@ int find_mount_root(const char *path, char **mount_root);
int get_device_info(int fd, u64 devid,
struct btrfs_ioctl_dev_info_args *di_args);
u64 disk_size(char *path);
+int get_device_info(int fd, u64 devid,
+ struct btrfs_ioctl_dev_info_args *di_args);
+u64 get_partition_size(char *dev);
+const char* group_type_str(u64 flags);
+const char* group_profile_str(u64 flags);
#endif
--
1.9.0

View File

@ -0,0 +1,193 @@
From b8eb50e005cc92d870faf6bfe285950c4ac66e09 Mon Sep 17 00:00:00 2001
From: Goffredo Baroncelli <kreijack@libero.it>
Date: Thu, 13 Feb 2014 20:20:12 +0100
Subject: [PATCH 25/42] btrfs-progs: Add btrfs device disk-usage command
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-device.c | 3 ++
cmds-fi-disk_usage.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++
cmds-fi-disk_usage.h | 3 ++
3 files changed, 142 insertions(+)
diff --git a/cmds-device.c b/cmds-device.c
index 29da661e2a0d..f2e08ba55ba6 100644
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -28,6 +28,7 @@
#include "ctree.h"
#include "ioctl.h"
#include "utils.h"
+#include "cmds-fi-disk_usage.h"
#include "commands.h"
@@ -435,6 +436,8 @@ const struct cmd_group device_cmd_group = {
{ "scan", cmd_scan_dev, cmd_scan_dev_usage, NULL, 0 },
{ "ready", cmd_ready_dev, cmd_ready_dev_usage, NULL, 0 },
{ "stats", cmd_dev_stats, cmd_dev_stats_usage, NULL, 0 },
+ { "disk-usage", cmd_device_disk_usage,
+ cmd_device_disk_usage_usage, NULL, 0 },
NULL_CMD_STRUCT
}
};
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index 16b3ab250956..e4eb72be0a88 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -942,3 +942,139 @@ int cmd_filesystem_disk_usage(int argc, char **argv)
return 0;
}
+
+static void print_disk_chunks(int fd,
+ u64 devid,
+ u64 total_size,
+ struct chunk_info *chunks_info_ptr,
+ int chunks_info_count,
+ int mode)
+{
+ int i;
+ u64 allocated = 0;
+
+ for (i = 0 ; i < chunks_info_count ; i++) {
+ const char *description;
+ const char *r_mode;
+ u64 flags;
+ u64 size;
+
+ if (chunks_info_ptr[i].devid != devid)
+ continue;
+
+ flags = chunks_info_ptr[i].type;
+
+ description = group_type_str(flags);
+ r_mode = group_profile_str(flags);
+ size = calc_chunk_size(chunks_info_ptr+i);
+ printf(" %s,%s:%*s%10s\n",
+ description,
+ r_mode,
+ (int)(20 - strlen(description) - strlen(r_mode)), "",
+ df_pretty_sizes(size, mode));
+
+ allocated += size;
+
+ }
+ printf(" Unallocated: %*s%10s\n",
+ (int)(20 - strlen("Unallocated")), "",
+ df_pretty_sizes(total_size - allocated, mode));
+
+}
+
+static int _cmd_device_disk_usage(int fd, char *path, int mode)
+{
+ int i;
+ int ret = 0;
+ int info_count = 0;
+ struct chunk_info *info_ptr = 0;
+ struct disk_info *disks_info_ptr = 0;
+ int disks_info_count = 0;
+
+ if (load_chunk_info(fd, &info_ptr, &info_count) ||
+ load_disks_info(fd, &disks_info_ptr, &disks_info_count)) {
+ ret = -1;
+ goto exit;
+ }
+
+ for (i = 0 ; i < disks_info_count ; i++) {
+ printf("%s\t%10s\n", disks_info_ptr[i].path,
+ df_pretty_sizes(disks_info_ptr[i].size, mode));
+
+ print_disk_chunks(fd, disks_info_ptr[i].devid,
+ disks_info_ptr[i].size,
+ info_ptr, info_count,
+ mode);
+ printf("\n");
+
+ }
+
+
+exit:
+
+ if (disks_info_ptr)
+ free(disks_info_ptr);
+ if (info_ptr)
+ free(info_ptr);
+
+ return ret;
+}
+
+const char * const cmd_device_disk_usage_usage[] = {
+ "btrfs device disk-usage [-b] <path> [<path>..]",
+ "Show which chunks are in a device.",
+ "",
+ "-b\tSet byte as unit",
+ NULL
+};
+
+int cmd_device_disk_usage(int argc, char **argv)
+{
+
+ int flags = DF_HUMAN_UNIT;
+ int i, more_than_one = 0;
+
+ optind = 1;
+ while (1) {
+ char c = getopt(argc, argv, "b");
+
+ if (c < 0)
+ break;
+
+ switch (c) {
+ case 'b':
+ flags &= ~DF_HUMAN_UNIT;
+ break;
+ default:
+ usage(cmd_device_disk_usage_usage);
+ }
+ }
+
+ if (check_argc_min(argc - optind, 1)) {
+ usage(cmd_device_disk_usage_usage);
+ return 21;
+ }
+
+ for (i = optind; i < argc ; i++) {
+ int r, fd;
+ DIR *dirstream = NULL;
+ if (more_than_one)
+ printf("\n");
+
+ fd = open_file_or_dir(argv[i], &dirstream);
+ if (fd < 0) {
+ fprintf(stderr, "ERROR: can't access to '%s'\n",
+ argv[1]);
+ return 12;
+ }
+ r = _cmd_device_disk_usage(fd, argv[i], flags);
+ close_file_or_dir(fd, dirstream);
+
+ if (r)
+ return r;
+ more_than_one = 1;
+
+ }
+
+ return 0;
+}
diff --git a/cmds-fi-disk_usage.h b/cmds-fi-disk_usage.h
index c7459b1521e4..c315004cd806 100644
--- a/cmds-fi-disk_usage.h
+++ b/cmds-fi-disk_usage.h
@@ -25,4 +25,7 @@ int cmd_filesystem_df(int argc, char **argv);
extern const char * const cmd_filesystem_disk_usage_usage[];
int cmd_filesystem_disk_usage(int argc, char **argv);
+extern const char * const cmd_device_disk_usage_usage[];
+int cmd_device_disk_usage(int argc, char **argv);
+
#endif
--
1.9.0

View File

@ -0,0 +1,57 @@
From a604369c26e4e816579c59d7a595279b1b720cbc Mon Sep 17 00:00:00 2001
From: Gui Hecheng <guihc.fnst@cn.fujitsu.com>
Date: Thu, 6 Mar 2014 11:36:46 +0800
Subject: [PATCH 26/42] btrfs-progs: cleanup dead return after usage() for
fi-disk_usage
The usage() calls exit() internally, so remove the return after it.
Signed-off-by: Gui Hecheng <guihc.fnst@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-fi-disk_usage.c | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index e4eb72be0a88..a3b06bebba72 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -494,10 +494,8 @@ int cmd_filesystem_df(int argc, char **argv)
}
}
- if (check_argc_min(argc - optind, 1)) {
+ if (check_argc_min(argc - optind, 1))
usage(cmd_filesystem_df_usage);
- return 21;
- }
for (i = optind; i < argc ; i++) {
int r, fd;
@@ -914,10 +912,8 @@ int cmd_filesystem_disk_usage(int argc, char **argv)
}
}
- if (check_argc_min(argc - optind, 1)) {
+ if (check_argc_min(argc - optind, 1))
usage(cmd_filesystem_disk_usage_usage);
- return 21;
- }
for (i = optind; i < argc ; i++) {
int r, fd;
@@ -1050,10 +1046,8 @@ int cmd_device_disk_usage(int argc, char **argv)
}
}
- if (check_argc_min(argc - optind, 1)) {
+ if (check_argc_min(argc - optind, 1))
usage(cmd_device_disk_usage_usage);
- return 21;
- }
for (i = optind; i < argc ; i++) {
int r, fd;
--
1.9.0

View File

@ -0,0 +1,28 @@
From ef568dad3da6887e656be617a178cbb69b36cdf3 Mon Sep 17 00:00:00 2001
From: Qu Wenruo <quwenruo@cn.fujitsu.com>
Date: Wed, 19 Mar 2014 06:10:02 +0000
Subject: [PATCH 27/42] btrfs-progs: Fix memleak in get_raid56_used()
Fix memleak in get_raid56_used().
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-fi-disk_usage.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index a3b06bebba72..2bd591db0f8a 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -352,6 +352,7 @@ static int get_raid56_used(int fd, u64 *raid5_used, u64 *raid6_used)
if (p->type & BTRFS_BLOCK_GROUP_RAID6)
(*raid6_used) += p->size / (p->num_stripes -2);
}
+ free(info_ptr);
return 0;
--
1.9.0

View File

@ -0,0 +1,38 @@
From b43d0660526d1a3e81f34fd499eb1dd038b00e08 Mon Sep 17 00:00:00 2001
From: Rakesh Pandit <rakesh@tuxera.com>
Date: Sat, 19 Apr 2014 14:12:03 +0300
Subject: [PATCH 28/42] Btrfs-progs: fi usage: free memory if realloc fails
Lets not assign *info_ptr to 0 before calling free on it and lose
track of already allocated memory if realloc fails in
add_info_to_list. Lets call free first.
Signed-off-by: Rakesh Pandit <rakesh@tuxera.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-fi-disk_usage.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index 2bd591db0f8a..cd71c8da3cf4 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -104,6 +104,7 @@ static int add_info_to_list(struct chunk_info **info_ptr,
struct chunk_info *res = realloc(*info_ptr, size);
if (!res) {
+ free(*info_ptr);
fprintf(stderr, "ERROR: not enough memory\n");
return -1;
}
@@ -224,7 +225,6 @@ static int load_chunk_info(int fd,
if (add_info_to_list(info_ptr, info_count, item)) {
*info_ptr = 0;
- free(*info_ptr);
return -100;
}
--
1.9.0

View File

@ -0,0 +1,60 @@
From 28c2061817b8cb266458249cc7bdd770eb2b407b Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Thu, 16 Jan 2014 14:18:37 +0100
Subject: [PATCH 29/42] btrfs-progs: read global reserve size from space infos
Kernels >= 3.15 export the global block reserve as a space info presented
by 'btrfs fi df' but would display 'unknown' instead of some meaningful
string.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
ctree.h | 6 ++++++
utils.c | 7 ++++++-
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/ctree.h b/ctree.h
index 8ac17619b9dc..5c43fc5f5f6e 100644
--- a/ctree.h
+++ b/ctree.h
@@ -862,6 +862,12 @@ struct btrfs_csum_item {
/* used in struct btrfs_balance_args fields */
#define BTRFS_AVAIL_ALLOC_BIT_SINGLE (1ULL << 48)
+/*
+ * GLOBAL_RSV does not exist as a on-disk block group type and is used
+ * internally for exporting info about global block reserve from space infos
+ */
+#define BTRFS_SPACE_INFO_GLOBAL_RSV (1ULL << 49)
+
#define BTRFS_QGROUP_STATUS_OFF 0
#define BTRFS_QGROUP_STATUS_ON 1
#define BTRFS_QGROUP_STATUS_SCANNING 2
diff --git a/utils.c b/utils.c
index f2ab416c28b2..ca150404ea6f 100644
--- a/utils.c
+++ b/utils.c
@@ -2240,7 +2240,10 @@ u64 get_partition_size(char *dev)
*/
const char *group_type_str(u64 flag)
{
- switch (flag & BTRFS_BLOCK_GROUP_TYPE_MASK) {
+ u64 mask = BTRFS_BLOCK_GROUP_TYPE_MASK |
+ BTRFS_SPACE_INFO_GLOBAL_RSV;
+
+ switch (flag & mask) {
case BTRFS_BLOCK_GROUP_DATA:
return "Data";
case BTRFS_BLOCK_GROUP_SYSTEM:
@@ -2249,6 +2252,8 @@ const char *group_type_str(u64 flag)
return "Metadata";
case BTRFS_BLOCK_GROUP_DATA|BTRFS_BLOCK_GROUP_METADATA:
return "Data+Metadata";
+ case BTRFS_SPACE_INFO_GLOBAL_RSV:
+ return "GlobalReserve";
default:
return "unknown";
}
--
1.9.0

View File

@ -0,0 +1,289 @@
From 90cbd00127631b5f8964d5518d6b22bfe994a686 Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Wed, 23 Apr 2014 18:47:52 +0200
Subject: [PATCH 30/42] btrfs-progs: add original 'df' and rename 'disk_usage'
to 'usage'
Add back the original output of the 'btrfs fi df' command for backward
compatibility. The rich output is moved from 'disk_usage' to 'usage'.
Agreed in http://www.spinics.net/lists/linux-btrfs/msg31698.html
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-fi-disk_usage.c | 85 ++++++++++------------------------------------------
cmds-fi-disk_usage.h | 7 ++---
cmds-filesystem.c | 55 ++++++++++++++++++++++++++++++++--
3 files changed, 71 insertions(+), 76 deletions(-)
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index cd71c8da3cf4..efc640d13148 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -328,6 +328,8 @@ static struct btrfs_ioctl_space_args *load_space_info(int fd, char *path)
return sargs;
}
+/* Not used, keep for later */
+#if 0
/*
* This function computes the space occuped by a *single* RAID5/RAID6 chunk.
* The computation is performed on the basis of the number of stripes
@@ -465,62 +467,7 @@ exit:
return ret;
}
-
-const char * const cmd_filesystem_df_usage[] = {
- "btrfs filesystem df [-b] <path> [<path>..]",
- "Show space usage information for a mount point(s).",
- "",
- "-b\tSet byte as unit",
- NULL
-};
-
-int cmd_filesystem_df(int argc, char **argv)
-{
-
- int flags = DF_HUMAN_UNIT;
- int i, more_than_one = 0;
-
- optind = 1;
- while (1) {
- char c = getopt(argc, argv, "b");
- if (c < 0)
- break;
-
- switch (c) {
- case 'b':
- flags &= ~DF_HUMAN_UNIT;
- break;
- default:
- usage(cmd_filesystem_df_usage);
- }
- }
-
- if (check_argc_min(argc - optind, 1))
- usage(cmd_filesystem_df_usage);
-
- for (i = optind; i < argc ; i++) {
- int r, fd;
- DIR *dirstream = NULL;
- if (more_than_one)
- printf("\n");
-
- fd = open_file_or_dir(argv[i], &dirstream);
- if (fd < 0) {
- fprintf(stderr, "ERROR: can't access to '%s'\n",
- argv[1]);
- return 12;
- }
- r = _cmd_disk_free(fd, argv[i], flags);
- close_file_or_dir(fd, dirstream);
-
- if (r)
- return r;
- more_than_one = 1;
-
- }
-
- return 0;
-}
+#endif
/*
* Helper to sort the disk_info structure
@@ -612,10 +559,10 @@ static u64 calc_chunk_size(struct chunk_info *ci)
}
/*
- * This function print the results of the command btrfs fi disk-usage
+ * This function print the results of the command "btrfs fi usage"
* in tabular format
*/
-static void _cmd_filesystem_disk_usage_tabular(int mode,
+static void _cmd_filesystem_usage_tabular(int mode,
struct btrfs_ioctl_space_args *sargs,
struct chunk_info *chunks_info_ptr,
int chunks_info_count,
@@ -795,10 +742,10 @@ static void print_chunk_disks(u64 chunk_type,
}
/*
- * This function print the results of the command btrfs fi disk-usage
+ * This function print the results of the command "btrfs fi usage"
* in linear format
*/
-static void _cmd_filesystem_disk_usage_linear(int mode,
+static void _cmd_filesystem_usage_linear(int mode,
struct btrfs_ioctl_space_args *sargs,
struct chunk_info *info_ptr,
int info_count,
@@ -839,7 +786,7 @@ static void _cmd_filesystem_disk_usage_linear(int mode,
}
-static int _cmd_filesystem_disk_usage(int fd, char *path, int mode, int tabular)
+static int _cmd_filesystem_usage(int fd, char *path, int mode, int tabular)
{
struct btrfs_ioctl_space_args *sargs = 0;
int info_count = 0;
@@ -860,11 +807,11 @@ static int _cmd_filesystem_disk_usage(int fd, char *path, int mode, int tabular)
}
if (tabular)
- _cmd_filesystem_disk_usage_tabular(mode, sargs,
+ _cmd_filesystem_usage_tabular(mode, sargs,
info_ptr, info_count,
disks_info_ptr, disks_info_count);
else
- _cmd_filesystem_disk_usage_linear(mode, sargs,
+ _cmd_filesystem_usage_linear(mode, sargs,
info_ptr, info_count,
disks_info_ptr, disks_info_count);
@@ -880,8 +827,8 @@ exit:
return ret;
}
-const char * const cmd_filesystem_disk_usage_usage[] = {
- "btrfs filesystem disk-usage [-b][-t] <path> [<path>..]",
+const char * const cmd_filesystem_usage_usage[] = {
+ "btrfs filesystem usage [-b][-t] <path> [<path>..]",
"Show in which disk the chunks are allocated.",
"",
"-b\tSet byte as unit",
@@ -889,7 +836,7 @@ const char * const cmd_filesystem_disk_usage_usage[] = {
NULL
};
-int cmd_filesystem_disk_usage(int argc, char **argv)
+int cmd_filesystem_usage(int argc, char **argv)
{
int flags = DF_HUMAN_UNIT;
@@ -909,12 +856,12 @@ int cmd_filesystem_disk_usage(int argc, char **argv)
tabular = 1;
break;
default:
- usage(cmd_filesystem_disk_usage_usage);
+ usage(cmd_filesystem_usage_usage);
}
}
if (check_argc_min(argc - optind, 1))
- usage(cmd_filesystem_disk_usage_usage);
+ usage(cmd_filesystem_usage_usage);
for (i = optind; i < argc ; i++) {
int r, fd;
@@ -928,7 +875,7 @@ int cmd_filesystem_disk_usage(int argc, char **argv)
argv[1]);
return 12;
}
- r = _cmd_filesystem_disk_usage(fd, argv[i], flags, tabular);
+ r = _cmd_filesystem_usage(fd, argv[i], flags, tabular);
close_file_or_dir(fd, dirstream);
if (r)
diff --git a/cmds-fi-disk_usage.h b/cmds-fi-disk_usage.h
index c315004cd806..95cf4aabefb4 100644
--- a/cmds-fi-disk_usage.h
+++ b/cmds-fi-disk_usage.h
@@ -19,11 +19,8 @@
#ifndef __CMDS_FI_DISK_USAGE__
#define __CMDS_FI_DISK_USAGE__
-extern const char * const cmd_filesystem_df_usage[];
-int cmd_filesystem_df(int argc, char **argv);
-
-extern const char * const cmd_filesystem_disk_usage_usage[];
-int cmd_filesystem_disk_usage(int argc, char **argv);
+extern const char * const cmd_filesystem_usage_usage[];
+int cmd_filesystem_usage(int argc, char **argv);
extern const char * const cmd_device_disk_usage_usage[];
int cmd_device_disk_usage(int argc, char **argv);
diff --git a/cmds-filesystem.c b/cmds-filesystem.c
index 214a0cda518c..9340cb61cabe 100644
--- a/cmds-filesystem.c
+++ b/cmds-filesystem.c
@@ -113,6 +113,26 @@ static const char * const filesystem_cmd_group_usage[] = {
NULL
};
+static const char * const cmd_filesystem_df_usage[] = {
+ "btrfs filesystem df <path>",
+ "Show space usage information for a mount point",
+ NULL
+};
+
+static void print_df(struct btrfs_ioctl_space_args *sargs)
+{
+ u64 i;
+ struct btrfs_ioctl_space_info *sp = sargs->spaces;
+
+ for (i = 0; i < sargs->total_spaces; i++, sp++) {
+ printf("%s, %s: total=%s, used=%s\n",
+ group_type_str(sp->flags),
+ group_profile_str(sp->flags),
+ pretty_size(sp->total_bytes),
+ pretty_size(sp->used_bytes));
+ }
+}
+
static int get_df(int fd, struct btrfs_ioctl_space_args **sargs_ret)
{
u64 count = 0;
@@ -161,6 +181,37 @@ static int get_df(int fd, struct btrfs_ioctl_space_args **sargs_ret)
return 0;
}
+static int cmd_filesystem_df(int argc, char **argv)
+{
+ struct btrfs_ioctl_space_args *sargs = NULL;
+ int ret;
+ int fd;
+ char *path;
+ DIR *dirstream = NULL;
+
+ if (check_argc_exact(argc, 2))
+ usage(cmd_filesystem_df_usage);
+
+ path = argv[1];
+
+ fd = open_file_or_dir(path, &dirstream);
+ if (fd < 0) {
+ fprintf(stderr, "ERROR: can't access '%s'\n", path);
+ return 1;
+ }
+ ret = get_df(fd, &sargs);
+
+ if (!ret && sargs) {
+ print_df(sargs);
+ free(sargs);
+ } else {
+ fprintf(stderr, "ERROR: get_df failed %s\n", strerror(-ret));
+ }
+
+ close_file_or_dir(fd, dirstream);
+ return !!ret;
+}
+
static int match_search_item_kernel(__u8 *fsid, char *mnt, char *label,
char *search)
{
@@ -918,8 +969,8 @@ const struct cmd_group filesystem_cmd_group = {
{ "balance", cmd_balance, NULL, &balance_cmd_group, 1 },
{ "resize", cmd_resize, cmd_resize_usage, NULL, 0 },
{ "label", cmd_label, cmd_label_usage, NULL, 0 },
- { "disk-usage", cmd_filesystem_disk_usage,
- cmd_filesystem_disk_usage_usage, NULL, 0 },
+ { "usage", cmd_filesystem_usage,
+ cmd_filesystem_usage_usage, NULL, 0 },
NULL_CMD_STRUCT
}
--
1.9.0

View File

@ -0,0 +1,712 @@
From 14462c746c40b97dd8efe0bea18cbc6372431a39 Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Wed, 23 Apr 2014 19:00:22 +0200
Subject: [PATCH 31/42] btrfs-progs: move device usage to cmds-device, more
cleanups
Move the command definitions where they belong, keep common 'usage'
functions in cmds-fi-disk_usage.c and add exports.
Rename structures containing 'disk' to 'device'.
Fix whitespace in the modified code.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-device.c | 96 +++++++++++++++++-
cmds-fi-disk_usage.c | 281 ++++++++++++---------------------------------------
cmds-fi-disk_usage.h | 30 +++++-
3 files changed, 188 insertions(+), 219 deletions(-)
diff --git a/cmds-device.c b/cmds-device.c
index f2e08ba55ba6..c20b26e9be90 100644
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -429,6 +429,98 @@ out:
return err;
}
+const char * const cmd_device_usage_usage[] = {
+ "btrfs device usage [-b] <path> [<path>..]",
+ "Show which chunks are in a device.",
+ "",
+ "-b\tSet byte as unit",
+ NULL
+};
+
+static int _cmd_device_usage(int fd, char *path, int mode)
+{
+ int i;
+ int ret = 0;
+ int info_count = 0;
+ struct chunk_info *info_ptr = 0;
+ struct device_info *device_info_ptr = 0;
+ int device_info_count = 0;
+
+ if (load_chunk_info(fd, &info_ptr, &info_count) ||
+ load_device_info(fd, &device_info_ptr, &device_info_count)) {
+ ret = -1;
+ goto exit;
+ }
+
+ for (i = 0; i < device_info_count; i++) {
+ printf("%s\t%10s\n", device_info_ptr[i].path,
+ df_pretty_sizes(device_info_ptr[i].size, mode));
+
+ print_device_chunks(fd, device_info_ptr[i].devid,
+ device_info_ptr[i].size,
+ info_ptr, info_count,
+ mode);
+ printf("\n");
+ }
+
+exit:
+ if (device_info_ptr)
+ free(device_info_ptr);
+ if (info_ptr)
+ free(info_ptr);
+
+ return ret;
+}
+
+int cmd_device_usage(int argc, char **argv)
+{
+
+ int flags = DF_HUMAN_UNIT;
+ int i, more_than_one = 0;
+
+ optind = 1;
+ while (1) {
+ char c = getopt(argc, argv, "b");
+
+ if (c < 0)
+ break;
+
+ switch (c) {
+ case 'b':
+ flags &= ~DF_HUMAN_UNIT;
+ break;
+ default:
+ usage(cmd_device_usage_usage);
+ }
+ }
+
+ if (check_argc_min(argc - optind, 1))
+ usage(cmd_device_usage_usage);
+
+ for (i = optind; i < argc ; i++) {
+ int r, fd;
+ DIR *dirstream = NULL;
+ if (more_than_one)
+ printf("\n");
+
+ fd = open_file_or_dir(argv[i], &dirstream);
+ if (fd < 0) {
+ fprintf(stderr, "ERROR: can't access to '%s'\n",
+ argv[1]);
+ return 12;
+ }
+ r = _cmd_device_usage(fd, argv[i], flags);
+ close_file_or_dir(fd, dirstream);
+
+ if (r)
+ return r;
+ more_than_one = 1;
+
+ }
+
+ return 0;
+}
+
const struct cmd_group device_cmd_group = {
device_cmd_group_usage, NULL, {
{ "add", cmd_add_dev, cmd_add_dev_usage, NULL, 0 },
@@ -436,8 +528,8 @@ const struct cmd_group device_cmd_group = {
{ "scan", cmd_scan_dev, cmd_scan_dev_usage, NULL, 0 },
{ "ready", cmd_ready_dev, cmd_ready_dev_usage, NULL, 0 },
{ "stats", cmd_dev_stats, cmd_dev_stats_usage, NULL, 0 },
- { "disk-usage", cmd_device_disk_usage,
- cmd_device_disk_usage_usage, NULL, 0 },
+ { "usage", cmd_device_usage,
+ cmd_device_usage_usage, NULL, 0 },
NULL_CMD_STRUCT
}
};
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index efc640d13148..023659daac0e 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -26,38 +26,16 @@
#include "kerncompat.h"
#include "ctree.h"
#include "string_table.h"
-
+#include "cmds-fi-disk_usage.h"
#include "commands.h"
#include "version.h"
-#define DF_HUMAN_UNIT (1<<0)
-
-/*
- * To store the size information about the chunks:
- * the chunks info are grouped by the tuple (type, devid, num_stripes),
- * i.e. if two chunks are of the same type (RAID1, DUP...), are on the
- * same disk, have the same stripes then their sizes are grouped
- */
-struct chunk_info {
- u64 type;
- u64 size;
- u64 devid;
- u64 num_stripes;
-};
-
-/* to store information about the disks */
-struct disk_info {
- u64 devid;
- char path[BTRFS_DEVICE_PATH_NAME_MAX];
- u64 size;
-};
-
/*
* Pretty print the size
* PAY ATTENTION: it return a statically buffer
*/
-static char *df_pretty_sizes(u64 size, int mode)
+char *df_pretty_sizes(u64 size, int mode)
{
static char buf[30];
@@ -163,14 +141,8 @@ static int cmp_chunk_info(const void *a, const void *b)
((struct chunk_info *)b)->type);
}
-/*
- * This function load all the chunk info from the 'fd' filesystem
- */
-static int load_chunk_info(int fd,
- struct chunk_info **info_ptr,
- int *info_count)
+int load_chunk_info(int fd, struct chunk_info **info_ptr, int *info_count)
{
-
int ret;
struct btrfs_ioctl_search_args args;
struct btrfs_ioctl_search_key *sk = &args.key;
@@ -178,7 +150,6 @@ static int load_chunk_info(int fd,
unsigned long off = 0;
int i, e;
-
memset(&args, 0, sizeof(args));
/*
@@ -186,8 +157,6 @@ static int load_chunk_info(int fd,
* snapshots pending deletion, we have to loop through
* them.
*/
-
-
sk->tree_id = BTRFS_CHUNK_TREE_OBJECTID;
sk->min_objectid = 0;
@@ -253,7 +222,6 @@ static int load_chunk_info(int fd,
cmp_chunk_info);
return 0;
-
}
/*
@@ -333,7 +301,7 @@ static struct btrfs_ioctl_space_args *load_space_info(int fd, char *path)
/*
* This function computes the space occuped by a *single* RAID5/RAID6 chunk.
* The computation is performed on the basis of the number of stripes
- * which compose the chunk, which could be different from the number of disks
+ * which compose the chunk, which could be different from the number of devices
* if a disk is added later.
*/
static int get_raid56_used(int fd, u64 *raid5_used, u64 *raid6_used)
@@ -367,7 +335,7 @@ static int _cmd_disk_free(int fd, char *path, int mode)
int ret = 0;
int e, width;
u64 total_disk; /* filesystem size == sum of
- disks sizes */
+ device sizes */
u64 total_chunks; /* sum of chunks sizes on disk(s) */
u64 total_used; /* logical space used */
u64 total_free; /* logical space un-used */
@@ -470,29 +438,27 @@ exit:
#endif
/*
- * Helper to sort the disk_info structure
+ * Helper to sort the device_info structure
*/
-static int cmp_disk_info(const void *a, const void *b)
+static int cmp_device_info(const void *a, const void *b)
{
- return strcmp(((struct disk_info *)a)->path,
- ((struct disk_info *)b)->path);
+ return strcmp(((struct device_info *)a)->path,
+ ((struct device_info *)b)->path);
}
/*
- * This function load the disk_info structure and put them in an array
+ * This function loads the device_info structure and put them in an array
*/
-static int load_disks_info(int fd,
- struct disk_info **disks_info_ptr,
- int *disks_info_count)
+int load_device_info(int fd, struct device_info **device_info_ptr,
+ int *device_info_count)
{
-
int ret, i, ndevs;
struct btrfs_ioctl_fs_info_args fi_args;
struct btrfs_ioctl_dev_info_args dev_info;
- struct disk_info *info;
+ struct device_info *info;
- *disks_info_count = 0;
- *disks_info_ptr = 0;
+ *device_info_count = 0;
+ *device_info_ptr = 0;
ret = ioctl(fd, BTRFS_IOC_FS_INFO, &fi_args);
if (ret < 0) {
@@ -500,7 +466,7 @@ static int load_disks_info(int fd,
return -1;
}
- info = malloc(sizeof(struct disk_info) * fi_args.num_devices);
+ info = malloc(sizeof(struct device_info) * fi_args.num_devices);
if (!info) {
fprintf(stderr, "ERROR: not enough memory\n");
return -1;
@@ -529,13 +495,12 @@ static int load_disks_info(int fd,
BUG_ON(ndevs != fi_args.num_devices);
qsort(info, fi_args.num_devices,
- sizeof(struct disk_info), cmp_disk_info);
+ sizeof(struct device_info), cmp_device_info);
- *disks_info_count = fi_args.num_devices;
- *disks_info_ptr = info;
+ *device_info_count = fi_args.num_devices;
+ *device_info_ptr = info;
return 0;
-
}
/*
@@ -566,8 +531,8 @@ static void _cmd_filesystem_usage_tabular(int mode,
struct btrfs_ioctl_space_args *sargs,
struct chunk_info *chunks_info_ptr,
int chunks_info_count,
- struct disk_info *disks_info_ptr,
- int disks_info_count)
+ struct device_info *device_info_ptr,
+ int device_info_count)
{
int i;
u64 total_unused = 0;
@@ -575,7 +540,7 @@ static void _cmd_filesystem_usage_tabular(int mode,
int ncols, nrows;
ncols = sargs->total_spaces + 2;
- nrows = 2 + 1 + disks_info_count + 1 + 2;
+ nrows = 2 + 1 + device_info_count + 1 + 2;
matrix = table_create(ncols, nrows);
if (!matrix) {
@@ -605,24 +570,23 @@ static void _cmd_filesystem_usage_tabular(int mode,
table_printf(matrix, 1+sargs->total_spaces, 1, "<Unallocated");
/* body */
- for (i = 0 ; i < disks_info_count ; i++) {
+ for (i = 0; i < device_info_count; i++) {
int k, col;
char *p;
u64 total_allocated = 0, unused;
- p = strrchr(disks_info_ptr[i].path, '/');
+ p = strrchr(device_info_ptr[i].path, '/');
if (!p)
- p = disks_info_ptr[i].path;
+ p = device_info_ptr[i].path;
else
p++;
- table_printf(matrix, 0, i+3, "<%s",
- disks_info_ptr[i].path);
+ table_printf(matrix, 0, i + 3, "<%s", device_info_ptr[i].path);
for (col = 1, k = 0 ; k < sargs->total_spaces ; k++) {
u64 flags = sargs->spaces[k].flags;
- u64 devid = disks_info_ptr[i].devid;
+ u64 devid = device_info_ptr[i].devid;
int j;
u64 size = 0;
@@ -645,8 +609,8 @@ static void _cmd_filesystem_usage_tabular(int mode,
col++;
}
- unused = get_partition_size(disks_info_ptr[i].path) -
- total_allocated;
+ unused = get_partition_size(device_info_ptr[i].path)
+ - total_allocated;
table_printf(matrix, sargs->total_spaces + 1, i + 3,
">%s", df_pretty_sizes(unused, mode));
@@ -655,28 +619,24 @@ static void _cmd_filesystem_usage_tabular(int mode,
}
for (i = 0; i <= sargs->total_spaces; i++)
- table_printf(matrix, i + 1, disks_info_count + 3, "=");
-
+ table_printf(matrix, i + 1, device_info_count + 3, "=");
/* footer */
- table_printf(matrix, 0, disks_info_count + 4, "<Total");
+ table_printf(matrix, 0, device_info_count + 4, "<Total");
for (i = 0; i < sargs->total_spaces; i++)
- table_printf(matrix, 1 + i, disks_info_count + 4,
- ">%s",
+ table_printf(matrix, 1 + i, device_info_count + 4, ">%s",
df_pretty_sizes(sargs->spaces[i].total_bytes, mode));
- table_printf(matrix, sargs->total_spaces+1, disks_info_count+4,
- ">%s", df_pretty_sizes(total_unused, mode));
+ table_printf(matrix, sargs->total_spaces + 1, device_info_count + 4,
+ ">%s", df_pretty_sizes(total_unused, mode));
- table_printf(matrix, 0, disks_info_count+5, "<Used");
+ table_printf(matrix, 0, device_info_count + 5, "<Used");
for (i = 0; i < sargs->total_spaces; i++)
- table_printf(matrix, 1+i, disks_info_count+5, ">%s",
+ table_printf(matrix, 1 + i, device_info_count+5, ">%s",
df_pretty_sizes(sargs->spaces[i].used_bytes, mode));
-
table_dump(matrix);
table_free(matrix);
-
}
/*
@@ -684,50 +644,46 @@ static void _cmd_filesystem_usage_tabular(int mode,
*/
static void print_unused(struct chunk_info *info_ptr,
int info_count,
- struct disk_info *disks_info_ptr,
- int disks_info_count,
+ struct device_info *device_info_ptr,
+ int device_info_count,
int mode)
{
int i;
- for (i = 0 ; i < disks_info_count ; i++) {
-
+ for (i = 0; i < device_info_count; i++) {
int j;
u64 total = 0;
- for (j = 0 ; j < info_count ; j++)
- if (info_ptr[j].devid == disks_info_ptr[i].devid)
+ for (j = 0; j < info_count; j++)
+ if (info_ptr[j].devid == device_info_ptr[i].devid)
total += calc_chunk_size(info_ptr+j);
printf(" %s\t%10s\n",
- disks_info_ptr[i].path,
- df_pretty_sizes(disks_info_ptr[i].size - total, mode));
-
+ device_info_ptr[i].path,
+ df_pretty_sizes(device_info_ptr[i].size - total, mode));
}
-
}
/*
* This function prints the allocated chunk per every disk
*/
-static void print_chunk_disks(u64 chunk_type,
+static void print_chunk_device(u64 chunk_type,
struct chunk_info *chunks_info_ptr,
int chunks_info_count,
- struct disk_info *disks_info_ptr,
- int disks_info_count,
+ struct device_info *device_info_ptr,
+ int device_info_count,
int mode)
{
int i;
- for (i = 0 ; i < disks_info_count ; i++) {
-
+ for (i = 0; i < device_info_count; i++) {
int j;
u64 total = 0;
- for (j = 0 ; j < chunks_info_count ; j++) {
+ for (j = 0; j < chunks_info_count; j++) {
if (chunks_info_ptr[j].type != chunk_type)
continue;
- if (chunks_info_ptr[j].devid != disks_info_ptr[i].devid)
+ if (chunks_info_ptr[j].devid != device_info_ptr[i].devid)
continue;
total += calc_chunk_size(&(chunks_info_ptr[j]));
@@ -736,7 +692,7 @@ static void print_chunk_disks(u64 chunk_type,
if (total > 0)
printf(" %s\t%10s\n",
- disks_info_ptr[i].path,
+ device_info_ptr[i].path,
df_pretty_sizes(total, mode));
}
}
@@ -749,8 +705,8 @@ static void _cmd_filesystem_usage_linear(int mode,
struct btrfs_ioctl_space_args *sargs,
struct chunk_info *info_ptr,
int info_count,
- struct disk_info *disks_info_ptr,
- int disks_info_count)
+ struct device_info *device_info_ptr,
+ int device_info_count)
{
int i;
@@ -768,22 +724,15 @@ static void _cmd_filesystem_usage_linear(int mode,
df_pretty_sizes(sargs->spaces[i].total_bytes ,
mode));
printf("Used:%s\n",
- df_pretty_sizes(sargs->spaces[i].used_bytes,
- mode));
- print_chunk_disks(flags, info_ptr, info_count,
- disks_info_ptr, disks_info_count,
- mode);
+ df_pretty_sizes(sargs->spaces[i].used_bytes, mode));
+ print_chunk_device(flags, info_ptr, info_count,
+ device_info_ptr, device_info_count, mode);
printf("\n");
-
}
printf("Unallocated:\n");
- print_unused(info_ptr, info_count,
- disks_info_ptr, disks_info_count,
+ print_unused(info_ptr, info_count, device_info_ptr, device_info_count,
mode);
-
-
-
}
static int _cmd_filesystem_usage(int fd, char *path, int mode, int tabular)
@@ -791,12 +740,12 @@ static int _cmd_filesystem_usage(int fd, char *path, int mode, int tabular)
struct btrfs_ioctl_space_args *sargs = 0;
int info_count = 0;
struct chunk_info *info_ptr = 0;
- struct disk_info *disks_info_ptr = 0;
- int disks_info_count = 0;
+ struct device_info *device_info_ptr = 0;
+ int device_info_count = 0;
int ret = 0;
if (load_chunk_info(fd, &info_ptr, &info_count) ||
- load_disks_info(fd, &disks_info_ptr, &disks_info_count)) {
+ load_device_info(fd, &device_info_ptr, &device_info_count)) {
ret = -1;
goto exit;
}
@@ -809,18 +758,18 @@ static int _cmd_filesystem_usage(int fd, char *path, int mode, int tabular)
if (tabular)
_cmd_filesystem_usage_tabular(mode, sargs,
info_ptr, info_count,
- disks_info_ptr, disks_info_count);
+ device_info_ptr, device_info_count);
else
_cmd_filesystem_usage_linear(mode, sargs,
info_ptr, info_count,
- disks_info_ptr, disks_info_count);
+ device_info_ptr, device_info_count);
exit:
if (sargs)
free(sargs);
- if (disks_info_ptr)
- free(disks_info_ptr);
+ if (device_info_ptr)
+ free(device_info_ptr);
if (info_ptr)
free(info_ptr);
@@ -887,12 +836,9 @@ int cmd_filesystem_usage(int argc, char **argv)
return 0;
}
-static void print_disk_chunks(int fd,
- u64 devid,
- u64 total_size,
- struct chunk_info *chunks_info_ptr,
- int chunks_info_count,
- int mode)
+void print_device_chunks(int fd, u64 devid, u64 total_size,
+ struct chunk_info *chunks_info_ptr,
+ int chunks_info_count, int mode)
{
int i;
u64 allocated = 0;
@@ -925,98 +871,3 @@ static void print_disk_chunks(int fd,
df_pretty_sizes(total_size - allocated, mode));
}
-
-static int _cmd_device_disk_usage(int fd, char *path, int mode)
-{
- int i;
- int ret = 0;
- int info_count = 0;
- struct chunk_info *info_ptr = 0;
- struct disk_info *disks_info_ptr = 0;
- int disks_info_count = 0;
-
- if (load_chunk_info(fd, &info_ptr, &info_count) ||
- load_disks_info(fd, &disks_info_ptr, &disks_info_count)) {
- ret = -1;
- goto exit;
- }
-
- for (i = 0 ; i < disks_info_count ; i++) {
- printf("%s\t%10s\n", disks_info_ptr[i].path,
- df_pretty_sizes(disks_info_ptr[i].size, mode));
-
- print_disk_chunks(fd, disks_info_ptr[i].devid,
- disks_info_ptr[i].size,
- info_ptr, info_count,
- mode);
- printf("\n");
-
- }
-
-
-exit:
-
- if (disks_info_ptr)
- free(disks_info_ptr);
- if (info_ptr)
- free(info_ptr);
-
- return ret;
-}
-
-const char * const cmd_device_disk_usage_usage[] = {
- "btrfs device disk-usage [-b] <path> [<path>..]",
- "Show which chunks are in a device.",
- "",
- "-b\tSet byte as unit",
- NULL
-};
-
-int cmd_device_disk_usage(int argc, char **argv)
-{
-
- int flags = DF_HUMAN_UNIT;
- int i, more_than_one = 0;
-
- optind = 1;
- while (1) {
- char c = getopt(argc, argv, "b");
-
- if (c < 0)
- break;
-
- switch (c) {
- case 'b':
- flags &= ~DF_HUMAN_UNIT;
- break;
- default:
- usage(cmd_device_disk_usage_usage);
- }
- }
-
- if (check_argc_min(argc - optind, 1))
- usage(cmd_device_disk_usage_usage);
-
- for (i = optind; i < argc ; i++) {
- int r, fd;
- DIR *dirstream = NULL;
- if (more_than_one)
- printf("\n");
-
- fd = open_file_or_dir(argv[i], &dirstream);
- if (fd < 0) {
- fprintf(stderr, "ERROR: can't access to '%s'\n",
- argv[1]);
- return 12;
- }
- r = _cmd_device_disk_usage(fd, argv[i], flags);
- close_file_or_dir(fd, dirstream);
-
- if (r)
- return r;
- more_than_one = 1;
-
- }
-
- return 0;
-}
diff --git a/cmds-fi-disk_usage.h b/cmds-fi-disk_usage.h
index 95cf4aabefb4..787b4eb56acf 100644
--- a/cmds-fi-disk_usage.h
+++ b/cmds-fi-disk_usage.h
@@ -19,10 +19,36 @@
#ifndef __CMDS_FI_DISK_USAGE__
#define __CMDS_FI_DISK_USAGE__
+#define DF_HUMAN_UNIT (1<<0)
+
extern const char * const cmd_filesystem_usage_usage[];
int cmd_filesystem_usage(int argc, char **argv);
-extern const char * const cmd_device_disk_usage_usage[];
-int cmd_device_disk_usage(int argc, char **argv);
+struct device_info {
+ u64 devid;
+ char path[BTRFS_DEVICE_PATH_NAME_MAX];
+ u64 size;
+};
+
+/*
+ * To store the size information about the chunks:
+ * the chunks info are grouped by the tuple (type, devid, num_stripes),
+ * i.e. if two chunks are of the same type (RAID1, DUP...), are on the
+ * same disk, have the same stripes then their sizes are grouped
+ */
+struct chunk_info {
+ u64 type;
+ u64 size;
+ u64 devid;
+ u64 num_stripes;
+};
+
+int load_device_info(int fd, struct device_info **device_info_ptr,
+ int *device_info_count);
+int load_chunk_info(int fd, struct chunk_info **info_ptr, int *info_count);
+char *df_pretty_sizes(u64 size, int mode);
+void print_device_chunks(int fd, u64 devid, u64 total_size,
+ struct chunk_info *chunks_info_ptr,
+ int chunks_info_count, int mode);
#endif
--
1.9.0

View File

@ -0,0 +1,45 @@
From a6979c52fbff0e0961a0a0546c45bca11f6a0658 Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Thu, 24 Apr 2014 15:21:16 +0200
Subject: [PATCH 32/42] btrfs-progs: check if we can't get info from ioctls due
to permissions
The TREE_SEARCH ioctl is root-only, FS_INFO will be available for
non-root users with an updated kernel, let the user know.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-fi-disk_usage.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index 023659daac0e..3fa2af004dc4 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -172,6 +172,12 @@ int load_chunk_info(int fd, struct chunk_info **info_ptr, int *info_count)
while (1) {
ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
e = errno;
+ if (ret == -EPERM) {
+ fprintf(stderr,
+ "ERROR: can't read detailed chunk info from ioctl(TREE_SEARCH), run as root\n");
+ return 0;
+ }
+
if (ret < 0) {
fprintf(stderr,
"ERROR: can't perform the search - %s\n",
@@ -461,6 +467,10 @@ int load_device_info(int fd, struct device_info **device_info_ptr,
*device_info_ptr = 0;
ret = ioctl(fd, BTRFS_IOC_FS_INFO, &fi_args);
+ if (ret == -EPERM) {
+ fprintf(stderr, "ERROR: can't get filesystem info from ioctl(FS_INFO), run as root\n");
+ return -1;
+ }
if (ret < 0) {
fprintf(stderr, "ERROR: cannot get filesystem info\n");
return -1;
--
1.9.0

View File

@ -0,0 +1,44 @@
From 70b51a393b7d9ee6d20b16be0c925c58ea88f3c5 Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Thu, 24 Apr 2014 18:37:50 +0200
Subject: [PATCH 33/42] btrfs-progs: zero out structures before calling ioctl
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-fi-disk_usage.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index 3fa2af004dc4..8c0462230510 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -248,7 +248,7 @@ static struct btrfs_ioctl_space_args *load_space_info(int fd, char *path)
struct btrfs_ioctl_space_args *sargs = 0, *sargs_orig = 0;
int e, ret, count;
- sargs_orig = sargs = malloc(sizeof(struct btrfs_ioctl_space_args));
+ sargs_orig = sargs = calloc(1, sizeof(struct btrfs_ioctl_space_args));
if (!sargs) {
fprintf(stderr, "ERROR: not enough memory\n");
return NULL;
@@ -476,15 +476,15 @@ int load_device_info(int fd, struct device_info **device_info_ptr,
return -1;
}
- info = malloc(sizeof(struct device_info) * fi_args.num_devices);
+ info = calloc(fi_args.num_devices, sizeof(struct device_info));
if (!info) {
fprintf(stderr, "ERROR: not enough memory\n");
return -1;
}
for (i = 0, ndevs = 0 ; i <= fi_args.max_id ; i++) {
-
BUG_ON(ndevs >= fi_args.num_devices);
+ memset(&dev_info, 0, sizeof(dev_info));
ret = get_device_info(fd, i, &dev_info);
if (ret == -ENODEV)
--
1.9.0

View File

@ -0,0 +1,28 @@
From 86b1a432b74285db0096fdd4894626cb26773eeb Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Thu, 24 Apr 2014 18:31:28 +0200
Subject: [PATCH 34/42] btrfs-progs: print B for bytes
This arguably helps parsers.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
utils.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/utils.c b/utils.c
index ca150404ea6f..159abf8bd0e4 100644
--- a/utils.c
+++ b/utils.c
@@ -1252,7 +1252,7 @@ out:
return ret;
}
-static char *size_strs[] = { "", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"};
+static char *size_strs[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"};
int pretty_size_snprintf(u64 size, char *str, size_t str_bytes)
{
int num_divs = 0;
--
1.9.0

View File

@ -0,0 +1,101 @@
From c856f30b979c71ab5cda62753993e725dae922e6 Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Thu, 24 Apr 2014 18:32:27 +0200
Subject: [PATCH 35/42] btrfs-progs: Print more info about device sizes
The entire device size may not be available to the filesystem, eg. if
it's modified via resize. Print this information if it can be obtained
from the DEV_INFO ioctl.
Print the device ID on the same line as the device name and move size to
the next line.
Sample:
/dev/sda7, ID: 3
Device size: 10.00GiB
FS occuppied: 5.00GiB
Data,RAID10: 512.00MiB
Metadata,RAID10: 512.00MiB
System,RAID10: 4.00MiB
Unallocated: 9.00GiB
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-device.c | 6 +++---
cmds-fi-disk_usage.c | 13 ++++++++++++-
cmds-fi-disk_usage.h | 6 +++++-
3 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/cmds-device.c b/cmds-device.c
index c20b26e9be90..154188643c8f 100644
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -453,9 +453,9 @@ static int _cmd_device_usage(int fd, char *path, int mode)
}
for (i = 0; i < device_info_count; i++) {
- printf("%s\t%10s\n", device_info_ptr[i].path,
- df_pretty_sizes(device_info_ptr[i].size, mode));
-
+ printf("%s, ID: %llu\n", device_info_ptr[i].path,
+ device_info_ptr[i].devid);
+ print_device_sizes(fd, &device_info_ptr[i], mode);
print_device_chunks(fd, device_info_ptr[i].devid,
device_info_ptr[i].size,
info_ptr, info_count,
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index 8c0462230510..63ed9ba089d5 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -499,7 +499,8 @@ int load_device_info(int fd, struct device_info **device_info_ptr,
info[ndevs].devid = dev_info.devid;
strcpy(info[ndevs].path, (char *)dev_info.path);
- info[ndevs].size = get_partition_size((char *)dev_info.path);
+ info[ndevs].device_size = get_partition_size((char *)dev_info.path);
+ info[ndevs].size = dev_info.total_size;
++ndevs;
}
@@ -879,5 +880,15 @@ void print_device_chunks(int fd, u64 devid, u64 total_size,
printf(" Unallocated: %*s%10s\n",
(int)(20 - strlen("Unallocated")), "",
df_pretty_sizes(total_size - allocated, mode));
+}
+void print_device_sizes(int fd, struct device_info *devinfo, int mode)
+{
+ printf(" Device size: %*s%10s\n",
+ (int)(20 - strlen("Device size")), "",
+ df_pretty_sizes(devinfo->device_size, mode));
+ printf(" FS occuppied:%*s%10s\n",
+ (int)(20 - strlen("FS occupied")), "",
+ df_pretty_sizes(devinfo->size, mode));
+ }
}
diff --git a/cmds-fi-disk_usage.h b/cmds-fi-disk_usage.h
index 787b4eb56acf..79cc2a115bc5 100644
--- a/cmds-fi-disk_usage.h
+++ b/cmds-fi-disk_usage.h
@@ -27,7 +27,10 @@ int cmd_filesystem_usage(int argc, char **argv);
struct device_info {
u64 devid;
char path[BTRFS_DEVICE_PATH_NAME_MAX];
- u64 size;
+ /* Size of the block device */
+ u64 device_size;
+ /* Size that's occupied by the filesystem, can be changed via resize */
+ u64 size;
};
/*
@@ -50,5 +53,6 @@ char *df_pretty_sizes(u64 size, int mode);
void print_device_chunks(int fd, u64 devid, u64 total_size,
struct chunk_info *chunks_info_ptr,
int chunks_info_count, int mode);
+void print_device_sizes(int fd, struct device_info *devinfo, int mode);
#endif
--
1.9.0

View File

@ -0,0 +1,96 @@
From a2b5656ac87bd741153b97ac1e7bcf40ecc4f16c Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Thu, 24 Apr 2014 18:57:12 +0200
Subject: [PATCH 36/42] btrfs-progs: compare unallocated space against the
correct value
The device may not be fully occupied by the filesystem, the value of
Unallocated should not be calculated against the device size but the
size provided by DEV_INFO.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-device.c | 6 ++----
cmds-fi-disk_usage.c | 9 ++++-----
cmds-fi-disk_usage.h | 2 +-
3 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/cmds-device.c b/cmds-device.c
index 154188643c8f..3e851badc116 100644
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -456,10 +456,8 @@ static int _cmd_device_usage(int fd, char *path, int mode)
printf("%s, ID: %llu\n", device_info_ptr[i].path,
device_info_ptr[i].devid);
print_device_sizes(fd, &device_info_ptr[i], mode);
- print_device_chunks(fd, device_info_ptr[i].devid,
- device_info_ptr[i].size,
- info_ptr, info_count,
- mode);
+ print_device_chunks(fd, &device_info_ptr[i],
+ info_ptr, info_count, mode);
printf("\n");
}
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index 63ed9ba089d5..0e93dc836f16 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -500,7 +500,7 @@ int load_device_info(int fd, struct device_info **device_info_ptr,
info[ndevs].devid = dev_info.devid;
strcpy(info[ndevs].path, (char *)dev_info.path);
info[ndevs].device_size = get_partition_size((char *)dev_info.path);
- info[ndevs].size = dev_info.total_size;
+ info[ndevs].size = dev_info.total_bytes;
++ndevs;
}
@@ -847,7 +847,7 @@ int cmd_filesystem_usage(int argc, char **argv)
return 0;
}
-void print_device_chunks(int fd, u64 devid, u64 total_size,
+void print_device_chunks(int fd, struct device_info *devinfo,
struct chunk_info *chunks_info_ptr,
int chunks_info_count, int mode)
{
@@ -860,7 +860,7 @@ void print_device_chunks(int fd, u64 devid, u64 total_size,
u64 flags;
u64 size;
- if (chunks_info_ptr[i].devid != devid)
+ if (chunks_info_ptr[i].devid != devinfo->devid)
continue;
flags = chunks_info_ptr[i].type;
@@ -879,7 +879,7 @@ void print_device_chunks(int fd, u64 devid, u64 total_size,
}
printf(" Unallocated: %*s%10s\n",
(int)(20 - strlen("Unallocated")), "",
- df_pretty_sizes(total_size - allocated, mode));
+ df_pretty_sizes(devinfo->size - allocated, mode));
}
void print_device_sizes(int fd, struct device_info *devinfo, int mode)
@@ -890,5 +890,4 @@ void print_device_sizes(int fd, struct device_info *devinfo, int mode)
printf(" FS occuppied:%*s%10s\n",
(int)(20 - strlen("FS occupied")), "",
df_pretty_sizes(devinfo->size, mode));
- }
}
diff --git a/cmds-fi-disk_usage.h b/cmds-fi-disk_usage.h
index 79cc2a115bc5..dbc2a10f31eb 100644
--- a/cmds-fi-disk_usage.h
+++ b/cmds-fi-disk_usage.h
@@ -50,7 +50,7 @@ int load_device_info(int fd, struct device_info **device_info_ptr,
int *device_info_count);
int load_chunk_info(int fd, struct chunk_info **info_ptr, int *info_count);
char *df_pretty_sizes(u64 size, int mode);
-void print_device_chunks(int fd, u64 devid, u64 total_size,
+void print_device_chunks(int fd, struct device_info *devinfo,
struct chunk_info *chunks_info_ptr,
int chunks_info_count, int mode);
void print_device_sizes(int fd, struct device_info *devinfo, int mode);
--
1.9.0

View File

@ -0,0 +1,107 @@
From d8ca04ddc42461c462e3b52031e1134f01c71663 Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Fri, 25 Apr 2014 17:24:40 +0200
Subject: [PATCH 37/42] btrfs-progs: add section of overall filesystem usage
The 'fi usage' lacks an overall report, this used to be in the enhanced
df command. Add it back.
Sample:
Overall:
Device size: 35.00GiB
Device allocated: 8.07GiB
Device unallocated: 26.93GiB
Used: 1.12MiB
Free (Estimated): 17.57GiB (Max: 30.98GiB, min: 17.52GiB)
Data to device ratio: 50 %
...
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-fi-disk_usage.c | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index 0e93dc836f16..e17f04e31d35 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -302,8 +302,6 @@ static struct btrfs_ioctl_space_args *load_space_info(int fd, char *path)
return sargs;
}
-/* Not used, keep for later */
-#if 0
/*
* This function computes the space occuped by a *single* RAID5/RAID6 chunk.
* The computation is performed on the basis of the number of stripes
@@ -331,7 +329,6 @@ static int get_raid56_used(int fd, u64 *raid5_used, u64 *raid6_used)
free(info_ptr);
return 0;
-
}
static int _cmd_disk_free(int fd, char *path, int mode)
@@ -416,22 +413,24 @@ static int _cmd_disk_free(int fd, char *path, int mode)
else
width = 18;
- printf("Disk size:\t\t%*s\n", width,
+ printf("Overall:\n");
+
+ printf(" Device size:\t\t%*s\n", width,
df_pretty_sizes(total_disk, mode));
- printf("Disk allocated:\t\t%*s\n", width,
+ printf(" Device allocated:\t\t%*s\n", width,
df_pretty_sizes(total_chunks, mode));
- printf("Disk unallocated:\t%*s\n", width,
+ printf(" Device unallocated:\t\t%*s\n", width,
df_pretty_sizes(total_disk-total_chunks, mode));
- printf("Used:\t\t\t%*s\n", width,
+ printf(" Used:\t\t\t%*s\n", width,
df_pretty_sizes(total_used, mode));
- printf("Free (Estimated):\t%*s\t(",
+ printf(" Free (Estimated):\t\t%*s\t(",
width,
df_pretty_sizes((u64)(K*total_disk-total_used), mode));
printf("Max: %s, ",
df_pretty_sizes(total_disk-total_chunks+total_free, mode));
printf("min: %s)\n",
df_pretty_sizes((total_disk-total_chunks)/2+total_free, mode));
- printf("Data to disk ratio:\t%*.0f %%\n",
+ printf(" Data to device ratio:\t%*.0f %%\n",
width-2, K*100);
exit:
@@ -441,7 +440,6 @@ exit:
return ret;
}
-#endif
/*
* Helper to sort the device_info structure
@@ -826,8 +824,6 @@ int cmd_filesystem_usage(int argc, char **argv)
for (i = optind; i < argc ; i++) {
int r, fd;
DIR *dirstream = NULL;
- if (more_than_one)
- printf("\n");
fd = open_file_or_dir(argv[i], &dirstream);
if (fd < 0) {
@@ -835,6 +831,11 @@ int cmd_filesystem_usage(int argc, char **argv)
argv[1]);
return 12;
}
+ if (more_than_one)
+ printf("\n");
+
+ r = _cmd_disk_free(fd, argv[i], flags);
+ printf("\n");
r = _cmd_filesystem_usage(fd, argv[i], flags, tabular);
close_file_or_dir(fd, dirstream);
--
1.9.0

View File

@ -0,0 +1,372 @@
From e81d2614ff21e3e9e723cc645cc73646a42d06e8 Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Fri, 25 Apr 2014 19:39:11 +0200
Subject: [PATCH 38/42] btrfs-progs: cleanup filesystem/device usage code
The main point of this is to load the device and chunk infos at one
place and pass down to the printers. The EPERM is handled separately, in
case kernel does not give us all the information about chunks or
devices, but we want to warn and print at least something.
For non-root users, 'filesystem usage' prints only the overall stats and
warns about RAID5/6.
The sole cleanup changes affect mostly the modified code and the related
functions, should be reasonably small.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-device.c | 31 +++++-----
cmds-fi-disk_usage.c | 163 +++++++++++++++++++++++++++------------------------
cmds-fi-disk_usage.h | 5 +-
3 files changed, 105 insertions(+), 94 deletions(-)
diff --git a/cmds-device.c b/cmds-device.c
index 3e851badc116..bf5898f6da68 100644
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -441,31 +441,29 @@ static int _cmd_device_usage(int fd, char *path, int mode)
{
int i;
int ret = 0;
- int info_count = 0;
- struct chunk_info *info_ptr = 0;
- struct device_info *device_info_ptr = 0;
- int device_info_count = 0;
+ struct chunk_info *chunkinfo = NULL;
+ struct device_info *devinfo = NULL;
+ int chunkcount = 0;
+ int devcount = 0;
- if (load_chunk_info(fd, &info_ptr, &info_count) ||
- load_device_info(fd, &device_info_ptr, &device_info_count)) {
+ ret = load_chunk_and_device_info(fd, &chunkinfo, &chunkcount, &devinfo,
+ &devcount);
+ if (ret) {
ret = -1;
goto exit;
}
- for (i = 0; i < device_info_count; i++) {
- printf("%s, ID: %llu\n", device_info_ptr[i].path,
- device_info_ptr[i].devid);
- print_device_sizes(fd, &device_info_ptr[i], mode);
- print_device_chunks(fd, &device_info_ptr[i],
- info_ptr, info_count, mode);
+ for (i = 0; i < devcount; i++) {
+ printf("%s, ID: %llu\n", devinfo[i].path, devinfo[i].devid);
+ print_device_sizes(fd, &devinfo[i], mode);
+ print_device_chunks(fd, &devinfo[i], chunkinfo, chunkcount,
+ mode);
printf("\n");
}
exit:
- if (device_info_ptr)
- free(device_info_ptr);
- if (info_ptr)
- free(info_ptr);
+ free(devinfo);
+ free(chunkinfo);
return ret;
}
@@ -507,6 +505,7 @@ int cmd_device_usage(int argc, char **argv)
argv[1]);
return 12;
}
+
r = _cmd_device_usage(fd, argv[i], flags);
close_file_or_dir(fd, dirstream);
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index e17f04e31d35..9d1c4085b4ea 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -141,7 +141,7 @@ static int cmp_chunk_info(const void *a, const void *b)
((struct chunk_info *)b)->type);
}
-int load_chunk_info(int fd, struct chunk_info **info_ptr, int *info_count)
+static int load_chunk_info(int fd, struct chunk_info **info_ptr, int *info_count)
{
int ret;
struct btrfs_ioctl_search_args args;
@@ -172,11 +172,8 @@ int load_chunk_info(int fd, struct chunk_info **info_ptr, int *info_count)
while (1) {
ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
e = errno;
- if (ret == -EPERM) {
- fprintf(stderr,
- "ERROR: can't read detailed chunk info from ioctl(TREE_SEARCH), run as root\n");
- return 0;
- }
+ if (ret == -EPERM)
+ return ret;
if (ret < 0) {
fprintf(stderr,
@@ -308,30 +305,23 @@ static struct btrfs_ioctl_space_args *load_space_info(int fd, char *path)
* which compose the chunk, which could be different from the number of devices
* if a disk is added later.
*/
-static int get_raid56_used(int fd, u64 *raid5_used, u64 *raid6_used)
+static void get_raid56_used(int fd, struct chunk_info *chunks, int chunkcount,
+ u64 *raid5_used, u64 *raid6_used)
{
- struct chunk_info *info_ptr=0, *p;
- int info_count=0;
- int ret;
-
- *raid5_used = *raid6_used =0;
-
- ret = load_chunk_info(fd, &info_ptr, &info_count);
- if( ret < 0)
- return ret;
-
- for ( p = info_ptr; info_count ; info_count--, p++ ) {
- if (p->type & BTRFS_BLOCK_GROUP_RAID5)
- (*raid5_used) += p->size / (p->num_stripes -1);
- if (p->type & BTRFS_BLOCK_GROUP_RAID6)
- (*raid6_used) += p->size / (p->num_stripes -2);
+ *raid5_used = 0;
+ *raid6_used = 0;
+
+ while (chunkcount-- > 0) {
+ if (chunks->type & BTRFS_BLOCK_GROUP_RAID5)
+ (*raid5_used) += chunks->size / (chunks->num_stripes - 1);
+ if (chunks->type & BTRFS_BLOCK_GROUP_RAID6)
+ (*raid6_used) += chunks->size / (chunks->num_stripes - 2);
}
- free(info_ptr);
-
- return 0;
}
-static int _cmd_disk_free(int fd, char *path, int mode)
+static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo,
+ int chunkcount, struct device_info *devinfo, int devcount,
+ char *path, int mode)
{
struct btrfs_ioctl_space_args *sargs = 0;
int i;
@@ -360,15 +350,11 @@ static int _cmd_disk_free(int fd, char *path, int mode)
ret = 19;
goto exit;
}
- if (get_raid56_used(fd, &raid5_used, &raid6_used) < 0) {
- fprintf(stderr,
- "ERROR: couldn't get space info on '%s'\n",
- path );
- ret = 20;
- goto exit;
- }
+ get_raid56_used(fd, chunkinfo, chunkcount, &raid5_used, &raid6_used);
- total_chunks = total_used = total_free = 0;
+ total_chunks = 0;
+ total_used = 0;
+ total_free = 0;
for (i = 0; i < sargs->total_spaces; i++) {
float ratio = 1;
@@ -453,7 +439,7 @@ static int cmp_device_info(const void *a, const void *b)
/*
* This function loads the device_info structure and put them in an array
*/
-int load_device_info(int fd, struct device_info **device_info_ptr,
+static int load_device_info(int fd, struct device_info **device_info_ptr,
int *device_info_count)
{
int ret, i, ndevs;
@@ -465,10 +451,8 @@ int load_device_info(int fd, struct device_info **device_info_ptr,
*device_info_ptr = 0;
ret = ioctl(fd, BTRFS_IOC_FS_INFO, &fi_args);
- if (ret == -EPERM) {
- fprintf(stderr, "ERROR: can't get filesystem info from ioctl(FS_INFO), run as root\n");
- return -1;
- }
+ if (ret == -EPERM)
+ return ret;
if (ret < 0) {
fprintf(stderr, "ERROR: cannot get filesystem info\n");
return -1;
@@ -512,6 +496,29 @@ int load_device_info(int fd, struct device_info **device_info_ptr,
return 0;
}
+int load_chunk_and_device_info(int fd, struct chunk_info **chunkinfo,
+ int *chunkcount, struct device_info **devinfo, int *devcount)
+{
+ int ret;
+
+ ret = load_chunk_info(fd, chunkinfo, chunkcount);
+ if (ret == -EPERM) {
+ fprintf(stderr,
+ "WARNING: can't read detailed chunk info, RAID5/6 numbers will be incorrect, run as root\n");
+ } else if (ret) {
+ return ret;
+ }
+
+ ret = load_device_info(fd, devinfo, devcount);
+ if (ret == -EPERM) {
+ fprintf(stderr,
+ "WARNING: can't get filesystem info from ioctl(FS_INFO), run as root\n");
+ ret = 0;
+ }
+
+ return ret;
+}
+
/*
* This function computes the size of a chunk in a disk
*/
@@ -744,43 +751,32 @@ static void _cmd_filesystem_usage_linear(int mode,
mode);
}
-static int _cmd_filesystem_usage(int fd, char *path, int mode, int tabular)
+static int print_filesystem_usage_by_chunk(int fd,
+ struct chunk_info *chunkinfo, int chunkcount,
+ struct device_info *devinfo, int devcount,
+ char *path, int mode, int tabular)
{
- struct btrfs_ioctl_space_args *sargs = 0;
- int info_count = 0;
- struct chunk_info *info_ptr = 0;
- struct device_info *device_info_ptr = 0;
- int device_info_count = 0;
+ struct btrfs_ioctl_space_args *sargs;
int ret = 0;
- if (load_chunk_info(fd, &info_ptr, &info_count) ||
- load_device_info(fd, &device_info_ptr, &device_info_count)) {
- ret = -1;
- goto exit;
- }
+ if (!chunkinfo)
+ return 0;
- if ((sargs = load_space_info(fd, path)) == NULL) {
- ret = -1;
+ sargs = load_space_info(fd, path);
+ if (!sargs) {
+ ret = 1;
goto exit;
}
if (tabular)
- _cmd_filesystem_usage_tabular(mode, sargs,
- info_ptr, info_count,
- device_info_ptr, device_info_count);
+ _cmd_filesystem_usage_tabular(mode, sargs, chunkinfo,
+ chunkcount, devinfo, devcount);
else
- _cmd_filesystem_usage_linear(mode, sargs,
- info_ptr, info_count,
- device_info_ptr, device_info_count);
+ _cmd_filesystem_usage_linear(mode, sargs, chunkinfo,
+ chunkcount, devinfo, devcount);
exit:
-
- if (sargs)
- free(sargs);
- if (device_info_ptr)
- free(device_info_ptr);
- if (info_ptr)
- free(info_ptr);
+ free(sargs);
return ret;
}
@@ -796,16 +792,17 @@ const char * const cmd_filesystem_usage_usage[] = {
int cmd_filesystem_usage(int argc, char **argv)
{
-
int flags = DF_HUMAN_UNIT;
int i, more_than_one = 0;
int tabular = 0;
optind = 1;
while (1) {
- char c = getopt(argc, argv, "bt");
+ int c = getopt(argc, argv, "bt");
+
if (c < 0)
break;
+
switch (c) {
case 'b':
flags &= ~DF_HUMAN_UNIT;
@@ -821,9 +818,14 @@ int cmd_filesystem_usage(int argc, char **argv)
if (check_argc_min(argc - optind, 1))
usage(cmd_filesystem_usage_usage);
- for (i = optind; i < argc ; i++) {
- int r, fd;
- DIR *dirstream = NULL;
+ for (i = optind; i < argc; i++) {
+ int ret;
+ int fd;
+ DIR *dirstream = NULL;
+ struct chunk_info *chunkinfo = NULL;
+ struct device_info *devinfo = NULL;
+ int chunkcount = 0;
+ int devcount = 0;
fd = open_file_or_dir(argv[i], &dirstream);
if (fd < 0) {
@@ -834,15 +836,26 @@ int cmd_filesystem_usage(int argc, char **argv)
if (more_than_one)
printf("\n");
- r = _cmd_disk_free(fd, argv[i], flags);
+ ret = load_chunk_and_device_info(fd, &chunkinfo, &chunkcount,
+ &devinfo, &devcount);
+ if (ret)
+ goto cleanup;
+
+ ret = print_filesystem_usage_overall(fd, chunkinfo, chunkcount,
+ devinfo, devcount, argv[i], flags);
+ if (ret)
+ goto cleanup;
printf("\n");
- r = _cmd_filesystem_usage(fd, argv[i], flags, tabular);
+ ret = print_filesystem_usage_by_chunk(fd, chunkinfo, chunkcount,
+ devinfo, devcount, argv[i], flags, tabular);
+cleanup:
close_file_or_dir(fd, dirstream);
+ free(chunkinfo);
+ free(devinfo);
- if (r)
- return r;
+ if (ret)
+ return ret;
more_than_one = 1;
-
}
return 0;
diff --git a/cmds-fi-disk_usage.h b/cmds-fi-disk_usage.h
index dbc2a10f31eb..0779defc71db 100644
--- a/cmds-fi-disk_usage.h
+++ b/cmds-fi-disk_usage.h
@@ -46,9 +46,8 @@ struct chunk_info {
u64 num_stripes;
};
-int load_device_info(int fd, struct device_info **device_info_ptr,
- int *device_info_count);
-int load_chunk_info(int fd, struct chunk_info **info_ptr, int *info_count);
+int load_chunk_and_device_info(int fd, struct chunk_info **chunkinfo,
+ int *chunkcount, struct device_info **devinfo, int *devcount);
char *df_pretty_sizes(u64 size, int mode);
void print_device_chunks(int fd, struct device_info *devinfo,
struct chunk_info *chunks_info_ptr,
--
1.9.0

View File

@ -0,0 +1,172 @@
From f54a92b54b57ea8be8d55ea012c9b69c9f0db5ff Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Mon, 28 Apr 2014 18:04:48 +0200
Subject: [PATCH 39/42] btrfs-progs: extend pretty printers with unit mode
The functionality of pretty unit printing was duplicated by
df_pretty_sizes, merge it with pretty_size and enhance the interface
with more suffix mode. Raw, binary or decimal.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-fi-disk_usage.c | 9 ++-----
utils.c | 71 ++++++++++++++++++++++++++++++++++++----------------
utils.h | 21 +++++++++++-----
3 files changed, 66 insertions(+), 35 deletions(-)
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index 9d1c4085b4ea..1e412c0b0e69 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -33,18 +33,13 @@
/*
* Pretty print the size
- * PAY ATTENTION: it return a statically buffer
*/
char *df_pretty_sizes(u64 size, int mode)
{
- static char buf[30];
-
if (mode & DF_HUMAN_UNIT)
- (void)pretty_size_snprintf(size, buf, sizeof(buf));
+ return pretty_size_mode(size, UNITS_HUMAN);
else
- sprintf(buf, "%llu", size);
-
- return buf;
+ return pretty_size_mode(size, UNITS_RAW);
}
/*
diff --git a/utils.c b/utils.c
index 159abf8bd0e4..69112be51cb2 100644
--- a/utils.c
+++ b/utils.c
@@ -1252,35 +1252,62 @@ out:
return ret;
}
-static char *size_strs[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"};
-int pretty_size_snprintf(u64 size, char *str, size_t str_bytes)
+static const char const *unit_suffix_binary[] =
+ { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"};
+static const char const *unit_suffix_decimal[] =
+ { "B", "KB", "MB", "GB", "TB", "PB", "EB"};
+
+int pretty_size_snprintf(u64 size, char *str, size_t str_size, int unit_mode)
{
- int num_divs = 0;
+ int num_divs;
float fraction;
+ int base = 0;
+ const char const **suffix = NULL;
+ u64 last_size;
- if (str_bytes == 0)
+ if (str_size == 0)
return 0;
- if( size < 1024 ){
- fraction = size;
- num_divs = 0;
- } else {
- u64 last_size = size;
- num_divs = 0;
- while(size >= 1024){
- last_size = size;
- size /= 1024;
- num_divs ++;
- }
+ if (unit_mode == UNITS_RAW) {
+ snprintf(str, str_size, "%llu", size);
+ return 0;
+ }
- if (num_divs >= ARRAY_SIZE(size_strs)) {
- str[0] = '\0';
- return -1;
- }
- fraction = (float)last_size / 1024;
+ if (unit_mode == UNITS_BINARY) {
+ base = 1024;
+ suffix = unit_suffix_binary;
+ } else if (unit_mode == UNITS_DECIMAL) {
+ base = 1000;
+ suffix = unit_suffix_decimal;
}
- return snprintf(str, str_bytes, "%.2f%s", fraction,
- size_strs[num_divs]);
+
+ /* Unknown mode */
+ if (!base) {
+ fprintf(stderr, "INTERNAL ERROR: unknown unit base, mode %d",
+ unit_mode);
+ assert(0);
+ return -1;
+ }
+
+ num_divs = 0;
+ last_size = size;
+
+ while (size >= base) {
+ last_size = size;
+ size /= base;
+ num_divs++;
+ }
+
+ if (num_divs >= ARRAY_SIZE(unit_suffix_binary)) {
+ str[0] = '\0';
+ printf("INTERNAL ERROR: unsupported unit suffix, index %d\n",
+ num_divs);
+ assert(0);
+ return -1;
+ }
+ fraction = (float)last_size / base;
+
+ return snprintf(str, str_size, "%.2f%s", fraction, suffix[num_divs]);
}
/*
diff --git a/utils.h b/utils.h
index 2d08e0b2a3a4..3aea8b47d9e7 100644
--- a/utils.h
+++ b/utils.h
@@ -39,6 +39,14 @@
#define BTRFS_UUID_UNPARSED_SIZE 37
+/*
+ * Output mode of byte units
+ */
+#define UNITS_RAW (1)
+#define UNITS_BINARY (2)
+#define UNITS_DECIMAL (3)
+#define UNITS_HUMAN UNITS_BINARY
+
int make_btrfs(int fd, const char *device, const char *label,
u64 blocks[6], u64 num_bytes, u32 nodesize,
u32 leafsize, u32 sectorsize, u32 stripesize, u64 features);
@@ -59,12 +67,13 @@ int check_mounted_where(int fd, const char *file, char *where, int size,
int btrfs_device_already_in_root(struct btrfs_root *root, int fd,
int super_offset);
-int pretty_size_snprintf(u64 size, char *str, size_t str_bytes);
-#define pretty_size(size) \
- ({ \
- static __thread char _str[24]; \
- (void)pretty_size_snprintf((size), _str, sizeof(_str)); \
- _str; \
+int pretty_size_snprintf(u64 size, char *str, size_t str_bytes, int unit_mode);
+#define pretty_size(size) pretty_size_mode(size, UNITS_BINARY)
+#define pretty_size_mode(size, mode) \
+ ({ \
+ static __thread char _str[32]; \
+ (void)pretty_size_snprintf((size), _str, sizeof(_str), mode); \
+ _str; \
})
int get_mountpt(char *dev, char *mntpt, size_t size);
--
1.9.0

View File

@ -0,0 +1,263 @@
From a1764abe279f04a664d2745d6d2ce49db722bce3 Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Mon, 28 Apr 2014 18:13:16 +0200
Subject: [PATCH 40/42] btrfs-progs: replace df_pretty_sizes with
pretty_size_mode
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-device.c | 8 +++----
cmds-fi-disk_usage.c | 63 ++++++++++++++++++++++------------------------------
cmds-fi-disk_usage.h | 3 ---
3 files changed, 30 insertions(+), 44 deletions(-)
diff --git a/cmds-device.c b/cmds-device.c
index bf5898f6da68..eb6b79ca5127 100644
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -471,19 +471,19 @@ exit:
int cmd_device_usage(int argc, char **argv)
{
- int flags = DF_HUMAN_UNIT;
+ int mode = UNITS_HUMAN;
int i, more_than_one = 0;
optind = 1;
while (1) {
- char c = getopt(argc, argv, "b");
+ int c = getopt(argc, argv, "b");
if (c < 0)
break;
switch (c) {
case 'b':
- flags &= ~DF_HUMAN_UNIT;
+ mode = UNITS_RAW;
break;
default:
usage(cmd_device_usage_usage);
@@ -506,7 +506,7 @@ int cmd_device_usage(int argc, char **argv)
return 12;
}
- r = _cmd_device_usage(fd, argv[i], flags);
+ r = _cmd_device_usage(fd, argv[i], mode);
close_file_or_dir(fd, dirstream);
if (r)
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index 1e412c0b0e69..d1b8bbddc4d5 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -32,17 +32,6 @@
#include "version.h"
/*
- * Pretty print the size
- */
-char *df_pretty_sizes(u64 size, int mode)
-{
- if (mode & DF_HUMAN_UNIT)
- return pretty_size_mode(size, UNITS_HUMAN);
- else
- return pretty_size_mode(size, UNITS_RAW);
-}
-
-/*
* Add the chunk info to the chunk_info list
*/
static int add_info_to_list(struct chunk_info **info_ptr,
@@ -389,7 +378,7 @@ static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo,
K = ((double)total_used + (double)total_free) / (double)total_chunks;
- if (mode & DF_HUMAN_UNIT)
+ if (mode == UNITS_HUMAN)
width = 10;
else
width = 18;
@@ -397,22 +386,22 @@ static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo,
printf("Overall:\n");
printf(" Device size:\t\t%*s\n", width,
- df_pretty_sizes(total_disk, mode));
+ pretty_size_mode(total_disk, mode));
printf(" Device allocated:\t\t%*s\n", width,
- df_pretty_sizes(total_chunks, mode));
+ pretty_size_mode(total_chunks, mode));
printf(" Device unallocated:\t\t%*s\n", width,
- df_pretty_sizes(total_disk-total_chunks, mode));
+ pretty_size_mode(total_disk - total_chunks, mode));
printf(" Used:\t\t\t%*s\n", width,
- df_pretty_sizes(total_used, mode));
+ pretty_size_mode(total_used, mode));
printf(" Free (Estimated):\t\t%*s\t(",
width,
- df_pretty_sizes((u64)(K*total_disk-total_used), mode));
+ pretty_size_mode((u64)(K * total_disk - total_used), mode));
printf("Max: %s, ",
- df_pretty_sizes(total_disk-total_chunks+total_free, mode));
+ pretty_size_mode(total_disk - total_chunks + total_free, mode));
printf("min: %s)\n",
- df_pretty_sizes((total_disk-total_chunks)/2+total_free, mode));
+ pretty_size_mode((total_disk-total_chunks) / 2 + total_free, mode));
printf(" Data to device ratio:\t%*.0f %%\n",
- width-2, K*100);
+ width - 2, K * 100);
exit:
@@ -612,7 +601,7 @@ static void _cmd_filesystem_usage_tabular(int mode,
if (size)
table_printf(matrix, col, i+3,
- ">%s", df_pretty_sizes(size, mode));
+ ">%s", pretty_size_mode(size, mode));
else
table_printf(matrix, col, i+3, ">-");
@@ -624,7 +613,7 @@ static void _cmd_filesystem_usage_tabular(int mode,
- total_allocated;
table_printf(matrix, sargs->total_spaces + 1, i + 3,
- ">%s", df_pretty_sizes(unused, mode));
+ ">%s", pretty_size_mode(unused, mode));
total_unused += unused;
}
@@ -636,15 +625,15 @@ static void _cmd_filesystem_usage_tabular(int mode,
table_printf(matrix, 0, device_info_count + 4, "<Total");
for (i = 0; i < sargs->total_spaces; i++)
table_printf(matrix, 1 + i, device_info_count + 4, ">%s",
- df_pretty_sizes(sargs->spaces[i].total_bytes, mode));
+ pretty_size_mode(sargs->spaces[i].total_bytes, mode));
table_printf(matrix, sargs->total_spaces + 1, device_info_count + 4,
- ">%s", df_pretty_sizes(total_unused, mode));
+ ">%s", pretty_size_mode(total_unused, mode));
table_printf(matrix, 0, device_info_count + 5, "<Used");
for (i = 0; i < sargs->total_spaces; i++)
table_printf(matrix, 1 + i, device_info_count+5, ">%s",
- df_pretty_sizes(sargs->spaces[i].used_bytes, mode));
+ pretty_size_mode(sargs->spaces[i].used_bytes, mode));
table_dump(matrix);
table_free(matrix);
@@ -670,7 +659,7 @@ static void print_unused(struct chunk_info *info_ptr,
printf(" %s\t%10s\n",
device_info_ptr[i].path,
- df_pretty_sizes(device_info_ptr[i].size - total, mode));
+ pretty_size_mode(device_info_ptr[i].size - total, mode));
}
}
@@ -704,7 +693,7 @@ static void print_chunk_device(u64 chunk_type,
if (total > 0)
printf(" %s\t%10s\n",
device_info_ptr[i].path,
- df_pretty_sizes(total, mode));
+ pretty_size_mode(total, mode));
}
}
@@ -732,10 +721,10 @@ static void _cmd_filesystem_usage_linear(int mode,
printf("%s,%s: Size:%s, ",
description,
r_mode,
- df_pretty_sizes(sargs->spaces[i].total_bytes ,
+ pretty_size_mode(sargs->spaces[i].total_bytes,
mode));
printf("Used:%s\n",
- df_pretty_sizes(sargs->spaces[i].used_bytes, mode));
+ pretty_size_mode(sargs->spaces[i].used_bytes, mode));
print_chunk_device(flags, info_ptr, info_count,
device_info_ptr, device_info_count, mode);
printf("\n");
@@ -787,7 +776,7 @@ const char * const cmd_filesystem_usage_usage[] = {
int cmd_filesystem_usage(int argc, char **argv)
{
- int flags = DF_HUMAN_UNIT;
+ int mode = UNITS_HUMAN;
int i, more_than_one = 0;
int tabular = 0;
@@ -800,7 +789,7 @@ int cmd_filesystem_usage(int argc, char **argv)
switch (c) {
case 'b':
- flags &= ~DF_HUMAN_UNIT;
+ mode = UNITS_RAW;
break;
case 't':
tabular = 1;
@@ -837,12 +826,12 @@ int cmd_filesystem_usage(int argc, char **argv)
goto cleanup;
ret = print_filesystem_usage_overall(fd, chunkinfo, chunkcount,
- devinfo, devcount, argv[i], flags);
+ devinfo, devcount, argv[i], mode);
if (ret)
goto cleanup;
printf("\n");
ret = print_filesystem_usage_by_chunk(fd, chunkinfo, chunkcount,
- devinfo, devcount, argv[i], flags, tabular);
+ devinfo, devcount, argv[i], mode, tabular);
cleanup:
close_file_or_dir(fd, dirstream);
free(chunkinfo);
@@ -881,22 +870,22 @@ void print_device_chunks(int fd, struct device_info *devinfo,
description,
r_mode,
(int)(20 - strlen(description) - strlen(r_mode)), "",
- df_pretty_sizes(size, mode));
+ pretty_size_mode(size, mode));
allocated += size;
}
printf(" Unallocated: %*s%10s\n",
(int)(20 - strlen("Unallocated")), "",
- df_pretty_sizes(devinfo->size - allocated, mode));
+ pretty_size_mode(devinfo->size - allocated, mode));
}
void print_device_sizes(int fd, struct device_info *devinfo, int mode)
{
printf(" Device size: %*s%10s\n",
(int)(20 - strlen("Device size")), "",
- df_pretty_sizes(devinfo->device_size, mode));
+ pretty_size_mode(devinfo->device_size, mode));
printf(" FS occuppied:%*s%10s\n",
(int)(20 - strlen("FS occupied")), "",
- df_pretty_sizes(devinfo->size, mode));
+ pretty_size_mode(devinfo->size, mode));
}
diff --git a/cmds-fi-disk_usage.h b/cmds-fi-disk_usage.h
index 0779defc71db..8a0c60f011e4 100644
--- a/cmds-fi-disk_usage.h
+++ b/cmds-fi-disk_usage.h
@@ -19,8 +19,6 @@
#ifndef __CMDS_FI_DISK_USAGE__
#define __CMDS_FI_DISK_USAGE__
-#define DF_HUMAN_UNIT (1<<0)
-
extern const char * const cmd_filesystem_usage_usage[];
int cmd_filesystem_usage(int argc, char **argv);
@@ -48,7 +46,6 @@ struct chunk_info {
int load_chunk_and_device_info(int fd, struct chunk_info **chunkinfo,
int *chunkcount, struct device_info **devinfo, int *devcount);
-char *df_pretty_sizes(u64 size, int mode);
void print_device_chunks(int fd, struct device_info *devinfo,
struct chunk_info *chunks_info_ptr,
int chunks_info_count, int mode);
--
1.9.0

View File

@ -0,0 +1,233 @@
From 2c574dd5564fbe11a9e6e9c707fa907a7418c687 Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Mon, 28 Apr 2014 18:55:05 +0200
Subject: [PATCH 41/42] btrfs-progs: clean up return codes and paths
Use the common patterns with one return statement at the end, pass down error
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-device.c | 27 +++++++++++++--------------
cmds-fi-disk_usage.c | 39 +++++++++++++++++++++------------------
2 files changed, 34 insertions(+), 32 deletions(-)
diff --git a/cmds-device.c b/cmds-device.c
index eb6b79ca5127..6dd5b05c7651 100644
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -448,10 +448,8 @@ static int _cmd_device_usage(int fd, char *path, int mode)
ret = load_chunk_and_device_info(fd, &chunkinfo, &chunkcount, &devinfo,
&devcount);
- if (ret) {
- ret = -1;
- goto exit;
- }
+ if (ret)
+ goto out;
for (i = 0; i < devcount; i++) {
printf("%s, ID: %llu\n", devinfo[i].path, devinfo[i].devid);
@@ -461,7 +459,7 @@ static int _cmd_device_usage(int fd, char *path, int mode)
printf("\n");
}
-exit:
+out:
free(devinfo);
free(chunkinfo);
@@ -472,6 +470,7 @@ int cmd_device_usage(int argc, char **argv)
{
int mode = UNITS_HUMAN;
+ int ret = 0;
int i, more_than_one = 0;
optind = 1;
@@ -494,28 +493,28 @@ int cmd_device_usage(int argc, char **argv)
usage(cmd_device_usage_usage);
for (i = optind; i < argc ; i++) {
- int r, fd;
+ int fd;
DIR *dirstream = NULL;
if (more_than_one)
printf("\n");
fd = open_file_or_dir(argv[i], &dirstream);
if (fd < 0) {
- fprintf(stderr, "ERROR: can't access to '%s'\n",
+ fprintf(stderr, "ERROR: can't access '%s'\n",
argv[1]);
- return 12;
+ ret = 1;
+ goto out;
}
- r = _cmd_device_usage(fd, argv[i], mode);
+ ret = _cmd_device_usage(fd, argv[i], mode);
close_file_or_dir(fd, dirstream);
- if (r)
- return r;
+ if (ret)
+ goto out;
more_than_one = 1;
-
}
-
- return 0;
+out:
+ return !!ret;
}
const struct cmd_group device_cmd_group = {
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index d1b8bbddc4d5..7c93247e4f54 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -68,7 +68,7 @@ static int add_info_to_list(struct chunk_info **info_ptr,
if (!res) {
free(*info_ptr);
fprintf(stderr, "ERROR: not enough memory\n");
- return -1;
+ return -ENOMEM;
}
*info_ptr = res;
@@ -163,7 +163,7 @@ static int load_chunk_info(int fd, struct chunk_info **info_ptr, int *info_count
fprintf(stderr,
"ERROR: can't perform the search - %s\n",
strerror(e));
- return -99;
+ return ret;
}
/* the ioctl returns the number of item it found in nr_items */
@@ -179,9 +179,10 @@ static int load_chunk_info(int fd, struct chunk_info **info_ptr, int *info_count
off += sizeof(*sh);
item = (struct btrfs_chunk *)(args.buf + off);
- if (add_info_to_list(info_ptr, info_count, item)) {
+ ret = add_info_to_list(info_ptr, info_count, item);
+ if (ret) {
*info_ptr = 0;
- return -100;
+ return ret;
}
off += sh->len;
@@ -319,8 +320,9 @@ static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo,
double K;
u64 raid5_used, raid6_used;
- if ((sargs = load_space_info(fd, path)) == NULL) {
- ret = -1;
+ sargs = load_space_info(fd, path);
+ if (!sargs) {
+ ret = 1;
goto exit;
}
@@ -331,7 +333,7 @@ static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo,
"ERROR: couldn't get space info on '%s' - %s\n",
path, strerror(e));
- ret = 19;
+ ret = 1;
goto exit;
}
get_raid56_used(fd, chunkinfo, chunkcount, &raid5_used, &raid6_used);
@@ -439,13 +441,13 @@ static int load_device_info(int fd, struct device_info **device_info_ptr,
return ret;
if (ret < 0) {
fprintf(stderr, "ERROR: cannot get filesystem info\n");
- return -1;
+ return ret;
}
info = calloc(fi_args.num_devices, sizeof(struct device_info));
if (!info) {
fprintf(stderr, "ERROR: not enough memory\n");
- return -1;
+ return ret;
}
for (i = 0, ndevs = 0 ; i <= fi_args.max_id ; i++) {
@@ -460,7 +462,7 @@ static int load_device_info(int fd, struct device_info **device_info_ptr,
"ERROR: cannot get info about device devid=%d\n",
i);
free(info);
- return -1;
+ return ret;
}
info[ndevs].devid = dev_info.devid;
@@ -749,7 +751,7 @@ static int print_filesystem_usage_by_chunk(int fd,
sargs = load_space_info(fd, path);
if (!sargs) {
ret = 1;
- goto exit;
+ goto out;
}
if (tabular)
@@ -759,9 +761,8 @@ static int print_filesystem_usage_by_chunk(int fd,
_cmd_filesystem_usage_linear(mode, sargs, chunkinfo,
chunkcount, devinfo, devcount);
-exit:
free(sargs);
-
+out:
return ret;
}
@@ -777,6 +778,7 @@ const char * const cmd_filesystem_usage_usage[] = {
int cmd_filesystem_usage(int argc, char **argv)
{
int mode = UNITS_HUMAN;
+ int ret = 0;
int i, more_than_one = 0;
int tabular = 0;
@@ -803,7 +805,6 @@ int cmd_filesystem_usage(int argc, char **argv)
usage(cmd_filesystem_usage_usage);
for (i = optind; i < argc; i++) {
- int ret;
int fd;
DIR *dirstream = NULL;
struct chunk_info *chunkinfo = NULL;
@@ -813,9 +814,10 @@ int cmd_filesystem_usage(int argc, char **argv)
fd = open_file_or_dir(argv[i], &dirstream);
if (fd < 0) {
- fprintf(stderr, "ERROR: can't access to '%s'\n",
+ fprintf(stderr, "ERROR: can't access '%s'\n",
argv[1]);
- return 12;
+ ret = 1;
+ goto out;
}
if (more_than_one)
printf("\n");
@@ -838,11 +840,12 @@ cleanup:
free(devinfo);
if (ret)
- return ret;
+ goto out;
more_than_one = 1;
}
- return 0;
+out:
+ return !!ret;
}
void print_device_chunks(int fd, struct device_info *devinfo,
--
1.9.0

View File

@ -0,0 +1,96 @@
From 552e2741a3b0ce344c73b3e1d80d385605d49e75 Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Tue, 29 Apr 2014 17:32:22 +0200
Subject: [PATCH 42/42] btrfs-progs: move global reserve to overall summary
It looks confusing among the chunks, it is not in fact a chunk type.
Sample:
Overall:
Device size: 35.00GiB
Device allocated: 8.07GiB
Device unallocated: 26.93GiB
Used: 1.12MiB
Free (Estimated): 17.57GiB (Max: 30.98GiB, min: 17.52GiB)
Data to device ratio: 50 %
Global reserve: 16.00MiB (used: 0.00B)
...
Signed-off-by: David Sterba <dsterba@suse.cz>
---
cmds-fi-disk_usage.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/cmds-fi-disk_usage.c b/cmds-fi-disk_usage.c
index 7c93247e4f54..0caba159b974 100644
--- a/cmds-fi-disk_usage.c
+++ b/cmds-fi-disk_usage.c
@@ -319,6 +319,8 @@ static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo,
u64 total_free; /* logical space un-used */
double K;
u64 raid5_used, raid6_used;
+ u64 global_reserve;
+ u64 global_reserve_used;
sargs = load_space_info(fd, path);
if (!sargs) {
@@ -341,6 +343,8 @@ static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo,
total_chunks = 0;
total_used = 0;
total_free = 0;
+ global_reserve = 0;
+ global_reserve_used = 0;
for (i = 0; i < sargs->total_spaces; i++) {
float ratio = 1;
@@ -366,6 +370,11 @@ static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo,
else
ratio = 1;
+ if (flags & BTRFS_SPACE_INFO_GLOBAL_RSV) {
+ global_reserve = sargs->spaces[i].total_bytes;
+ global_reserve_used = sargs->spaces[i].used_bytes;
+ }
+
allocated = sargs->spaces[i].total_bytes * ratio;
total_chunks += allocated;
@@ -404,6 +413,9 @@ static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo,
pretty_size_mode((total_disk-total_chunks) / 2 + total_free, mode));
printf(" Data to device ratio:\t%*.0f %%\n",
width - 2, K * 100);
+ printf(" Global reserve:\t\t%*s\t(used: %s)\n", width,
+ pretty_size_mode(global_reserve, mode),
+ pretty_size_mode(global_reserve_used, mode));
exit:
@@ -553,8 +565,11 @@ static void _cmd_filesystem_usage_tabular(int mode,
/* header */
for (i = 0; i < sargs->total_spaces; i++) {
const char *description;
-
u64 flags = sargs->spaces[i].flags;
+
+ if (flags & BTRFS_SPACE_INFO_GLOBAL_RSV)
+ continue;
+
description = group_type_str(flags);
table_printf(matrix, 1+i, 0, "<%s", description);
@@ -715,8 +730,11 @@ static void _cmd_filesystem_usage_linear(int mode,
for (i = 0; i < sargs->total_spaces; i++) {
const char *description;
const char *r_mode;
-
u64 flags = sargs->spaces[i].flags;
+
+ if (flags & BTRFS_SPACE_INFO_GLOBAL_RSV)
+ continue;
+
description= group_type_str(flags);
r_mode = group_profile_str(flags);
--
1.9.0

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:91b731c9889cdad80d36e6f0345b9dc6fa0e7f98eda5730bfd88947ff4afedb1
size 281329

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d5680d1ae0a88f6f07350e1dd8e81a1d6933bf7eccd4233c9d24f5a7b8f482bd
size 281254

View File

@ -1,3 +1,53 @@
-------------------------------------------------------------------
Fri May 2 13:37:04 UTC 2014 - dsterba@suse.cz
- update to upstream 3.14.1
- mkfs:
- fix TRIM detection
- do not zero-out end of device unconditionally
- no crash with --features option
- fsck:
- clear log tree in repair mode
- check reloc roots
- btrfs - reworked space reporting (bnc#873106)
- btrfs fi usage - new command
- btrfs dev usage - new command
- btrfs fi df - enhanced output with GlobalReserve
- Removed patches:
* 0001-btrfs-progs-move-arg_strtou64-to-a-separate-file-for.patch
- Added patches:
* 0001-Btrfs-progs-fix-check-to-test-trim-support.patch
* 0002-Btrfs-progs-fsck-fix-double-free-memory-crash.patch
* 0003-Btrfs-progs-mkfs-Remove-zero_end-1-since-it-has-been.patch
* 0004-btrfs-progs-fix-wrong-max-system-array-size-check-in.patch
* 0005-btrfs-progs-move-arg_strtou64-to-a-separate-file-for.patch
* 0006-Btrfs-progs-fsck-clear-out-log-tree-in-repair-mode.patch
* 0007-Btrfs-progs-fsck-avoid-pinning-same-block-several-ti.patch
* 0008-Btrfs-progs-fsck-add-ability-to-check-reloc-roots.patch
* 0009-btrfs-progs-prevent-close_root-if-the-root-to-close-.patch
* 0010-btrfs-progs-fix-mkfs.btrfs-segfault-with-features-op.patch
* 0011-btrfs-progs-Enhance-the-command-btrfs-filesystem-df.patch
* 0012-btrfs-progs-Add-helpers-functions-to-handle-the-prin.patch
* 0013-btrfs-progs-Add-command-btrfs-filesystem-disk-usage.patch
* 0014-btrfs-progs-Add-btrfs-device-disk-usage-command.patch
* 0015-btrfs-progs-cleanup-dead-return-after-usage-for-fi-d.patch
* 0016-btrfs-progs-Fix-memleak-in-get_raid56_used.patch
* 0017-Btrfs-progs-fi-usage-free-memory-if-realloc-fails.patch
* 0018-btrfs-progs-read-global-reserve-size-from-space-info.patch
* 0019-btrfs-progs-add-original-df-and-rename-disk_usage-to.patch
* 0020-btrfs-progs-move-device-usage-to-cmds-device-more-cl.patch
* 0021-btrfs-progs-check-if-we-can-t-get-info-from-ioctls-d.patch
* 0022-btrfs-progs-zero-out-structures-before-calling-ioctl.patch
* 0023-btrfs-progs-print-B-for-bytes.patch
* 0024-btrfs-progs-Print-more-info-about-device-sizes.patch
* 0025-btrfs-progs-compare-unallocated-space-against-the-co.patch
* 0026-btrfs-progs-add-section-of-overall-filesystem-usage.patch
* 0027-btrfs-progs-cleanup-filesystem-device-usage-code.patch
* 0028-btrfs-progs-extend-pretty-printers-with-unit-mode.patch
* 0029-btrfs-progs-replace-df_pretty_sizes-with-pretty_size.patch
* 0030-btrfs-progs-clean-up-return-codes-and-paths.patch
* 0031-btrfs-progs-move-global-reserve-to-overall-summary.patch
-------------------------------------------------------------------
Sat Apr 26 09:45:23 UTC 2014 - coolo@suse.com

View File

@ -16,9 +16,9 @@
#
%define tar_version v3.14
%define tar_version v3.14.1
Name: btrfsprogs
Version: 3.14
Version: 3.14.1
Release: 0
Summary: Utilities for the Btrfs filesystem
License: GPL-2.0
@ -31,7 +31,37 @@ Source: btrfs-progs-%{tar_version}.tar.bz2
Source1: boot-btrfs.sh
Source4: setup-btrfs.sh
Patch1: 0001-btrfs-progs-move-arg_strtou64-to-a-separate-file-for.patch
Patch1: 0001-Btrfs-progs-fix-check-to-test-trim-support.patch
Patch2: 0002-Btrfs-progs-fsck-fix-double-free-memory-crash.patch
Patch3: 0003-Btrfs-progs-mkfs-Remove-zero_end-1-since-it-has-been.patch
Patch4: 0004-btrfs-progs-fix-wrong-max-system-array-size-check-in.patch
Patch5: 0005-btrfs-progs-move-arg_strtou64-to-a-separate-file-for.patch
Patch6: 0006-Btrfs-progs-fsck-clear-out-log-tree-in-repair-mode.patch
Patch7: 0007-Btrfs-progs-fsck-avoid-pinning-same-block-several-ti.patch
Patch8: 0008-Btrfs-progs-fsck-add-ability-to-check-reloc-roots.patch
Patch9: 0009-btrfs-progs-prevent-close_root-if-the-root-to-close-.patch
Patch10: 0010-btrfs-progs-fix-mkfs.btrfs-segfault-with-features-op.patch
Patch11: 0011-btrfs-progs-Enhance-the-command-btrfs-filesystem-df.patch
Patch12: 0012-btrfs-progs-Add-helpers-functions-to-handle-the-prin.patch
Patch13: 0013-btrfs-progs-Add-command-btrfs-filesystem-disk-usage.patch
Patch14: 0014-btrfs-progs-Add-btrfs-device-disk-usage-command.patch
Patch15: 0015-btrfs-progs-cleanup-dead-return-after-usage-for-fi-d.patch
Patch16: 0016-btrfs-progs-Fix-memleak-in-get_raid56_used.patch
Patch17: 0017-Btrfs-progs-fi-usage-free-memory-if-realloc-fails.patch
Patch18: 0018-btrfs-progs-read-global-reserve-size-from-space-info.patch
Patch19: 0019-btrfs-progs-add-original-df-and-rename-disk_usage-to.patch
Patch20: 0020-btrfs-progs-move-device-usage-to-cmds-device-more-cl.patch
Patch21: 0021-btrfs-progs-check-if-we-can-t-get-info-from-ioctls-d.patch
Patch22: 0022-btrfs-progs-zero-out-structures-before-calling-ioctl.patch
Patch23: 0023-btrfs-progs-print-B-for-bytes.patch
Patch24: 0024-btrfs-progs-Print-more-info-about-device-sizes.patch
Patch25: 0025-btrfs-progs-compare-unallocated-space-against-the-co.patch
Patch26: 0026-btrfs-progs-add-section-of-overall-filesystem-usage.patch
Patch27: 0027-btrfs-progs-cleanup-filesystem-device-usage-code.patch
Patch28: 0028-btrfs-progs-extend-pretty-printers-with-unit-mode.patch
Patch29: 0029-btrfs-progs-replace-df_pretty_sizes-with-pretty_size.patch
Patch30: 0030-btrfs-progs-clean-up-return-codes-and-paths.patch
Patch31: 0031-btrfs-progs-move-global-reserve-to-overall-summary.patch
Patch163: 0163-btrfs-progs-fsck-fix-segfault.patch
Patch164: 0164-btrfs-progs-convert-set-label-or-copy-from-origin.patch
@ -77,6 +107,36 @@ build applications to interface with btrfs.
%prep
%setup -q -n btrfs-progs-%{tar_version}
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%patch25 -p1
%patch26 -p1
%patch27 -p1
%patch28 -p1
%patch29 -p1
%patch30 -p1
%patch31 -p1
%patch163 -p1
%patch164 -p1
%patch167 -p1

View File

@ -6,8 +6,8 @@ Index: btrfs-progs-v0.19-116-g13eced9/version.sh
# Copyright 2008, Oracle
# Released under the GNU GPLv2
-v="v3.14"
+v="v3.14+20140408"
-v="v3.14.1"
+v="v3.14.1+20140502"
which git &> /dev/null
if [ $? == 0 -a -d .git ]; then