--- /dev/null
+From d8fe29e9dea8d7d61fd140d8779326856478fc62 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fusionio.com>
+Date: Fri, 29 Mar 2013 08:09:34 -0600
+Subject: Btrfs: don't drop path when printing out tree errors in scrub
+
+From: Josef Bacik <jbacik@fusionio.com>
+
+commit d8fe29e9dea8d7d61fd140d8779326856478fc62 upstream.
+
+A user reported a panic where we were panicing somewhere in
+tree_backref_for_extent from scrub_print_warning. He only captured the trace
+but looking at scrub_print_warning we drop the path right before we mess with
+the extent buffer to print out a bunch of stuff, which isn't right. So fix this
+by dropping the path after we use the eb if we need to. 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/scrub.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/btrfs/scrub.c
++++ b/fs/btrfs/scrub.c
+@@ -383,7 +383,6 @@ static void scrub_print_warning(const ch
+ eb = path->nodes[0];
+ ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item);
+ item_size = btrfs_item_size_nr(eb, path->slots[0]);
+- btrfs_release_path(path);
+
+ if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
+ do {
+@@ -398,7 +397,9 @@ static void scrub_print_warning(const ch
+ ret < 0 ? -1 : ref_level,
+ ret < 0 ? -1 : ref_root);
+ } while (ret != 1);
++ btrfs_release_path(path);
+ } else {
++ btrfs_release_path(path);
+ swarn.path = path;
+ iterate_extent_inodes(fs_info, found_key.objectid,
+ extent_item_pos, 1,
--- /dev/null
+From 4adaa611020fa6ac65b0ac8db78276af4ec04e63 Mon Sep 17 00:00:00 2001
+From: Chris Mason <chris.mason@fusionio.com>
+Date: Tue, 26 Mar 2013 13:07:00 -0400
+Subject: Btrfs: fix race between mmap writes and compression
+
+From: Chris Mason <chris.mason@fusionio.com>
+
+commit 4adaa611020fa6ac65b0ac8db78276af4ec04e63 upstream.
+
+Btrfs uses page_mkwrite to ensure stable pages during
+crc calculations and mmap workloads. We call clear_page_dirty_for_io
+before we do any crcs, and this forces any application with the file
+mapped to wait for the crc to finish before it is allowed to change
+the file.
+
+With compression on, the clear_page_dirty_for_io step is happening after
+we've compressed the pages. This means the applications might be
+changing the pages while we are compressing them, and some of those
+modifications might not hit the disk.
+
+This commit adds the clear_page_dirty_for_io before compression starts
+and makes sure to redirty the page if we have to fallback to
+uncompressed IO as well.
+
+Signed-off-by: Chris Mason <chris.mason@fusionio.com>
+Reported-by: Alexandre Oliva <oliva@gnu.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/extent_io.c | 33 +++++++++++++++++++++++++++++++++
+ fs/btrfs/extent_io.h | 2 ++
+ fs/btrfs/inode.c | 14 ++++++++++++++
+ 3 files changed, 49 insertions(+)
+
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -1238,6 +1238,39 @@ int unlock_extent(struct extent_io_tree
+ GFP_NOFS);
+ }
+
++int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end)
++{
++ unsigned long index = start >> PAGE_CACHE_SHIFT;
++ unsigned long end_index = end >> PAGE_CACHE_SHIFT;
++ struct page *page;
++
++ while (index <= end_index) {
++ page = find_get_page(inode->i_mapping, index);
++ BUG_ON(!page); /* Pages should be in the extent_io_tree */
++ clear_page_dirty_for_io(page);
++ page_cache_release(page);
++ index++;
++ }
++ return 0;
++}
++
++int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end)
++{
++ unsigned long index = start >> PAGE_CACHE_SHIFT;
++ unsigned long end_index = end >> PAGE_CACHE_SHIFT;
++ struct page *page;
++
++ while (index <= end_index) {
++ page = find_get_page(inode->i_mapping, index);
++ BUG_ON(!page); /* Pages should be in the extent_io_tree */
++ account_page_redirty(page);
++ __set_page_dirty_nobuffers(page);
++ page_cache_release(page);
++ index++;
++ }
++ return 0;
++}
++
+ /*
+ * helper function to set both pages and extents in the tree writeback
+ */
+--- a/fs/btrfs/extent_io.h
++++ b/fs/btrfs/extent_io.h
+@@ -312,6 +312,8 @@ int map_private_extent_buffer(struct ext
+ unsigned long *map_len);
+ int extent_range_uptodate(struct extent_io_tree *tree,
+ u64 start, u64 end);
++int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end);
++int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end);
+ int extent_clear_unlock_delalloc(struct inode *inode,
+ struct extent_io_tree *tree,
+ u64 start, u64 end, struct page *locked_page,
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -349,6 +349,7 @@ static noinline int compress_file_range(
+ int i;
+ int will_compress;
+ int compress_type = root->fs_info->compress_type;
++ int redirty = 0;
+
+ /* if this is a small write inside eof, kick off a defrag */
+ if ((end - start + 1) < 16 * 1024 &&
+@@ -411,6 +412,17 @@ again:
+ if (BTRFS_I(inode)->force_compress)
+ compress_type = BTRFS_I(inode)->force_compress;
+
++ /*
++ * we need to call clear_page_dirty_for_io on each
++ * page in the range. Otherwise applications with the file
++ * mmap'd can wander in and change the page contents while
++ * we are compressing them.
++ *
++ * If the compression fails for any reason, we set the pages
++ * dirty again later on.
++ */
++ extent_range_clear_dirty_for_io(inode, start, end);
++ redirty = 1;
+ ret = btrfs_compress_pages(compress_type,
+ inode->i_mapping, start,
+ total_compressed, pages,
+@@ -552,6 +564,8 @@ cleanup_and_bail_uncompressed:
+ __set_page_dirty_nobuffers(locked_page);
+ /* unlocked later on in the async handlers */
+ }
++ if (redirty)
++ extent_range_redirty_for_io(inode, start, end);
+ add_async_extent(async_cow, start, end - start + 1,
+ 0, NULL, 0, BTRFS_COMPRESS_NONE);
+ *num_added += 1;
--- /dev/null
+From fdf30d1c1b386e1b73116cc7e0fb14e962b763b0 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fusionio.com>
+Date: Tue, 26 Mar 2013 15:31:45 -0400
+Subject: Btrfs: limit the global reserve to 512mb
+
+From: Josef Bacik <jbacik@fusionio.com>
+
+commit fdf30d1c1b386e1b73116cc7e0fb14e962b763b0 upstream.
+
+A user reported a problem where he was getting early ENOSPC with hundreds of
+gigs of free data space and 6 gigs of free metadata space. This is because the
+global block reserve was taking up the entire free metadata space. This is
+ridiculous, we have infrastructure in place to throttle if we start using too
+much of the global reserve, so instead of letting it get this huge just limit it
+to 512mb so that users can still get work done. This allowed the user to
+complete his rsync without issues. Thanks
+
+Reported-and-tested-by: Stefan Priebe <s.priebe@profihost.ag>
+Signed-off-by: Josef Bacik <jbacik@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/extent-tree.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -4217,7 +4217,7 @@ static void update_global_block_rsv(stru
+ spin_lock(&sinfo->lock);
+ spin_lock(&block_rsv->lock);
+
+- block_rsv->size = num_bytes;
++ block_rsv->size = min_t(u64, num_bytes, 512 * 1024 * 1024);
+
+ num_bytes = sinfo->bytes_used + sinfo->bytes_pinned +
+ sinfo->bytes_reserved + sinfo->bytes_readonly +