]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.2-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 12 Dec 2015 19:46:45 +0000 (11:46 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 12 Dec 2015 19:46:45 +0000 (11:46 -0800)
added patches:
btrfs-fix-regression-running-delayed-references-when-using-qgroups.patch

queue-4.2/btrfs-fix-regression-running-delayed-references-when-using-qgroups.patch [new file with mode: 0644]
queue-4.2/ext4-crypto-fix-bugs-in-ext4_encrypted_zeroout.patch [deleted file]
queue-4.2/series

diff --git a/queue-4.2/btrfs-fix-regression-running-delayed-references-when-using-qgroups.patch b/queue-4.2/btrfs-fix-regression-running-delayed-references-when-using-qgroups.patch
new file mode 100644 (file)
index 0000000..221f17f
--- /dev/null
@@ -0,0 +1,832 @@
+From b06c4bf5c874a57254b197f53ddf588e7a24a2bf Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Fri, 23 Oct 2015 07:52:54 +0100
+Subject: Btrfs: fix regression running delayed references when using qgroups
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit b06c4bf5c874a57254b197f53ddf588e7a24a2bf upstream.
+
+In the kernel 4.2 merge window we had a big changes to the implementation
+of delayed references and qgroups which made the no_quota field of delayed
+references not used anymore. More specifically the no_quota field is not
+used anymore as of:
+
+  commit 0ed4792af0e8 ("btrfs: qgroup: Switch to new extent-oriented qgroup mechanism.")
+
+Leaving the no_quota field actually prevents delayed references from
+getting merged, which in turn cause the following BUG_ON(), at
+fs/btrfs/extent-tree.c, to be hit when qgroups are enabled:
+
+  static int run_delayed_tree_ref(...)
+  {
+     (...)
+     BUG_ON(node->ref_mod != 1);
+     (...)
+  }
+
+This happens on a scenario like the following:
+
+  1) Ref1 bytenr X, action = BTRFS_ADD_DELAYED_REF, no_quota = 1, added.
+
+  2) Ref2 bytenr X, action = BTRFS_DROP_DELAYED_REF, no_quota = 0, added.
+     It's not merged with Ref1 because Ref1->no_quota != Ref2->no_quota.
+
+  3) Ref3 bytenr X, action = BTRFS_ADD_DELAYED_REF, no_quota = 1, added.
+     It's not merged with the reference at the tail of the list of refs
+     for bytenr X because the reference at the tail, Ref2 is incompatible
+     due to Ref2->no_quota != Ref3->no_quota.
+
+  4) Ref4 bytenr X, action = BTRFS_DROP_DELAYED_REF, no_quota = 0, added.
+     It's not merged with the reference at the tail of the list of refs
+     for bytenr X because the reference at the tail, Ref3 is incompatible
+     due to Ref3->no_quota != Ref4->no_quota.
+
+  5) We run delayed references, trigger merging of delayed references,
+     through __btrfs_run_delayed_refs() -> btrfs_merge_delayed_refs().
+
+  6) Ref1 and Ref3 are merged as Ref1->no_quota = Ref3->no_quota and
+     all other conditions are satisfied too. So Ref1 gets a ref_mod
+     value of 2.
+
+  7) Ref2 and Ref4 are merged as Ref2->no_quota = Ref4->no_quota and
+     all other conditions are satisfied too. So Ref2 gets a ref_mod
+     value of 2.
+
+  8) Ref1 and Ref2 aren't merged, because they have different values
+     for their no_quota field.
+
+  9) Delayed reference Ref1 is picked for running (select_delayed_ref()
+     always prefers references with an action == BTRFS_ADD_DELAYED_REF).
+     So run_delayed_tree_ref() is called for Ref1 which triggers the
+     BUG_ON because Ref1->red_mod != 1 (equals 2).
+
+So fix this by removing the no_quota field, as it's not used anymore as
+of commit 0ed4792af0e8 ("btrfs: qgroup: Switch to new extent-oriented
+qgroup mechanism.").
+
+The use of no_quota was also buggy in at least two places:
+
+1) At delayed-refs.c:btrfs_add_delayed_tree_ref() - we were setting
+   no_quota to 0 instead of 1 when the following condition was true:
+   is_fstree(ref_root) || !fs_info->quota_enabled
+
+2) At extent-tree.c:__btrfs_inc_extent_ref() - we were attempting to
+   reset a node's no_quota when the condition "!is_fstree(root_objectid)
+   || !root->fs_info->quota_enabled" was true but we did it only in
+   an unused local stack variable, that is, we never reset the no_quota
+   value in the node itself.
+
+This fixes the remainder of problems several people have been having when
+running delayed references, mostly while a balance is running in parallel,
+on a 4.2+ kernel.
+
+Very special thanks to Stéphane Lesimple for helping debugging this issue
+and testing this fix on his multi terabyte filesystem (which took more
+than one day to balance alone, plus fsck, etc).
+
+Also, this fixes deadlock issue when using the clone ioctl with qgroups
+enabled, as reported by Elias Probst in the mailing list. The deadlock
+happens because after calling btrfs_insert_empty_item we have our path
+holding a write lock on a leaf of the fs/subvol tree and then before
+releasing the path we called check_ref() which did backref walking, when
+qgroups are enabled, and tried to read lock the same leaf. The trace for
+this case is the following:
+
+  INFO: task systemd-nspawn:6095 blocked for more than 120 seconds.
+  (...)
+  Call Trace:
+    [<ffffffff86999201>] schedule+0x74/0x83
+    [<ffffffff863ef64c>] btrfs_tree_read_lock+0xc0/0xea
+    [<ffffffff86137ed7>] ? wait_woken+0x74/0x74
+    [<ffffffff8639f0a7>] btrfs_search_old_slot+0x51a/0x810
+    [<ffffffff863a129b>] btrfs_next_old_leaf+0xdf/0x3ce
+    [<ffffffff86413a00>] ? ulist_add_merge+0x1b/0x127
+    [<ffffffff86411688>] __resolve_indirect_refs+0x62a/0x667
+    [<ffffffff863ef546>] ? btrfs_clear_lock_blocking_rw+0x78/0xbe
+    [<ffffffff864122d3>] find_parent_nodes+0xaf3/0xfc6
+    [<ffffffff86412838>] __btrfs_find_all_roots+0x92/0xf0
+    [<ffffffff864128f2>] btrfs_find_all_roots+0x45/0x65
+    [<ffffffff8639a75b>] ? btrfs_get_tree_mod_seq+0x2b/0x88
+    [<ffffffff863e852e>] check_ref+0x64/0xc4
+    [<ffffffff863e9e01>] btrfs_clone+0x66e/0xb5d
+    [<ffffffff863ea77f>] btrfs_ioctl_clone+0x48f/0x5bb
+    [<ffffffff86048a68>] ? native_sched_clock+0x28/0x77
+    [<ffffffff863ed9b0>] btrfs_ioctl+0xabc/0x25cb
+  (...)
+
+The problem goes away by eleminating check_ref(), which no longer is
+needed as its purpose was to get a value for the no_quota field of
+a delayed reference (this patch removes the no_quota field as mentioned
+earlier).
+
+Reported-by: Stéphane Lesimple <stephane_btrfs@lesimple.fr>
+Tested-by: Stéphane Lesimple <stephane_btrfs@lesimple.fr>
+Reported-by: Elias Probst <mail@eliasprobst.eu>
+Reported-by: Peter Becker <floyd.net@gmail.com>
+Reported-by: Malte Schröder <malte@tnxip.de>
+Reported-by: Derek Dongray <derek@valedon.co.uk>
+Reported-by: Erkki Seppala <flux-btrfs@inside.org>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/ctree.h       |    4 -
+ fs/btrfs/delayed-ref.c |  139 ++++++++++++++++++++++++++++++++++++++++++-------
+ fs/btrfs/delayed-ref.h |    7 --
+ fs/btrfs/extent-tree.c |   45 +++++----------
+ fs/btrfs/file.c        |   10 +--
+ fs/btrfs/inode.c       |    4 -
+ fs/btrfs/ioctl.c       |   62 ---------------------
+ fs/btrfs/relocation.c  |   16 ++---
+ fs/btrfs/tree-log.c    |    2 
+ 9 files changed, 156 insertions(+), 133 deletions(-)
+
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -3404,7 +3404,7 @@ int btrfs_set_disk_extent_flags(struct b
+ int btrfs_free_extent(struct btrfs_trans_handle *trans,
+                     struct btrfs_root *root,
+                     u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid,
+-                    u64 owner, u64 offset, int no_quota);
++                    u64 owner, u64 offset);
+ int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len,
+                              int delalloc);
+@@ -3417,7 +3417,7 @@ int btrfs_finish_extent_commit(struct bt
+ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
+                        struct btrfs_root *root,
+                        u64 bytenr, u64 num_bytes, u64 parent,
+-                       u64 root_objectid, u64 owner, u64 offset, int no_quota);
++                       u64 root_objectid, u64 owner, u64 offset);
+ int btrfs_start_dirty_block_groups(struct btrfs_trans_handle *trans,
+                                  struct btrfs_root *root);
+--- a/fs/btrfs/delayed-ref.c
++++ b/fs/btrfs/delayed-ref.c
+@@ -310,6 +310,119 @@ next:
+       }
+ }
++static bool merge_ref(struct btrfs_trans_handle *trans,
++                    struct btrfs_delayed_ref_root *delayed_refs,
++                    struct btrfs_delayed_ref_head *head,
++                    struct btrfs_delayed_ref_node *ref,
++                    u64 seq)
++{
++      struct btrfs_delayed_ref_node *next;
++      bool done = false;
++
++      next = list_first_entry(&head->ref_list, struct btrfs_delayed_ref_node,
++                              list);
++      while (!done && &next->list != &head->ref_list) {
++              int mod;
++              struct btrfs_delayed_ref_node *next2;
++
++              next2 = list_next_entry(next, list);
++
++              if (next == ref)
++                      goto next;
++
++              if (seq && next->seq >= seq)
++                      goto next;
++
++              if (next->type != ref->type)
++                      goto next;
++
++              if ((ref->type == BTRFS_TREE_BLOCK_REF_KEY ||
++                   ref->type == BTRFS_SHARED_BLOCK_REF_KEY) &&
++                  comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref),
++                                 btrfs_delayed_node_to_tree_ref(next),
++                                 ref->type))
++                      goto next;
++              if ((ref->type == BTRFS_EXTENT_DATA_REF_KEY ||
++                   ref->type == BTRFS_SHARED_DATA_REF_KEY) &&
++                  comp_data_refs(btrfs_delayed_node_to_data_ref(ref),
++                                 btrfs_delayed_node_to_data_ref(next)))
++                      goto next;
++
++              if (ref->action == next->action) {
++                      mod = next->ref_mod;
++              } else {
++                      if (ref->ref_mod < next->ref_mod) {
++                              swap(ref, next);
++                              done = true;
++                      }
++                      mod = -next->ref_mod;
++              }
++
++              drop_delayed_ref(trans, delayed_refs, head, next);
++              ref->ref_mod += mod;
++              if (ref->ref_mod == 0) {
++                      drop_delayed_ref(trans, delayed_refs, head, ref);
++                      done = true;
++              } else {
++                      /*
++                       * Can't have multiples of the same ref on a tree block.
++                       */
++                      WARN_ON(ref->type == BTRFS_TREE_BLOCK_REF_KEY ||
++                              ref->type == BTRFS_SHARED_BLOCK_REF_KEY);
++              }
++next:
++              next = next2;
++      }
++
++      return done;
++}
++
++void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans,
++                            struct btrfs_fs_info *fs_info,
++                            struct btrfs_delayed_ref_root *delayed_refs,
++                            struct btrfs_delayed_ref_head *head)
++{
++      struct btrfs_delayed_ref_node *ref;
++      u64 seq = 0;
++
++      assert_spin_locked(&head->lock);
++
++      if (list_empty(&head->ref_list))
++              return;
++
++      /* We don't have too many refs to merge for data. */
++      if (head->is_data)
++              return;
++
++      spin_lock(&fs_info->tree_mod_seq_lock);
++      if (!list_empty(&fs_info->tree_mod_seq_list)) {
++              struct seq_list *elem;
++
++              elem = list_first_entry(&fs_info->tree_mod_seq_list,
++                                      struct seq_list, list);
++              seq = elem->seq;
++      }
++      spin_unlock(&fs_info->tree_mod_seq_lock);
++
++      ref = list_first_entry(&head->ref_list, struct btrfs_delayed_ref_node,
++                             list);
++      while (&ref->list != &head->ref_list) {
++              if (seq && ref->seq >= seq)
++                      goto next;
++
++              if (merge_ref(trans, delayed_refs, head, ref, seq)) {
++                      if (list_empty(&head->ref_list))
++                              break;
++                      ref = list_first_entry(&head->ref_list,
++                                             struct btrfs_delayed_ref_node,
++                                             list);
++                      continue;
++              }
++next:
++              ref = list_next_entry(ref, list);
++      }
++}
++
+ int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info,
+                           struct btrfs_delayed_ref_root *delayed_refs,
+                           u64 seq)
+@@ -405,8 +518,7 @@ add_delayed_ref_tail_merge(struct btrfs_
+       exist = list_entry(href->ref_list.prev, struct btrfs_delayed_ref_node,
+                          list);
+       /* No need to compare bytenr nor is_head */
+-      if (exist->type != ref->type || exist->no_quota != ref->no_quota ||
+-          exist->seq != ref->seq)
++      if (exist->type != ref->type || exist->seq != ref->seq)
+               goto add_tail;
+       if ((exist->type == BTRFS_TREE_BLOCK_REF_KEY ||
+@@ -637,7 +749,7 @@ add_delayed_tree_ref(struct btrfs_fs_inf
+                    struct btrfs_delayed_ref_head *head_ref,
+                    struct btrfs_delayed_ref_node *ref, u64 bytenr,
+                    u64 num_bytes, u64 parent, u64 ref_root, int level,
+-                   int action, int no_quota)
++                   int action)
+ {
+       struct btrfs_delayed_tree_ref *full_ref;
+       struct btrfs_delayed_ref_root *delayed_refs;
+@@ -659,7 +771,6 @@ add_delayed_tree_ref(struct btrfs_fs_inf
+       ref->action = action;
+       ref->is_head = 0;
+       ref->in_tree = 1;
+-      ref->no_quota = no_quota;
+       ref->seq = seq;
+       full_ref = btrfs_delayed_node_to_tree_ref(ref);
+@@ -692,7 +803,7 @@ add_delayed_data_ref(struct btrfs_fs_inf
+                    struct btrfs_delayed_ref_head *head_ref,
+                    struct btrfs_delayed_ref_node *ref, u64 bytenr,
+                    u64 num_bytes, u64 parent, u64 ref_root, u64 owner,
+-                   u64 offset, int action, int no_quota)
++                   u64 offset, int action)
+ {
+       struct btrfs_delayed_data_ref *full_ref;
+       struct btrfs_delayed_ref_root *delayed_refs;
+@@ -715,7 +826,6 @@ add_delayed_data_ref(struct btrfs_fs_inf
+       ref->action = action;
+       ref->is_head = 0;
+       ref->in_tree = 1;
+-      ref->no_quota = no_quota;
+       ref->seq = seq;
+       full_ref = btrfs_delayed_node_to_data_ref(ref);
+@@ -746,17 +856,13 @@ int btrfs_add_delayed_tree_ref(struct bt
+                              struct btrfs_trans_handle *trans,
+                              u64 bytenr, u64 num_bytes, u64 parent,
+                              u64 ref_root,  int level, int action,
+-                             struct btrfs_delayed_extent_op *extent_op,
+-                             int no_quota)
++                             struct btrfs_delayed_extent_op *extent_op)
+ {
+       struct btrfs_delayed_tree_ref *ref;
+       struct btrfs_delayed_ref_head *head_ref;
+       struct btrfs_delayed_ref_root *delayed_refs;
+       struct btrfs_qgroup_extent_record *record = NULL;
+-      if (!is_fstree(ref_root) || !fs_info->quota_enabled)
+-              no_quota = 0;
+-
+       BUG_ON(extent_op && extent_op->is_data);
+       ref = kmem_cache_alloc(btrfs_delayed_tree_ref_cachep, GFP_NOFS);
+       if (!ref)
+@@ -785,8 +891,7 @@ int btrfs_add_delayed_tree_ref(struct bt
+                                       bytenr, num_bytes, action, 0);
+       add_delayed_tree_ref(fs_info, trans, head_ref, &ref->node, bytenr,
+-                                 num_bytes, parent, ref_root, level, action,
+-                                 no_quota);
++                           num_bytes, parent, ref_root, level, action);
+       spin_unlock(&delayed_refs->lock);
+       return 0;
+@@ -807,17 +912,13 @@ int btrfs_add_delayed_data_ref(struct bt
+                              u64 bytenr, u64 num_bytes,
+                              u64 parent, u64 ref_root,
+                              u64 owner, u64 offset, int action,
+-                             struct btrfs_delayed_extent_op *extent_op,
+-                             int no_quota)
++                             struct btrfs_delayed_extent_op *extent_op)
+ {
+       struct btrfs_delayed_data_ref *ref;
+       struct btrfs_delayed_ref_head *head_ref;
+       struct btrfs_delayed_ref_root *delayed_refs;
+       struct btrfs_qgroup_extent_record *record = NULL;
+-      if (!is_fstree(ref_root) || !fs_info->quota_enabled)
+-              no_quota = 0;
+-
+       BUG_ON(extent_op && !extent_op->is_data);
+       ref = kmem_cache_alloc(btrfs_delayed_data_ref_cachep, GFP_NOFS);
+       if (!ref)
+@@ -853,7 +954,7 @@ int btrfs_add_delayed_data_ref(struct bt
+       add_delayed_data_ref(fs_info, trans, head_ref, &ref->node, bytenr,
+                                  num_bytes, parent, ref_root, owner, offset,
+-                                 action, no_quota);
++                                 action);
+       spin_unlock(&delayed_refs->lock);
+       return 0;
+--- a/fs/btrfs/delayed-ref.h
++++ b/fs/btrfs/delayed-ref.h
+@@ -68,7 +68,6 @@ struct btrfs_delayed_ref_node {
+       unsigned int action:8;
+       unsigned int type:8;
+-      unsigned int no_quota:1;
+       /* is this node still in the rbtree? */
+       unsigned int is_head:1;
+       unsigned int in_tree:1;
+@@ -233,15 +232,13 @@ int btrfs_add_delayed_tree_ref(struct bt
+                              struct btrfs_trans_handle *trans,
+                              u64 bytenr, u64 num_bytes, u64 parent,
+                              u64 ref_root, int level, int action,
+-                             struct btrfs_delayed_extent_op *extent_op,
+-                             int no_quota);
++                             struct btrfs_delayed_extent_op *extent_op);
+ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
+                              struct btrfs_trans_handle *trans,
+                              u64 bytenr, u64 num_bytes,
+                              u64 parent, u64 ref_root,
+                              u64 owner, u64 offset, int action,
+-                             struct btrfs_delayed_extent_op *extent_op,
+-                             int no_quota);
++                             struct btrfs_delayed_extent_op *extent_op);
+ int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info,
+                               struct btrfs_trans_handle *trans,
+                               u64 bytenr, u64 num_bytes,
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -95,8 +95,7 @@ static int alloc_reserved_tree_block(str
+                                    struct btrfs_root *root,
+                                    u64 parent, u64 root_objectid,
+                                    u64 flags, struct btrfs_disk_key *key,
+-                                   int level, struct btrfs_key *ins,
+-                                   int no_quota);
++                                   int level, struct btrfs_key *ins);
+ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
+                         struct btrfs_root *extent_root, u64 flags,
+                         int force);
+@@ -1941,8 +1940,7 @@ int btrfs_discard_extent(struct btrfs_ro
+ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
+                        struct btrfs_root *root,
+                        u64 bytenr, u64 num_bytes, u64 parent,
+-                       u64 root_objectid, u64 owner, u64 offset,
+-                       int no_quota)
++                       u64 root_objectid, u64 owner, u64 offset)
+ {
+       int ret;
+       struct btrfs_fs_info *fs_info = root->fs_info;
+@@ -1954,12 +1952,12 @@ int btrfs_inc_extent_ref(struct btrfs_tr
+               ret = btrfs_add_delayed_tree_ref(fs_info, trans, bytenr,
+                                       num_bytes,
+                                       parent, root_objectid, (int)owner,
+-                                      BTRFS_ADD_DELAYED_REF, NULL, no_quota);
++                                      BTRFS_ADD_DELAYED_REF, NULL);
+       } else {
+               ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr,
+                                       num_bytes,
+                                       parent, root_objectid, owner, offset,
+-                                      BTRFS_ADD_DELAYED_REF, NULL, no_quota);
++                                      BTRFS_ADD_DELAYED_REF, NULL);
+       }
+       return ret;
+ }
+@@ -1980,15 +1978,11 @@ static int __btrfs_inc_extent_ref(struct
+       u64 num_bytes = node->num_bytes;
+       u64 refs;
+       int ret;
+-      int no_quota = node->no_quota;
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+-      if (!is_fstree(root_objectid) || !root->fs_info->quota_enabled)
+-              no_quota = 1;
+-
+       path->reada = 1;
+       path->leave_spinning = 1;
+       /* this will setup the path even if it fails to insert the back ref */
+@@ -2223,8 +2217,7 @@ static int run_delayed_tree_ref(struct b
+                                               parent, ref_root,
+                                               extent_op->flags_to_set,
+                                               &extent_op->key,
+-                                              ref->level, &ins,
+-                                              node->no_quota);
++                                              ref->level, &ins);
+       } else if (node->action == BTRFS_ADD_DELAYED_REF) {
+               ret = __btrfs_inc_extent_ref(trans, root, node,
+                                            parent, ref_root,
+@@ -3052,7 +3045,7 @@ static int __btrfs_mod_ref(struct btrfs_
+       int level;
+       int ret = 0;
+       int (*process_func)(struct btrfs_trans_handle *, struct btrfs_root *,
+-                          u64, u64, u64, u64, u64, u64, int);
++                          u64, u64, u64, u64, u64, u64);
+       if (btrfs_test_is_dummy_root(root))
+@@ -3093,15 +3086,14 @@ static int __btrfs_mod_ref(struct btrfs_
+                       key.offset -= btrfs_file_extent_offset(buf, fi);
+                       ret = process_func(trans, root, bytenr, num_bytes,
+                                          parent, ref_root, key.objectid,
+-                                         key.offset, 1);
++                                         key.offset);
+                       if (ret)
+                               goto fail;
+               } else {
+                       bytenr = btrfs_node_blockptr(buf, i);
+                       num_bytes = root->nodesize;
+                       ret = process_func(trans, root, bytenr, num_bytes,
+-                                         parent, ref_root, level - 1, 0,
+-                                         1);
++                                         parent, ref_root, level - 1, 0);
+                       if (ret)
+                               goto fail;
+               }
+@@ -6151,7 +6143,6 @@ static int __btrfs_free_extent(struct bt
+       int extent_slot = 0;
+       int found_extent = 0;
+       int num_to_del = 1;
+-      int no_quota = node->no_quota;
+       u32 item_size;
+       u64 refs;
+       u64 bytenr = node->bytenr;
+@@ -6160,9 +6151,6 @@ static int __btrfs_free_extent(struct bt
+       bool skinny_metadata = btrfs_fs_incompat(root->fs_info,
+                                                SKINNY_METADATA);
+-      if (!info->quota_enabled || !is_fstree(root_objectid))
+-              no_quota = 1;
+-
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+@@ -6488,7 +6476,7 @@ void btrfs_free_tree_block(struct btrfs_
+                                       buf->start, buf->len,
+                                       parent, root->root_key.objectid,
+                                       btrfs_header_level(buf),
+-                                      BTRFS_DROP_DELAYED_REF, NULL, 0);
++                                      BTRFS_DROP_DELAYED_REF, NULL);
+               BUG_ON(ret); /* -ENOMEM */
+       }
+@@ -6536,7 +6524,7 @@ out:
+ /* Can return -ENOMEM */
+ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+                     u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid,
+-                    u64 owner, u64 offset, int no_quota)
++                    u64 owner, u64 offset)
+ {
+       int ret;
+       struct btrfs_fs_info *fs_info = root->fs_info;
+@@ -6559,13 +6547,13 @@ int btrfs_free_extent(struct btrfs_trans
+               ret = btrfs_add_delayed_tree_ref(fs_info, trans, bytenr,
+                                       num_bytes,
+                                       parent, root_objectid, (int)owner,
+-                                      BTRFS_DROP_DELAYED_REF, NULL, no_quota);
++                                      BTRFS_DROP_DELAYED_REF, NULL);
+       } else {
+               ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr,
+                                               num_bytes,
+                                               parent, root_objectid, owner,
+                                               offset, BTRFS_DROP_DELAYED_REF,
+-                                              NULL, no_quota);
++                                              NULL);
+       }
+       return ret;
+ }
+@@ -7347,8 +7335,7 @@ static int alloc_reserved_tree_block(str
+                                    struct btrfs_root *root,
+                                    u64 parent, u64 root_objectid,
+                                    u64 flags, struct btrfs_disk_key *key,
+-                                   int level, struct btrfs_key *ins,
+-                                   int no_quota)
++                                   int level, struct btrfs_key *ins)
+ {
+       int ret;
+       struct btrfs_fs_info *fs_info = root->fs_info;
+@@ -7438,7 +7425,7 @@ int btrfs_alloc_reserved_file_extent(str
+       ret = btrfs_add_delayed_data_ref(root->fs_info, trans, ins->objectid,
+                                        ins->offset, 0,
+                                        root_objectid, owner, offset,
+-                                       BTRFS_ADD_DELAYED_EXTENT, NULL, 0);
++                                       BTRFS_ADD_DELAYED_EXTENT, NULL);
+       return ret;
+ }
+@@ -7655,7 +7642,7 @@ struct extent_buffer *btrfs_alloc_tree_b
+                                                ins.objectid, ins.offset,
+                                                parent, root_objectid, level,
+                                                BTRFS_ADD_DELAYED_EXTENT,
+-                                               extent_op, 0);
++                                               extent_op);
+               if (ret)
+                       goto out_free_delayed;
+       }
+@@ -8203,7 +8190,7 @@ skip:
+                       }
+               }
+               ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent,
+-                              root->root_key.objectid, level - 1, 0, 0);
++                              root->root_key.objectid, level - 1, 0);
+               BUG_ON(ret); /* -ENOMEM */
+       }
+       btrfs_tree_unlock(next);
+--- a/fs/btrfs/file.c
++++ b/fs/btrfs/file.c
+@@ -855,7 +855,7 @@ next_slot:
+                                               disk_bytenr, num_bytes, 0,
+                                               root->root_key.objectid,
+                                               new_key.objectid,
+-                                              start - extent_offset, 1);
++                                              start - extent_offset);
+                               BUG_ON(ret); /* -ENOMEM */
+                       }
+                       key.offset = start;
+@@ -933,7 +933,7 @@ delete_extent_item:
+                                               disk_bytenr, num_bytes, 0,
+                                               root->root_key.objectid,
+                                               key.objectid, key.offset -
+-                                              extent_offset, 0);
++                                              extent_offset);
+                               BUG_ON(ret); /* -ENOMEM */
+                               inode_sub_bytes(inode,
+                                               extent_end - key.offset);
+@@ -1212,7 +1212,7 @@ again:
+               ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0,
+                                          root->root_key.objectid,
+-                                         ino, orig_offset, 1);
++                                         ino, orig_offset);
+               BUG_ON(ret); /* -ENOMEM */
+               if (split == start) {
+@@ -1239,7 +1239,7 @@ again:
+               del_nr++;
+               ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
+                                       0, root->root_key.objectid,
+-                                      ino, orig_offset, 0);
++                                      ino, orig_offset);
+               BUG_ON(ret); /* -ENOMEM */
+       }
+       other_start = 0;
+@@ -1256,7 +1256,7 @@ again:
+               del_nr++;
+               ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
+                                       0, root->root_key.objectid,
+-                                      ino, orig_offset, 0);
++                                      ino, orig_offset);
+               BUG_ON(ret); /* -ENOMEM */
+       }
+       if (del_nr == 0) {
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -2575,7 +2575,7 @@ again:
+       ret = btrfs_inc_extent_ref(trans, root, new->bytenr,
+                       new->disk_len, 0,
+                       backref->root_id, backref->inum,
+-                      new->file_pos, 0);      /* start - extent_offset */
++                      new->file_pos); /* start - extent_offset */
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto out_free_path;
+@@ -4488,7 +4488,7 @@ delete:
+                       ret = btrfs_free_extent(trans, root, extent_start,
+                                               extent_num_bytes, 0,
+                                               btrfs_header_owner(leaf),
+-                                              ino, extent_offset, 0);
++                                              ino, extent_offset);
+                       BUG_ON(ret);
+                       if (btrfs_should_throttle_delayed_refs(trans, root))
+                               btrfs_async_run_delayed_refs(root,
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -3195,41 +3195,6 @@ out:
+       return ret;
+ }
+-/* Helper to check and see if this root currently has a ref on the given disk
+- * bytenr.  If it does then we need to update the quota for this root.  This
+- * doesn't do anything if quotas aren't enabled.
+- */
+-static int check_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+-                   u64 disko)
+-{
+-      struct seq_list tree_mod_seq_elem = SEQ_LIST_INIT(tree_mod_seq_elem);
+-      struct ulist *roots;
+-      struct ulist_iterator uiter;
+-      struct ulist_node *root_node = NULL;
+-      int ret;
+-
+-      if (!root->fs_info->quota_enabled)
+-              return 1;
+-
+-      btrfs_get_tree_mod_seq(root->fs_info, &tree_mod_seq_elem);
+-      ret = btrfs_find_all_roots(trans, root->fs_info, disko,
+-                                 tree_mod_seq_elem.seq, &roots);
+-      if (ret < 0)
+-              goto out;
+-      ret = 0;
+-      ULIST_ITER_INIT(&uiter);
+-      while ((root_node = ulist_next(roots, &uiter))) {
+-              if (root_node->val == root->objectid) {
+-                      ret = 1;
+-                      break;
+-              }
+-      }
+-      ulist_free(roots);
+-out:
+-      btrfs_put_tree_mod_seq(root->fs_info, &tree_mod_seq_elem);
+-      return ret;
+-}
+-
+ static int clone_finish_inode_update(struct btrfs_trans_handle *trans,
+                                    struct inode *inode,
+                                    u64 endoff,
+@@ -3488,9 +3453,7 @@ static int btrfs_clone(struct inode *src
+       u32 nritems;
+       int slot;
+       int ret;
+-      int no_quota;
+       const u64 len = olen_aligned;
+-      u64 last_disko = 0;
+       u64 last_dest_end = destoff;
+       ret = -ENOMEM;
+@@ -3536,7 +3499,6 @@ static int btrfs_clone(struct inode *src
+               nritems = btrfs_header_nritems(path->nodes[0]);
+ process_slot:
+-              no_quota = 1;
+               if (path->slots[0] >= nritems) {
+                       ret = btrfs_next_leaf(BTRFS_I(src)->root, path);
+                       if (ret < 0)
+@@ -3688,35 +3650,13 @@ process_slot:
+                               btrfs_set_file_extent_num_bytes(leaf, extent,
+                                                               datal);
+-                              /*
+-                               * We need to look up the roots that point at
+-                               * this bytenr and see if the new root does.  If
+-                               * it does not we need to make sure we update
+-                               * quotas appropriately.
+-                               */
+-                              if (disko && root != BTRFS_I(src)->root &&
+-                                  disko != last_disko) {
+-                                      no_quota = check_ref(trans, root,
+-                                                           disko);
+-                                      if (no_quota < 0) {
+-                                              btrfs_abort_transaction(trans,
+-                                                                      root,
+-                                                                      ret);
+-                                              btrfs_end_transaction(trans,
+-                                                                    root);
+-                                              ret = no_quota;
+-                                              goto out;
+-                                      }
+-                              }
+-
+                               if (disko) {
+                                       inode_add_bytes(inode, datal);
+                                       ret = btrfs_inc_extent_ref(trans, root,
+                                                       disko, diskl, 0,
+                                                       root->root_key.objectid,
+                                                       btrfs_ino(inode),
+-                                                      new_key.offset - datao,
+-                                                      no_quota);
++                                                      new_key.offset - datao);
+                                       if (ret) {
+                                               btrfs_abort_transaction(trans,
+                                                                       root,
+--- a/fs/btrfs/relocation.c
++++ b/fs/btrfs/relocation.c
+@@ -1716,7 +1716,7 @@ int replace_file_extents(struct btrfs_tr
+               ret = btrfs_inc_extent_ref(trans, root, new_bytenr,
+                                          num_bytes, parent,
+                                          btrfs_header_owner(leaf),
+-                                         key.objectid, key.offset, 1);
++                                         key.objectid, key.offset);
+               if (ret) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       break;
+@@ -1724,7 +1724,7 @@ int replace_file_extents(struct btrfs_tr
+               ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
+                                       parent, btrfs_header_owner(leaf),
+-                                      key.objectid, key.offset, 1);
++                                      key.objectid, key.offset);
+               if (ret) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       break;
+@@ -1900,23 +1900,21 @@ again:
+               ret = btrfs_inc_extent_ref(trans, src, old_bytenr, blocksize,
+                                       path->nodes[level]->start,
+-                                      src->root_key.objectid, level - 1, 0,
+-                                      1);
++                                      src->root_key.objectid, level - 1, 0);
+               BUG_ON(ret);
+               ret = btrfs_inc_extent_ref(trans, dest, new_bytenr, blocksize,
+                                       0, dest->root_key.objectid, level - 1,
+-                                      0, 1);
++                                      0);
+               BUG_ON(ret);
+               ret = btrfs_free_extent(trans, src, new_bytenr, blocksize,
+                                       path->nodes[level]->start,
+-                                      src->root_key.objectid, level - 1, 0,
+-                                      1);
++                                      src->root_key.objectid, level - 1, 0);
+               BUG_ON(ret);
+               ret = btrfs_free_extent(trans, dest, old_bytenr, blocksize,
+                                       0, dest->root_key.objectid, level - 1,
+-                                      0, 1);
++                                      0);
+               BUG_ON(ret);
+               btrfs_unlock_up_safe(path, 0);
+@@ -2746,7 +2744,7 @@ static int do_relocation(struct btrfs_tr
+                                               node->eb->start, blocksize,
+                                               upper->eb->start,
+                                               btrfs_header_owner(upper->eb),
+-                                              node->level, 0, 1);
++                                              node->level, 0);
+                       BUG_ON(ret);
+                       ret = btrfs_drop_subtree(trans, root, eb, upper->eb);
+--- a/fs/btrfs/tree-log.c
++++ b/fs/btrfs/tree-log.c
+@@ -700,7 +700,7 @@ static noinline int replay_one_extent(st
+                               ret = btrfs_inc_extent_ref(trans, root,
+                                               ins.objectid, ins.offset,
+                                               0, root->root_key.objectid,
+-                                              key->objectid, offset, 0);
++                                              key->objectid, offset);
+                               if (ret)
+                                       goto out;
+                       } else {
diff --git a/queue-4.2/ext4-crypto-fix-bugs-in-ext4_encrypted_zeroout.patch b/queue-4.2/ext4-crypto-fix-bugs-in-ext4_encrypted_zeroout.patch
deleted file mode 100644 (file)
index 09eb740..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-From 36086d43f6575c081067de9855786a2fc91df77b Mon Sep 17 00:00:00 2001
-From: Theodore Ts'o <tytso@mit.edu>
-Date: Sat, 3 Oct 2015 10:49:29 -0400
-Subject: ext4 crypto: fix bugs in ext4_encrypted_zeroout()
-
-From: Theodore Ts'o <tytso@mit.edu>
-
-commit 36086d43f6575c081067de9855786a2fc91df77b upstream.
-
-Fix multiple bugs in ext4_encrypted_zeroout(), including one that
-could cause us to write an encrypted zero page to the wrong location
-on disk, potentially causing data and file system corruption.
-Fortunately, this tends to only show up in stress tests, but even with
-these fixes, we are seeing some test failures with generic/127 --- but
-these are now caused by data failures instead of metadata corruption.
-
-Since ext4_encrypted_zeroout() is only used for some optimizations to
-keep the extent tree from being too fragmented, and
-ext4_encrypted_zeroout() itself isn't all that optimized from a time
-or IOPS perspective, disable the extent tree optimization for
-encrypted inodes for now.  This prevents the data corruption issues
-reported by generic/127 until we can figure out what's going wrong.
-
-Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
----
- fs/ext4/crypto.c  |   23 +++++++++++++++++++----
- fs/ext4/extents.c |    3 +++
- 2 files changed, 22 insertions(+), 4 deletions(-)
-
---- a/fs/ext4/crypto.c
-+++ b/fs/ext4/crypto.c
-@@ -410,7 +410,13 @@ int ext4_encrypted_zeroout(struct inode
-       ext4_lblk_t             lblk = ex->ee_block;
-       ext4_fsblk_t            pblk = ext4_ext_pblock(ex);
-       unsigned int            len = ext4_ext_get_actual_len(ex);
--      int                     err = 0;
-+      int                     ret, err = 0;
-+
-+#if 0
-+      ext4_msg(inode->i_sb, KERN_CRIT,
-+               "ext4_encrypted_zeroout ino %lu lblk %u len %u",
-+               (unsigned long) inode->i_ino, lblk, len);
-+#endif
-       BUG_ON(inode->i_sb->s_blocksize != PAGE_CACHE_SIZE);
-@@ -436,17 +442,26 @@ int ext4_encrypted_zeroout(struct inode
-                       goto errout;
-               }
-               bio->bi_bdev = inode->i_sb->s_bdev;
--              bio->bi_iter.bi_sector = pblk;
--              err = bio_add_page(bio, ciphertext_page,
-+              bio->bi_iter.bi_sector =
-+                      pblk << (inode->i_sb->s_blocksize_bits - 9);
-+              ret = bio_add_page(bio, ciphertext_page,
-                                  inode->i_sb->s_blocksize, 0);
--              if (err) {
-+              if (ret != inode->i_sb->s_blocksize) {
-+                      /* should never happen! */
-+                      ext4_msg(inode->i_sb, KERN_ERR,
-+                               "bio_add_page failed: %d", ret);
-+                      WARN_ON(1);
-                       bio_put(bio);
-+                      err = -EIO;
-                       goto errout;
-               }
-               err = submit_bio_wait(WRITE, bio);
-+              if ((err == 0) && bio->bi_error)
-+                      err = -EIO;
-               bio_put(bio);
-               if (err)
-                       goto errout;
-+              lblk++; pblk++;
-       }
-       err = 0;
- errout:
---- a/fs/ext4/extents.c
-+++ b/fs/ext4/extents.c
-@@ -3558,6 +3558,9 @@ static int ext4_ext_convert_to_initializ
-               max_zeroout = sbi->s_extent_max_zeroout_kb >>
-                       (inode->i_sb->s_blocksize_bits - 10);
-+      if (ext4_encrypted_inode(inode))
-+              max_zeroout = 0;
-+
-       /* If extent is less than s_max_zeroout_kb, zeroout directly */
-       if (max_zeroout && (ee_len <= max_zeroout)) {
-               err = ext4_ext_zeroout(inode, ex);
index 5237c581be48577b6ee5983bc872ee5463190e9f..ce9bf3efc19a53876463818d9fa8634f01e9bdb2 100644 (file)
@@ -47,7 +47,6 @@ btrfs-fix-signed-overflows-in-btrfs_sync_file.patch
 rbd-don-t-put-snap_context-twice-in-rbd_queue_workfn.patch
 ext4-crypto-fix-memory-leak-in-ext4_bio_write_page.patch
 ext4-crypto-replace-some-bug_on-s-with-error-checks.patch
-ext4-crypto-fix-bugs-in-ext4_encrypted_zeroout.patch
 ext4-fix-potential-use-after-free-in-__ext4_journal_stop.patch
 ext4-jbd2-ensure-entering-into-panic-after-recording-an-error-in-superblock.patch
 firewire-ohci-fix-jmicron-jmb38x-it-context-discovery.patch
@@ -60,3 +59,4 @@ ocfs2-fix-umask-ignored-issue.patch
 ceph-fix-message-length-computation.patch
 alsa-hda-hdmi-apply-skylake-fix-ups-to-broxton-display-codec.patch
 cobalt-fix-kconfig-dependency.patch
+btrfs-fix-regression-running-delayed-references-when-using-qgroups.patch