From: Greg Kroah-Hartman Date: Sun, 19 Oct 2014 23:11:48 +0000 (+0800) Subject: 3.10-stable patches X-Git-Tag: v3.10.59~42 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c59201a4b6a4e1e4bd25c62318cedb7a72554022;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch btrfs-fix-race-in-wait_sync-ioctl.patch btrfs-try-not-to-enospc-on-log-replay.patch --- diff --git a/queue-3.10/btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch b/queue-3.10/btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch new file mode 100644 index 00000000000..c6e6db33477 --- /dev/null +++ b/queue-3.10/btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch @@ -0,0 +1,63 @@ +From bbe9051441effce51c9a533d2c56440df64db2d7 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Fri, 19 Sep 2014 15:43:34 -0400 +Subject: Btrfs: fix build_backref_tree issue with multiple shared blocks + +From: Josef Bacik + +commit bbe9051441effce51c9a533d2c56440df64db2d7 upstream. + +Marc Merlin sent me a broken fs image months ago where it would blow up in the +upper->checked BUG_ON() in build_backref_tree. This is because we had a +scenario like this + +block a -- level 4 (not shared) + | +block b -- level 3 (reloc block, shared) + | +block c -- level 2 (not shared) + | +block d -- level 1 (shared) + | +block e -- level 0 (shared) + +We go to build a backref tree for block e, we notice block d is shared and add +it to the list of blocks to lookup it's backrefs for. Now when we loop around +we will check edges for the block, so we will see we looked up block c last +time. So we lookup block d and then see that the block that points to it is +block c and we can just skip that edge since we've already been up this path. +The problem is because we clear need_check when we see block d (as it is shared) +we never add block b as needing to be checked. And because block c is in our +path already we bail out before we walk up to block b and add it to the backref +check list. + +To fix this we need to reset need_check if we trip over a block that doesn't +need to be checked. This will make sure that any subsequent blocks in the path +as we're walking up afterwards are added to the list to be processed. With this +patch I can now mount Marc's fs image and it'll complete the balance without +panicing. Thanks, + +Reported-by: Marc MERLIN +Signed-off-by: Josef Bacik +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/relocation.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -967,8 +967,11 @@ again: + need_check = false; + list_add_tail(&edge->list[UPPER], + &list); +- } else ++ } else { ++ if (upper->checked) ++ need_check = true; + INIT_LIST_HEAD(&edge->list[UPPER]); ++ } + } else { + upper = rb_entry(rb_node, struct backref_node, + rb_node); diff --git a/queue-3.10/btrfs-fix-race-in-wait_sync-ioctl.patch b/queue-3.10/btrfs-fix-race-in-wait_sync-ioctl.patch new file mode 100644 index 00000000000..d40f4503fc8 --- /dev/null +++ b/queue-3.10/btrfs-fix-race-in-wait_sync-ioctl.patch @@ -0,0 +1,56 @@ +From 42383020beb1cfb05f5d330cc311931bc4917a97 Mon Sep 17 00:00:00 2001 +From: Sage Weil +Date: Fri, 26 Sep 2014 08:30:06 -0700 +Subject: Btrfs: fix race in WAIT_SYNC ioctl + +From: Sage Weil + +commit 42383020beb1cfb05f5d330cc311931bc4917a97 upstream. + +We check whether transid is already committed via last_trans_committed and +then search through trans_list for pending transactions. If +last_trans_committed is updated by btrfs_commit_transaction after we check +it (there is no locking), we will fail to find the committed transaction +and return EINVAL to the caller. This has been observed occasionally by +ceph-osd (which uses this ioctl heavily). + +Fix by rechecking whether the provided transid <= last_trans_committed +after the search fails, and if so return 0. + +Signed-off-by: Sage Weil +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/transaction.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -524,7 +524,6 @@ int btrfs_wait_for_commit(struct btrfs_r + if (transid <= root->fs_info->last_trans_committed) + goto out; + +- ret = -EINVAL; + /* find specified transaction */ + spin_lock(&root->fs_info->trans_lock); + list_for_each_entry(t, &root->fs_info->trans_list, list) { +@@ -540,9 +539,16 @@ int btrfs_wait_for_commit(struct btrfs_r + } + } + spin_unlock(&root->fs_info->trans_lock); +- /* The specified transaction doesn't exist */ +- if (!cur_trans) ++ ++ /* ++ * The specified transaction doesn't exist, or we ++ * raced with btrfs_commit_transaction ++ */ ++ if (!cur_trans) { ++ if (transid > root->fs_info->last_trans_committed) ++ ret = -EINVAL; + goto out; ++ } + } else { + /* find newest transaction that is committing | committed */ + spin_lock(&root->fs_info->trans_lock); diff --git a/queue-3.10/btrfs-try-not-to-enospc-on-log-replay.patch b/queue-3.10/btrfs-try-not-to-enospc-on-log-replay.patch new file mode 100644 index 00000000000..735b08ea819 --- /dev/null +++ b/queue-3.10/btrfs-try-not-to-enospc-on-log-replay.patch @@ -0,0 +1,40 @@ +From 1d52c78afbbf80b58299e076a159617d6b42fe3c Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Thu, 18 Sep 2014 11:30:44 -0400 +Subject: Btrfs: try not to ENOSPC on log replay + +From: Josef Bacik + +commit 1d52c78afbbf80b58299e076a159617d6b42fe3c upstream. + +When doing log replay we may have to update inodes, which traditionally goes +through our delayed inode stuff. This will try to move space over from the +trans handle, but we don't reserve space in our trans handle on replay since we +don't know how much we will need, so instead we try to flush. But because we +have a trans handle open we won't flush anything, so if we are out of reserve +space we will simply return ENOSPC. Since we know that if an operation made it +into the log then we definitely had space before the box bought the farm then we +don't need to worry about doing this space reservation. Use the +fs_info->log_root_recovering flag to skip the delayed inode stuff and update the +item directly. Thanks, + +Signed-off-by: Josef Bacik +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/inode.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -3545,7 +3545,8 @@ noinline int btrfs_update_inode(struct b + * without delay + */ + if (!btrfs_is_free_space_inode(inode) +- && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) { ++ && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID ++ && !root->fs_info->log_root_recovering) { + btrfs_update_root_times(trans, root); + + ret = btrfs_delayed_update_inode(trans, root, inode); diff --git a/queue-3.10/series b/queue-3.10/series index e69de29bb2d..e62c71d19e5 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -0,0 +1,3 @@ +btrfs-try-not-to-enospc-on-log-replay.patch +btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch +btrfs-fix-race-in-wait_sync-ioctl.patch