Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

btrfs: fix deadlock in delayed_ref_async_start

"Btrfs: track transid for delayed ref flushing" was deadlocking on
btrfs_attach_transaction because its not safe to call from the async
delayed ref start code. This commit brings back btrfs_join_transaction
instead and checks for a blocked commit.

Signed-off-by: Josef Bacik <jbacik@fb.com>
Signed-off-by: Chris Mason <clm@fb.com>

+11 -9
+11 -9
fs/btrfs/extent-tree.c
··· 2851 2851 2852 2852 async = container_of(work, struct async_delayed_refs, work); 2853 2853 2854 - trans = btrfs_attach_transaction(async->root); 2855 - if (IS_ERR(trans)) { 2856 - if (PTR_ERR(trans) != -ENOENT) 2857 - async->error = PTR_ERR(trans); 2854 + /* if the commit is already started, we don't need to wait here */ 2855 + if (btrfs_transaction_blocked(async->root->fs_info)) 2858 2856 goto done; 2859 - } 2860 2857 2861 - /* Don't bother flushing if we got into a different transaction */ 2862 - if (trans->transid != async->transid) { 2863 - btrfs_end_transaction(trans, async->root); 2858 + trans = btrfs_join_transaction(async->root); 2859 + if (IS_ERR(trans)) { 2860 + async->error = PTR_ERR(trans); 2864 2861 goto done; 2865 2862 } 2866 2863 ··· 2866 2869 * wait on delayed refs 2867 2870 */ 2868 2871 trans->sync = true; 2872 + 2873 + /* Don't bother flushing if we got into a different transaction */ 2874 + if (trans->transid > async->transid) 2875 + goto end; 2876 + 2869 2877 ret = btrfs_run_delayed_refs(trans, async->root, async->count); 2870 2878 if (ret) 2871 2879 async->error = ret; 2872 - 2880 + end: 2873 2881 ret = btrfs_end_transaction(trans, async->root); 2874 2882 if (ret && !async->error) 2875 2883 async->error = ret;