| From e100b9b1b6cf52334b8630a29050f9bbd6b4e6d1 Mon Sep 17 00:00:00 2001 |
| From: Filipe Manana <fdmanana@suse.com> |
| Date: Tue, 10 Mar 2020 12:13:53 +0000 |
| Subject: [PATCH] btrfs: fix log context list corruption after rename whiteout |
| error |
| |
| commit 236ebc20d9afc5e9ff52f3cf3f365a91583aac10 upstream. |
| |
| During a rename whiteout, if btrfs_whiteout_for_rename() returns an error |
| we can end up returning from btrfs_rename() with the log context object |
| still in the root's log context list - this happens if 'sync_log' was |
| set to true before we called btrfs_whiteout_for_rename() and it is |
| dangerous because we end up with a corrupt linked list (root->log_ctxs) |
| as the log context object was allocated on the stack. |
| |
| After btrfs_rename() returns, any task that is running btrfs_sync_log() |
| concurrently can end up crashing because that linked list is traversed by |
| btrfs_sync_log() (through btrfs_remove_all_log_ctxs()). That results in |
| the same issue that commit e6c617102c7e4 ("Btrfs: fix log context list |
| corruption after rename exchange operation") fixed. |
| |
| Fixes: d4682ba03ef618 ("Btrfs: sync log after logging new name") |
| CC: stable@vger.kernel.org # 4.19+ |
| Signed-off-by: Filipe Manana <fdmanana@suse.com> |
| Signed-off-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c |
| index ac6698bcd8ae..cba20e93d050 100644 |
| --- a/fs/btrfs/inode.c |
| +++ b/fs/btrfs/inode.c |
| @@ -10100,6 +10100,10 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, |
| ret = btrfs_sync_log(trans, BTRFS_I(old_inode)->root, &ctx); |
| if (ret) |
| commit_transaction = true; |
| + } else if (sync_log) { |
| + mutex_lock(&root->log_mutex); |
| + list_del(&ctx.list); |
| + mutex_unlock(&root->log_mutex); |
| } |
| if (commit_transaction) { |
| ret = btrfs_commit_transaction(trans); |
| -- |
| 2.7.4 |
| |