]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 19 Oct 2014 23:11:48 +0000 (07:11 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 19 Oct 2014 23:11:48 +0000 (07:11 +0800)
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

queue-3.10/btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch [new file with mode: 0644]
queue-3.10/btrfs-fix-race-in-wait_sync-ioctl.patch [new file with mode: 0644]
queue-3.10/btrfs-try-not-to-enospc-on-log-replay.patch [new file with mode: 0644]
queue-3.10/series

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 (file)
index 0000000..c6e6db3
--- /dev/null
@@ -0,0 +1,63 @@
+From bbe9051441effce51c9a533d2c56440df64db2d7 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fb.com>
+Date: Fri, 19 Sep 2014 15:43:34 -0400
+Subject: Btrfs: fix build_backref_tree issue with multiple shared blocks
+
+From: Josef Bacik <jbacik@fb.com>
+
+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 <marc@merlins.org>
+Signed-off-by: Josef Bacik <jbacik@fb.com>
+Signed-off-by: Chris Mason <clm@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..d40f450
--- /dev/null
@@ -0,0 +1,56 @@
+From 42383020beb1cfb05f5d330cc311931bc4917a97 Mon Sep 17 00:00:00 2001
+From: Sage Weil <sage@redhat.com>
+Date: Fri, 26 Sep 2014 08:30:06 -0700
+Subject: Btrfs: fix race in WAIT_SYNC ioctl
+
+From: Sage Weil <sage@redhat.com>
+
+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 <sage@redhat.com>
+Signed-off-by: Chris Mason <clm@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..735b08e
--- /dev/null
@@ -0,0 +1,40 @@
+From 1d52c78afbbf80b58299e076a159617d6b42fe3c Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fb.com>
+Date: Thu, 18 Sep 2014 11:30:44 -0400
+Subject: Btrfs: try not to ENOSPC on log replay
+
+From: Josef Bacik <jbacik@fb.com>
+
+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 <jbacik@fb.com>
+Signed-off-by: Chris Mason <clm@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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);
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e62c71d19e5ab1d056eb15b578ad17b85704fb7d 100644 (file)
@@ -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