]> git.hungrycats.org Git - linux/commitdiff
btrfs: tree mod log vs zoned fix 2 from fdmanana tree-mod-test
authorZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Sat, 6 Mar 2021 14:31:03 +0000 (09:31 -0500)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Sat, 6 Mar 2021 14:44:41 +0000 (09:44 -0500)
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.

fs/btrfs/extent-tree.c

index b5f24bb879713af9be0a440908c2d4e3489ae5d4..d840a626e01d28bb9cf9f702e850b4fc599f657f 100644 (file)
@@ -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;\r
 
                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)) {
+               /*\r
+                * If there are tree mod log users, we may have recorded mog log\r
+                * operations on this extent buffer, so we can not add back this\r
+                * extent buffer to the free space cache/tree, because if it gets\r
+                * allocated and changed while there are mod log users, replaying\r
+                * the mod log operations will result in all sorts of unexpected\r
+                * results.\r
+                */\r
+               read_lock(&fs_info->tree_mod_log_lock);\r
+               have_mod_log_users = !list_empty(&fs_info->tree_mod_seq_list);\r
+               read_unlock(&fs_info->tree_mod_log_lock);\r
+\r
+               if (have_mod_log_users || btrfs_is_zoned(fs_info)) {\r
                        btrfs_redirty_list_add(trans->transaction, buf);
                        pin_down_extent(trans, cache, buf->start, buf->len, 1);
                        btrfs_put_block_group(cache);