* [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).