summaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorJosef Bacik2009-10-01 23:10:23 +0200
committerChris Mason2009-10-01 23:10:23 +0200
commitfbf190874407f23d2891b53ffdf7d3c6be8d47ff (patch)
treec60ab388e2b19b02fd3bbcef76498a3520f9dcbd /fs/btrfs
parentBtrfs: take i_mutex before generic_write_checks (diff)
downloadkernel-qcow2-linux-fbf190874407f23d2891b53ffdf7d3c6be8d47ff.tar.gz
kernel-qcow2-linux-fbf190874407f23d2891b53ffdf7d3c6be8d47ff.tar.xz
kernel-qcow2-linux-fbf190874407f23d2891b53ffdf7d3c6be8d47ff.zip
Btrfs: fix data space leak fix
There is a problem where page_mkwrite can be called on a dirtied page that already has a delalloc range associated with it. The fix is to clear any delalloc bits for the range we are dirtying so the space accounting gets handled properly. This is the same thing we do in the normal write case, so we are consistent across the board. With this patch we no longer leak reserved space. Signed-off-by: Josef Bacik <jbacik@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/inode.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 3cc5677f5440..3a6f953337b5 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -4909,10 +4909,21 @@ again:
goto again;
}
+ /*
+ * XXX - page_mkwrite gets called every time the page is dirtied, even
+ * if it was already dirty, so for space accounting reasons we need to
+ * clear any delalloc bits for the range we are fixing to save. There
+ * is probably a better way to do this, but for now keep consistent with
+ * prepare_pages in the normal write path.
+ */
+ clear_extent_bits(&BTRFS_I(inode)->io_tree, page_start, page_end,
+ EXTENT_DIRTY | EXTENT_DELALLOC, GFP_NOFS);
+
ret = btrfs_set_extent_delalloc(inode, page_start, page_end);
if (ret) {
unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
ret = VM_FAULT_SIGBUS;
+ btrfs_free_reserved_data_space(root, inode, PAGE_CACHE_SIZE);
goto out_unlock;
}
ret = 0;