Patch "btrfs: fix races on root_log_ctx lists" has been added to the 4.4-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
btrfs: fix races on root_log_ctx lists
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
btrfs-fix-races-on-root_log_ctx-lists.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
570dd45042a7c8a7aba1ee029c5dd0f5ccf41b9bMon Sep 17 00:00:00 2001
From: Chris Mason <[email protected]>
Date: Thu, 27 Oct 2016 10:42:20 -0700
Subject: btrfs: fix races on root_log_ctx lists
From: Chris Mason <[email protected]>
commit 570dd45042a7c8a7aba1ee029c5dd0f5ccf41b9b upstream.
btrfs_remove_all_log_ctxs takes a shortcut where it avoids walking the list because it knows all of the waiters are patiently waiting for the commit to finish.
But, there's a small race where btrfs_sync_log can remove itself from the list if it finds a log commit is already done. Also, it uses list_del_init() to remove itself from the list, but there's no way to know if btrfs_remove_all_log_ctxs has already run, so we don't know for sure if it is safe to call list_del_init().
This gets rid of all the shortcuts for btrfs_remove_all_log_ctxs(), and just calls it with the proper locking.
This is part two of the corruption fixed by cbd60aa7cd1. I should have done this in the first place, but convinced myself the optimizations were safe. A 12 hour run of dbench 2048 will eventually trigger a list debug WARN_ON for the list_del_init() in btrfs_sync_log().
--- fs/btrfs/tree-log.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-)
fs/btrfs/tree-log.c +6 -14
@@ -2696,14 +2696,12 @@ static inline void btrfs_remove_all_log_ int index, int error) {struct btrfs_log_ctx *ctx; +struct btrfs_log_ctx *safe; -if (!error) { -INIT_LIST_HEAD (&root->log_ctxs[index]); -return ; - } - -list_for_each_entry (ctx, &root->log_ctxs[index], list) +list_for_each_entry_safe (ctx, safe, &root->log_ctxs[index], list) { +list_del_init (&ctx->list); ctx->log_ret = error; + }INIT_LIST_HEAD (&root->log_ctxs[index]); }
@@ -2944,13 +2942,9 @@ int btrfs_sync_log(struct btrfs_trans_hamutex_unlock (&root->log_mutex); out_wake_log_root: -/* -* We needn't get log_mutex here because we are sure all -* the other tasks are blocked. -*/ +mutex_lock (&log_root_tree->log_mutex);btrfs_remove_all_log_ctxs (log_root_tree, index2, ret); -mutex_lock (&log_root_tree->log_mutex); log_root_tree->log_transid_committed++;atomic_set (&log_root_tree->log_commit[index2],0 );mutex_unlock (&log_root_tree->log_mutex);
@@ -2961,10 +2955,8 @@ out_wake_log_root:if (waitqueue_active (&log_root_tree->log_commit_wait[index2]))wake_up (&log_root_tree->log_commit_wait[index2]); out: -/* See above. */ -btrfs_remove_all_log_ctxs (root, index1, ret); -mutex_lock (&root->log_mutex); +btrfs_remove_all_log_ctxs (root, index1, ret); root->log_transid_committed++;atomic_set (&root->log_commit[index1],0 );mutex_unlock (&root->log_mutex);
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/btrfs-fix-races-on-root_log_ctx-lists.patch