* [PATCH 0/2][v3] Some leaked root fixes @ 2020-09-03 18:29 Josef Bacik 2020-09-03 18:29 ` [PATCH 1/2] btrfs: free fs roots on failed mount Josef Bacik 2020-09-03 18:29 ` [PATCH 2/2] btrfs: pretty print leaked root name Josef Bacik 0 siblings, 2 replies; 15+ messages in thread From: Josef Bacik @ 2020-09-03 18:29 UTC (permalink / raw) To: linux-btrfs, kernel-team v2->v3: - Reworked the pretty print for roots so it's a little cleaner, also made it so only reloc roots spit out the offset, since that's the only time we care. - Added Nikolay's reviewed-by for the first patch. --- Original email --- Hello, These are two fixes for a leaked root problem I noticed a while ago. One is the actual leaked root fix, the other is to add a pretty print for the leaked root message, as figuring out that some giant %llu number was the data reloc root is not a feat meant for humans. Thanks, Josef Josef Bacik (2): btrfs: free fs roots on failed mount btrfs: pretty print leaked root name fs/btrfs/disk-io.c | 8 ++++++-- fs/btrfs/print-tree.c | 39 +++++++++++++++++++++++++++++++++++++++ fs/btrfs/print-tree.h | 3 +++ 3 files changed, 48 insertions(+), 2 deletions(-) -- 2.24.1 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/2] btrfs: free fs roots on failed mount 2020-09-03 18:29 [PATCH 0/2][v3] Some leaked root fixes Josef Bacik @ 2020-09-03 18:29 ` Josef Bacik 2020-09-07 12:50 ` David Sterba 2020-09-03 18:29 ` [PATCH 2/2] btrfs: pretty print leaked root name Josef Bacik 1 sibling, 1 reply; 15+ messages in thread From: Josef Bacik @ 2020-09-03 18:29 UTC (permalink / raw) To: linux-btrfs, kernel-team; +Cc: Nikolay Borisov While testing a weird problem with -o degraded, I noticed I was getting leaked root errors BTRFS warning (device loop0): writable mount is not allowed due to too many missing devices BTRFS error (device loop0): open_ctree failed BTRFS error (device loop0): leaked root -9-0 refcount 1 This is the DATA_RELOC root, which gets read before the other fs roots, but is included in the fs roots radix tree. Handle this by adding a btrfs_drop_and_free_fs_root() on the data reloc root if it exists. This is ok to do here if we fail further up because we will only drop the ref if we delete the root from the radix tree, and all other cleanup won't be duplicated. Reviewed-by: Nikolay Borisov <nborisov@suse.com> Signed-off-by: Josef Bacik <josef@toxicpanda.com> --- fs/btrfs/disk-io.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 0df589c95d86..7147237d9bf0 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3415,6 +3415,8 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device btrfs_put_block_group_cache(fs_info); fail_tree_roots: + if (fs_info->data_reloc_root) + btrfs_drop_and_free_fs_root(fs_info, fs_info->data_reloc_root); free_root_pointers(fs_info, true); invalidate_inode_pages2(fs_info->btree_inode->i_mapping); -- 2.24.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] btrfs: free fs roots on failed mount 2020-09-03 18:29 ` [PATCH 1/2] btrfs: free fs roots on failed mount Josef Bacik @ 2020-09-07 12:50 ` David Sterba 0 siblings, 0 replies; 15+ messages in thread From: David Sterba @ 2020-09-07 12:50 UTC (permalink / raw) To: Josef Bacik; +Cc: linux-btrfs, kernel-team, Nikolay Borisov On Thu, Sep 03, 2020 at 02:29:50PM -0400, Josef Bacik wrote: > While testing a weird problem with -o degraded, I noticed I was getting > leaked root errors > > BTRFS warning (device loop0): writable mount is not allowed due to too many missing devices > BTRFS error (device loop0): open_ctree failed > BTRFS error (device loop0): leaked root -9-0 refcount 1 > > This is the DATA_RELOC root, which gets read before the other fs roots, > but is included in the fs roots radix tree. Handle this by adding a > btrfs_drop_and_free_fs_root() on the data reloc root if it exists. This > is ok to do here if we fail further up because we will only drop the ref > if we delete the root from the radix tree, and all other cleanup won't > be duplicated. > > Reviewed-by: Nikolay Borisov <nborisov@suse.com> > Signed-off-by: Josef Bacik <josef@toxicpanda.com> I'll add this to misc-next as this is the fix and does not need to wait on the root pretty printing. ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/2] btrfs: pretty print leaked root name 2020-09-03 18:29 [PATCH 0/2][v3] Some leaked root fixes Josef Bacik 2020-09-03 18:29 ` [PATCH 1/2] btrfs: free fs roots on failed mount Josef Bacik @ 2020-09-03 18:29 ` Josef Bacik 2020-09-07 12:28 ` David Sterba 1 sibling, 1 reply; 15+ messages in thread From: Josef Bacik @ 2020-09-03 18:29 UTC (permalink / raw) To: linux-btrfs, kernel-team I'm a actual human being so am incapable of converting u64 to s64 in my head, so add a helper to get the pretty name of a root objectid and use that helper to spit out the name for any special roots for leaked roots, so I don't have to scratch my head and figure out which root I messed up the refs for. Signed-off-by: Josef Bacik <josef@toxicpanda.com> --- fs/btrfs/disk-io.c | 6 ++++-- fs/btrfs/print-tree.c | 39 +++++++++++++++++++++++++++++++++++++++ fs/btrfs/print-tree.h | 3 +++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 7147237d9bf0..71beb9493ab4 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1504,10 +1504,12 @@ void btrfs_check_leaked_roots(struct btrfs_fs_info *fs_info) struct btrfs_root *root; while (!list_empty(&fs_info->allocated_roots)) { + char buf[BTRFS_ROOT_NAME_BUF_LEN]; + root = list_first_entry(&fs_info->allocated_roots, struct btrfs_root, leak_list); - btrfs_err(fs_info, "leaked root %llu-%llu refcount %d", - root->root_key.objectid, root->root_key.offset, + btrfs_err(fs_info, "leaked root %s refcount %d", + btrfs_root_name(root->root_key.objectid, buf), refcount_read(&root->refs)); while (refcount_read(&root->refs) > 1) btrfs_put_root(root); diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c index 80567c11ec12..d0370075a719 100644 --- a/fs/btrfs/print-tree.c +++ b/fs/btrfs/print-tree.c @@ -7,6 +7,45 @@ #include "disk-io.h" #include "print-tree.h" +struct name_map { + u64 id; + char *name; +}; + +static const struct name_map root_map[] = { + { BTRFS_ROOT_TREE_OBJECTID, "ROOT_TREE" }, + { BTRFS_EXTENT_TREE_OBJECTID, "EXTENT_TREE" }, + { BTRFS_CHUNK_TREE_OBJECTID, "CHUNK_TREE" }, + { BTRFS_DEV_TREE_OBJECTID, "DEV_TREE" }, + { BTRFS_FS_TREE_OBJECTID, "FS_TREE" }, + { BTRFS_ROOT_TREE_DIR_OBJECTID, "ROOT_TREE_DIR" }, + { BTRFS_CSUM_TREE_OBJECTID, "CSUM_TREE" }, + { BTRFS_TREE_LOG_OBJECTID, "TREE_LOG" }, + { BTRFS_QUOTA_TREE_OBJECTID, "QUOTA_TREE" }, + { BTRFS_UUID_TREE_OBJECTID, "UUID_TREE" }, + { BTRFS_FREE_SPACE_TREE_OBJECTID, "FREE_SPACE_TREE" }, + { BTRFS_DATA_RELOC_TREE_OBJECTID, "DATA_RELOC_TREE" }, +}; + +char *btrfs_root_name(u64 objectid, char *buf) +{ + int i; + + if (objectid == BTRFS_TREE_RELOC_OBJECTID) { + snprintf(buf, BTRFS_ROOT_NAME_BUF_LEN, + "TREE_RELOC offset=%llu", objectid); + return buf; + } + + for (i = 0; i < ARRAY_SIZE(root_map); i++) { + if (root_map[i].id == objectid) + return root_map[i].name; + } + + snprintf(buf, BTRFS_ROOT_NAME_BUF_LEN, "%llu", objectid); + return buf; +} + static void print_chunk(struct extent_buffer *eb, struct btrfs_chunk *chunk) { int num_stripes = btrfs_chunk_num_stripes(eb, chunk); diff --git a/fs/btrfs/print-tree.h b/fs/btrfs/print-tree.h index e6bb38fd75ad..8d07f80cead4 100644 --- a/fs/btrfs/print-tree.h +++ b/fs/btrfs/print-tree.h @@ -6,7 +6,10 @@ #ifndef BTRFS_PRINT_TREE_H #define BTRFS_PRINT_TREE_H +#define BTRFS_ROOT_NAME_BUF_LEN 48 + void btrfs_print_leaf(struct extent_buffer *l); void btrfs_print_tree(struct extent_buffer *c, bool follow); +char *btrfs_root_name(u64 objectid, char *buf); #endif -- 2.24.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] btrfs: pretty print leaked root name 2020-09-03 18:29 ` [PATCH 2/2] btrfs: pretty print leaked root name Josef Bacik @ 2020-09-07 12:28 ` David Sterba 2020-09-09 7:37 ` David Sterba 0 siblings, 1 reply; 15+ messages in thread From: David Sterba @ 2020-09-07 12:28 UTC (permalink / raw) To: Josef Bacik; +Cc: linux-btrfs, kernel-team On Thu, Sep 03, 2020 at 02:29:51PM -0400, Josef Bacik wrote: > I'm a actual human being so am incapable of converting u64 to s64 in my > head, so add a helper to get the pretty name of a root objectid and use > that helper to spit out the name for any special roots for leaked roots, > so I don't have to scratch my head and figure out which root I messed up > the refs for. > > Signed-off-by: Josef Bacik <josef@toxicpanda.com> > --- > fs/btrfs/disk-io.c | 6 ++++-- > fs/btrfs/print-tree.c | 39 +++++++++++++++++++++++++++++++++++++++ > fs/btrfs/print-tree.h | 3 +++ > 3 files changed, 46 insertions(+), 2 deletions(-) > > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > index 7147237d9bf0..71beb9493ab4 100644 > --- a/fs/btrfs/disk-io.c > +++ b/fs/btrfs/disk-io.c > @@ -1504,10 +1504,12 @@ void btrfs_check_leaked_roots(struct btrfs_fs_info *fs_info) > struct btrfs_root *root; > > while (!list_empty(&fs_info->allocated_roots)) { > + char buf[BTRFS_ROOT_NAME_BUF_LEN]; > + > root = list_first_entry(&fs_info->allocated_roots, > struct btrfs_root, leak_list); > - btrfs_err(fs_info, "leaked root %llu-%llu refcount %d", > - root->root_key.objectid, root->root_key.offset, > + btrfs_err(fs_info, "leaked root %s refcount %d", > + btrfs_root_name(root->root_key.objectid, buf), > refcount_read(&root->refs)); > while (refcount_read(&root->refs) > 1) > btrfs_put_root(root); > diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c > index 80567c11ec12..d0370075a719 100644 > --- a/fs/btrfs/print-tree.c > +++ b/fs/btrfs/print-tree.c > @@ -7,6 +7,45 @@ > #include "disk-io.h" > #include "print-tree.h" > > +struct name_map { > + u64 id; > + char *name; const char* or maybe even a fixed length string, removing the _TREE suffix > +}; > + > +static const struct name_map root_map[] = { > + { BTRFS_ROOT_TREE_OBJECTID, "ROOT_TREE" }, > + { BTRFS_EXTENT_TREE_OBJECTID, "EXTENT_TREE" }, > + { BTRFS_CHUNK_TREE_OBJECTID, "CHUNK_TREE" }, > + { BTRFS_DEV_TREE_OBJECTID, "DEV_TREE" }, > + { BTRFS_FS_TREE_OBJECTID, "FS_TREE" }, > + { BTRFS_ROOT_TREE_DIR_OBJECTID, "ROOT_TREE_DIR" }, This is not a tree id > + { BTRFS_CSUM_TREE_OBJECTID, "CSUM_TREE" }, > + { BTRFS_TREE_LOG_OBJECTID, "TREE_LOG" }, > + { BTRFS_QUOTA_TREE_OBJECTID, "QUOTA_TREE" }, > + { BTRFS_UUID_TREE_OBJECTID, "UUID_TREE" }, > + { BTRFS_FREE_SPACE_TREE_OBJECTID, "FREE_SPACE_TREE" }, > + { BTRFS_DATA_RELOC_TREE_OBJECTID, "DATA_RELOC_TREE" }, I've noticed we have the id -> str mapping already in btrfs_lockdep_keysets, so there could be just one such structure and we'd add wrappers around that. Also the C99 initializers should be used. > +}; > + > +char *btrfs_root_name(u64 objectid, char *buf) > +{ > + int i; > + > + if (objectid == BTRFS_TREE_RELOC_OBJECTID) { > + snprintf(buf, BTRFS_ROOT_NAME_BUF_LEN, > + "TREE_RELOC offset=%llu", objectid); The reloc tree is an outlier here so I wonder if we'd rather have a nice pretty printer of the tree root name and deal with the oddities where required rather than inside the helper. In this case there would have to be some conditionals in btrfs_check_leaked_roots, as we can't do that in the format string. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] btrfs: pretty print leaked root name 2020-09-07 12:28 ` David Sterba @ 2020-09-09 7:37 ` David Sterba 0 siblings, 0 replies; 15+ messages in thread From: David Sterba @ 2020-09-09 7:37 UTC (permalink / raw) To: dsterba, Josef Bacik, linux-btrfs, kernel-team On Mon, Sep 07, 2020 at 02:28:54PM +0200, David Sterba wrote: > On Thu, Sep 03, 2020 at 02:29:51PM -0400, Josef Bacik wrote: > > --- a/fs/btrfs/print-tree.c > > +++ b/fs/btrfs/print-tree.c > > @@ -7,6 +7,45 @@ > > #include "disk-io.h" > > #include "print-tree.h" > > > > +struct name_map { > > + u64 id; > > + char *name; > > const char* or maybe even a fixed length string, removing the > _TREE suffix > > > +}; > > + > > +static const struct name_map root_map[] = { > > + { BTRFS_ROOT_TREE_OBJECTID, "ROOT_TREE" }, > > + { BTRFS_EXTENT_TREE_OBJECTID, "EXTENT_TREE" }, > > + { BTRFS_CHUNK_TREE_OBJECTID, "CHUNK_TREE" }, > > + { BTRFS_DEV_TREE_OBJECTID, "DEV_TREE" }, > > + { BTRFS_FS_TREE_OBJECTID, "FS_TREE" }, > > + { BTRFS_ROOT_TREE_DIR_OBJECTID, "ROOT_TREE_DIR" }, > > This is not a tree id > > > + { BTRFS_CSUM_TREE_OBJECTID, "CSUM_TREE" }, > > + { BTRFS_TREE_LOG_OBJECTID, "TREE_LOG" }, > > + { BTRFS_QUOTA_TREE_OBJECTID, "QUOTA_TREE" }, > > + { BTRFS_UUID_TREE_OBJECTID, "UUID_TREE" }, > > + { BTRFS_FREE_SPACE_TREE_OBJECTID, "FREE_SPACE_TREE" }, > > + { BTRFS_DATA_RELOC_TREE_OBJECTID, "DATA_RELOC_TREE" }, > > I've noticed we have the id -> str mapping already in > btrfs_lockdep_keysets, so there could be just one such structure and > we'd add wrappers around that. > > Also the C99 initializers should be used. > > > +}; > > + > > +char *btrfs_root_name(u64 objectid, char *buf) > > +{ > > + int i; > > + > > + if (objectid == BTRFS_TREE_RELOC_OBJECTID) { > > + snprintf(buf, BTRFS_ROOT_NAME_BUF_LEN, > > + "TREE_RELOC offset=%llu", objectid); > > The reloc tree is an outlier here so I wonder if we'd rather have a nice > pretty printer of the tree root name and deal with the oddities where > required rather than inside the helper. In this case there would have to > be some conditionals in btrfs_check_leaked_roots, as we can't do that in > the format string. I had another thought, we want a pretty printer, the above still holds but needs more restructuring so let's take this. I'll do the fixups and add it to misc-next. ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 0/2][v2] Some leaked root fixes @ 2020-08-20 20:00 Josef Bacik 2020-08-20 20:00 ` [PATCH 1/2] btrfs: free fs roots on failed mount Josef Bacik 0 siblings, 1 reply; 15+ messages in thread From: Josef Bacik @ 2020-08-20 20:00 UTC (permalink / raw) To: linux-btrfs, kernel-team Hello, These are two fixes for a leaked root problem I noticed a while ago. One is the actual leaked root fix, the other is to add a pretty print for the leaked root message, as figuring out that some giant %llu number was the data reloc root is not a feat meant for humans. Thanks, Josef ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/2] btrfs: free fs roots on failed mount 2020-08-20 20:00 [PATCH 0/2][v2] Some leaked root fixes Josef Bacik @ 2020-08-20 20:00 ` Josef Bacik 2020-08-21 7:31 ` Nikolay Borisov 0 siblings, 1 reply; 15+ messages in thread From: Josef Bacik @ 2020-08-20 20:00 UTC (permalink / raw) To: linux-btrfs, kernel-team While testing a weird problem with -o degraded, I noticed I was getting leaked root errors BTRFS warning (device loop0): writable mount is not allowed due to too many missing devices BTRFS error (device loop0): open_ctree failed BTRFS error (device loop0): leaked root -9-0 refcount 1 This is the DATA_RELOC root, which gets read before the other fs roots, but is included in the fs roots radix tree. Handle this by adding a btrfs_drop_and_free_fs_root() on the data reloc root if it exists. This is ok to do here if we fail further up because we will only drop the ref if we delete the root from the radix tree, and all other cleanup won't be duplicated. Signed-off-by: Josef Bacik <josef@toxicpanda.com> --- fs/btrfs/disk-io.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 814f8de395fe..ac6d6fddd5f4 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3418,6 +3418,8 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device btrfs_put_block_group_cache(fs_info); fail_tree_roots: + if (fs_info->data_reloc_root) + btrfs_drop_and_free_fs_root(fs_info, fs_info->data_reloc_root); free_root_pointers(fs_info, true); invalidate_inode_pages2(fs_info->btree_inode->i_mapping); -- 2.24.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] btrfs: free fs roots on failed mount 2020-08-20 20:00 ` [PATCH 1/2] btrfs: free fs roots on failed mount Josef Bacik @ 2020-08-21 7:31 ` Nikolay Borisov 2020-08-21 13:59 ` Josef Bacik 0 siblings, 1 reply; 15+ messages in thread From: Nikolay Borisov @ 2020-08-21 7:31 UTC (permalink / raw) To: Josef Bacik, linux-btrfs, kernel-team On 20.08.20 г. 23:00 ч., Josef Bacik wrote: > While testing a weird problem with -o degraded, I noticed I was getting > leaked root errors > > BTRFS warning (device loop0): writable mount is not allowed due to too many missing devices > BTRFS error (device loop0): open_ctree failed > BTRFS error (device loop0): leaked root -9-0 refcount 1 > > This is the DATA_RELOC root, which gets read before the other fs roots, > but is included in the fs roots radix tree. Handle this by adding a > btrfs_drop_and_free_fs_root() on the data reloc root if it exists. This > is ok to do here if we fail further up because we will only drop the ref > if we delete the root from the radix tree, and all other cleanup won't > be duplicated. > > Signed-off-by: Josef Bacik <josef@toxicpanda.com> > --- > fs/btrfs/disk-io.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > index 814f8de395fe..ac6d6fddd5f4 100644 > --- a/fs/btrfs/disk-io.c > +++ b/fs/btrfs/disk-io.c > @@ -3418,6 +3418,8 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device > btrfs_put_block_group_cache(fs_info); > > fail_tree_roots: > + if (fs_info->data_reloc_root) > + btrfs_drop_and_free_fs_root(fs_info, fs_info->data_reloc_root); But will this really free the root? So the newly allocated data_reloc_root has it's ref set to 1 from btrfs_get_root_ref->btrfs_read_tree_root->btrfs_alloc_root and to 2 from being added to the radix tree in btrfs_insert_fs_root(). But btrfs_drop_and_free_fs_root makes a single call to btrfs_put_root. So won't the reloc tree be left with a refcount of 1 ? > free_root_pointers(fs_info, true); > invalidate_inode_pages2(fs_info->btree_inode->i_mapping); > > ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] btrfs: free fs roots on failed mount 2020-08-21 7:31 ` Nikolay Borisov @ 2020-08-21 13:59 ` Josef Bacik 2020-08-21 14:07 ` Nikolay Borisov 0 siblings, 1 reply; 15+ messages in thread From: Josef Bacik @ 2020-08-21 13:59 UTC (permalink / raw) To: Nikolay Borisov, linux-btrfs, kernel-team On 8/21/20 3:31 AM, Nikolay Borisov wrote: > > > On 20.08.20 г. 23:00 ч., Josef Bacik wrote: >> While testing a weird problem with -o degraded, I noticed I was getting >> leaked root errors >> >> BTRFS warning (device loop0): writable mount is not allowed due to too many missing devices >> BTRFS error (device loop0): open_ctree failed >> BTRFS error (device loop0): leaked root -9-0 refcount 1 >> >> This is the DATA_RELOC root, which gets read before the other fs roots, >> but is included in the fs roots radix tree. Handle this by adding a >> btrfs_drop_and_free_fs_root() on the data reloc root if it exists. This >> is ok to do here if we fail further up because we will only drop the ref >> if we delete the root from the radix tree, and all other cleanup won't >> be duplicated. >> >> Signed-off-by: Josef Bacik <josef@toxicpanda.com> >> --- >> fs/btrfs/disk-io.c | 2 ++ >> 1 file changed, 2 insertions(+) >> >> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c >> index 814f8de395fe..ac6d6fddd5f4 100644 >> --- a/fs/btrfs/disk-io.c >> +++ b/fs/btrfs/disk-io.c >> @@ -3418,6 +3418,8 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device >> btrfs_put_block_group_cache(fs_info); >> >> fail_tree_roots: >> + if (fs_info->data_reloc_root) >> + btrfs_drop_and_free_fs_root(fs_info, fs_info->data_reloc_root); > > But will this really free the root? So the newly allocated > data_reloc_root has it's ref set to 1 from > btrfs_get_root_ref->btrfs_read_tree_root->btrfs_alloc_root and to 2 from > being added to the radix tree in btrfs_insert_fs_root(). > > But btrfs_drop_and_free_fs_root makes a single call to btrfs_put_root. > So won't the reloc tree be left with a refcount of 1 ? It's a global root, so it's final put happens in btrfs_free_fs_info(), we just need to drop the radix tree ref here. Thanks, Josef ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] btrfs: free fs roots on failed mount 2020-08-21 13:59 ` Josef Bacik @ 2020-08-21 14:07 ` Nikolay Borisov 0 siblings, 0 replies; 15+ messages in thread From: Nikolay Borisov @ 2020-08-21 14:07 UTC (permalink / raw) To: Josef Bacik, linux-btrfs, kernel-team On 21.08.20 г. 16:59 ч., Josef Bacik wrote: > On 8/21/20 3:31 AM, Nikolay Borisov wrote: >> >> >> On 20.08.20 г. 23:00 ч., Josef Bacik wrote: >>> While testing a weird problem with -o degraded, I noticed I was getting >>> leaked root errors >>> >>> BTRFS warning (device loop0): writable mount is not allowed due to >>> too many missing devices >>> BTRFS error (device loop0): open_ctree failed >>> BTRFS error (device loop0): leaked root -9-0 refcount 1 >>> >>> This is the DATA_RELOC root, which gets read before the other fs roots, >>> but is included in the fs roots radix tree. Handle this by adding a >>> btrfs_drop_and_free_fs_root() on the data reloc root if it exists. This >>> is ok to do here if we fail further up because we will only drop the ref >>> if we delete the root from the radix tree, and all other cleanup won't >>> be duplicated. >>> >>> Signed-off-by: Josef Bacik <josef@toxicpanda.com> >>> --- >>> fs/btrfs/disk-io.c | 2 ++ >>> 1 file changed, 2 insertions(+) >>> >>> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c >>> index 814f8de395fe..ac6d6fddd5f4 100644 >>> --- a/fs/btrfs/disk-io.c >>> +++ b/fs/btrfs/disk-io.c >>> @@ -3418,6 +3418,8 @@ int __cold open_ctree(struct super_block *sb, >>> struct btrfs_fs_devices *fs_device >>> btrfs_put_block_group_cache(fs_info); >>> fail_tree_roots: >>> + if (fs_info->data_reloc_root) >>> + btrfs_drop_and_free_fs_root(fs_info, fs_info->data_reloc_root); >> >> But will this really free the root? So the newly allocated >> data_reloc_root has it's ref set to 1 from >> btrfs_get_root_ref->btrfs_read_tree_root->btrfs_alloc_root and to 2 from >> being added to the radix tree in btrfs_insert_fs_root(). >> >> But btrfs_drop_and_free_fs_root makes a single call to btrfs_put_root. >> So won't the reloc tree be left with a refcount of 1 ? > > It's a global root, so it's final put happens in btrfs_free_fs_info(), > we just need to drop the radix tree ref here. Thanks, Fair enough, but this really shows that btrfs_drop_and_free_fs_root has a horrible name which doesn't reflect what it does fully... Any case the patch itself is good, so : Reviewed-by: Nikolay Borisov <nborisov@suse.com> > > Josef > ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/2] btrfs: free fs roots on failed mount @ 2020-07-22 16:07 Josef Bacik 2020-07-27 14:19 ` David Sterba 0 siblings, 1 reply; 15+ messages in thread From: Josef Bacik @ 2020-07-22 16:07 UTC (permalink / raw) To: linux-btrfs, kernel-team While testing a weird problem with -o degraded, I noticed I was getting leaked root errors BTRFS warning (device loop0): writable mount is not allowed due to too many missing devices BTRFS error (device loop0): open_ctree failed BTRFS error (device loop0): leaked root -9-0 refcount 1 This is the DATA_RELOC root, which gets read before the other fs roots, but is included in the fs roots radix tree, and thus gets freed by btrfs_free_fs_roots. Fix this by moving the call into fail_tree_roots: in open_ctree. With this fix we no longer leak that root on mount failure. Signed-off-by: Josef Bacik <josef@toxicpanda.com> --- fs/btrfs/disk-io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index c850d7f44fbe..f1fdbdd44c02 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3421,7 +3421,6 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device fail_trans_kthread: kthread_stop(fs_info->transaction_kthread); btrfs_cleanup_transaction(fs_info); - btrfs_free_fs_roots(fs_info); fail_cleaner: kthread_stop(fs_info->cleaner_kthread); @@ -3441,6 +3440,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device btrfs_put_block_group_cache(fs_info); fail_tree_roots: + btrfs_free_fs_roots(fs_info); free_root_pointers(fs_info, true); invalidate_inode_pages2(fs_info->btree_inode->i_mapping); -- 2.24.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] btrfs: free fs roots on failed mount 2020-07-22 16:07 Josef Bacik @ 2020-07-27 14:19 ` David Sterba 2020-07-27 14:33 ` Josef Bacik 0 siblings, 1 reply; 15+ messages in thread From: David Sterba @ 2020-07-27 14:19 UTC (permalink / raw) To: Josef Bacik; +Cc: linux-btrfs, kernel-team On Wed, Jul 22, 2020 at 12:07:21PM -0400, Josef Bacik wrote: > While testing a weird problem with -o degraded, I noticed I was getting > leaked root errors > > BTRFS warning (device loop0): writable mount is not allowed due to too many missing devices > BTRFS error (device loop0): open_ctree failed > BTRFS error (device loop0): leaked root -9-0 refcount 1 > > This is the DATA_RELOC root, which gets read before the other fs roots, > but is included in the fs roots radix tree, and thus gets freed by > btrfs_free_fs_roots. Fix this by moving the call into fail_tree_roots: > in open_ctree. With this fix we no longer leak that root on mount > failure. > > Signed-off-by: Josef Bacik <josef@toxicpanda.com> > --- > fs/btrfs/disk-io.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > index c850d7f44fbe..f1fdbdd44c02 100644 > --- a/fs/btrfs/disk-io.c > +++ b/fs/btrfs/disk-io.c > @@ -3421,7 +3421,6 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device > fail_trans_kthread: > kthread_stop(fs_info->transaction_kthread); > btrfs_cleanup_transaction(fs_info); > - btrfs_free_fs_roots(fs_info); > fail_cleaner: > kthread_stop(fs_info->cleaner_kthread); > > @@ -3441,6 +3440,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device > btrfs_put_block_group_cache(fs_info); > > fail_tree_roots: > + btrfs_free_fs_roots(fs_info); > free_root_pointers(fs_info, true); The data reloc tree is freed inside free_root_pointers, that it's also in the radix tree is for convenience so I'd rather fix it inside free_root_pointers and not reorder btrfs_free_fs_roots. > invalidate_inode_pages2(fs_info->btree_inode->i_mapping); > > -- > 2.24.1 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] btrfs: free fs roots on failed mount 2020-07-27 14:19 ` David Sterba @ 2020-07-27 14:33 ` Josef Bacik 2020-07-27 15:17 ` David Sterba 0 siblings, 1 reply; 15+ messages in thread From: Josef Bacik @ 2020-07-27 14:33 UTC (permalink / raw) To: dsterba, linux-btrfs, kernel-team On 7/27/20 10:19 AM, David Sterba wrote: > On Wed, Jul 22, 2020 at 12:07:21PM -0400, Josef Bacik wrote: >> While testing a weird problem with -o degraded, I noticed I was getting >> leaked root errors >> >> BTRFS warning (device loop0): writable mount is not allowed due to too many missing devices >> BTRFS error (device loop0): open_ctree failed >> BTRFS error (device loop0): leaked root -9-0 refcount 1 >> >> This is the DATA_RELOC root, which gets read before the other fs roots, >> but is included in the fs roots radix tree, and thus gets freed by >> btrfs_free_fs_roots. Fix this by moving the call into fail_tree_roots: >> in open_ctree. With this fix we no longer leak that root on mount >> failure. >> >> Signed-off-by: Josef Bacik <josef@toxicpanda.com> >> --- >> fs/btrfs/disk-io.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c >> index c850d7f44fbe..f1fdbdd44c02 100644 >> --- a/fs/btrfs/disk-io.c >> +++ b/fs/btrfs/disk-io.c >> @@ -3421,7 +3421,6 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device >> fail_trans_kthread: >> kthread_stop(fs_info->transaction_kthread); >> btrfs_cleanup_transaction(fs_info); >> - btrfs_free_fs_roots(fs_info); >> fail_cleaner: >> kthread_stop(fs_info->cleaner_kthread); >> >> @@ -3441,6 +3440,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device >> btrfs_put_block_group_cache(fs_info); >> >> fail_tree_roots: >> + btrfs_free_fs_roots(fs_info); >> free_root_pointers(fs_info, true); > > The data reloc tree is freed inside free_root_pointers, that it's also > in the radix tree is for convenience so I'd rather fix it inside > free_root_pointers and not reorder btrfs_free_fs_roots. > We can't do that, because free_root_pointers() is called to drop the extent buffers when we're looping through the backup roots. btrfs_free_fs_roots() is the correct thing to do here, it goes through anything that ended up in the radix tree. Thanks, Josef ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] btrfs: free fs roots on failed mount 2020-07-27 14:33 ` Josef Bacik @ 2020-07-27 15:17 ` David Sterba 2020-07-27 15:37 ` Josef Bacik 0 siblings, 1 reply; 15+ messages in thread From: David Sterba @ 2020-07-27 15:17 UTC (permalink / raw) To: Josef Bacik; +Cc: dsterba, linux-btrfs, kernel-team On Mon, Jul 27, 2020 at 10:33:32AM -0400, Josef Bacik wrote: > >> @@ -3441,6 +3440,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device > >> btrfs_put_block_group_cache(fs_info); > >> > >> fail_tree_roots: > >> + btrfs_free_fs_roots(fs_info); > >> free_root_pointers(fs_info, true); > > > > The data reloc tree is freed inside free_root_pointers, that it's also > > in the radix tree is for convenience so I'd rather fix it inside > > free_root_pointers and not reorder btrfs_free_fs_roots. > > We can't do that, because free_root_pointers() is called to drop the extent > buffers when we're looping through the backup roots. btrfs_free_fs_roots() is > the correct thing to do here, it goes through anything that ended up in the > radix tree. Thanks, I see, free_root_pointers is used elsewhere. I'm concerned about the reordeing because there are several functions that are now called after the roots are freed. (before) btrfs_free_fs_roots(fs_info); kthread_stop(fs_info->cleaner_kthread); filemap_write_and_wait(fs_info->btree_inode->i_mapping); btrfs_sysfs_remove_mounted(fs_info); btrfs_sysfs_remove_fsid(fs_info->fs_devices); btrfs_put_block_group_cache(fs_info); (after) btrfs_free_fs_roots(fs_info); If something called by btrfs_free_fs_roots depends on structures removed/cleaned by the other functions, eg. btrfs_put_block_group_cache ti could be a problem. I haven't spotted anything so far, the functions are called after failure still during mount, this is easier than shutdown sequence after a full mount. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] btrfs: free fs roots on failed mount 2020-07-27 15:17 ` David Sterba @ 2020-07-27 15:37 ` Josef Bacik 0 siblings, 0 replies; 15+ messages in thread From: Josef Bacik @ 2020-07-27 15:37 UTC (permalink / raw) To: dsterba, linux-btrfs, kernel-team On 7/27/20 11:17 AM, David Sterba wrote: > On Mon, Jul 27, 2020 at 10:33:32AM -0400, Josef Bacik wrote: >>>> @@ -3441,6 +3440,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device >>>> btrfs_put_block_group_cache(fs_info); >>>> >>>> fail_tree_roots: >>>> + btrfs_free_fs_roots(fs_info); >>>> free_root_pointers(fs_info, true); >>> >>> The data reloc tree is freed inside free_root_pointers, that it's also >>> in the radix tree is for convenience so I'd rather fix it inside >>> free_root_pointers and not reorder btrfs_free_fs_roots. >> >> We can't do that, because free_root_pointers() is called to drop the extent >> buffers when we're looping through the backup roots. btrfs_free_fs_roots() is >> the correct thing to do here, it goes through anything that ended up in the >> radix tree. Thanks, > > I see, free_root_pointers is used elsewhere. I'm concerned about the > reordeing because there are several functions that are now called after > the roots are freed. > > (before) btrfs_free_fs_roots(fs_info); > > kthread_stop(fs_info->cleaner_kthread); > filemap_write_and_wait(fs_info->btree_inode->i_mapping); > btrfs_sysfs_remove_mounted(fs_info); > btrfs_sysfs_remove_fsid(fs_info->fs_devices); > btrfs_put_block_group_cache(fs_info); > > (after) btrfs_free_fs_roots(fs_info); > > If something called by btrfs_free_fs_roots depends on structures > removed/cleaned by the other functions, eg. btrfs_put_block_group_cache > ti could be a problem. > > I haven't spotted anything so far, the functions are called after > failure still during mount, this is easier than shutdown sequence after > a full mount. > Yeah I'm always loathe to move this stuff around. I actually think we can end up with the case described in close_ctree if we get an error during log replay on mount. I'll rework this some more. Thanks, Josef ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2020-09-09 7:38 UTC | newest] Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-09-03 18:29 [PATCH 0/2][v3] Some leaked root fixes Josef Bacik 2020-09-03 18:29 ` [PATCH 1/2] btrfs: free fs roots on failed mount Josef Bacik 2020-09-07 12:50 ` David Sterba 2020-09-03 18:29 ` [PATCH 2/2] btrfs: pretty print leaked root name Josef Bacik 2020-09-07 12:28 ` David Sterba 2020-09-09 7:37 ` David Sterba -- strict thread matches above, loose matches on Subject: below -- 2020-08-20 20:00 [PATCH 0/2][v2] Some leaked root fixes Josef Bacik 2020-08-20 20:00 ` [PATCH 1/2] btrfs: free fs roots on failed mount Josef Bacik 2020-08-21 7:31 ` Nikolay Borisov 2020-08-21 13:59 ` Josef Bacik 2020-08-21 14:07 ` Nikolay Borisov 2020-07-22 16:07 Josef Bacik 2020-07-27 14:19 ` David Sterba 2020-07-27 14:33 ` Josef Bacik 2020-07-27 15:17 ` David Sterba 2020-07-27 15:37 ` Josef Bacik
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).