]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 18 Dec 2013 20:56:14 +0000 (12:56 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 18 Dec 2013 20:56:14 +0000 (12:56 -0800)
added patches:
btrfs-do-a-full-search-everytime-in-btrfs_search_old_slot.patch
btrfs-do-not-run-snapshot-aware-defragment-on-error.patch
btrfs-fix-a-crash-when-running-balance-and-defrag-concurrently.patch
btrfs-fix-hole-check-in-log_one_extent.patch
btrfs-fix-incorrect-inode-acl-reset.patch
btrfs-fix-lockdep-error-in-async-commit.patch
btrfs-fix-memory-leak-of-chunks-extent-map.patch
btrfs-reset-intwrite-on-transaction-abort.patch
btrfs-stop-using-vfs_read-in-send.patch
btrfs-take-ordered-root-lock-when-removing-ordered-operations-inode.patch

queue-3.12/btrfs-do-a-full-search-everytime-in-btrfs_search_old_slot.patch [new file with mode: 0644]
queue-3.12/btrfs-do-not-run-snapshot-aware-defragment-on-error.patch [new file with mode: 0644]
queue-3.12/btrfs-fix-a-crash-when-running-balance-and-defrag-concurrently.patch [new file with mode: 0644]
queue-3.12/btrfs-fix-hole-check-in-log_one_extent.patch [new file with mode: 0644]
queue-3.12/btrfs-fix-incorrect-inode-acl-reset.patch [new file with mode: 0644]
queue-3.12/btrfs-fix-lockdep-error-in-async-commit.patch [new file with mode: 0644]
queue-3.12/btrfs-fix-memory-leak-of-chunks-extent-map.patch [new file with mode: 0644]
queue-3.12/btrfs-reset-intwrite-on-transaction-abort.patch [new file with mode: 0644]
queue-3.12/btrfs-stop-using-vfs_read-in-send.patch [new file with mode: 0644]
queue-3.12/btrfs-take-ordered-root-lock-when-removing-ordered-operations-inode.patch [new file with mode: 0644]
queue-3.12/series

diff --git a/queue-3.12/btrfs-do-a-full-search-everytime-in-btrfs_search_old_slot.patch b/queue-3.12/btrfs-do-a-full-search-everytime-in-btrfs_search_old_slot.patch
new file mode 100644 (file)
index 0000000..faea3dc
--- /dev/null
@@ -0,0 +1,57 @@
+From d4b4087c43cc00a196c5be57fac41f41309f1d56 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fusionio.com>
+Date: Tue, 24 Sep 2013 14:09:34 -0400
+Subject: Btrfs: do a full search everytime in btrfs_search_old_slot
+
+From: Josef Bacik <jbacik@fusionio.com>
+
+commit d4b4087c43cc00a196c5be57fac41f41309f1d56 upstream.
+
+While running some snashot aware defrag tests I noticed I was panicing every
+once and a while in key_search.  This is because of the optimization that says
+if we find a key at slot 0 it will be at slot 0 all the way down the rest of the
+tree.  This isn't the case for btrfs_search_old_slot since it will likely replay
+changes to a buffer if something has changed since we took our sequence number.
+So short circuit this optimization by setting prev_cmp to -1 every time we call
+key_search so we will do our normal binary search.  With this patch I am no
+longer seeing the panics I was seeing before.  Thanks,
+
+Signed-off-by: Josef Bacik <jbacik@fusionio.com>
+Signed-off-by: Chris Mason <chris.mason@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/ctree.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/fs/btrfs/ctree.c
++++ b/fs/btrfs/ctree.c
+@@ -2758,7 +2758,7 @@ int btrfs_search_old_slot(struct btrfs_r
+       int level;
+       int lowest_unlock = 1;
+       u8 lowest_level = 0;
+-      int prev_cmp;
++      int prev_cmp = -1;
+       lowest_level = p->lowest_level;
+       WARN_ON(p->nodes[0] != NULL);
+@@ -2769,7 +2769,6 @@ int btrfs_search_old_slot(struct btrfs_r
+       }
+ again:
+-      prev_cmp = -1;
+       b = get_old_root(root, time_seq);
+       level = btrfs_header_level(b);
+       p->locks[level] = BTRFS_READ_LOCK;
+@@ -2787,6 +2786,11 @@ again:
+                */
+               btrfs_unlock_up_safe(p, level + 1);
++              /*
++               * Since we can unwind eb's we want to do a real search every
++               * time.
++               */
++              prev_cmp = -1;
+               ret = key_search(b, key, level, &prev_cmp, &slot);
+               if (level != 0) {
diff --git a/queue-3.12/btrfs-do-not-run-snapshot-aware-defragment-on-error.patch b/queue-3.12/btrfs-do-not-run-snapshot-aware-defragment-on-error.patch
new file mode 100644 (file)
index 0000000..9dfe1de
--- /dev/null
@@ -0,0 +1,131 @@
+From 6f519564d7d978c00351d9ab6abac3deeac31621 Mon Sep 17 00:00:00 2001
+From: Liu Bo <bo.li.liu@oracle.com>
+Date: Tue, 29 Oct 2013 10:45:05 +0800
+Subject: Btrfs: do not run snapshot-aware defragment on error
+
+From: Liu Bo <bo.li.liu@oracle.com>
+
+commit 6f519564d7d978c00351d9ab6abac3deeac31621 upstream.
+
+If something wrong happens in write endio, running snapshot-aware defragment
+can end up with undefined results, maybe a crash, so we should avoid it.
+
+In order to share similar code, this also adds a helper to free the struct for
+snapshot-aware defrag.
+
+Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
+Signed-off-by: Josef Bacik <jbacik@fusionio.com>
+Signed-off-by: Chris Mason <chris.mason@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/inode.c |   47 ++++++++++++++++++++++++++++-------------------
+ 1 file changed, 28 insertions(+), 19 deletions(-)
+
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -2367,10 +2367,23 @@ out_unlock:
+       return ret;
+ }
++static void free_sa_defrag_extent(struct new_sa_defrag_extent *new)
++{
++      struct old_sa_defrag_extent *old, *tmp;
++
++      if (!new)
++              return;
++
++      list_for_each_entry_safe(old, tmp, &new->head, list) {
++              list_del(&old->list);
++              kfree(old);
++      }
++      kfree(new);
++}
++
+ static void relink_file_extents(struct new_sa_defrag_extent *new)
+ {
+       struct btrfs_path *path;
+-      struct old_sa_defrag_extent *old, *tmp;
+       struct sa_defrag_extent_backref *backref;
+       struct sa_defrag_extent_backref *prev = NULL;
+       struct inode *inode;
+@@ -2413,16 +2426,11 @@ static void relink_file_extents(struct n
+       kfree(prev);
+       btrfs_free_path(path);
+-
+-      list_for_each_entry_safe(old, tmp, &new->head, list) {
+-              list_del(&old->list);
+-              kfree(old);
+-      }
+ out:
++      free_sa_defrag_extent(new);
++
+       atomic_dec(&root->fs_info->defrag_running);
+       wake_up(&root->fs_info->transaction_wait);
+-
+-      kfree(new);
+ }
+ static struct new_sa_defrag_extent *
+@@ -2432,7 +2440,7 @@ record_old_file_extents(struct inode *in
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct btrfs_path *path;
+       struct btrfs_key key;
+-      struct old_sa_defrag_extent *old, *tmp;
++      struct old_sa_defrag_extent *old;
+       struct new_sa_defrag_extent *new;
+       int ret;
+@@ -2480,7 +2488,7 @@ record_old_file_extents(struct inode *in
+               if (slot >= btrfs_header_nritems(l)) {
+                       ret = btrfs_next_leaf(root, path);
+                       if (ret < 0)
+-                              goto out_free_list;
++                              goto out_free_path;
+                       else if (ret > 0)
+                               break;
+                       continue;
+@@ -2509,7 +2517,7 @@ record_old_file_extents(struct inode *in
+               old = kmalloc(sizeof(*old), GFP_NOFS);
+               if (!old)
+-                      goto out_free_list;
++                      goto out_free_path;
+               offset = max(new->file_pos, key.offset);
+               end = min(new->file_pos + new->len, key.offset + num_bytes);
+@@ -2531,15 +2539,10 @@ next:
+       return new;
+-out_free_list:
+-      list_for_each_entry_safe(old, tmp, &new->head, list) {
+-              list_del(&old->list);
+-              kfree(old);
+-      }
+ out_free_path:
+       btrfs_free_path(path);
+ out_kfree:
+-      kfree(new);
++      free_sa_defrag_extent(new);
+       return NULL;
+ }
+@@ -2710,8 +2713,14 @@ out:
+       btrfs_remove_ordered_extent(inode, ordered_extent);
+       /* for snapshot-aware defrag */
+-      if (new)
+-              relink_file_extents(new);
++      if (new) {
++              if (ret) {
++                      free_sa_defrag_extent(new);
++                      atomic_dec(&root->fs_info->defrag_running);
++              } else {
++                      relink_file_extents(new);
++              }
++      }
+       /* once for us */
+       btrfs_put_ordered_extent(ordered_extent);
diff --git a/queue-3.12/btrfs-fix-a-crash-when-running-balance-and-defrag-concurrently.patch b/queue-3.12/btrfs-fix-a-crash-when-running-balance-and-defrag-concurrently.patch
new file mode 100644 (file)
index 0000000..cc60d4c
--- /dev/null
@@ -0,0 +1,67 @@
+From 48ec47364b6d493f0a9cdc116977bf3f34e5c3ec Mon Sep 17 00:00:00 2001
+From: Liu Bo <bo.li.liu@oracle.com>
+Date: Wed, 30 Oct 2013 13:25:24 +0800
+Subject: Btrfs: fix a crash when running balance and defrag concurrently
+
+From: Liu Bo <bo.li.liu@oracle.com>
+
+commit 48ec47364b6d493f0a9cdc116977bf3f34e5c3ec upstream.
+
+Running balance and defrag concurrently can end up with a crash:
+
+kernel BUG at fs/btrfs/relocation.c:4528!
+RIP: 0010:[<ffffffffa01ac33b>]  [<ffffffffa01ac33b>] btrfs_reloc_cow_block+ 0x1eb/0x230 [btrfs]
+Call Trace:
+  [<ffffffffa01398c1>] ? update_ref_for_cow+0x241/0x380 [btrfs]
+  [<ffffffffa0180bad>] ? copy_extent_buffer+0xad/0x110 [btrfs]
+  [<ffffffffa0139da1>] __btrfs_cow_block+0x3a1/0x520 [btrfs]
+  [<ffffffffa013a0b6>] btrfs_cow_block+0x116/0x1b0 [btrfs]
+  [<ffffffffa013ddad>] btrfs_search_slot+0x43d/0x970 [btrfs]
+  [<ffffffffa0153c57>] btrfs_lookup_file_extent+0x37/0x40 [btrfs]
+  [<ffffffffa0172a5e>] __btrfs_drop_extents+0x11e/0xae0 [btrfs]
+  [<ffffffffa013b3fd>] ? generic_bin_search.constprop.39+0x8d/0x1a0 [btrfs]
+  [<ffffffff8117d14a>] ? kmem_cache_alloc+0x1da/0x200
+  [<ffffffffa0138e7a>] ? btrfs_alloc_path+0x1a/0x20 [btrfs]
+  [<ffffffffa0173ef0>] btrfs_drop_extents+0x60/0x90 [btrfs]
+  [<ffffffffa016b24d>] relink_extent_backref+0x2ed/0x780 [btrfs]
+  [<ffffffffa0162fe0>] ? btrfs_submit_bio_hook+0x1e0/0x1e0 [btrfs]
+  [<ffffffffa01b8ed7>] ? iterate_inodes_from_logical+0x87/0xa0 [btrfs]
+  [<ffffffffa016b909>] btrfs_finish_ordered_io+0x229/0xac0 [btrfs]
+  [<ffffffffa016c3b5>] finish_ordered_fn+0x15/0x20 [btrfs]
+  [<ffffffffa018cbe5>] worker_loop+0x125/0x4e0 [btrfs]
+  [<ffffffffa018cac0>] ? btrfs_queue_worker+0x300/0x300 [btrfs]
+  [<ffffffff81075ea0>] kthread+0xc0/0xd0
+  [<ffffffff81075de0>] ? insert_kthread_work+0x40/0x40
+  [<ffffffff8164796c>] ret_from_fork+0x7c/0xb0
+  [<ffffffff81075de0>] ? insert_kthread_work+0x40/0x40
+----------------------------------------------------------------------
+
+It turns out to be that balance operation will bump root's @last_snapshot,
+which enables snapshot-aware defrag path, and backref walking stuff will
+find data reloc tree as refs' parent, and hit the BUG_ON() during COW.
+
+As data reloc tree's data is just for relocation purpose, and will be deleted right
+after relocation is done, it's unnecessary to walk those refs belonged to data reloc
+tree, it'd be better to skip them.
+
+Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
+Signed-off-by: Josef Bacik <jbacik@fusionio.com>
+Signed-off-by: Chris Mason <chris.mason@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/backref.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/fs/btrfs/backref.c
++++ b/fs/btrfs/backref.c
+@@ -185,6 +185,9 @@ static int __add_prelim_ref(struct list_
+ {
+       struct __prelim_ref *ref;
++      if (root_id == BTRFS_DATA_RELOC_TREE_OBJECTID)
++              return 0;
++
+       ref = kmem_cache_alloc(btrfs_prelim_ref_cache, gfp_mask);
+       if (!ref)
+               return -ENOMEM;
diff --git a/queue-3.12/btrfs-fix-hole-check-in-log_one_extent.patch b/queue-3.12/btrfs-fix-hole-check-in-log_one_extent.patch
new file mode 100644 (file)
index 0000000..d19f7bb
--- /dev/null
@@ -0,0 +1,34 @@
+From ed9e8af88e2551aaa6bf51d8063a2493e2d71597 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fusionio.com>
+Date: Mon, 14 Oct 2013 17:23:08 -0400
+Subject: Btrfs: fix hole check in log_one_extent
+
+From: Josef Bacik <jbacik@fusionio.com>
+
+commit ed9e8af88e2551aaa6bf51d8063a2493e2d71597 upstream.
+
+I added an assert to make sure we were looking up aligned offsets for csums and
+I tripped it when running xfstests.  This is because log_one_extent was checking
+if block_start == 0 for a hole instead of EXTENT_MAP_HOLE.  This worked out fine
+in practice it seems, but it adds a lot of extra work that is uneeded.  With
+this fix I'm no longer tripping my assert.  Thanks,
+
+Signed-off-by: Josef Bacik <jbacik@fusionio.com>
+Signed-off-by: Chris Mason <chris.mason@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/tree-log.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/btrfs/tree-log.c
++++ b/fs/btrfs/tree-log.c
+@@ -3375,7 +3375,7 @@ static int log_one_extent(struct btrfs_t
+               btrfs_set_token_file_extent_type(leaf, fi,
+                                                BTRFS_FILE_EXTENT_REG,
+                                                &token);
+-              if (em->block_start == 0)
++              if (em->block_start == EXTENT_MAP_HOLE)
+                       skip_csum = true;
+       }
diff --git a/queue-3.12/btrfs-fix-incorrect-inode-acl-reset.patch b/queue-3.12/btrfs-fix-incorrect-inode-acl-reset.patch
new file mode 100644 (file)
index 0000000..e6f9dae
--- /dev/null
@@ -0,0 +1,72 @@
+From 8185554d3eb09d23a805456b6fa98dcbb34aa518 Mon Sep 17 00:00:00 2001
+From: Filipe David Borba Manana <fdmanana@gmail.com>
+Date: Tue, 15 Oct 2013 18:44:00 +0100
+Subject: Btrfs: fix incorrect inode acl reset
+
+From: Filipe David Borba Manana <fdmanana@gmail.com>
+
+commit 8185554d3eb09d23a805456b6fa98dcbb34aa518 upstream.
+
+When a directory has a default ACL and a subdirectory is created
+under that directory, btrfs_init_acl() is called when the
+subdirectory's inode is created to initialize the inode's ACL
+(inherited from the parent directory) but it was clearing the ACL
+from the inode after setting it if posix_acl_create() returned
+success, instead of clearing it only if it returned an error.
+
+To reproduce this issue:
+
+$ mkfs.btrfs -f /dev/loop0
+$ mount /dev/loop0 /mnt
+$ mkdir /mnt/acl
+$ setfacl -d --set u::rwx,g::rwx,o::- /mnt/acl
+$ getfacl /mnt/acl
+user::rwx
+group::rwx
+other::r-x
+default:user::rwx
+default:group::rwx
+default:other::---
+
+$ mkdir /mnt/acl/dir1
+$ getfacl /mnt/acl/dir1
+user::rwx
+group::rwx
+other::---
+
+After unmounting and mounting again the filesystem, fgetacl returned the
+expected ACL:
+
+$ umount /mnt/acl
+$ mount /dev/loop0 /mnt
+$ getfacl /mnt/acl/dir1
+user::rwx
+group::rwx
+other::---
+default:user::rwx
+default:group::rwx
+default:other::---
+
+Meaning that the underlying xattr was persisted.
+
+Reported-by: Giuseppe Fierro <giuseppe@fierro.org>
+Signed-off-by: Filipe David Borba Manana <fdmanana@gmail.com>
+Signed-off-by: Josef Bacik <jbacik@fusionio.com>
+Signed-off-by: Chris Mason <chris.mason@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/acl.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/btrfs/acl.c
++++ b/fs/btrfs/acl.c
+@@ -229,7 +229,7 @@ int btrfs_init_acl(struct btrfs_trans_ha
+               if (ret > 0) {
+                       /* we need an acl */
+                       ret = btrfs_set_acl(trans, inode, acl, ACL_TYPE_ACCESS);
+-              } else {
++              } else if (ret < 0) {
+                       cache_no_acl(inode);
+               }
+       } else {
diff --git a/queue-3.12/btrfs-fix-lockdep-error-in-async-commit.patch b/queue-3.12/btrfs-fix-lockdep-error-in-async-commit.patch
new file mode 100644 (file)
index 0000000..c52735b
--- /dev/null
@@ -0,0 +1,84 @@
+From b1a06a4b574996692b72b742bf6e6aa0c711a948 Mon Sep 17 00:00:00 2001
+From: Liu Bo <bo.li.liu@oracle.com>
+Date: Wed, 6 Nov 2013 16:57:55 +0800
+Subject: Btrfs: fix lockdep error in async commit
+
+From: Liu Bo <bo.li.liu@oracle.com>
+
+commit b1a06a4b574996692b72b742bf6e6aa0c711a948 upstream.
+
+Lockdep complains about btrfs's async commit:
+
+[ 2372.462171] [ BUG: bad unlock balance detected! ]
+[ 2372.462191] 3.12.0+ #32 Tainted: G        W
+[ 2372.462209] -------------------------------------
+[ 2372.462228] ceph-osd/14048 is trying to release lock (sb_internal) at:
+[ 2372.462275] [<ffffffffa022cb10>] btrfs_commit_transaction_async+0x1b0/0x2a0 [btrfs]
+[ 2372.462305] but there are no more locks to release!
+[ 2372.462324]
+[ 2372.462324] other info that might help us debug this:
+[ 2372.462349] no locks held by ceph-osd/14048.
+[ 2372.462367]
+[ 2372.462367] stack backtrace:
+[ 2372.462386] CPU: 2 PID: 14048 Comm: ceph-osd Tainted: G        W    3.12.0+ #32
+[ 2372.462414] Hardware name: To Be Filled By O.E.M. To Be Filled By O.E.M./To be filled by O.E.M., BIOS 080015  11/09/2011
+[ 2372.462455]  ffffffffa022cb10 ffff88007490fd28 ffffffff816f094a ffff8800378aa320
+[ 2372.462491]  ffff88007490fd50 ffffffff810adf4c ffff8800378aa320 ffff88009af97650
+[ 2372.462526]  ffffffffa022cb10 ffff88007490fd88 ffffffff810b01ee ffff8800898c0000
+[ 2372.462562] Call Trace:
+[ 2372.462584]  [<ffffffffa022cb10>] ? btrfs_commit_transaction_async+0x1b0/0x2a0 [btrfs]
+[ 2372.462619]  [<ffffffff816f094a>] dump_stack+0x45/0x56
+[ 2372.462642]  [<ffffffff810adf4c>] print_unlock_imbalance_bug+0xec/0x100
+[ 2372.462677]  [<ffffffffa022cb10>] ? btrfs_commit_transaction_async+0x1b0/0x2a0 [btrfs]
+[ 2372.462710]  [<ffffffff810b01ee>] lock_release+0x18e/0x210
+[ 2372.462742]  [<ffffffffa022cb36>] btrfs_commit_transaction_async+0x1d6/0x2a0 [btrfs]
+[ 2372.462783]  [<ffffffffa025a7ce>] btrfs_ioctl_start_sync+0x3e/0xc0 [btrfs]
+[ 2372.462822]  [<ffffffffa025f1d3>] btrfs_ioctl+0x4c3/0x1f70 [btrfs]
+[ 2372.462849]  [<ffffffff812c0321>] ? avc_has_perm+0x121/0x1b0
+[ 2372.462873]  [<ffffffff812c0224>] ? avc_has_perm+0x24/0x1b0
+[ 2372.462897]  [<ffffffff8107ecc8>] ? sched_clock_cpu+0xa8/0x100
+[ 2372.462922]  [<ffffffff8117b145>] do_vfs_ioctl+0x2e5/0x4e0
+[ 2372.462946]  [<ffffffff812c19e6>] ? file_has_perm+0x86/0xa0
+[ 2372.462969]  [<ffffffff8117b3c1>] SyS_ioctl+0x81/0xa0
+[ 2372.462991]  [<ffffffff817045a4>] tracesys+0xdd/0xe2
+
+====================================================
+
+It's because that we don't do the right thing when checking if it's ok to
+tell lockdep that we're trying to release the rwsem.
+
+If the trans handle's type is TRANS_ATTACH, we won't acquire the freeze rwsem, but
+as TRANS_ATTACH fits the check (trans < TRANS_JOIN_NOLOCK), we'll release the freeze
+rwsem, which makes lockdep complains a lot.
+
+Reported-by: Ma Jianpeng <majianpeng@gmail.com>
+Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
+Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
+Signed-off-by: Josef Bacik <jbacik@fusionio.com>
+Signed-off-by: Chris Mason <chris.mason@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/transaction.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/btrfs/transaction.c
++++ b/fs/btrfs/transaction.c
+@@ -1453,7 +1453,7 @@ static void do_async_commit(struct work_
+        * We've got freeze protection passed with the transaction.
+        * Tell lockdep about it.
+        */
+-      if (ac->newtrans->type < TRANS_JOIN_NOLOCK)
++      if (ac->newtrans->type & __TRANS_FREEZABLE)
+               rwsem_acquire_read(
+                    &ac->root->fs_info->sb->s_writers.lock_map[SB_FREEZE_FS-1],
+                    0, 1, _THIS_IP_);
+@@ -1494,7 +1494,7 @@ int btrfs_commit_transaction_async(struc
+        * Tell lockdep we've released the freeze rwsem, since the
+        * async commit thread will be the one to unlock it.
+        */
+-      if (trans->type < TRANS_JOIN_NOLOCK)
++      if (ac->newtrans->type & __TRANS_FREEZABLE)
+               rwsem_release(
+                       &root->fs_info->sb->s_writers.lock_map[SB_FREEZE_FS-1],
+                       1, _THIS_IP_);
diff --git a/queue-3.12/btrfs-fix-memory-leak-of-chunks-extent-map.patch b/queue-3.12/btrfs-fix-memory-leak-of-chunks-extent-map.patch
new file mode 100644 (file)
index 0000000..5cceaa6
--- /dev/null
@@ -0,0 +1,39 @@
+From 7d3d1744f8a7d62e4875bd69cc2192a939813880 Mon Sep 17 00:00:00 2001
+From: Liu Bo <bo.li.liu@oracle.com>
+Date: Sun, 29 Sep 2013 10:33:16 +0800
+Subject: Btrfs: fix memory leak of chunks' extent map
+
+From: Liu Bo <bo.li.liu@oracle.com>
+
+commit 7d3d1744f8a7d62e4875bd69cc2192a939813880 upstream.
+
+As we're hold a ref on looking up the extent map, we need to drop the ref
+before returning to callers.
+
+Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
+Signed-off-by: Josef Bacik <jbacik@fusionio.com>
+Signed-off-by: Chris Mason <chris.mason@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/volumes.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/btrfs/volumes.c
++++ b/fs/btrfs/volumes.c
+@@ -4488,6 +4488,7 @@ int btrfs_num_copies(struct btrfs_fs_inf
+               btrfs_crit(fs_info, "Invalid mapping for %Lu-%Lu, got "
+                           "%Lu-%Lu\n", logical, logical+len, em->start,
+                           em->start + em->len);
++              free_extent_map(em);
+               return 1;
+       }
+@@ -4668,6 +4669,7 @@ static int __btrfs_map_block(struct btrf
+               btrfs_crit(fs_info, "found a bad mapping, wanted %Lu, "
+                          "found %Lu-%Lu\n", logical, em->start,
+                          em->start + em->len);
++              free_extent_map(em);
+               return -EINVAL;
+       }
diff --git a/queue-3.12/btrfs-reset-intwrite-on-transaction-abort.patch b/queue-3.12/btrfs-reset-intwrite-on-transaction-abort.patch
new file mode 100644 (file)
index 0000000..ccd7b11
--- /dev/null
@@ -0,0 +1,31 @@
+From e0228285a8cad70e4b7b4833cc650e36ecd8de89 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fusionio.com>
+Date: Fri, 20 Sep 2013 22:26:29 -0400
+Subject: Btrfs: reset intwrite on transaction abort
+
+From: Josef Bacik <jbacik@fusionio.com>
+
+commit e0228285a8cad70e4b7b4833cc650e36ecd8de89 upstream.
+
+If we abort a transaction in the middle of a commit we weren't undoing the
+intwrite locking.  This patch fixes that problem.
+
+Signed-off-by: Josef Bacik <jbacik@fusionio.com>
+Signed-off-by: Chris Mason <chris.mason@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/transaction.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/btrfs/transaction.c
++++ b/fs/btrfs/transaction.c
+@@ -1552,6 +1552,8 @@ static void cleanup_transaction(struct b
+               root->fs_info->running_transaction = NULL;
+       spin_unlock(&root->fs_info->trans_lock);
++      if (trans->type & __TRANS_FREEZABLE)
++              sb_end_intwrite(root->fs_info->sb);
+       put_transaction(cur_trans);
+       put_transaction(cur_trans);
diff --git a/queue-3.12/btrfs-stop-using-vfs_read-in-send.patch b/queue-3.12/btrfs-stop-using-vfs_read-in-send.patch
new file mode 100644 (file)
index 0000000..1c711aa
--- /dev/null
@@ -0,0 +1,257 @@
+From ed2590953bd06b892f0411fc94e19175d32f197a Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fusionio.com>
+Date: Fri, 25 Oct 2013 11:36:01 -0400
+Subject: Btrfs: stop using vfs_read in send
+
+From: Josef Bacik <jbacik@fusionio.com>
+
+commit ed2590953bd06b892f0411fc94e19175d32f197a upstream.
+
+Apparently we don't actually close the files until we return to userspace, so
+stop using vfs_read in send.  This is actually better for us since we can avoid
+all the extra logic of holding the file we're sending open and making sure to
+clean it up.  This will fix people who have been hitting too many files open
+errors when trying to send.  Thanks,
+
+Signed-off-by: Josef Bacik <jbacik@fusionio.com>
+Signed-off-by: Chris Mason <chris.mason@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/send.c |  175 +++++++++++++++++++++++---------------------------------
+ 1 file changed, 72 insertions(+), 103 deletions(-)
+
+--- a/fs/btrfs/send.c
++++ b/fs/btrfs/send.c
+@@ -121,7 +121,6 @@ struct send_ctx {
+       struct list_head name_cache_list;
+       int name_cache_size;
+-      struct file *cur_inode_filp;
+       char *read_buf;
+ };
+@@ -2120,77 +2119,6 @@ out:
+ }
+ /*
+- * Called for regular files when sending extents data. Opens a struct file
+- * to read from the file.
+- */
+-static int open_cur_inode_file(struct send_ctx *sctx)
+-{
+-      int ret = 0;
+-      struct btrfs_key key;
+-      struct path path;
+-      struct inode *inode;
+-      struct dentry *dentry;
+-      struct file *filp;
+-      int new = 0;
+-
+-      if (sctx->cur_inode_filp)
+-              goto out;
+-
+-      key.objectid = sctx->cur_ino;
+-      key.type = BTRFS_INODE_ITEM_KEY;
+-      key.offset = 0;
+-
+-      inode = btrfs_iget(sctx->send_root->fs_info->sb, &key, sctx->send_root,
+-                      &new);
+-      if (IS_ERR(inode)) {
+-              ret = PTR_ERR(inode);
+-              goto out;
+-      }
+-
+-      dentry = d_obtain_alias(inode);
+-      inode = NULL;
+-      if (IS_ERR(dentry)) {
+-              ret = PTR_ERR(dentry);
+-              goto out;
+-      }
+-
+-      path.mnt = sctx->mnt;
+-      path.dentry = dentry;
+-      filp = dentry_open(&path, O_RDONLY | O_LARGEFILE, current_cred());
+-      dput(dentry);
+-      dentry = NULL;
+-      if (IS_ERR(filp)) {
+-              ret = PTR_ERR(filp);
+-              goto out;
+-      }
+-      sctx->cur_inode_filp = filp;
+-
+-out:
+-      /*
+-       * no xxxput required here as every vfs op
+-       * does it by itself on failure
+-       */
+-      return ret;
+-}
+-
+-/*
+- * Closes the struct file that was created in open_cur_inode_file
+- */
+-static int close_cur_inode_file(struct send_ctx *sctx)
+-{
+-      int ret = 0;
+-
+-      if (!sctx->cur_inode_filp)
+-              goto out;
+-
+-      ret = filp_close(sctx->cur_inode_filp, NULL);
+-      sctx->cur_inode_filp = NULL;
+-
+-out:
+-      return ret;
+-}
+-
+-/*
+  * Sends a BTRFS_SEND_C_SUBVOL command/item to userspace
+  */
+ static int send_subvol_begin(struct send_ctx *sctx)
+@@ -3622,6 +3550,72 @@ out:
+       return ret;
+ }
++static ssize_t fill_read_buf(struct send_ctx *sctx, u64 offset, u32 len)
++{
++      struct btrfs_root *root = sctx->send_root;
++      struct btrfs_fs_info *fs_info = root->fs_info;
++      struct inode *inode;
++      struct page *page;
++      char *addr;
++      struct btrfs_key key;
++      pgoff_t index = offset >> PAGE_CACHE_SHIFT;
++      pgoff_t last_index;
++      unsigned pg_offset = offset & ~PAGE_CACHE_MASK;
++      ssize_t ret = 0;
++
++      key.objectid = sctx->cur_ino;
++      key.type = BTRFS_INODE_ITEM_KEY;
++      key.offset = 0;
++
++      inode = btrfs_iget(fs_info->sb, &key, root, NULL);
++      if (IS_ERR(inode))
++              return PTR_ERR(inode);
++
++      if (offset + len > i_size_read(inode)) {
++              if (offset > i_size_read(inode))
++                      len = 0;
++              else
++                      len = offset - i_size_read(inode);
++      }
++      if (len == 0)
++              goto out;
++
++      last_index = (offset + len - 1) >> PAGE_CACHE_SHIFT;
++      while (index <= last_index) {
++              unsigned cur_len = min_t(unsigned, len,
++                                       PAGE_CACHE_SIZE - pg_offset);
++              page = find_or_create_page(inode->i_mapping, index, GFP_NOFS);
++              if (!page) {
++                      ret = -ENOMEM;
++                      break;
++              }
++
++              if (!PageUptodate(page)) {
++                      btrfs_readpage(NULL, page);
++                      lock_page(page);
++                      if (!PageUptodate(page)) {
++                              unlock_page(page);
++                              page_cache_release(page);
++                              ret = -EIO;
++                              break;
++                      }
++              }
++
++              addr = kmap(page);
++              memcpy(sctx->read_buf + ret, addr + pg_offset, cur_len);
++              kunmap(page);
++              unlock_page(page);
++              page_cache_release(page);
++              index++;
++              pg_offset = 0;
++              len -= cur_len;
++              ret += cur_len;
++      }
++out:
++      iput(inode);
++      return ret;
++}
++
+ /*
+  * Read some bytes from the current inode/file and send a write command to
+  * user space.
+@@ -3630,35 +3624,20 @@ static int send_write(struct send_ctx *s
+ {
+       int ret = 0;
+       struct fs_path *p;
+-      loff_t pos = offset;
+-      int num_read = 0;
+-      mm_segment_t old_fs;
++      ssize_t num_read = 0;
+       p = fs_path_alloc();
+       if (!p)
+               return -ENOMEM;
+-      /*
+-       * vfs normally only accepts user space buffers for security reasons.
+-       * we only read from the file and also only provide the read_buf buffer
+-       * to vfs. As this buffer does not come from a user space call, it's
+-       * ok to temporary allow kernel space buffers.
+-       */
+-      old_fs = get_fs();
+-      set_fs(KERNEL_DS);
+-
+ verbose_printk("btrfs: send_write offset=%llu, len=%d\n", offset, len);
+-      ret = open_cur_inode_file(sctx);
+-      if (ret < 0)
+-              goto out;
+-
+-      ret = vfs_read(sctx->cur_inode_filp, sctx->read_buf, len, &pos);
+-      if (ret < 0)
+-              goto out;
+-      num_read = ret;
+-      if (!num_read)
++      num_read = fill_read_buf(sctx, offset, len);
++      if (num_read <= 0) {
++              if (num_read < 0)
++                      ret = num_read;
+               goto out;
++      }
+       ret = begin_cmd(sctx, BTRFS_SEND_C_WRITE);
+       if (ret < 0)
+@@ -3677,7 +3656,6 @@ verbose_printk("btrfs: send_write offset
+ tlv_put_failure:
+ out:
+       fs_path_free(p);
+-      set_fs(old_fs);
+       if (ret < 0)
+               return ret;
+       return num_read;
+@@ -4222,10 +4200,6 @@ static int changed_inode(struct send_ctx
+       u64 left_gen = 0;
+       u64 right_gen = 0;
+-      ret = close_cur_inode_file(sctx);
+-      if (ret < 0)
+-              goto out;
+-
+       sctx->cur_ino = key->objectid;
+       sctx->cur_inode_new_gen = 0;
+@@ -4686,11 +4660,6 @@ static int send_subvol(struct send_ctx *
+       }
+ out:
+-      if (!ret)
+-              ret = close_cur_inode_file(sctx);
+-      else
+-              close_cur_inode_file(sctx);
+-
+       free_recorded_refs(sctx);
+       return ret;
+ }
diff --git a/queue-3.12/btrfs-take-ordered-root-lock-when-removing-ordered-operations-inode.patch b/queue-3.12/btrfs-take-ordered-root-lock-when-removing-ordered-operations-inode.patch
new file mode 100644 (file)
index 0000000..8667dcd
--- /dev/null
@@ -0,0 +1,33 @@
+From 93858769172c4e3678917810e9d5de360eb991cc Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fusionio.com>
+Date: Mon, 28 Oct 2013 09:13:25 -0400
+Subject: Btrfs: take ordered root lock when removing ordered operations inode
+
+From: Josef Bacik <jbacik@fusionio.com>
+
+commit 93858769172c4e3678917810e9d5de360eb991cc upstream.
+
+A user reported a list corruption warning from btrfs_remove_ordered_extent, it
+is because we aren't taking the ordered_root_lock when we remove the inode from
+the ordered operations list.  Thanks,
+
+Signed-off-by: Josef Bacik <jbacik@fusionio.com>
+Signed-off-by: Chris Mason <chris.mason@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/ordered-data.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/btrfs/ordered-data.c
++++ b/fs/btrfs/ordered-data.c
+@@ -537,7 +537,9 @@ void btrfs_remove_ordered_extent(struct
+        */
+       if (RB_EMPTY_ROOT(&tree->tree) &&
+           !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_DIRTY)) {
++              spin_lock(&root->fs_info->ordered_root_lock);
+               list_del_init(&BTRFS_I(inode)->ordered_operations);
++              spin_unlock(&root->fs_info->ordered_root_lock);
+       }
+       if (!root->nr_ordered_extents) {
index 23b37845d01961d4f9aa6ea9c72f7da54a92f7bd..c2db0092adf14004f714307e428efde2a7996d4e 100644 (file)
@@ -103,3 +103,13 @@ sc1200_wdt-fix-oops.patch
 nfsv4-wait-on-recovery-for-async-session-errors.patch
 input-elantech-add-support-for-newer-august-2013-devices.patch
 revert-net-update-consumers-of-msg_more-to-recognize-msg_sendpage_notlast.patch
+btrfs-do-a-full-search-everytime-in-btrfs_search_old_slot.patch
+btrfs-reset-intwrite-on-transaction-abort.patch
+btrfs-fix-memory-leak-of-chunks-extent-map.patch
+btrfs-fix-hole-check-in-log_one_extent.patch
+btrfs-fix-incorrect-inode-acl-reset.patch
+btrfs-stop-using-vfs_read-in-send.patch
+btrfs-take-ordered-root-lock-when-removing-ordered-operations-inode.patch
+btrfs-do-not-run-snapshot-aware-defragment-on-error.patch
+btrfs-fix-a-crash-when-running-balance-and-defrag-concurrently.patch
+btrfs-fix-lockdep-error-in-async-commit.patch