]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.16-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 19 Oct 2014 23:11:58 +0000 (07:11 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 19 Oct 2014 23:11:58 +0000 (07:11 +0800)
added patches:
btrfs-add-missing-compression-property-remove-in-btrfs_ioctl_setflags.patch
btrfs-cleanup-error-handling-in-build_backref_tree.patch
btrfs-don-t-do-async-reclaim-during-log-replay.patch
btrfs-fix-a-deadlock-in-btrfs_dev_replace_finishing.patch
btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch
btrfs-fix-race-in-wait_sync-ioctl.patch
btrfs-fix-up-bounds-checking-in-lseek.patch
btrfs-try-not-to-enospc-on-log-replay.patch
btrfs-wake-up-transaction-thread-from-sync_fs-ioctl.patch

queue-3.16/btrfs-add-missing-compression-property-remove-in-btrfs_ioctl_setflags.patch [new file with mode: 0644]
queue-3.16/btrfs-cleanup-error-handling-in-build_backref_tree.patch [new file with mode: 0644]
queue-3.16/btrfs-don-t-do-async-reclaim-during-log-replay.patch [new file with mode: 0644]
queue-3.16/btrfs-fix-a-deadlock-in-btrfs_dev_replace_finishing.patch [new file with mode: 0644]
queue-3.16/btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch [new file with mode: 0644]
queue-3.16/btrfs-fix-race-in-wait_sync-ioctl.patch [new file with mode: 0644]
queue-3.16/btrfs-fix-up-bounds-checking-in-lseek.patch [new file with mode: 0644]
queue-3.16/btrfs-try-not-to-enospc-on-log-replay.patch [new file with mode: 0644]
queue-3.16/btrfs-wake-up-transaction-thread-from-sync_fs-ioctl.patch [new file with mode: 0644]
queue-3.16/series

diff --git a/queue-3.16/btrfs-add-missing-compression-property-remove-in-btrfs_ioctl_setflags.patch b/queue-3.16/btrfs-add-missing-compression-property-remove-in-btrfs_ioctl_setflags.patch
new file mode 100644 (file)
index 0000000..bad832e
--- /dev/null
@@ -0,0 +1,53 @@
+From 78a017a2c92df9b571db0a55a016280f9019c65e Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Thu, 11 Sep 2014 11:44:49 +0100
+Subject: Btrfs: add missing compression property remove in btrfs_ioctl_setflags
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 78a017a2c92df9b571db0a55a016280f9019c65e upstream.
+
+The behaviour of a 'chattr -c' consists of getting the current flags,
+clearing the FS_COMPR_FL bit and then sending the result to the set
+flags ioctl - this means the bit FS_NOCOMP_FL isn't set in the flags
+passed to the ioctl. This results in the compression property not being
+cleared from the inode - it was cleared only if the bit FS_NOCOMP_FL
+was set in the received flags.
+
+Reproducer:
+
+    $ mkfs.btrfs -f /dev/sdd
+    $ mount /dev/sdd /mnt && cd /mnt
+    $ mkdir a
+    $ chattr +c a
+    $ touch a/file
+    $ lsattr a/file
+    --------c------- a/file
+    $ chattr -c a
+    $ touch a/file2
+    $ lsattr a/file2
+    --------c------- a/file2
+    $ lsattr -d a
+    ---------------- a
+
+Reported-by: Andreas Schneider <asn@cryptomilk.org>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Chris Mason <clm@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/ioctl.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -332,6 +332,9 @@ static int btrfs_ioctl_setflags(struct f
+                       goto out_drop;
+       } else {
++              ret = btrfs_set_prop(inode, "btrfs.compression", NULL, 0, 0);
++              if (ret && ret != -ENODATA)
++                      goto out_drop;
+               ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
+       }
diff --git a/queue-3.16/btrfs-cleanup-error-handling-in-build_backref_tree.patch b/queue-3.16/btrfs-cleanup-error-handling-in-build_backref_tree.patch
new file mode 100644 (file)
index 0000000..66eb500
--- /dev/null
@@ -0,0 +1,215 @@
+From 75bfb9aff45e44625260f52a5fd581b92ace3e62 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fb.com>
+Date: Fri, 19 Sep 2014 10:40:00 -0400
+Subject: Btrfs: cleanup error handling in build_backref_tree
+
+From: Josef Bacik <jbacik@fb.com>
+
+commit 75bfb9aff45e44625260f52a5fd581b92ace3e62 upstream.
+
+When balance panics it tends to panic in the
+
+BUG_ON(!upper->checked);
+
+test, because it means it couldn't build the backref tree properly.  This is
+annoying to users and frankly a recoverable error, nothing in this function is
+actually fatal since it is just an in-memory building of the backrefs for a
+given bytenr.  So go through and change all the BUG_ON()'s to ASSERT()'s, and
+fix the BUG_ON(!upper->checked) thing to just return an error.
+
+This patch also fixes the error handling so it tears down the work we've done
+properly.  This code was horribly broken since we always just panic'ed instead
+of actually erroring out, so it needed to be completely re-worked.  With this
+patch my broken image no longer panics when I mount it.  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/relocation.c |   88 +++++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 59 insertions(+), 29 deletions(-)
+
+--- a/fs/btrfs/relocation.c
++++ b/fs/btrfs/relocation.c
+@@ -736,7 +736,8 @@ again:
+               err = ret;
+               goto out;
+       }
+-      BUG_ON(!ret || !path1->slots[0]);
++      ASSERT(ret);
++      ASSERT(path1->slots[0]);
+       path1->slots[0]--;
+@@ -746,10 +747,10 @@ again:
+                * the backref was added previously when processing
+                * backref of type BTRFS_TREE_BLOCK_REF_KEY
+                */
+-              BUG_ON(!list_is_singular(&cur->upper));
++              ASSERT(list_is_singular(&cur->upper));
+               edge = list_entry(cur->upper.next, struct backref_edge,
+                                 list[LOWER]);
+-              BUG_ON(!list_empty(&edge->list[UPPER]));
++              ASSERT(list_empty(&edge->list[UPPER]));
+               exist = edge->node[UPPER];
+               /*
+                * add the upper level block to pending list if we need
+@@ -831,7 +832,7 @@ again:
+                                       cur->cowonly = 1;
+                       }
+ #else
+-              BUG_ON(key.type == BTRFS_EXTENT_REF_V0_KEY);
++              ASSERT(key.type != BTRFS_EXTENT_REF_V0_KEY);
+               if (key.type == BTRFS_SHARED_BLOCK_REF_KEY) {
+ #endif
+                       if (key.objectid == key.offset) {
+@@ -840,7 +841,7 @@ again:
+                                * backref of this type.
+                                */
+                               root = find_reloc_root(rc, cur->bytenr);
+-                              BUG_ON(!root);
++                              ASSERT(root);
+                               cur->root = root;
+                               break;
+                       }
+@@ -868,7 +869,7 @@ again:
+                       } else {
+                               upper = rb_entry(rb_node, struct backref_node,
+                                                rb_node);
+-                              BUG_ON(!upper->checked);
++                              ASSERT(upper->checked);
+                               INIT_LIST_HEAD(&edge->list[UPPER]);
+                       }
+                       list_add_tail(&edge->list[LOWER], &cur->upper);
+@@ -892,7 +893,7 @@ again:
+               if (btrfs_root_level(&root->root_item) == cur->level) {
+                       /* tree root */
+-                      BUG_ON(btrfs_root_bytenr(&root->root_item) !=
++                      ASSERT(btrfs_root_bytenr(&root->root_item) ==
+                              cur->bytenr);
+                       if (should_ignore_root(root))
+                               list_add(&cur->list, &useless);
+@@ -927,7 +928,7 @@ again:
+               need_check = true;
+               for (; level < BTRFS_MAX_LEVEL; level++) {
+                       if (!path2->nodes[level]) {
+-                              BUG_ON(btrfs_root_bytenr(&root->root_item) !=
++                              ASSERT(btrfs_root_bytenr(&root->root_item) ==
+                                      lower->bytenr);
+                               if (should_ignore_root(root))
+                                       list_add(&lower->list, &useless);
+@@ -982,7 +983,7 @@ again:
+                       } else {
+                               upper = rb_entry(rb_node, struct backref_node,
+                                                rb_node);
+-                              BUG_ON(!upper->checked);
++                              ASSERT(upper->checked);
+                               INIT_LIST_HEAD(&edge->list[UPPER]);
+                               if (!upper->owner)
+                                       upper->owner = btrfs_header_owner(eb);
+@@ -1026,7 +1027,7 @@ next:
+        * everything goes well, connect backref nodes and insert backref nodes
+        * into the cache.
+        */
+-      BUG_ON(!node->checked);
++      ASSERT(node->checked);
+       cowonly = node->cowonly;
+       if (!cowonly) {
+               rb_node = tree_insert(&cache->rb_root, node->bytenr,
+@@ -1062,8 +1063,21 @@ next:
+                       continue;
+               }
+-              BUG_ON(!upper->checked);
+-              BUG_ON(cowonly != upper->cowonly);
++              if (!upper->checked) {
++                      /*
++                       * Still want to blow up for developers since this is a
++                       * logic bug.
++                       */
++                      ASSERT(0);
++                      err = -EINVAL;
++                      goto out;
++              }
++              if (cowonly != upper->cowonly) {
++                      ASSERT(0);
++                      err = -EINVAL;
++                      goto out;
++              }
++
+               if (!cowonly) {
+                       rb_node = tree_insert(&cache->rb_root, upper->bytenr,
+                                             &upper->rb_node);
+@@ -1086,7 +1100,7 @@ next:
+       while (!list_empty(&useless)) {
+               upper = list_entry(useless.next, struct backref_node, list);
+               list_del_init(&upper->list);
+-              BUG_ON(!list_empty(&upper->upper));
++              ASSERT(list_empty(&upper->upper));
+               if (upper == node)
+                       node = NULL;
+               if (upper->lowest) {
+@@ -1119,29 +1133,45 @@ out:
+       if (err) {
+               while (!list_empty(&useless)) {
+                       lower = list_entry(useless.next,
+-                                         struct backref_node, upper);
+-                      list_del_init(&lower->upper);
++                                         struct backref_node, list);
++                      list_del_init(&lower->list);
+               }
+-              upper = node;
+-              INIT_LIST_HEAD(&list);
+-              while (upper) {
+-                      if (RB_EMPTY_NODE(&upper->rb_node)) {
+-                              list_splice_tail(&upper->upper, &list);
+-                              free_backref_node(cache, upper);
+-                      }
+-
+-                      if (list_empty(&list))
+-                              break;
+-
+-                      edge = list_entry(list.next, struct backref_edge,
+-                                        list[LOWER]);
++              while (!list_empty(&list)) {
++                      edge = list_first_entry(&list, struct backref_edge,
++                                              list[UPPER]);
++                      list_del(&edge->list[UPPER]);
+                       list_del(&edge->list[LOWER]);
++                      lower = edge->node[LOWER];
+                       upper = edge->node[UPPER];
+                       free_backref_edge(cache, edge);
++
++                      /*
++                       * Lower is no longer linked to any upper backref nodes
++                       * and isn't in the cache, we can free it ourselves.
++                       */
++                      if (list_empty(&lower->upper) &&
++                          RB_EMPTY_NODE(&lower->rb_node))
++                              list_add(&lower->list, &useless);
++
++                      if (!RB_EMPTY_NODE(&upper->rb_node))
++                              continue;
++
++                      /* Add this guy's upper edges to the list to proces */
++                      list_for_each_entry(edge, &upper->upper, list[LOWER])
++                              list_add_tail(&edge->list[UPPER], &list);
++                      if (list_empty(&upper->upper))
++                              list_add(&upper->list, &useless);
++              }
++
++              while (!list_empty(&useless)) {
++                      lower = list_entry(useless.next,
++                                         struct backref_node, list);
++                      list_del_init(&lower->list);
++                      free_backref_node(cache, lower);
+               }
+               return ERR_PTR(err);
+       }
+-      BUG_ON(node && node->detached);
++      ASSERT(!node || !node->detached);
+       return node;
+ }
diff --git a/queue-3.16/btrfs-don-t-do-async-reclaim-during-log-replay.patch b/queue-3.16/btrfs-don-t-do-async-reclaim-during-log-replay.patch
new file mode 100644 (file)
index 0000000..44c7c8e
--- /dev/null
@@ -0,0 +1,39 @@
+From f6acfd50110b335c7af636cf1fc8e55319cae5fc Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fb.com>
+Date: Thu, 18 Sep 2014 11:27:17 -0400
+Subject: Btrfs: don't do async reclaim during log replay
+
+From: Josef Bacik <jbacik@fb.com>
+
+commit f6acfd50110b335c7af636cf1fc8e55319cae5fc upstream.
+
+Trying to reproduce a log enospc bug I hit a panic in the async reclaim code
+during log replay.  This is because we use fs_info->fs_root as our root for
+shrinking and such.  Technically we can use whatever root we want, but let's
+just not allow async reclaim while we're doing log replay.  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/extent-tree.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -4508,7 +4508,13 @@ again:
+               space_info->flush = 1;
+       } else if (!ret && space_info->flags & BTRFS_BLOCK_GROUP_METADATA) {
+               used += orig_bytes;
+-              if (need_do_async_reclaim(space_info, root->fs_info, used) &&
++              /*
++               * We will do the space reservation dance during log replay,
++               * which means we won't have fs_info->fs_root set, so don't do
++               * the async reclaim as we will panic.
++               */
++              if (!root->fs_info->log_root_recovering &&
++                  need_do_async_reclaim(space_info, root->fs_info, used) &&
+                   !work_busy(&root->fs_info->async_reclaim_work))
+                       queue_work(system_unbound_wq,
+                                  &root->fs_info->async_reclaim_work);
diff --git a/queue-3.16/btrfs-fix-a-deadlock-in-btrfs_dev_replace_finishing.patch b/queue-3.16/btrfs-fix-a-deadlock-in-btrfs_dev_replace_finishing.patch
new file mode 100644 (file)
index 0000000..c131540
--- /dev/null
@@ -0,0 +1,67 @@
+From 12b894cb288d57292b01cf158177b6d5c89a6272 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <quwenruo@cn.fujitsu.com>
+Date: Wed, 20 Aug 2014 16:10:15 +0800
+Subject: btrfs: Fix a deadlock in btrfs_dev_replace_finishing()
+
+From: Qu Wenruo <quwenruo@cn.fujitsu.com>
+
+commit 12b894cb288d57292b01cf158177b6d5c89a6272 upstream.
+
+btrfs-transacion:5657
+[stack snip]
+btrfs_bio_map()
+    btrfs_bio_counter_inc_blocked()
+        percpu_counter_inc(&fs_info->bio_counter)  ###bio_counter > 0(A)
+        __btrfs_bio_map()
+            btrfs_dev_replace_lock()
+                mutex_lock(dev_replace->lock)     ###wait mutex(B)
+
+btrfs:32612
+[stack snip]
+btrfs_dev_replace_start()
+    btrfs_dev_replace_lock()
+       mutex_lock(dev_replace->lock)              ###hold mutex(B)
+    btrfs_dev_replace_finishing()
+        btrfs_rm_dev_replace_blocked()
+            wait until percpu_counter_sum == 0    ###wait on bio_counter(A)
+
+This bug can be triggered quite easily by the following test script:
+http://pastebin.com/MQmb37Cy
+
+This patch will fix the ABBA problem by calling
+btrfs_dev_replace_unlock() before btrfs_rm_dev_replace_blocked().
+
+The consistency of btrfs devices list and their superblocks is protected
+by device_list_mutex, not btrfs_dev_replace_lock/unlock().
+So it is safe the move btrfs_dev_replace_unlock() before
+btrfs_rm_dev_replace_blocked().
+
+Reported-by: Zhao Lei <zhaolei@cn.fujitsu.com>
+Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
+Cc: Stefan Behrens <sbehrens@giantdisaster.de>
+Signed-off-by: Chris Mason <clm@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/dev-replace.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/btrfs/dev-replace.c
++++ b/fs/btrfs/dev-replace.c
+@@ -567,6 +567,8 @@ static int btrfs_dev_replace_finishing(s
+       btrfs_kobj_rm_device(fs_info, src_device);
+       btrfs_kobj_add_device(fs_info, tgt_device);
++      btrfs_dev_replace_unlock(dev_replace);
++
+       btrfs_rm_dev_replace_blocked(fs_info);
+       btrfs_rm_dev_replace_srcdev(fs_info, src_device);
+@@ -580,7 +582,6 @@ static int btrfs_dev_replace_finishing(s
+        * superblock is scratched out so that it is no longer marked to
+        * belong to this filesystem.
+        */
+-      btrfs_dev_replace_unlock(dev_replace);
+       mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
+       mutex_unlock(&root->fs_info->chunk_mutex);
diff --git a/queue-3.16/btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch b/queue-3.16/btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch
new file mode 100644 (file)
index 0000000..3f5d12e
--- /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
+@@ -978,8 +978,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.16/btrfs-fix-race-in-wait_sync-ioctl.patch b/queue-3.16/btrfs-fix-race-in-wait_sync-ioctl.patch
new file mode 100644 (file)
index 0000000..dc00af6
--- /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
+@@ -609,7 +609,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) {
+@@ -625,9 +624,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.16/btrfs-fix-up-bounds-checking-in-lseek.patch b/queue-3.16/btrfs-fix-up-bounds-checking-in-lseek.patch
new file mode 100644 (file)
index 0000000..f3eab46
--- /dev/null
@@ -0,0 +1,88 @@
+From 4d1a40c66bed0b3fa43b9da5fbd5cbe332e4eccf Mon Sep 17 00:00:00 2001
+From: Liu Bo <bo.li.liu@oracle.com>
+Date: Tue, 16 Sep 2014 17:49:30 +0800
+Subject: Btrfs: fix up bounds checking in lseek
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Liu Bo <bo.li.liu@oracle.com>
+
+commit 4d1a40c66bed0b3fa43b9da5fbd5cbe332e4eccf upstream.
+
+An user reported this, it is because that lseek's SEEK_SET/SEEK_CUR/SEEK_END
+allow a negative value for @offset, but btrfs's SEEK_DATA/SEEK_HOLE don't
+prepare for that and convert the negative @offset into unsigned type,
+so we get (end < start) warning.
+
+[ 1269.835374] ------------[ cut here ]------------
+[ 1269.836809] WARNING: CPU: 0 PID: 1241 at fs/btrfs/extent_io.c:430 insert_state+0x11d/0x140()
+[ 1269.838816] BTRFS: end < start 4094 18446744073709551615
+[ 1269.840334] CPU: 0 PID: 1241 Comm: a.out Tainted: G        W      3.16.0+ #306
+[ 1269.858229] Call Trace:
+[ 1269.858612]  [<ffffffff81801a69>] dump_stack+0x4e/0x68
+[ 1269.858952]  [<ffffffff8107894c>] warn_slowpath_common+0x8c/0xc0
+[ 1269.859416]  [<ffffffff81078a36>] warn_slowpath_fmt+0x46/0x50
+[ 1269.859929]  [<ffffffff813b0fbd>] insert_state+0x11d/0x140
+[ 1269.860409]  [<ffffffff813b1396>] __set_extent_bit+0x3b6/0x4e0
+[ 1269.860805]  [<ffffffff813b21c7>] lock_extent_bits+0x87/0x200
+[ 1269.861697]  [<ffffffff813a5b28>] btrfs_file_llseek+0x148/0x2a0
+[ 1269.862168]  [<ffffffff811f201e>] SyS_lseek+0xae/0xc0
+[ 1269.862620]  [<ffffffff8180b212>] system_call_fastpath+0x16/0x1b
+[ 1269.862970] ---[ end trace 4d33ea885832054b ]---
+
+This assumes that btrfs starts finding DATA/HOLE from the beginning of file
+if the assigned @offset is negative.
+
+Also we add alignment for lock_extent_bits 's range.
+
+Reported-by: Toralf Förster <toralf.foerster@gmx.de>
+Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
+Signed-off-by: Chris Mason <clm@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/file.c |   25 +++++++++++++++----------
+ 1 file changed, 15 insertions(+), 10 deletions(-)
+
+--- a/fs/btrfs/file.c
++++ b/fs/btrfs/file.c
+@@ -2622,23 +2622,28 @@ static int find_desired_extent(struct in
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct extent_map *em = NULL;
+       struct extent_state *cached_state = NULL;
+-      u64 lockstart = *offset;
+-      u64 lockend = i_size_read(inode);
+-      u64 start = *offset;
+-      u64 len = i_size_read(inode);
++      u64 lockstart;
++      u64 lockend;
++      u64 start;
++      u64 len;
+       int ret = 0;
+-      lockend = max_t(u64, root->sectorsize, lockend);
++      if (inode->i_size == 0)
++              return -ENXIO;
++
++      /*
++       * *offset can be negative, in this case we start finding DATA/HOLE from
++       * the very start of the file.
++       */
++      start = max_t(loff_t, 0, *offset);
++
++      lockstart = round_down(start, root->sectorsize);
++      lockend = round_up(i_size_read(inode), root->sectorsize);
+       if (lockend <= lockstart)
+               lockend = lockstart + root->sectorsize;
+-
+       lockend--;
+       len = lockend - lockstart + 1;
+-      len = max_t(u64, len, root->sectorsize);
+-      if (inode->i_size == 0)
+-              return -ENXIO;
+-
+       lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend, 0,
+                        &cached_state);
diff --git a/queue-3.16/btrfs-try-not-to-enospc-on-log-replay.patch b/queue-3.16/btrfs-try-not-to-enospc-on-log-replay.patch
new file mode 100644 (file)
index 0000000..70c621c
--- /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
+@@ -3656,7 +3656,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.16/btrfs-wake-up-transaction-thread-from-sync_fs-ioctl.patch b/queue-3.16/btrfs-wake-up-transaction-thread-from-sync_fs-ioctl.patch
new file mode 100644 (file)
index 0000000..f7cdc1f
--- /dev/null
@@ -0,0 +1,39 @@
+From 2fad4e83e12591eb3bd213875b9edc2d18e93383 Mon Sep 17 00:00:00 2001
+From: David Sterba <dsterba@suse.cz>
+Date: Wed, 23 Jul 2014 14:39:35 +0200
+Subject: btrfs: wake up transaction thread from SYNC_FS ioctl
+
+From: David Sterba <dsterba@suse.cz>
+
+commit 2fad4e83e12591eb3bd213875b9edc2d18e93383 upstream.
+
+The transaction thread may want to do more work, namely it pokes the
+cleaner ktread that will start processing uncleaned subvols.
+
+This can be triggered by user via the 'btrfs fi sync' command, otherwise
+there was a delay up to 30 seconds before the cleaner started to clean
+old snapshots.
+
+Signed-off-by: David Sterba <dsterba@suse.cz>
+Signed-off-by: Chris Mason <clm@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/ioctl.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -5309,6 +5309,12 @@ long btrfs_ioctl(struct file *file, unsi
+               if (ret)
+                       return ret;
+               ret = btrfs_sync_fs(file->f_dentry->d_sb, 1);
++              /*
++               * The transaction thread may want to do more work,
++               * namely it pokes the cleaner ktread that will start
++               * processing uncleaned subvols.
++               */
++              wake_up_process(root->fs_info->transaction_kthread);
+               return ret;
+       }
+       case BTRFS_IOC_START_SYNC:
index 19607c0b9adce49b31b04b7f4685187e48d51453..d70c95e8b70acd7c390054cc0ddce15c8ac72143 100644 (file)
@@ -1 +1,9 @@
 btrfs-wake-up-transaction-thread-from-sync_fs-ioctl.patch
+btrfs-fix-a-deadlock-in-btrfs_dev_replace_finishing.patch
+btrfs-add-missing-compression-property-remove-in-btrfs_ioctl_setflags.patch
+btrfs-fix-up-bounds-checking-in-lseek.patch
+btrfs-don-t-do-async-reclaim-during-log-replay.patch
+btrfs-try-not-to-enospc-on-log-replay.patch
+btrfs-cleanup-error-handling-in-build_backref_tree.patch
+btrfs-fix-build_backref_tree-issue-with-multiple-shared-blocks.patch
+btrfs-fix-race-in-wait_sync-ioctl.patch