--- /dev/null
+From 8bd98f0e6bf792e8fa7c3fed709321ad42ba8d2e Mon Sep 17 00:00:00 2001
+From: Alex Lyakas <alex.bolshoy@gmail.com>
+Date: Thu, 10 Mar 2016 13:09:46 +0200
+Subject: btrfs: csum_tree_block: return proper errno value
+
+From: Alex Lyakas <alex.bolshoy@gmail.com>
+
+commit 8bd98f0e6bf792e8fa7c3fed709321ad42ba8d2e upstream.
+
+Signed-off-by: Alex Lyakas <alex@zadarastorage.com>
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/disk-io.c | 13 +++++--------
+ 1 file changed, 5 insertions(+), 8 deletions(-)
+
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -303,7 +303,7 @@ static int csum_tree_block(struct btrfs_
+ err = map_private_extent_buffer(buf, offset, 32,
+ &kaddr, &map_start, &map_len);
+ if (err)
+- return 1;
++ return err;
+ cur_len = min(len, map_len - (offset - map_start));
+ crc = btrfs_csum_data(kaddr + offset - map_start,
+ crc, cur_len);
+@@ -313,7 +313,7 @@ static int csum_tree_block(struct btrfs_
+ if (csum_size > sizeof(inline_result)) {
+ result = kzalloc(csum_size, GFP_NOFS);
+ if (!result)
+- return 1;
++ return -ENOMEM;
+ } else {
+ result = (char *)&inline_result;
+ }
+@@ -334,7 +334,7 @@ static int csum_tree_block(struct btrfs_
+ val, found, btrfs_header_level(buf));
+ if (result != (char *)&inline_result)
+ kfree(result);
+- return 1;
++ return -EUCLEAN;
+ }
+ } else {
+ write_extent_buffer(buf, result, 0, csum_size);
+@@ -516,8 +516,7 @@ static int csum_dirty_buffer(struct btrf
+ found_start = btrfs_header_bytenr(eb);
+ if (WARN_ON(found_start != start || !PageUptodate(page)))
+ return 0;
+- csum_tree_block(fs_info, eb, 0);
+- return 0;
++ return csum_tree_block(fs_info, eb, 0);
+ }
+
+ static int check_tree_block_fsid(struct btrfs_fs_info *fs_info,
+@@ -660,10 +659,8 @@ static int btree_readpage_end_io_hook(st
+ eb, found_level);
+
+ ret = csum_tree_block(root->fs_info, eb, 1);
+- if (ret) {
+- ret = -EIO;
++ if (ret)
+ goto err;
+- }
+
+ /*
+ * If this is a leaf block and it is corrupt, set the corrupt bit so
--- /dev/null
+From 0f805531daa2ebfb5706422dc2ead1cff9e53e65 Mon Sep 17 00:00:00 2001
+From: Alex Lyakas <alex.bolshoy@gmail.com>
+Date: Thu, 10 Mar 2016 13:10:15 +0200
+Subject: btrfs: do not write corrupted metadata blocks to disk
+
+From: Alex Lyakas <alex.bolshoy@gmail.com>
+
+commit 0f805531daa2ebfb5706422dc2ead1cff9e53e65 upstream.
+
+csum_dirty_buffer was issuing a warning in case the extent buffer
+did not look alright, but was still returning success.
+Let's return error in this case, and also add an additional sanity
+check on the extent buffer header.
+The caller up the chain may BUG_ON on this, for example flush_epd_write_bio will,
+but it is better than to have a silent metadata corruption on disk.
+
+Signed-off-by: Alex Lyakas <alex@zadarastorage.com>
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/disk-io.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -513,9 +513,20 @@ static int csum_dirty_buffer(struct btrf
+ eb = (struct extent_buffer *)page->private;
+ if (page != eb->pages[0])
+ return 0;
++
+ found_start = btrfs_header_bytenr(eb);
+- if (WARN_ON(found_start != start || !PageUptodate(page)))
+- return 0;
++ /*
++ * Please do not consolidate these warnings into a single if.
++ * It is useful to know what went wrong.
++ */
++ if (WARN_ON(found_start != start))
++ return -EUCLEAN;
++ if (WARN_ON(!PageUptodate(page)))
++ return -EUCLEAN;
++
++ ASSERT(memcmp_extent_buffer(eb, fs_info->fsid,
++ btrfs_header_fsid(), BTRFS_FSID_SIZE) == 0);
++
+ return csum_tree_block(fs_info, eb, 0);
+ }
+
--- /dev/null
+From c79b4713304f812d3d6c95826fc3e5fc2c0b0c14 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fb.com>
+Date: Fri, 25 Mar 2016 10:02:41 -0400
+Subject: Btrfs: don't use src fd for printk
+
+From: Josef Bacik <jbacik@fb.com>
+
+commit c79b4713304f812d3d6c95826fc3e5fc2c0b0c14 upstream.
+
+The fd we pass in may not be on a btrfs file system, so don't try to do
+BTRFS_I() on it. Thanks,
+
+Signed-off-by: Josef Bacik <jbacik@fb.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/ioctl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -1657,7 +1657,7 @@ static noinline int btrfs_ioctl_snap_cre
+
+ src_inode = file_inode(src.file);
+ if (src_inode->i_sb != file_inode(file)->i_sb) {
+- btrfs_info(BTRFS_I(src_inode)->root->fs_info,
++ btrfs_info(BTRFS_I(file_inode(file))->root->fs_info,
+ "Snapshot src from another FS");
+ ret = -EXDEV;
+ } else if (!inode_owner_or_capable(src_inode)) {
--- /dev/null
+From 8f282f71eaee7ac979cdbe525f76daa0722798a8 Mon Sep 17 00:00:00 2001
+From: David Sterba <dsterba@suse.com>
+Date: Wed, 30 Mar 2016 16:01:12 +0200
+Subject: btrfs: fallback to vmalloc in btrfs_compare_tree
+
+From: David Sterba <dsterba@suse.com>
+
+commit 8f282f71eaee7ac979cdbe525f76daa0722798a8 upstream.
+
+The allocation of node could fail if the memory is too fragmented for a
+given node size, practically observed with 64k.
+
+http://article.gmane.org/gmane.comp.file-systems.btrfs/54689
+
+Reported-and-tested-by: Jean-Denis Girard <jd.girard@sysnux.pf>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/ctree.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/fs/btrfs/ctree.c
++++ b/fs/btrfs/ctree.c
+@@ -19,6 +19,7 @@
+ #include <linux/sched.h>
+ #include <linux/slab.h>
+ #include <linux/rbtree.h>
++#include <linux/vmalloc.h>
+ #include "ctree.h"
+ #include "disk-io.h"
+ #include "transaction.h"
+@@ -5361,10 +5362,13 @@ int btrfs_compare_trees(struct btrfs_roo
+ goto out;
+ }
+
+- tmp_buf = kmalloc(left_root->nodesize, GFP_NOFS);
++ tmp_buf = kmalloc(left_root->nodesize, GFP_KERNEL | __GFP_NOWARN);
+ if (!tmp_buf) {
+- ret = -ENOMEM;
+- goto out;
++ tmp_buf = vmalloc(left_root->nodesize);
++ if (!tmp_buf) {
++ ret = -ENOMEM;
++ goto out;
++ }
+ }
+
+ left_path->search_commit_root = 1;
+@@ -5565,7 +5569,7 @@ int btrfs_compare_trees(struct btrfs_roo
+ out:
+ btrfs_free_path(left_path);
+ btrfs_free_path(right_path);
+- kfree(tmp_buf);
++ kvfree(tmp_buf);
+ return ret;
+ }
+
--- /dev/null
+From 264813acb1c756aebc337b16b832604a0c9aadaf Mon Sep 17 00:00:00 2001
+From: Liu Bo <bo.li.liu@oracle.com>
+Date: Mon, 21 Mar 2016 14:59:53 -0700
+Subject: Btrfs: fix invalid reference in replace_path
+
+From: Liu Bo <bo.li.liu@oracle.com>
+
+commit 264813acb1c756aebc337b16b832604a0c9aadaf upstream.
+
+Dan Carpenter's static checker has found this error, it's introduced by
+commit 64c043de466d
+("Btrfs: fix up read_tree_block to return proper error")
+
+It's really supposed to 'break' the loop on error like others.
+
+Cc: Dan Carpenter <dan.carpenter@oracle.com>
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/relocation.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/btrfs/relocation.c
++++ b/fs/btrfs/relocation.c
+@@ -1850,6 +1850,7 @@ again:
+ eb = read_tree_block(dest, old_bytenr, old_ptr_gen);
+ if (IS_ERR(eb)) {
+ ret = PTR_ERR(eb);
++ break;
+ } else if (!extent_buffer_uptodate(eb)) {
+ ret = -EIO;
+ free_extent_buffer(eb);
--- /dev/null
+From 918c2ee103cf9956f1c61d3f848dbb49fd2d104a Mon Sep 17 00:00:00 2001
+From: Mark Fasheh <mfasheh@suse.de>
+Date: Wed, 30 Mar 2016 17:57:48 -0700
+Subject: btrfs: handle non-fatal errors in btrfs_qgroup_inherit()
+
+From: Mark Fasheh <mfasheh@suse.de>
+
+commit 918c2ee103cf9956f1c61d3f848dbb49fd2d104a upstream.
+
+create_pending_snapshot() will go readonly on _any_ error return from
+btrfs_qgroup_inherit(). If qgroups are enabled, a user can crash their fs by
+just making a snapshot and asking it to inherit from an invalid qgroup. For
+example:
+
+$ btrfs sub snap -i 1/10 /btrfs/ /btrfs/foo
+
+Will cause a transaction abort.
+
+Fix this by only throwing errors in btrfs_qgroup_inherit() when we know
+going readonly is acceptable.
+
+The following xfstests test case reproduces this bug:
+
+ seq=`basename $0`
+ seqres=$RESULT_DIR/$seq
+ echo "QA output created by $seq"
+
+ here=`pwd`
+ tmp=/tmp/$$
+ status=1 # failure is the default!
+ trap "_cleanup; exit \$status" 0 1 2 3 15
+
+ _cleanup()
+ {
+ cd /
+ rm -f $tmp.*
+ }
+
+ # get standard environment, filters and checks
+ . ./common/rc
+ . ./common/filter
+
+ # remove previous $seqres.full before test
+ rm -f $seqres.full
+
+ # real QA test starts here
+ _supported_fs btrfs
+ _supported_os Linux
+ _require_scratch
+
+ rm -f $seqres.full
+
+ _scratch_mkfs
+ _scratch_mount
+ _run_btrfs_util_prog quota enable $SCRATCH_MNT
+ # The qgroup '1/10' does not exist and should be silently ignored
+ _run_btrfs_util_prog subvolume snapshot -i 1/10 $SCRATCH_MNT $SCRATCH_MNT/snap1
+
+ _scratch_unmount
+
+ echo "Silence is golden"
+
+ status=0
+ exit
+
+Signed-off-by: Mark Fasheh <mfasheh@suse.de>
+Reviewed-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/qgroup.c | 54 ++++++++++++++++++++++++++++++++----------------------
+ 1 file changed, 32 insertions(+), 22 deletions(-)
+
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -1842,8 +1842,10 @@ out:
+ }
+
+ /*
+- * copy the acounting information between qgroups. This is necessary when a
+- * snapshot or a subvolume is created
++ * Copy the acounting information between qgroups. This is necessary
++ * when a snapshot or a subvolume is created. Throwing an error will
++ * cause a transaction abort so we take extra care here to only error
++ * when a readonly fs is a reasonable outcome.
+ */
+ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
+ struct btrfs_fs_info *fs_info, u64 srcid, u64 objectid,
+@@ -1873,15 +1875,15 @@ int btrfs_qgroup_inherit(struct btrfs_tr
+ 2 * inherit->num_excl_copies;
+ for (i = 0; i < nums; ++i) {
+ srcgroup = find_qgroup_rb(fs_info, *i_qgroups);
+- if (!srcgroup) {
+- ret = -EINVAL;
+- goto out;
+- }
+
+- if ((srcgroup->qgroupid >> 48) <= (objectid >> 48)) {
+- ret = -EINVAL;
+- goto out;
+- }
++ /*
++ * Zero out invalid groups so we can ignore
++ * them later.
++ */
++ if (!srcgroup ||
++ ((srcgroup->qgroupid >> 48) <= (objectid >> 48)))
++ *i_qgroups = 0ULL;
++
+ ++i_qgroups;
+ }
+ }
+@@ -1916,17 +1918,19 @@ int btrfs_qgroup_inherit(struct btrfs_tr
+ */
+ if (inherit) {
+ i_qgroups = (u64 *)(inherit + 1);
+- for (i = 0; i < inherit->num_qgroups; ++i) {
++ for (i = 0; i < inherit->num_qgroups; ++i, ++i_qgroups) {
++ if (*i_qgroups == 0)
++ continue;
+ ret = add_qgroup_relation_item(trans, quota_root,
+ objectid, *i_qgroups);
+- if (ret)
++ if (ret && ret != -EEXIST)
+ goto out;
+ ret = add_qgroup_relation_item(trans, quota_root,
+ *i_qgroups, objectid);
+- if (ret)
++ if (ret && ret != -EEXIST)
+ goto out;
+- ++i_qgroups;
+ }
++ ret = 0;
+ }
+
+
+@@ -1987,17 +1991,22 @@ int btrfs_qgroup_inherit(struct btrfs_tr
+
+ i_qgroups = (u64 *)(inherit + 1);
+ for (i = 0; i < inherit->num_qgroups; ++i) {
+- ret = add_relation_rb(quota_root->fs_info, objectid,
+- *i_qgroups);
+- if (ret)
+- goto unlock;
++ if (*i_qgroups) {
++ ret = add_relation_rb(quota_root->fs_info, objectid,
++ *i_qgroups);
++ if (ret)
++ goto unlock;
++ }
+ ++i_qgroups;
+ }
+
+- for (i = 0; i < inherit->num_ref_copies; ++i) {
++ for (i = 0; i < inherit->num_ref_copies; ++i, i_qgroups += 2) {
+ struct btrfs_qgroup *src;
+ struct btrfs_qgroup *dst;
+
++ if (!i_qgroups[0] || !i_qgroups[1])
++ continue;
++
+ src = find_qgroup_rb(fs_info, i_qgroups[0]);
+ dst = find_qgroup_rb(fs_info, i_qgroups[1]);
+
+@@ -2008,12 +2017,14 @@ int btrfs_qgroup_inherit(struct btrfs_tr
+
+ dst->rfer = src->rfer - level_size;
+ dst->rfer_cmpr = src->rfer_cmpr - level_size;
+- i_qgroups += 2;
+ }
+- for (i = 0; i < inherit->num_excl_copies; ++i) {
++ for (i = 0; i < inherit->num_excl_copies; ++i, i_qgroups += 2) {
+ struct btrfs_qgroup *src;
+ struct btrfs_qgroup *dst;
+
++ if (!i_qgroups[0] || !i_qgroups[1])
++ continue;
++
+ src = find_qgroup_rb(fs_info, i_qgroups[0]);
+ dst = find_qgroup_rb(fs_info, i_qgroups[1]);
+
+@@ -2024,7 +2035,6 @@ int btrfs_qgroup_inherit(struct btrfs_tr
+
+ dst->excl = src->excl + level_size;
+ dst->excl_cmpr = src->excl_cmpr + level_size;
+- i_qgroups += 2;
+ }
+
+ unlock:
--- /dev/null
+From 7ccefb98ce3e5c4493cd213cd03714b7149cf0cb Mon Sep 17 00:00:00 2001
+From: Yauhen Kharuzhy <yauhen.kharuzhy@zavadatar.com>
+Date: Tue, 29 Mar 2016 14:17:48 -0700
+Subject: btrfs: Reset IO error counters before start of device replacing
+
+From: Yauhen Kharuzhy <yauhen.kharuzhy@zavadatar.com>
+
+commit 7ccefb98ce3e5c4493cd213cd03714b7149cf0cb upstream.
+
+If device replace entry was found on disk at mounting and its num_write_errors
+stats counter has non-NULL value, then replace operation will never be
+finished and -EIO error will be reported by btrfs_scrub_dev() because
+this counter is never reset.
+
+ # mount -o degraded /media/a4fb5c0a-21c5-4fe7-8d0e-fdd87d5f71ee/
+ # btrfs replace status /media/a4fb5c0a-21c5-4fe7-8d0e-fdd87d5f71ee/
+ Started on 25.Mar 07:28:00, canceled on 25.Mar 07:28:01 at 0.0%, 40 write errs, 0 uncorr. read errs
+ # btrfs replace start -B 4 /dev/sdg /media/a4fb5c0a-21c5-4fe7-8d0e-fdd87d5f71ee/
+ ERROR: ioctl(DEV_REPLACE_START) failed on "/media/a4fb5c0a-21c5-4fe7-8d0e-fdd87d5f71ee/": Input/output error, no error
+
+Reset num_write_errors and num_uncorrectable_read_errors counters in the
+dev_replace structure before start of replacing.
+
+Signed-off-by: Yauhen Kharuzhy <yauhen.kharuzhy@zavadatar.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/dev-replace.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/btrfs/dev-replace.c
++++ b/fs/btrfs/dev-replace.c
+@@ -394,6 +394,8 @@ int btrfs_dev_replace_start(struct btrfs
+ dev_replace->cursor_right = 0;
+ dev_replace->is_valid = 1;
+ dev_replace->item_needs_writeback = 1;
++ atomic64_set(&dev_replace->num_write_errors, 0);
++ atomic64_set(&dev_replace->num_uncorrectable_read_errors, 0);
+ args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR;
+ btrfs_dev_replace_unlock(dev_replace);
+
btrfs-fix-deadlock-between-direct-io-reads-and-buffered-writes.patch
btrfs-fix-race-when-checking-if-we-can-skip-fsync-ing-an-inode.patch
btrfs-do-not-collect-ordered-extents-when-logging-that-inode-exists.patch
+btrfs-csum_tree_block-return-proper-errno-value.patch
+btrfs-do-not-write-corrupted-metadata-blocks-to-disk.patch
+btrfs-fix-invalid-reference-in-replace_path.patch
+btrfs-handle-non-fatal-errors-in-btrfs_qgroup_inherit.patch
+btrfs-fallback-to-vmalloc-in-btrfs_compare_tree.patch
+btrfs-don-t-use-src-fd-for-printk.patch
+btrfs-reset-io-error-counters-before-start-of-device-replacing.patch