OSDN Git Service

btrfs: output more debug messages for uncommitted transaction
authorQu Wenruo <wqu@suse.com>
Thu, 16 Dec 2021 11:47:36 +0000 (19:47 +0800)
committerDavid Sterba <dsterba@suse.com>
Fri, 7 Jan 2022 13:18:27 +0000 (14:18 +0100)
Print extra information about how many dirty bytes an uncommitted
has at the end of mount.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/disk-io.c

index 41dea24..87a5add 100644 (file)
@@ -4483,6 +4483,48 @@ int btrfs_commit_super(struct btrfs_fs_info *fs_info)
        return btrfs_commit_transaction(trans);
 }
 
+static void warn_about_uncommitted_trans(struct btrfs_fs_info *fs_info)
+{
+       struct btrfs_transaction *trans;
+       struct btrfs_transaction *tmp;
+       bool found = false;
+
+       if (list_empty(&fs_info->trans_list))
+               return;
+
+       /*
+        * This function is only called at the very end of close_ctree(),
+        * thus no other running transaction, no need to take trans_lock.
+        */
+       ASSERT(test_bit(BTRFS_FS_CLOSING_DONE, &fs_info->flags));
+       list_for_each_entry_safe(trans, tmp, &fs_info->trans_list, list) {
+               struct extent_state *cached = NULL;
+               u64 dirty_bytes = 0;
+               u64 cur = 0;
+               u64 found_start;
+               u64 found_end;
+
+               found = true;
+               while (!find_first_extent_bit(&trans->dirty_pages, cur,
+                       &found_start, &found_end, EXTENT_DIRTY, &cached)) {
+                       dirty_bytes += found_end + 1 - found_start;
+                       cur = found_end + 1;
+               }
+               btrfs_warn(fs_info,
+       "transaction %llu (with %llu dirty metadata bytes) is not committed",
+                          trans->transid, dirty_bytes);
+               btrfs_cleanup_one_transaction(trans, fs_info);
+
+               if (trans == fs_info->running_transaction)
+                       fs_info->running_transaction = NULL;
+               list_del_init(&trans->list);
+
+               btrfs_put_transaction(trans);
+               trace_btrfs_transaction_commit(fs_info);
+       }
+       ASSERT(!found);
+}
+
 void __cold close_ctree(struct btrfs_fs_info *fs_info)
 {
        int ret;
@@ -4591,7 +4633,7 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
        btrfs_stop_all_workers(fs_info);
 
        /* We shouldn't have any transaction open at this point */
-       ASSERT(list_empty(&fs_info->trans_list));
+       warn_about_uncommitted_trans(fs_info);
 
        clear_bit(BTRFS_FS_OPEN, &fs_info->flags);
        free_root_pointers(fs_info, true);