@@ -52,6 +52,7 @@
#include "relocation.h"
#include "scrub.h"
#include "super.h"
+#include "raid-stripe-tree.h"
#define BTRFS_SUPER_FLAG_SUPP (BTRFS_HEADER_FLAG_WRITTEN |\
BTRFS_HEADER_FLAG_RELOC |\
@@ -1538,6 +1539,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);
@@ -36,6 +36,36 @@ 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 (!btrfs_stripe_tree_root(fs_info) ||
+ RB_EMPTY_ROOT(&fs_info->stripe_update_tree))
+ return;
+
+ WARN_ON_ONCE(1);
+ write_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);
+
+ write_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);
+ write_lock(&fs_info->stripe_update_lock);
+ }
+ write_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;
@@ -38,6 +38,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 | 30 ++++++++++++++++++++++++++++++ fs/btrfs/raid-stripe-tree.h | 1 + 3 files changed, 33 insertions(+)