From: Zygo Blaxell Date: Sat, 6 Mar 2021 14:31:03 +0000 (-0500) Subject: btrfs: tree mod log vs zoned fix 2 from fdmanana X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Ftree-mod-test;p=linux btrfs: tree mod log vs zoned fix 2 from fdmanana Great! Ok, so that seems to confirm what I suspected and made me run into other sorts of weirdness during logical ino calls (returning unexpected results). I haven't hit the BUG_ON() as you do, but if this is indeed caused by allowing to reuse unwritten extent buffers in the same transaction, it's no wonder that BUG_ON() and many other weird issues happen. Can you now try the following version? https://pastebin.com/raw/5VHjzdn6 Leave it for at least as many days as you tested the previous patch, hell, even a week or more if you can. Thanks, much appreciated. --- diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index b5f24bb879713..d840a626e01d2 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3336,6 +3336,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, if (last_ref && btrfs_header_generation(buf) == trans->transid) { struct btrfs_block_group *cache; + bool have_mod_log_users; if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) { ret = check_ref_cleanup(trans, buf->start); @@ -3353,7 +3354,19 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, goto out; } - if (btrfs_is_zoned(fs_info)) { + /* + * If there are tree mod log users, we may have recorded mog log + * operations on this extent buffer, so we can not add back this + * extent buffer to the free space cache/tree, because if it gets + * allocated and changed while there are mod log users, replaying + * the mod log operations will result in all sorts of unexpected + * results. + */ + read_lock(&fs_info->tree_mod_log_lock); + have_mod_log_users = !list_empty(&fs_info->tree_mod_seq_list); + read_unlock(&fs_info->tree_mod_log_lock); + + if (have_mod_log_users || btrfs_is_zoned(fs_info)) { btrfs_redirty_list_add(trans->transaction, buf); pin_down_extent(trans, cache, buf->start, buf->len, 1); btrfs_put_block_group(cache);