Message ID | c939c2fdd361800a4361707bf9d5cc68e30e7907.1666007330.git.johannes.thumshirn@wdc.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | btrfs: raid-stripe-tree draft patches | expand |
On Mon, Oct 17, 2022 at 04:55:28AM -0700, Johannes Thumshirn wrote: > Check if we're leaking any ordered stripes when unmounting a filesystem > with an stripe tree. > > This check is gated behind CONFIG_BTRFS_DEBUG to not affect any production > type systems. > > Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> > --- > fs/btrfs/disk-io.c | 2 ++ > fs/btrfs/raid-stripe-tree.c | 29 +++++++++++++++++++++++++++++ > fs/btrfs/raid-stripe-tree.h | 1 + > 3 files changed, 32 insertions(+) > > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > index 190caabf5fb7..e479e9829c3e 100644 > --- a/fs/btrfs/disk-io.c > +++ b/fs/btrfs/disk-io.c > @@ -43,6 +43,7 @@ > #include "space-info.h" > #include "zoned.h" > #include "subpage.h" > +#include "raid-stripe-tree.h" > > #define BTRFS_SUPER_FLAG_SUPP (BTRFS_HEADER_FLAG_WRITTEN |\ > BTRFS_HEADER_FLAG_RELOC |\ > @@ -1480,6 +1481,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info) > btrfs_put_root(fs_info->stripe_root); > btrfs_check_leaked_roots(fs_info); > btrfs_extent_buffer_leak_debug_check(fs_info); > + btrfs_check_ordered_stripe_leak(fs_info); > kfree(fs_info->super_copy); > kfree(fs_info->super_for_commit); > kfree(fs_info->subpage_info); > diff --git a/fs/btrfs/raid-stripe-tree.c b/fs/btrfs/raid-stripe-tree.c > index 91e67600e01a..9a913c4cd44e 100644 > --- a/fs/btrfs/raid-stripe-tree.c > +++ b/fs/btrfs/raid-stripe-tree.c > @@ -30,6 +30,35 @@ static int ordered_stripe_less(struct rb_node *rba, const struct rb_node *rbb) > return ordered_stripe_cmp(&stripe->logical, rbb); > } > > +void btrfs_check_ordered_stripe_leak(struct btrfs_fs_info *fs_info) > +{ > +#ifdef CONFIG_BTRFS_DEBUG > + struct rb_node *node; > + > + if (!fs_info->stripe_root || > + RB_EMPTY_ROOT(&fs_info->stripe_update_tree)) > + return; > + > + mutex_lock(&fs_info->stripe_update_lock); > + while ((node = rb_first_postorder(&fs_info->stripe_update_tree)) > + != NULL) { > + struct btrfs_ordered_stripe *stripe = > + rb_entry(node, struct btrfs_ordered_stripe, rb_node); > + Can we get a WARN_ON_ONCE() in here? That way xfstests failures will get noticed as we'll get the dmesg failures. Thanks, Josef
On 20.10.22 17:37, Josef Bacik wrote: +void btrfs_check_ordered_stripe_leak(struct btrfs_fs_info *fs_info) >> +{ >> +#ifdef CONFIG_BTRFS_DEBUG >> + struct rb_node *node; >> + >> + if (!fs_info->stripe_root || >> + RB_EMPTY_ROOT(&fs_info->stripe_update_tree)) >> + return; >> + >> + mutex_lock(&fs_info->stripe_update_lock); >> + while ((node = rb_first_postorder(&fs_info->stripe_update_tree)) >> + != NULL) { >> + struct btrfs_ordered_stripe *stripe = >> + rb_entry(node, struct btrfs_ordered_stripe, rb_node); >> + > > Can we get a WARN_ON_ONCE() in here? That way xfstests failures will get > noticed as we'll get the dmesg failures. Thanks, Sure.
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 190caabf5fb7..e479e9829c3e 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -43,6 +43,7 @@ #include "space-info.h" #include "zoned.h" #include "subpage.h" +#include "raid-stripe-tree.h" #define BTRFS_SUPER_FLAG_SUPP (BTRFS_HEADER_FLAG_WRITTEN |\ BTRFS_HEADER_FLAG_RELOC |\ @@ -1480,6 +1481,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info) btrfs_put_root(fs_info->stripe_root); btrfs_check_leaked_roots(fs_info); btrfs_extent_buffer_leak_debug_check(fs_info); + btrfs_check_ordered_stripe_leak(fs_info); kfree(fs_info->super_copy); kfree(fs_info->super_for_commit); kfree(fs_info->subpage_info); diff --git a/fs/btrfs/raid-stripe-tree.c b/fs/btrfs/raid-stripe-tree.c index 91e67600e01a..9a913c4cd44e 100644 --- a/fs/btrfs/raid-stripe-tree.c +++ b/fs/btrfs/raid-stripe-tree.c @@ -30,6 +30,35 @@ static int ordered_stripe_less(struct rb_node *rba, const struct rb_node *rbb) return ordered_stripe_cmp(&stripe->logical, rbb); } +void btrfs_check_ordered_stripe_leak(struct btrfs_fs_info *fs_info) +{ +#ifdef CONFIG_BTRFS_DEBUG + struct rb_node *node; + + if (!fs_info->stripe_root || + RB_EMPTY_ROOT(&fs_info->stripe_update_tree)) + return; + + mutex_lock(&fs_info->stripe_update_lock); + while ((node = rb_first_postorder(&fs_info->stripe_update_tree)) + != NULL) { + struct btrfs_ordered_stripe *stripe = + rb_entry(node, struct btrfs_ordered_stripe, rb_node); + + mutex_unlock(&fs_info->stripe_update_lock); + btrfs_err(fs_info, + "ordered_stripe [%llu, %llu] leaked, refcount=%d", + stripe->logical, stripe->logical + stripe->num_bytes, + refcount_read(&stripe->ref)); + while (refcount_read(&stripe->ref) > 1) + btrfs_put_ordered_stripe(fs_info, stripe); + btrfs_put_ordered_stripe(fs_info, stripe); + mutex_lock(&fs_info->stripe_update_lock); + } + mutex_unlock(&fs_info->stripe_update_lock); +#endif +} + int btrfs_add_ordered_stripe(struct btrfs_io_context *bioc) { struct btrfs_fs_info *fs_info = bioc->fs_info; diff --git a/fs/btrfs/raid-stripe-tree.h b/fs/btrfs/raid-stripe-tree.h index d1885b428cd4..5ffb10bf219e 100644 --- a/fs/btrfs/raid-stripe-tree.h +++ b/fs/btrfs/raid-stripe-tree.h @@ -31,6 +31,7 @@ struct btrfs_ordered_stripe *btrfs_lookup_ordered_stripe( int btrfs_add_ordered_stripe(struct btrfs_io_context *bioc); void btrfs_put_ordered_stripe(struct btrfs_fs_info *fs_info, struct btrfs_ordered_stripe *stripe); +void btrfs_check_ordered_stripe_leak(struct btrfs_fs_info *fs_info); static inline bool btrfs_need_stripe_tree_update(struct btrfs_fs_info *fs_info, u64 map_type)
Check if we're leaking any ordered stripes when unmounting a filesystem with an stripe tree. This check is gated behind CONFIG_BTRFS_DEBUG to not affect any production type systems. Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> --- fs/btrfs/disk-io.c | 2 ++ fs/btrfs/raid-stripe-tree.c | 29 +++++++++++++++++++++++++++++ fs/btrfs/raid-stripe-tree.h | 1 + 3 files changed, 32 insertions(+)