linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] btrfs-progs: better space_cache=v2 support
@ 2016-11-13 19:35 Omar Sandoval
  2016-11-13 19:35 ` [PATCH 1/6] btrfs-progs: add the FREE_SPACE_TREE_VALID compat_ro bit definition Omar Sandoval
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Omar Sandoval @ 2016-11-13 19:35 UTC (permalink / raw)
  To: linux-btrfs; +Cc: kernel-team

From: Omar Sandoval <osandov@fb.com>

Hi,

This series implements some support for space_cache=v2 in btrfs-progs.
In particular, this adds support for `btrfs check --clear-space-cache v2`,
proper printing of the free space tree flags for `btrfs inspect-internal
dump-super`, and better documentation.

We'd previously talked about always making btrfs-progs always invalidate
the free space tree when doing write operations, but I decided that this
should be an action explicitly requested by the user. It'd also be
unsafe if using a kernel without the free space tree valid bit support,
which is why I didn't implement a `btrfs check --invalidate-free-space-cache`
option. Doing the full clear is always safe.

Still missing is full read-write support, but this should hopefully
cover most btrfs-progs usage.

Thanks!

Omar Sandoval (6):
  btrfs-progs: add the FREE_SPACE_TREE_VALID compat_ro bit definition
  btrfs-progs: format FREE_SPACE_TREE{,_VALID} nicely in dump-super
  btrfs-progs: add OPEN_CTREE_INVALIDATE_FST flag
  btrfs-progs: add btrfs_clear_free_space_tree() from the kernel
  btrfs-progs: implement btrfs check --clear-space-cache v2
  btrfs-progs: document space_cache=v2 more thoroughly

 Documentation/btrfs-check.asciidoc | 14 +++---
 Documentation/btrfs-man5.asciidoc  | 43 +++++++++++--------
 chunk-recover.c                    |  2 +-
 cmds-check.c                       | 34 +++++++++++----
 cmds-inspect-dump-super.c          | 24 +++++++++++
 ctree.h                            | 19 +++++++++
 disk-io.c                          | 28 +++++++-----
 disk-io.h                          |  8 +++-
 extent-tree.c                      | 10 +++++
 free-space-tree.c                  | 87 ++++++++++++++++++++++++++++++++++++++
 free-space-tree.h                  |  1 +
 root-tree.c                        | 22 ++++++++++
 12 files changed, 248 insertions(+), 44 deletions(-)

-- 
2.10.2


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/6] btrfs-progs: add the FREE_SPACE_TREE_VALID compat_ro bit definition
  2016-11-13 19:35 [PATCH 0/6] btrfs-progs: better space_cache=v2 support Omar Sandoval
@ 2016-11-13 19:35 ` Omar Sandoval
  2016-11-13 19:35 ` [PATCH 2/6] btrfs-progs: format FREE_SPACE_TREE{,_VALID} nicely in dump-super Omar Sandoval
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Omar Sandoval @ 2016-11-13 19:35 UTC (permalink / raw)
  To: linux-btrfs; +Cc: kernel-team

From: Omar Sandoval <osandov@fb.com>

This is just the definition; we don't support it yet.

Signed-off-by: Omar Sandoval <osandov@fb.com>
---
 ctree.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/ctree.h b/ctree.h
index d47f0ae..d67b852 100644
--- a/ctree.h
+++ b/ctree.h
@@ -467,6 +467,14 @@ struct btrfs_super_block {
  * ones specified below then we will fail to mount
  */
 #define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE	(1ULL << 0)
+/*
+ * Older kernels on big-endian systems produced broken free space tree bitmaps,
+ * and btrfs-progs also used to corrupt the free space tree. If this bit is
+ * clear, then the free space tree cannot be trusted. btrfs-progs can also
+ * intentionally clear this bit to ask the kernel to rebuild the free space
+ * tree.
+ */
+#define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID	(1ULL << 1)
 
 #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF	(1ULL << 0)
 #define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL	(1ULL << 1)
@@ -493,6 +501,11 @@ struct btrfs_super_block {
 
 #define BTRFS_FEATURE_COMPAT_SUPP		0ULL
 
+/*
+ * The FREE_SPACE_TREE and FREE_SPACE_TREE_VALID compat_ro bits must not be
+ * added here until read-write support for the free space tree is implemented in
+ * btrfs-progs.
+ */
 #define BTRFS_FEATURE_COMPAT_RO_SUPP		0ULL
 
 #define BTRFS_FEATURE_INCOMPAT_SUPP			\
-- 
2.10.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/6] btrfs-progs: format FREE_SPACE_TREE{,_VALID} nicely in dump-super
  2016-11-13 19:35 [PATCH 0/6] btrfs-progs: better space_cache=v2 support Omar Sandoval
  2016-11-13 19:35 ` [PATCH 1/6] btrfs-progs: add the FREE_SPACE_TREE_VALID compat_ro bit definition Omar Sandoval
@ 2016-11-13 19:35 ` Omar Sandoval
  2016-11-13 19:35 ` [PATCH 3/6] btrfs-progs: add OPEN_CTREE_INVALIDATE_FST flag Omar Sandoval
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Omar Sandoval @ 2016-11-13 19:35 UTC (permalink / raw)
  To: linux-btrfs; +Cc: kernel-team

From: Omar Sandoval <osandov@fb.com>

Signed-off-by: Omar Sandoval <osandov@fb.com>
---
 cmds-inspect-dump-super.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/cmds-inspect-dump-super.c b/cmds-inspect-dump-super.c
index d9f7bfb..ba0d708 100644
--- a/cmds-inspect-dump-super.c
+++ b/cmds-inspect-dump-super.c
@@ -197,6 +197,16 @@ struct readable_flag_entry {
 	char *output;
 };
 
+#define DEF_COMPAT_RO_FLAG_ENTRY(bit_name)		\
+	{BTRFS_FEATURE_COMPAT_RO_##bit_name, #bit_name}
+
+static struct readable_flag_entry compat_ro_flags_array[] = {
+	DEF_COMPAT_RO_FLAG_ENTRY(FREE_SPACE_TREE),
+	DEF_COMPAT_RO_FLAG_ENTRY(FREE_SPACE_TREE_VALID),
+};
+static const int compat_ro_flags_num = sizeof(compat_ro_flags_array) /
+				       sizeof(struct readable_flag_entry);
+
 #define DEF_INCOMPAT_FLAG_ENTRY(bit_name)		\
 	{BTRFS_FEATURE_INCOMPAT_##bit_name, #bit_name}
 
@@ -268,6 +278,19 @@ static void __print_readable_flag(u64 flag, struct readable_flag_entry *array,
 	printf(")\n");
 }
 
+static void print_readable_compat_ro_flag(u64 flag)
+{
+	/*
+	 * We know about the FREE_SPACE_TREE{,_VALID} bits, but we don't
+	 * actually support them yet.
+	 */
+	return __print_readable_flag(flag, compat_ro_flags_array,
+				     compat_ro_flags_num,
+				     BTRFS_FEATURE_COMPAT_RO_SUPP |
+				     BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE |
+				     BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID);
+}
+
 static void print_readable_incompat_flag(u64 flag)
 {
 	return __print_readable_flag(flag, incompat_flags_array,
@@ -377,6 +400,7 @@ static void dump_superblock(struct btrfs_super_block *sb, int full)
 	       (unsigned long long)btrfs_super_compat_flags(sb));
 	printf("compat_ro_flags\t\t0x%llx\n",
 	       (unsigned long long)btrfs_super_compat_ro_flags(sb));
+	print_readable_compat_ro_flag(btrfs_super_compat_ro_flags(sb));
 	printf("incompat_flags\t\t0x%llx\n",
 	       (unsigned long long)btrfs_super_incompat_flags(sb));
 	print_readable_incompat_flag(btrfs_super_incompat_flags(sb));
-- 
2.10.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/6] btrfs-progs: add OPEN_CTREE_INVALIDATE_FST flag
  2016-11-13 19:35 [PATCH 0/6] btrfs-progs: better space_cache=v2 support Omar Sandoval
  2016-11-13 19:35 ` [PATCH 1/6] btrfs-progs: add the FREE_SPACE_TREE_VALID compat_ro bit definition Omar Sandoval
  2016-11-13 19:35 ` [PATCH 2/6] btrfs-progs: format FREE_SPACE_TREE{,_VALID} nicely in dump-super Omar Sandoval
@ 2016-11-13 19:35 ` Omar Sandoval
  2016-11-14  1:22   ` Qu Wenruo
  2016-11-13 19:35 ` [PATCH 4/6] btrfs-progs: add btrfs_clear_free_space_tree() from the kernel Omar Sandoval
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Omar Sandoval @ 2016-11-13 19:35 UTC (permalink / raw)
  To: linux-btrfs; +Cc: kernel-team

From: Omar Sandoval <osandov@fb.com>

If this flag is passed to open_ctree(), we'll clear the
FREE_SPACE_TREE_VALID compat_ro bit. The kernel will then reconstruct
the free space tree the next time the filesystem is mounted.

Signed-off-by: Omar Sandoval <osandov@fb.com>
---
 chunk-recover.c |  2 +-
 disk-io.c       | 28 ++++++++++++++++++----------
 disk-io.h       |  8 +++++++-
 3 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/chunk-recover.c b/chunk-recover.c
index e33ee8b..e6b26ac 100644
--- a/chunk-recover.c
+++ b/chunk-recover.c
@@ -1477,7 +1477,7 @@ open_ctree_with_broken_chunk(struct recover_control *rc)
 
 	memcpy(fs_info->fsid, &disk_super->fsid, BTRFS_FSID_SIZE);
 
-	ret = btrfs_check_fs_compatibility(disk_super, 1);
+	ret = btrfs_check_fs_compatibility(disk_super, OPEN_CTREE_WRITES);
 	if (ret)
 		goto out_devices;
 
diff --git a/disk-io.c b/disk-io.c
index a576300..a55fcc1 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -904,7 +904,7 @@ free_all:
 	return NULL;
 }
 
-int btrfs_check_fs_compatibility(struct btrfs_super_block *sb, int writable)
+int btrfs_check_fs_compatibility(struct btrfs_super_block *sb, unsigned flags)
 {
 	u64 features;
 
@@ -923,13 +923,22 @@ int btrfs_check_fs_compatibility(struct btrfs_super_block *sb, int writable)
 		btrfs_set_super_incompat_flags(sb, features);
 	}
 
-	features = btrfs_super_compat_ro_flags(sb) &
-		~BTRFS_FEATURE_COMPAT_RO_SUPP;
-	if (writable && features) {
-		printk("couldn't open RDWR because of unsupported "
-		       "option features (%Lx).\n",
-		       (unsigned long long)features);
-		return -ENOTSUP;
+	features = btrfs_super_compat_ro_flags(sb);
+	if (flags & OPEN_CTREE_WRITES) {
+		if (flags & OPEN_CTREE_INVALIDATE_FST) {
+			/* Clear the FREE_SPACE_TREE_VALID bit on disk... */
+			features &= ~BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID;
+			btrfs_set_super_compat_ro_flags(sb, features);
+			/* ... and ignore the free space tree bit. */
+			features &= ~BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE;
+		}
+		if (features & ~BTRFS_FEATURE_COMPAT_RO_SUPP) {
+			printk("couldn't open RDWR because of unsupported "
+			       "option features (%Lx).\n",
+			       (unsigned long long)features);
+			return -ENOTSUP;
+		}
+
 	}
 	return 0;
 }
@@ -1320,8 +1329,7 @@ static struct btrfs_fs_info *__open_ctree_fd(int fp, const char *path,
 
 	memcpy(fs_info->fsid, &disk_super->fsid, BTRFS_FSID_SIZE);
 
-	ret = btrfs_check_fs_compatibility(fs_info->super_copy,
-					   flags & OPEN_CTREE_WRITES);
+	ret = btrfs_check_fs_compatibility(fs_info->super_copy, flags);
 	if (ret)
 		goto out_devices;
 
diff --git a/disk-io.h b/disk-io.h
index 8ab36aa..5d4b281 100644
--- a/disk-io.h
+++ b/disk-io.h
@@ -74,6 +74,12 @@ enum btrfs_open_ctree_flags {
 
 	/* Allow to open a partially created filesystem */
 	OPEN_CTREE_FS_PARTIAL = (1U << 12),
+
+	/*
+	 * Invalidate the free space tree (i.e., clear the FREE_SPACE_TREE_VALID
+	 * compat_ro bit).
+	 */
+	OPEN_CTREE_INVALIDATE_FST = (1U << 13),
 };
 
 /*
@@ -128,7 +134,7 @@ int clean_tree_block(struct btrfs_trans_handle *trans,
 
 void btrfs_free_fs_info(struct btrfs_fs_info *fs_info);
 struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr);
-int btrfs_check_fs_compatibility(struct btrfs_super_block *sb, int writable);
+int btrfs_check_fs_compatibility(struct btrfs_super_block *sb, unsigned flags);
 int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
 			  unsigned flags);
 void btrfs_release_all_roots(struct btrfs_fs_info *fs_info);
-- 
2.10.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/6] btrfs-progs: add btrfs_clear_free_space_tree() from the kernel
  2016-11-13 19:35 [PATCH 0/6] btrfs-progs: better space_cache=v2 support Omar Sandoval
                   ` (2 preceding siblings ...)
  2016-11-13 19:35 ` [PATCH 3/6] btrfs-progs: add OPEN_CTREE_INVALIDATE_FST flag Omar Sandoval
@ 2016-11-13 19:35 ` Omar Sandoval
  2016-11-14  1:38   ` Qu Wenruo
  2016-11-13 19:35 ` [PATCH 5/6] btrfs-progs: implement btrfs check --clear-space-cache v2 Omar Sandoval
  2016-11-13 19:35 ` [PATCH 6/6] btrfs-progs: document space_cache=v2 more thoroughly Omar Sandoval
  5 siblings, 1 reply; 12+ messages in thread
From: Omar Sandoval @ 2016-11-13 19:35 UTC (permalink / raw)
  To: linux-btrfs; +Cc: kernel-team

From: Omar Sandoval <osandov@fb.com>

Signed-off-by: Omar Sandoval <osandov@fb.com>
---
 ctree.h           |  6 ++++
 extent-tree.c     | 10 +++++++
 free-space-tree.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 free-space-tree.h |  1 +
 root-tree.c       | 22 ++++++++++++++
 5 files changed, 126 insertions(+)

diff --git a/ctree.h b/ctree.h
index d67b852..90193ad 100644
--- a/ctree.h
+++ b/ctree.h
@@ -2504,6 +2504,10 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		  struct extent_buffer *buf, int record_parent);
 int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		  struct extent_buffer *buf, int record_parent);
+void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+			   struct btrfs_root *root,
+			   struct extent_buffer *buf,
+			   u64 parent, int last_ref);
 int btrfs_free_extent(struct btrfs_trans_handle *trans,
 		      struct btrfs_root *root,
 		      u64 bytenr, u64 num_bytes, u64 parent,
@@ -2664,6 +2668,8 @@ int btrfs_add_root_ref(struct btrfs_trans_handle *trans,
 int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
 		      *root, struct btrfs_key *key, struct btrfs_root_item
 		      *item);
+int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+		   struct btrfs_key *key);
 int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
 		      *root, struct btrfs_key *key, struct btrfs_root_item
 		      *item);
diff --git a/extent-tree.c b/extent-tree.c
index 3b1577e..d445723 100644
--- a/extent-tree.c
+++ b/extent-tree.c
@@ -2467,6 +2467,16 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
 	return err;
 }
 
+
+void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+			   struct btrfs_root *root,
+			   struct extent_buffer *buf,
+			   u64 parent, int last_ref)
+{
+	btrfs_free_extent(trans, root, buf->start, buf->len, parent,
+			  root->root_key.objectid, btrfs_header_level(buf), 0);
+}
+
 /*
  * remove an extent from the root, returns 0 on success
  */
diff --git a/free-space-tree.c b/free-space-tree.c
index 3c7a246..d972f26 100644
--- a/free-space-tree.c
+++ b/free-space-tree.c
@@ -20,6 +20,7 @@
 #include "disk-io.h"
 #include "free-space-cache.h"
 #include "free-space-tree.h"
+#include "transaction.h"
 
 static struct btrfs_free_space_info *
 search_free_space_info(struct btrfs_trans_handle *trans,
@@ -67,6 +68,92 @@ static int free_space_test_bit(struct btrfs_block_group_cache *block_group,
 	return !!extent_buffer_test_bit(leaf, ptr, i);
 }
 
+static int clear_free_space_tree(struct btrfs_trans_handle *trans,
+				 struct btrfs_root *root)
+{
+	struct btrfs_path *path;
+	struct btrfs_key key;
+	int nr;
+	int ret;
+
+	path = btrfs_alloc_path();
+	if (!path)
+		return -ENOMEM;
+
+	key.objectid = 0;
+	key.type = 0;
+	key.offset = 0;
+
+	while (1) {
+		ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
+		if (ret < 0)
+			goto out;
+
+		nr = btrfs_header_nritems(path->nodes[0]);
+		if (!nr)
+			break;
+
+		path->slots[0] = 0;
+		ret = btrfs_del_items(trans, root, path, 0, nr);
+		if (ret)
+			goto out;
+
+		btrfs_release_path(path);
+	}
+
+	ret = 0;
+out:
+	btrfs_free_path(path);
+	return ret;
+}
+
+int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
+{
+	struct btrfs_trans_handle *trans;
+	struct btrfs_root *tree_root = fs_info->tree_root;
+	struct btrfs_root *free_space_root = fs_info->free_space_root;
+	int ret;
+	u64 features;
+
+	trans = btrfs_start_transaction(tree_root, 0);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
+
+
+	features = btrfs_super_compat_ro_flags(fs_info->super_copy);
+	features &= ~(BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID |
+		      BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE);
+	btrfs_set_super_compat_ro_flags(fs_info->super_copy, features);
+	fs_info->free_space_root = NULL;
+
+	ret = clear_free_space_tree(trans, free_space_root);
+	if (ret)
+		goto abort;
+
+	ret = btrfs_del_root(trans, tree_root, &free_space_root->root_key);
+	if (ret)
+		goto abort;
+
+	list_del(&free_space_root->dirty_list);
+
+	clean_tree_block(trans, tree_root, free_space_root->node);
+	btrfs_free_tree_block(trans, free_space_root, free_space_root->node,
+			      0, 1);
+
+	free_extent_buffer(free_space_root->node);
+	free_extent_buffer(free_space_root->commit_root);
+	kfree(free_space_root);
+
+	ret = btrfs_commit_transaction(trans, tree_root);
+	if (ret)
+		return ret;
+
+	return 0;
+
+abort:
+	return ret;
+}
+
 static int load_free_space_bitmaps(struct btrfs_fs_info *fs_info,
 				   struct btrfs_block_group_cache *block_group,
 				   struct btrfs_path *path,
diff --git a/free-space-tree.h b/free-space-tree.h
index 7529a46..4845f13 100644
--- a/free-space-tree.h
+++ b/free-space-tree.h
@@ -19,6 +19,7 @@
 #ifndef __BTRFS_FREE_SPACE_TREE_H__
 #define __BTRFS_FREE_SPACE_TREE_H__
 
+int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info);
 int load_free_space_tree(struct btrfs_fs_info *fs_info,
 			 struct btrfs_block_group_cache *block_group);
 
diff --git a/root-tree.c b/root-tree.c
index cca424e..c660447 100644
--- a/root-tree.c
+++ b/root-tree.c
@@ -143,6 +143,28 @@ int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
 	return ret;
 }
 
+/* drop the root item for 'key' from 'root' */
+int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+		   struct btrfs_key *key)
+{
+	struct btrfs_path *path;
+	int ret;
+
+	path = btrfs_alloc_path();
+	if (!path)
+		return -ENOMEM;
+	ret = btrfs_search_slot(trans, root, key, path, -1, 1);
+	if (ret < 0)
+		goto out;
+
+	BUG_ON(ret != 0);
+
+	ret = btrfs_del_item(trans, root, path);
+out:
+	btrfs_free_path(path);
+	return ret;
+}
+
 /*
  * add a btrfs_root_ref item.  type is either BTRFS_ROOT_REF_KEY
  * or BTRFS_ROOT_BACKREF_KEY.
-- 
2.10.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/6] btrfs-progs: implement btrfs check --clear-space-cache v2
  2016-11-13 19:35 [PATCH 0/6] btrfs-progs: better space_cache=v2 support Omar Sandoval
                   ` (3 preceding siblings ...)
  2016-11-13 19:35 ` [PATCH 4/6] btrfs-progs: add btrfs_clear_free_space_tree() from the kernel Omar Sandoval
@ 2016-11-13 19:35 ` Omar Sandoval
  2016-11-14  1:44   ` Qu Wenruo
  2016-11-13 19:35 ` [PATCH 6/6] btrfs-progs: document space_cache=v2 more thoroughly Omar Sandoval
  5 siblings, 1 reply; 12+ messages in thread
From: Omar Sandoval @ 2016-11-13 19:35 UTC (permalink / raw)
  To: linux-btrfs; +Cc: kernel-team

From: Omar Sandoval <osandov@fb.com>

Signed-off-by: Omar Sandoval <osandov@fb.com>
---
 Documentation/btrfs-check.asciidoc | 14 +++++++++-----
 cmds-check.c                       | 34 +++++++++++++++++++++++++---------
 2 files changed, 34 insertions(+), 14 deletions(-)

diff --git a/Documentation/btrfs-check.asciidoc b/Documentation/btrfs-check.asciidoc
index 5ef414e..633cbbf 100644
--- a/Documentation/btrfs-check.asciidoc
+++ b/Documentation/btrfs-check.asciidoc
@@ -80,12 +80,16 @@ superblock is damaged.
 
 --clear-space-cache v1|v2::
 completely wipe all free space cache of given type
-
-NOTE: Only v1 free space cache supported is implemented.
 +
-Kernel mount option 'clear_cache' is only designed to rebuild free space cache
-which is modified during the lifetime of that mount option.  It doesn't rebuild
-all free space cache, nor clear them out.
+For free space cache 'v1', the 'clear_cache' kernel mount option only rebuilds
+the free space cache for block groups that are modified while the filesystem is
+mounted with that option. Thus, using this option with 'v1' makes it possible
+to actually clear the entire free space cache.
++
+For free space cache 'v2', the 'clear_cache' kernel mount option does destroy
+the entire free space cache. This option with 'v2' provides an alternative
+method of clearing the free space cache that doesn't require mounting the
+filesystem.
 
 
 DANGEROUS OPTIONS
diff --git a/cmds-check.c b/cmds-check.c
index 57c4300..0eca102 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -11170,7 +11170,6 @@ const char * const cmd_check_usage[] = {
 	"--chunk-root <bytenr>       use the given bytenr for the chunk tree root",
 	"-p|--progress               indicate progress",
 	"--clear-space-cache v1|v2   clear space cache for v1 or v2",
-	"                            NOTE: v1 support implemented",
 	NULL
 };
 
@@ -11292,13 +11291,16 @@ int cmd_check(int argc, char **argv)
 				}
 				break;
 			case GETOPT_VAL_CLEAR_SPACE_CACHE:
-				if (strcmp(optarg, "v1") != 0) {
-					error(
-			"only v1 support implmented, unrecognized value %s",
-			optarg);
+				if (strcmp(optarg, "v1") == 0) {
+					clear_space_cache = 1;
+				} else if (strcmp(optarg, "v2") == 0) {
+					clear_space_cache = 2;
+					ctree_flags |= OPEN_CTREE_INVALIDATE_FST;
+				} else {
+					error("invalid argument to --clear-space-cache; "
+					      "must be v1 or v2");
 					exit(1);
 				}
-				clear_space_cache = 1;
 				ctree_flags |= OPEN_CTREE_WRITES;
 				break;
 		}
@@ -11352,11 +11354,10 @@ int cmd_check(int argc, char **argv)
 
 	global_info = info;
 	root = info->fs_root;
-	if (clear_space_cache) {
+	if (clear_space_cache == 1) {
 		if (btrfs_fs_compat_ro(info,
 				BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE)) {
-			error(
-			"free space cache v2 detected, clearing not implemented");
+			error("free space cache v2 detected; use --clear-space-cache v2");
 			ret = 1;
 			goto close_out;
 		}
@@ -11369,6 +11370,21 @@ int cmd_check(int argc, char **argv)
 			printf("Free space cache cleared\n");
 		}
 		goto close_out;
+	} else if (clear_space_cache == 2) {
+		if (!btrfs_fs_compat_ro(info, BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE)) {
+			printf("No free space cache v2 to clear\n");
+			ret = 0;
+			goto close_out;
+		}
+		printf("Clear free space cache v2\n");
+		ret = btrfs_clear_free_space_tree(info);
+		if (ret) {
+			error("Failed to clear free space cache v2");
+			ret = 1;
+		} else {
+			printf("Free space cache v2 cleared\n");
+		}
+		goto close_out;
 	}
 
 	/*
-- 
2.10.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6/6] btrfs-progs: document space_cache=v2 more thoroughly
  2016-11-13 19:35 [PATCH 0/6] btrfs-progs: better space_cache=v2 support Omar Sandoval
                   ` (4 preceding siblings ...)
  2016-11-13 19:35 ` [PATCH 5/6] btrfs-progs: implement btrfs check --clear-space-cache v2 Omar Sandoval
@ 2016-11-13 19:35 ` Omar Sandoval
  5 siblings, 0 replies; 12+ messages in thread
From: Omar Sandoval @ 2016-11-13 19:35 UTC (permalink / raw)
  To: linux-btrfs; +Cc: kernel-team

From: Omar Sandoval <osandov@fb.com>

Signed-off-by: Omar Sandoval <osandov@fb.com>
---
 Documentation/btrfs-man5.asciidoc | 43 +++++++++++++++++++++++----------------
 1 file changed, 25 insertions(+), 18 deletions(-)

diff --git a/Documentation/btrfs-man5.asciidoc b/Documentation/btrfs-man5.asciidoc
index d12b059..3b003d3 100644
--- a/Documentation/btrfs-man5.asciidoc
+++ b/Documentation/btrfs-man5.asciidoc
@@ -319,25 +319,32 @@ May be resumed with *btrfs balance resume* or the paused state can be removed
 by *btrfs balance cancel*. The default behaviour is to start interrutpd balance.
 
 *space_cache*::
-*space_cache=v2*::
+*space_cache='version'*::
 *nospace_cache*::
-('nospace_cache' since: 3.2, 'space_cache=v2' since 4.5, default: on)
-+
-Options to control the free space cache.  This affects performance as searching
-for new free blocks could take longer if the space cache is not enabled. On the
-other hand, managing the space cache consumes some resources.  It can be
-disabled without clearing at mount time.
-+
-There are two implementations of how the space is tracked. The safe default is
-'v1'.  On large filesystems (many-terabytes) and certain workloads the 'v1'
-performance may degrade.  This problem is addressed by 'v2', that is based on
-b-trees, sometimes referred to as 'free-space-tree'.
-+
-'Compatibility notes:'
-+
-* the 'v2' has to be enabled manually at mount time, once
-* kernel without 'v2' support will be able to mount the filesystem in read-only mode
-* 'v2' can be removed by mounting with 'clear_cache'
+('nospace_cache' since: 3.2, 'space_cache=v1' and 'space_cache=v2' since 4.5, default: 'space_cache=v1')
++
+Options to control the free space cache. The free space cache greatly improves
+performance when reading block group free space into memory. However, managing
+the space cache consumes some resources, including a small amount of disk
+space.
++
+There are two implementations of the free space cache. The original
+implementation, 'v1', is the safe default. The 'v1' space cache can be disabled
+at mount time with 'nospace_cache' without clearing.
++
+On very large filesystems (many terabytes) and certain workloads, the
+performance of the 'v1' space cache may degrade drastically. The 'v2'
+implementation, which adds a new B-tree called the free space tree, addresses
+this issue. Once enabled, the 'v2' space cache will always be used and cannot
+be disabled unless it is cleared. Use 'clear_cache,space_cache=v1' or
+'clear_cache,nospace_cache' to do so. If 'v2' is enabled, kernels without 'v2'
+support will only be able to mount the filesystem in read-only mode. The
+`btrfs(8)` command currently only has read-only support for 'v2'. A read-write
+command may be run on a 'v2' filesystem by clearing the cache, running the
+command, and then remounting with 'space_cache=v2'.
++
+If a version is not explicitly specified, the default implementation will be
+chosen, which is 'v1' as of 4.9.
 
 *ssd*::
 *nossd*::
-- 
2.10.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 3/6] btrfs-progs: add OPEN_CTREE_INVALIDATE_FST flag
  2016-11-13 19:35 ` [PATCH 3/6] btrfs-progs: add OPEN_CTREE_INVALIDATE_FST flag Omar Sandoval
@ 2016-11-14  1:22   ` Qu Wenruo
       [not found]     ` <20161114162256.GA22223@vader>
  0 siblings, 1 reply; 12+ messages in thread
From: Qu Wenruo @ 2016-11-14  1:22 UTC (permalink / raw)
  To: Omar Sandoval, linux-btrfs; +Cc: kernel-team



At 11/14/2016 03:35 AM, Omar Sandoval wrote:
> From: Omar Sandoval <osandov@fb.com>
>
> If this flag is passed to open_ctree(), we'll clear the
> FREE_SPACE_TREE_VALID compat_ro bit. The kernel will then reconstruct
> the free space tree the next time the filesystem is mounted.

This feature is really helpful.

Especially for users reporting failed to mount v2 space_cache fs.

Despite a small nit commented below, feel free to add my reviewed by tag.

Reviewed-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
>
> Signed-off-by: Omar Sandoval <osandov@fb.com>
> ---
>  chunk-recover.c |  2 +-
>  disk-io.c       | 28 ++++++++++++++++++----------
>  disk-io.h       |  8 +++++++-
>  3 files changed, 26 insertions(+), 12 deletions(-)
>
> diff --git a/chunk-recover.c b/chunk-recover.c
> index e33ee8b..e6b26ac 100644
> --- a/chunk-recover.c
> +++ b/chunk-recover.c
> @@ -1477,7 +1477,7 @@ open_ctree_with_broken_chunk(struct recover_control *rc)
>
>  	memcpy(fs_info->fsid, &disk_super->fsid, BTRFS_FSID_SIZE);
>
> -	ret = btrfs_check_fs_compatibility(disk_super, 1);
> +	ret = btrfs_check_fs_compatibility(disk_super, OPEN_CTREE_WRITES);
>  	if (ret)
>  		goto out_devices;
>
> diff --git a/disk-io.c b/disk-io.c
> index a576300..a55fcc1 100644
> --- a/disk-io.c
> +++ b/disk-io.c
> @@ -904,7 +904,7 @@ free_all:
>  	return NULL;
>  }
>
> -int btrfs_check_fs_compatibility(struct btrfs_super_block *sb, int writable)
> +int btrfs_check_fs_compatibility(struct btrfs_super_block *sb, unsigned flags)

IIRC kernel checkpatch will warn on single "unsigned", as it's 
recommended to use "unsigned int".

Thanks,
Qu

>  {
>  	u64 features;
>
> @@ -923,13 +923,22 @@ int btrfs_check_fs_compatibility(struct btrfs_super_block *sb, int writable)
>  		btrfs_set_super_incompat_flags(sb, features);
>  	}
>
> -	features = btrfs_super_compat_ro_flags(sb) &
> -		~BTRFS_FEATURE_COMPAT_RO_SUPP;
> -	if (writable && features) {
> -		printk("couldn't open RDWR because of unsupported "
> -		       "option features (%Lx).\n",
> -		       (unsigned long long)features);
> -		return -ENOTSUP;
> +	features = btrfs_super_compat_ro_flags(sb);
> +	if (flags & OPEN_CTREE_WRITES) {
> +		if (flags & OPEN_CTREE_INVALIDATE_FST) {
> +			/* Clear the FREE_SPACE_TREE_VALID bit on disk... */
> +			features &= ~BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID;
> +			btrfs_set_super_compat_ro_flags(sb, features);
> +			/* ... and ignore the free space tree bit. */
> +			features &= ~BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE;
> +		}
> +		if (features & ~BTRFS_FEATURE_COMPAT_RO_SUPP) {
> +			printk("couldn't open RDWR because of unsupported "
> +			       "option features (%Lx).\n",
> +			       (unsigned long long)features);
> +			return -ENOTSUP;
> +		}
> +
>  	}
>  	return 0;
>  }
> @@ -1320,8 +1329,7 @@ static struct btrfs_fs_info *__open_ctree_fd(int fp, const char *path,
>
>  	memcpy(fs_info->fsid, &disk_super->fsid, BTRFS_FSID_SIZE);
>
> -	ret = btrfs_check_fs_compatibility(fs_info->super_copy,
> -					   flags & OPEN_CTREE_WRITES);
> +	ret = btrfs_check_fs_compatibility(fs_info->super_copy, flags);
>  	if (ret)
>  		goto out_devices;
>
> diff --git a/disk-io.h b/disk-io.h
> index 8ab36aa..5d4b281 100644
> --- a/disk-io.h
> +++ b/disk-io.h
> @@ -74,6 +74,12 @@ enum btrfs_open_ctree_flags {
>
>  	/* Allow to open a partially created filesystem */
>  	OPEN_CTREE_FS_PARTIAL = (1U << 12),
> +
> +	/*
> +	 * Invalidate the free space tree (i.e., clear the FREE_SPACE_TREE_VALID
> +	 * compat_ro bit).
> +	 */
> +	OPEN_CTREE_INVALIDATE_FST = (1U << 13),
>  };
>
>  /*
> @@ -128,7 +134,7 @@ int clean_tree_block(struct btrfs_trans_handle *trans,
>
>  void btrfs_free_fs_info(struct btrfs_fs_info *fs_info);
>  struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr);
> -int btrfs_check_fs_compatibility(struct btrfs_super_block *sb, int writable);
> +int btrfs_check_fs_compatibility(struct btrfs_super_block *sb, unsigned flags);
>  int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
>  			  unsigned flags);
>  void btrfs_release_all_roots(struct btrfs_fs_info *fs_info);
>



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 4/6] btrfs-progs: add btrfs_clear_free_space_tree() from the kernel
  2016-11-13 19:35 ` [PATCH 4/6] btrfs-progs: add btrfs_clear_free_space_tree() from the kernel Omar Sandoval
@ 2016-11-14  1:38   ` Qu Wenruo
  2016-11-14 16:33     ` Omar Sandoval
  0 siblings, 1 reply; 12+ messages in thread
From: Qu Wenruo @ 2016-11-14  1:38 UTC (permalink / raw)
  To: Omar Sandoval, linux-btrfs; +Cc: kernel-team



At 11/14/2016 03:35 AM, Omar Sandoval wrote:
> From: Omar Sandoval <osandov@fb.com>
>
> Signed-off-by: Omar Sandoval <osandov@fb.com>

Only small nits about the BUG_ON() and return value.
Despite that, feel free to add my reviewed-by:

Reviewed-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
> ---
>  ctree.h           |  6 ++++
>  extent-tree.c     | 10 +++++++
>  free-space-tree.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  free-space-tree.h |  1 +
>  root-tree.c       | 22 ++++++++++++++
>  5 files changed, 126 insertions(+)
>
> diff --git a/ctree.h b/ctree.h
> index d67b852..90193ad 100644
> --- a/ctree.h
> +++ b/ctree.h
> @@ -2504,6 +2504,10 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
>  		  struct extent_buffer *buf, int record_parent);
>  int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
>  		  struct extent_buffer *buf, int record_parent);
> +void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
> +			   struct btrfs_root *root,
> +			   struct extent_buffer *buf,
> +			   u64 parent, int last_ref);
>  int btrfs_free_extent(struct btrfs_trans_handle *trans,
>  		      struct btrfs_root *root,
>  		      u64 bytenr, u64 num_bytes, u64 parent,
> @@ -2664,6 +2668,8 @@ int btrfs_add_root_ref(struct btrfs_trans_handle *trans,
>  int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
>  		      *root, struct btrfs_key *key, struct btrfs_root_item
>  		      *item);
> +int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
> +		   struct btrfs_key *key);
>  int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
>  		      *root, struct btrfs_key *key, struct btrfs_root_item
>  		      *item);
> diff --git a/extent-tree.c b/extent-tree.c
> index 3b1577e..d445723 100644
> --- a/extent-tree.c
> +++ b/extent-tree.c
> @@ -2467,6 +2467,16 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
>  	return err;
>  }
>
> +
> +void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
> +			   struct btrfs_root *root,
> +			   struct extent_buffer *buf,
> +			   u64 parent, int last_ref)
> +{
> +	btrfs_free_extent(trans, root, buf->start, buf->len, parent,
> +			  root->root_key.objectid, btrfs_header_level(buf), 0);
> +}

btrfs_free_extent() will return int.

Better return it.

> +
>  /*
>   * remove an extent from the root, returns 0 on success
>   */
> diff --git a/free-space-tree.c b/free-space-tree.c
> index 3c7a246..d972f26 100644
> --- a/free-space-tree.c
> +++ b/free-space-tree.c
> @@ -20,6 +20,7 @@
>  #include "disk-io.h"
>  #include "free-space-cache.h"
>  #include "free-space-tree.h"
> +#include "transaction.h"
>
>  static struct btrfs_free_space_info *
>  search_free_space_info(struct btrfs_trans_handle *trans,
> @@ -67,6 +68,92 @@ static int free_space_test_bit(struct btrfs_block_group_cache *block_group,
>  	return !!extent_buffer_test_bit(leaf, ptr, i);
>  }
>
> +static int clear_free_space_tree(struct btrfs_trans_handle *trans,
> +				 struct btrfs_root *root)
> +{
> +	struct btrfs_path *path;
> +	struct btrfs_key key;
> +	int nr;
> +	int ret;
> +
> +	path = btrfs_alloc_path();
> +	if (!path)
> +		return -ENOMEM;
> +
> +	key.objectid = 0;
> +	key.type = 0;
> +	key.offset = 0;
> +
> +	while (1) {
> +		ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
> +		if (ret < 0)
> +			goto out;
> +
> +		nr = btrfs_header_nritems(path->nodes[0]);
> +		if (!nr)
> +			break;
> +
> +		path->slots[0] = 0;
> +		ret = btrfs_del_items(trans, root, path, 0, nr);
> +		if (ret)
> +			goto out;
> +
> +		btrfs_release_path(path);
> +	}
> +
> +	ret = 0;
> +out:
> +	btrfs_free_path(path);
> +	return ret;
> +}
> +
> +int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
> +{
> +	struct btrfs_trans_handle *trans;
> +	struct btrfs_root *tree_root = fs_info->tree_root;
> +	struct btrfs_root *free_space_root = fs_info->free_space_root;
> +	int ret;
> +	u64 features;
> +
> +	trans = btrfs_start_transaction(tree_root, 0);
> +	if (IS_ERR(trans))
> +		return PTR_ERR(trans);
> +
> +
> +	features = btrfs_super_compat_ro_flags(fs_info->super_copy);
> +	features &= ~(BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID |
> +		      BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE);
> +	btrfs_set_super_compat_ro_flags(fs_info->super_copy, features);
> +	fs_info->free_space_root = NULL;
> +
> +	ret = clear_free_space_tree(trans, free_space_root);
> +	if (ret)
> +		goto abort;
> +
> +	ret = btrfs_del_root(trans, tree_root, &free_space_root->root_key);
> +	if (ret)
> +		goto abort;
> +
> +	list_del(&free_space_root->dirty_list);
> +
> +	clean_tree_block(trans, tree_root, free_space_root->node);

Better catch the return value.

> +	btrfs_free_tree_block(trans, free_space_root, free_space_root->node,
> +			      0, 1);

Here too.

> +
> +	free_extent_buffer(free_space_root->node);
> +	free_extent_buffer(free_space_root->commit_root);
> +	kfree(free_space_root);
> +
> +	ret = btrfs_commit_transaction(trans, tree_root);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +
> +abort:

This reminds me again that we really need a btrfs_abort_transaction() in 
btrfs-progs.
(And I always forget to implement it)

> +	return ret;
> +}
> +
>  static int load_free_space_bitmaps(struct btrfs_fs_info *fs_info,
>  				   struct btrfs_block_group_cache *block_group,
>  				   struct btrfs_path *path,
> diff --git a/free-space-tree.h b/free-space-tree.h
> index 7529a46..4845f13 100644
> --- a/free-space-tree.h
> +++ b/free-space-tree.h
> @@ -19,6 +19,7 @@
>  #ifndef __BTRFS_FREE_SPACE_TREE_H__
>  #define __BTRFS_FREE_SPACE_TREE_H__
>
> +int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info);
>  int load_free_space_tree(struct btrfs_fs_info *fs_info,
>  			 struct btrfs_block_group_cache *block_group);
>
> diff --git a/root-tree.c b/root-tree.c
> index cca424e..c660447 100644
> --- a/root-tree.c
> +++ b/root-tree.c
> @@ -143,6 +143,28 @@ int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
>  	return ret;
>  }
>
> +/* drop the root item for 'key' from 'root' */
> +int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
> +		   struct btrfs_key *key)
> +{
> +	struct btrfs_path *path;
> +	int ret;
> +
> +	path = btrfs_alloc_path();
> +	if (!path)
> +		return -ENOMEM;
> +	ret = btrfs_search_slot(trans, root, key, path, -1, 1);
> +	if (ret < 0)
> +		goto out;
> +
> +	BUG_ON(ret != 0);

Better to avoid BUG_ON().

Return -ENOENT seems good enough.

Thanks,
Qu

> +
> +	ret = btrfs_del_item(trans, root, path);
> +out:
> +	btrfs_free_path(path);
> +	return ret;
> +}
> +
>  /*
>   * add a btrfs_root_ref item.  type is either BTRFS_ROOT_REF_KEY
>   * or BTRFS_ROOT_BACKREF_KEY.
>



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 5/6] btrfs-progs: implement btrfs check --clear-space-cache v2
  2016-11-13 19:35 ` [PATCH 5/6] btrfs-progs: implement btrfs check --clear-space-cache v2 Omar Sandoval
@ 2016-11-14  1:44   ` Qu Wenruo
  0 siblings, 0 replies; 12+ messages in thread
From: Qu Wenruo @ 2016-11-14  1:44 UTC (permalink / raw)
  To: Omar Sandoval, linux-btrfs; +Cc: kernel-team



At 11/14/2016 03:35 AM, Omar Sandoval wrote:
> From: Omar Sandoval <osandov@fb.com>
>
> Signed-off-by: Omar Sandoval <osandov@fb.com>

Reviewed-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
> ---
>  Documentation/btrfs-check.asciidoc | 14 +++++++++-----
>  cmds-check.c                       | 34 +++++++++++++++++++++++++---------
>  2 files changed, 34 insertions(+), 14 deletions(-)
>
> diff --git a/Documentation/btrfs-check.asciidoc b/Documentation/btrfs-check.asciidoc
> index 5ef414e..633cbbf 100644
> --- a/Documentation/btrfs-check.asciidoc
> +++ b/Documentation/btrfs-check.asciidoc
> @@ -80,12 +80,16 @@ superblock is damaged.
>
>  --clear-space-cache v1|v2::
>  completely wipe all free space cache of given type
> -
> -NOTE: Only v1 free space cache supported is implemented.
>  +
> -Kernel mount option 'clear_cache' is only designed to rebuild free space cache
> -which is modified during the lifetime of that mount option.  It doesn't rebuild
> -all free space cache, nor clear them out.
> +For free space cache 'v1', the 'clear_cache' kernel mount option only rebuilds
> +the free space cache for block groups that are modified while the filesystem is
> +mounted with that option. Thus, using this option with 'v1' makes it possible
> +to actually clear the entire free space cache.
> ++
> +For free space cache 'v2', the 'clear_cache' kernel mount option does destroy
> +the entire free space cache. This option with 'v2' provides an alternative
> +method of clearing the free space cache that doesn't require mounting the
> +filesystem.

This is quite helpful.

The behavior of clear_cache should be the correct one.

Thanks,
Qu

>
>
>  DANGEROUS OPTIONS
> diff --git a/cmds-check.c b/cmds-check.c
> index 57c4300..0eca102 100644
> --- a/cmds-check.c
> +++ b/cmds-check.c
> @@ -11170,7 +11170,6 @@ const char * const cmd_check_usage[] = {
>  	"--chunk-root <bytenr>       use the given bytenr for the chunk tree root",
>  	"-p|--progress               indicate progress",
>  	"--clear-space-cache v1|v2   clear space cache for v1 or v2",
> -	"                            NOTE: v1 support implemented",
>  	NULL
>  };
>
> @@ -11292,13 +11291,16 @@ int cmd_check(int argc, char **argv)
>  				}
>  				break;
>  			case GETOPT_VAL_CLEAR_SPACE_CACHE:
> -				if (strcmp(optarg, "v1") != 0) {
> -					error(
> -			"only v1 support implmented, unrecognized value %s",
> -			optarg);
> +				if (strcmp(optarg, "v1") == 0) {
> +					clear_space_cache = 1;
> +				} else if (strcmp(optarg, "v2") == 0) {
> +					clear_space_cache = 2;
> +					ctree_flags |= OPEN_CTREE_INVALIDATE_FST;
> +				} else {
> +					error("invalid argument to --clear-space-cache; "
> +					      "must be v1 or v2");
>  					exit(1);
>  				}
> -				clear_space_cache = 1;
>  				ctree_flags |= OPEN_CTREE_WRITES;
>  				break;
>  		}
> @@ -11352,11 +11354,10 @@ int cmd_check(int argc, char **argv)
>
>  	global_info = info;
>  	root = info->fs_root;
> -	if (clear_space_cache) {
> +	if (clear_space_cache == 1) {
>  		if (btrfs_fs_compat_ro(info,
>  				BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE)) {
> -			error(
> -			"free space cache v2 detected, clearing not implemented");
> +			error("free space cache v2 detected; use --clear-space-cache v2");
>  			ret = 1;
>  			goto close_out;
>  		}
> @@ -11369,6 +11370,21 @@ int cmd_check(int argc, char **argv)
>  			printf("Free space cache cleared\n");
>  		}
>  		goto close_out;
> +	} else if (clear_space_cache == 2) {
> +		if (!btrfs_fs_compat_ro(info, BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE)) {
> +			printf("No free space cache v2 to clear\n");
> +			ret = 0;
> +			goto close_out;
> +		}
> +		printf("Clear free space cache v2\n");
> +		ret = btrfs_clear_free_space_tree(info);
> +		if (ret) {
> +			error("Failed to clear free space cache v2");
> +			ret = 1;
> +		} else {
> +			printf("Free space cache v2 cleared\n");
> +		}
> +		goto close_out;
>  	}
>
>  	/*
>



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 4/6] btrfs-progs: add btrfs_clear_free_space_tree() from the kernel
  2016-11-14  1:38   ` Qu Wenruo
@ 2016-11-14 16:33     ` Omar Sandoval
  0 siblings, 0 replies; 12+ messages in thread
From: Omar Sandoval @ 2016-11-14 16:33 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: linux-btrfs, kernel-team

On Mon, Nov 14, 2016 at 09:38:19AM +0800, Qu Wenruo wrote:
> 
> 
> At 11/14/2016 03:35 AM, Omar Sandoval wrote:
> > From: Omar Sandoval <osandov@fb.com>
> > 
> > Signed-off-by: Omar Sandoval <osandov@fb.com>
> 
> Only small nits about the BUG_ON() and return value.
> Despite that, feel free to add my reviewed-by:
> 
> Reviewed-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
> > ---
> >  ctree.h           |  6 ++++
> >  extent-tree.c     | 10 +++++++
> >  free-space-tree.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  free-space-tree.h |  1 +
> >  root-tree.c       | 22 ++++++++++++++
> >  5 files changed, 126 insertions(+)
> > 
> > diff --git a/ctree.h b/ctree.h
> > index d67b852..90193ad 100644
> > --- a/ctree.h
> > +++ b/ctree.h
> > @@ -2504,6 +2504,10 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
> >  		  struct extent_buffer *buf, int record_parent);
> >  int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
> >  		  struct extent_buffer *buf, int record_parent);
> > +void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
> > +			   struct btrfs_root *root,
> > +			   struct extent_buffer *buf,
> > +			   u64 parent, int last_ref);
> >  int btrfs_free_extent(struct btrfs_trans_handle *trans,
> >  		      struct btrfs_root *root,
> >  		      u64 bytenr, u64 num_bytes, u64 parent,
> > @@ -2664,6 +2668,8 @@ int btrfs_add_root_ref(struct btrfs_trans_handle *trans,
> >  int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
> >  		      *root, struct btrfs_key *key, struct btrfs_root_item
> >  		      *item);
> > +int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
> > +		   struct btrfs_key *key);
> >  int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
> >  		      *root, struct btrfs_key *key, struct btrfs_root_item
> >  		      *item);
> > diff --git a/extent-tree.c b/extent-tree.c
> > index 3b1577e..d445723 100644
> > --- a/extent-tree.c
> > +++ b/extent-tree.c
> > @@ -2467,6 +2467,16 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
> >  	return err;
> >  }
> > 
> > +
> > +void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
> > +			   struct btrfs_root *root,
> > +			   struct extent_buffer *buf,
> > +			   u64 parent, int last_ref)
> > +{
> > +	btrfs_free_extent(trans, root, buf->start, buf->len, parent,
> > +			  root->root_key.objectid, btrfs_header_level(buf), 0);
> > +}
> 
> btrfs_free_extent() will return int.
> 
> Better return it.

Will fix.

> > +
> >  /*
> >   * remove an extent from the root, returns 0 on success
> >   */
> > diff --git a/free-space-tree.c b/free-space-tree.c
> > index 3c7a246..d972f26 100644
> > --- a/free-space-tree.c
> > +++ b/free-space-tree.c
> > @@ -20,6 +20,7 @@
> >  #include "disk-io.h"
> >  #include "free-space-cache.h"
> >  #include "free-space-tree.h"
> > +#include "transaction.h"
> > 
> >  static struct btrfs_free_space_info *
> >  search_free_space_info(struct btrfs_trans_handle *trans,
> > @@ -67,6 +68,92 @@ static int free_space_test_bit(struct btrfs_block_group_cache *block_group,
> >  	return !!extent_buffer_test_bit(leaf, ptr, i);
> >  }
> > 
> > +static int clear_free_space_tree(struct btrfs_trans_handle *trans,
> > +				 struct btrfs_root *root)
> > +{
> > +	struct btrfs_path *path;
> > +	struct btrfs_key key;
> > +	int nr;
> > +	int ret;
> > +
> > +	path = btrfs_alloc_path();
> > +	if (!path)
> > +		return -ENOMEM;
> > +
> > +	key.objectid = 0;
> > +	key.type = 0;
> > +	key.offset = 0;
> > +
> > +	while (1) {
> > +		ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
> > +		if (ret < 0)
> > +			goto out;
> > +
> > +		nr = btrfs_header_nritems(path->nodes[0]);
> > +		if (!nr)
> > +			break;
> > +
> > +		path->slots[0] = 0;
> > +		ret = btrfs_del_items(trans, root, path, 0, nr);
> > +		if (ret)
> > +			goto out;
> > +
> > +		btrfs_release_path(path);
> > +	}
> > +
> > +	ret = 0;
> > +out:
> > +	btrfs_free_path(path);
> > +	return ret;
> > +}
> > +
> > +int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
> > +{
> > +	struct btrfs_trans_handle *trans;
> > +	struct btrfs_root *tree_root = fs_info->tree_root;
> > +	struct btrfs_root *free_space_root = fs_info->free_space_root;
> > +	int ret;
> > +	u64 features;
> > +
> > +	trans = btrfs_start_transaction(tree_root, 0);
> > +	if (IS_ERR(trans))
> > +		return PTR_ERR(trans);
> > +
> > +
> > +	features = btrfs_super_compat_ro_flags(fs_info->super_copy);
> > +	features &= ~(BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID |
> > +		      BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE);
> > +	btrfs_set_super_compat_ro_flags(fs_info->super_copy, features);
> > +	fs_info->free_space_root = NULL;
> > +
> > +	ret = clear_free_space_tree(trans, free_space_root);
> > +	if (ret)
> > +		goto abort;
> > +
> > +	ret = btrfs_del_root(trans, tree_root, &free_space_root->root_key);
> > +	if (ret)
> > +		goto abort;
> > +
> > +	list_del(&free_space_root->dirty_list);
> > +
> > +	clean_tree_block(trans, tree_root, free_space_root->node);
> 
> Better catch the return value.
> 
> > +	btrfs_free_tree_block(trans, free_space_root, free_space_root->node,
> > +			      0, 1);
> 
> Here too.

Oh yeah these two return void in the kernel, but I'll fix it here.

> > +
> > +	free_extent_buffer(free_space_root->node);
> > +	free_extent_buffer(free_space_root->commit_root);
> > +	kfree(free_space_root);
> > +
> > +	ret = btrfs_commit_transaction(trans, tree_root);
> > +	if (ret)
> > +		return ret;
> > +
> > +	return 0;
> > +
> > +abort:
> 
> This reminds me again that we really need a btrfs_abort_transaction() in
> btrfs-progs.
> (And I always forget to implement it)
> 
> > +	return ret;
> > +}
> > +
> >  static int load_free_space_bitmaps(struct btrfs_fs_info *fs_info,
> >  				   struct btrfs_block_group_cache *block_group,
> >  				   struct btrfs_path *path,
> > diff --git a/free-space-tree.h b/free-space-tree.h
> > index 7529a46..4845f13 100644
> > --- a/free-space-tree.h
> > +++ b/free-space-tree.h
> > @@ -19,6 +19,7 @@
> >  #ifndef __BTRFS_FREE_SPACE_TREE_H__
> >  #define __BTRFS_FREE_SPACE_TREE_H__
> > 
> > +int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info);
> >  int load_free_space_tree(struct btrfs_fs_info *fs_info,
> >  			 struct btrfs_block_group_cache *block_group);
> > 
> > diff --git a/root-tree.c b/root-tree.c
> > index cca424e..c660447 100644
> > --- a/root-tree.c
> > +++ b/root-tree.c
> > @@ -143,6 +143,28 @@ int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
> >  	return ret;
> >  }
> > 
> > +/* drop the root item for 'key' from 'root' */
> > +int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
> > +		   struct btrfs_key *key)
> > +{
> > +	struct btrfs_path *path;
> > +	int ret;
> > +
> > +	path = btrfs_alloc_path();
> > +	if (!path)
> > +		return -ENOMEM;
> > +	ret = btrfs_search_slot(trans, root, key, path, -1, 1);
> > +	if (ret < 0)
> > +		goto out;
> > +
> > +	BUG_ON(ret != 0);
> 
> Better to avoid BUG_ON().
> 
> Return -ENOENT seems good enough.

Copied this straight from the kernel, but you're right, no reason to
crash progs.

Thanks for the review!

> Thanks,
> Qu
> 
> > +
> > +	ret = btrfs_del_item(trans, root, path);
> > +out:
> > +	btrfs_free_path(path);
> > +	return ret;
> > +}
> > +
> >  /*
> >   * add a btrfs_root_ref item.  type is either BTRFS_ROOT_REF_KEY
> >   * or BTRFS_ROOT_BACKREF_KEY.
> > 
> 
> 

-- 
Omar

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 3/6] btrfs-progs: add OPEN_CTREE_INVALIDATE_FST flag
       [not found]     ` <20161114162256.GA22223@vader>
@ 2016-11-14 16:40       ` David Sterba
  0 siblings, 0 replies; 12+ messages in thread
From: David Sterba @ 2016-11-14 16:40 UTC (permalink / raw)
  To: Omar Sandoval; +Cc: Qu Wenruo, linux-btrfs, kernel-team

On Mon, Nov 14, 2016 at 08:22:56AM -0800, Omar Sandoval wrote:
> > > --- a/disk-io.c
> > > +++ b/disk-io.c
> > > @@ -904,7 +904,7 @@ free_all:
> > >  	return NULL;
> > >  }
> > > 
> > > -int btrfs_check_fs_compatibility(struct btrfs_super_block *sb, int writable)
> > > +int btrfs_check_fs_compatibility(struct btrfs_super_block *sb, unsigned flags)
> > 
> > IIRC kernel checkpatch will warn on single "unsigned", as it's recommended
> > to use "unsigned int".
> 
> I was going for consistency with the rest of disk-io.c, but I can fix
> it.

Not needed IMHO, we don't use unsinged int/unsigned consistently.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2016-11-14 16:40 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-11-13 19:35 [PATCH 0/6] btrfs-progs: better space_cache=v2 support Omar Sandoval
2016-11-13 19:35 ` [PATCH 1/6] btrfs-progs: add the FREE_SPACE_TREE_VALID compat_ro bit definition Omar Sandoval
2016-11-13 19:35 ` [PATCH 2/6] btrfs-progs: format FREE_SPACE_TREE{,_VALID} nicely in dump-super Omar Sandoval
2016-11-13 19:35 ` [PATCH 3/6] btrfs-progs: add OPEN_CTREE_INVALIDATE_FST flag Omar Sandoval
2016-11-14  1:22   ` Qu Wenruo
     [not found]     ` <20161114162256.GA22223@vader>
2016-11-14 16:40       ` David Sterba
2016-11-13 19:35 ` [PATCH 4/6] btrfs-progs: add btrfs_clear_free_space_tree() from the kernel Omar Sandoval
2016-11-14  1:38   ` Qu Wenruo
2016-11-14 16:33     ` Omar Sandoval
2016-11-13 19:35 ` [PATCH 5/6] btrfs-progs: implement btrfs check --clear-space-cache v2 Omar Sandoval
2016-11-14  1:44   ` Qu Wenruo
2016-11-13 19:35 ` [PATCH 6/6] btrfs-progs: document space_cache=v2 more thoroughly Omar Sandoval

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).