--- /dev/null
+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) {
--- /dev/null
+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);
--- /dev/null
+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;
--- /dev/null
+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;
+ }
+
--- /dev/null
+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 {
--- /dev/null
+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_);
--- /dev/null
+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;
+ }
+
--- /dev/null
+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);
+
--- /dev/null
+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;
+ }
--- /dev/null
+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) {
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