aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-06-17 17:14:39 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-07-01 08:52:33 -0400
commita71754fc68f740b7ed46bb83123c63fbbc130611 (patch)
treec39655c68a713d4707cb476ac28702bb4e302ed2
parent0b08851fdaa5f9f74357345d7be44ea584665d5f (diff)
Btrfs: move btrfs_truncate_page to btrfs_cont_expand instead of btrfs_truncate
This has plagued us forever and I'm so over working around it. When we truncate down to a non-page aligned offset we will call btrfs_truncate_page to zero out the end of the page and write it back to disk, this will keep us from exposing stale data if we truncate back up from that point. The problem with this is it requires data space to do this, and people don't really expect to get ENOSPC from truncate() for these sort of things. This also tends to bite the orphan cleanup stuff too which keeps people from mounting. To get around this we can just move this into btrfs_cont_expand() to make sure if we are truncating up from a non-page size aligned i_size we will zero out the rest of this page so that we don't expose stale data. This will give ENOSPC if you try to truncate() up or if you try to write past the end of isize, which is much more reasonable. This fixes xfstests generic/083 failing to mount because of the orphan cleanup failing. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
-rw-r--r--fs/btrfs/extent_io.c11
-rw-r--r--fs/btrfs/file.c21
-rw-r--r--fs/btrfs/inode.c15
3 files changed, 35 insertions, 12 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 03ca3ab95898..a83d7019ede9 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -2477,11 +2477,12 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
2477 struct extent_state *cached = NULL; 2477 struct extent_state *cached = NULL;
2478 struct extent_state *state; 2478 struct extent_state *state;
2479 struct btrfs_io_bio *io_bio = btrfs_io_bio(bio); 2479 struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
2480 struct inode *inode = page->mapping->host;
2480 2481
2481 pr_debug("end_bio_extent_readpage: bi_sector=%llu, err=%d, " 2482 pr_debug("end_bio_extent_readpage: bi_sector=%llu, err=%d, "
2482 "mirror=%lu\n", (u64)bio->bi_sector, err, 2483 "mirror=%lu\n", (u64)bio->bi_sector, err,
2483 io_bio->mirror_num); 2484 io_bio->mirror_num);
2484 tree = &BTRFS_I(page->mapping->host)->io_tree; 2485 tree = &BTRFS_I(inode)->io_tree;
2485 2486
2486 /* We always issue full-page reads, but if some block 2487 /* We always issue full-page reads, but if some block
2487 * in a page fails to read, blk_update_request() will 2488 * in a page fails to read, blk_update_request() will
@@ -2555,6 +2556,14 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
2555 unlock_extent_cached(tree, start, end, &cached, GFP_ATOMIC); 2556 unlock_extent_cached(tree, start, end, &cached, GFP_ATOMIC);
2556 2557
2557 if (uptodate) { 2558 if (uptodate) {
2559 loff_t i_size = i_size_read(inode);
2560 pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
2561 unsigned offset;
2562
2563 /* Zero out the end if this page straddles i_size */
2564 offset = i_size & (PAGE_CACHE_SIZE-1);
2565 if (page->index == end_index && offset)
2566 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
2558 SetPageUptodate(page); 2567 SetPageUptodate(page);
2559 } else { 2568 } else {
2560 ClearPageUptodate(page); 2569 ClearPageUptodate(page);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 185af15ad9e4..5ffde5603686 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -2173,12 +2173,6 @@ static long btrfs_fallocate(struct file *file, int mode,
2173 goto out_reserve_fail; 2173 goto out_reserve_fail;
2174 } 2174 }
2175 2175
2176 /*
2177 * wait for ordered IO before we have any locks. We'll loop again
2178 * below with the locks held.
2179 */
2180 btrfs_wait_ordered_range(inode, alloc_start, alloc_end - alloc_start);
2181
2182 mutex_lock(&inode->i_mutex); 2176 mutex_lock(&inode->i_mutex);
2183 ret = inode_newsize_ok(inode, alloc_end); 2177 ret = inode_newsize_ok(inode, alloc_end);
2184 if (ret) 2178 if (ret)
@@ -2189,8 +2183,23 @@ static long btrfs_fallocate(struct file *file, int mode,
2189 alloc_start); 2183 alloc_start);
2190 if (ret) 2184 if (ret)
2191 goto out; 2185 goto out;
2186 } else {
2187 /*
2188 * If we are fallocating from the end of the file onward we
2189 * need to zero out the end of the page if i_size lands in the
2190 * middle of a page.
2191 */
2192 ret = btrfs_truncate_page(inode, inode->i_size, 0, 0);
2193 if (ret)
2194 goto out;
2192 } 2195 }
2193 2196
2197 /*
2198 * wait for ordered IO before we have any locks. We'll loop again
2199 * below with the locks held.
2200 */
2201 btrfs_wait_ordered_range(inode, alloc_start, alloc_end - alloc_start);
2202
2194 locked_end = alloc_end - 1; 2203 locked_end = alloc_end - 1;
2195 while (1) { 2204 while (1) {
2196 struct btrfs_ordered_extent *ordered; 2205 struct btrfs_ordered_extent *ordered;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 509112da6118..b7fa96f72ecd 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -4253,6 +4253,15 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
4253 u64 hole_size; 4253 u64 hole_size;
4254 int err = 0; 4254 int err = 0;
4255 4255
4256 /*
4257 * If our size started in the middle of a page we need to zero out the
4258 * rest of the page before we expand the i_size, otherwise we could
4259 * expose stale data.
4260 */
4261 err = btrfs_truncate_page(inode, oldsize, 0, 0);
4262 if (err)
4263 return err;
4264
4256 if (size <= hole_start) 4265 if (size <= hole_start)
4257 return 0; 4266 return 0;
4258 4267
@@ -7565,16 +7574,12 @@ static int btrfs_truncate(struct inode *inode)
7565{ 7574{
7566 struct btrfs_root *root = BTRFS_I(inode)->root; 7575 struct btrfs_root *root = BTRFS_I(inode)->root;
7567 struct btrfs_block_rsv *rsv; 7576 struct btrfs_block_rsv *rsv;
7568 int ret; 7577 int ret = 0;
7569 int err = 0; 7578 int err = 0;
7570 struct btrfs_trans_handle *trans; 7579 struct btrfs_trans_handle *trans;
7571 u64 mask = root->sectorsize - 1; 7580 u64 mask = root->sectorsize - 1;
7572 u64 min_size = btrfs_calc_trunc_metadata_size(root, 1); 7581 u64 min_size = btrfs_calc_trunc_metadata_size(root, 1);
7573 7582
7574 ret = btrfs_truncate_page(inode, inode->i_size, 0, 0);
7575 if (ret)
7576 return ret;
7577
7578 btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1); 7583 btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1);
7579 btrfs_ordered_update_i_size(inode, inode->i_size, NULL); 7584 btrfs_ordered_update_i_size(inode, inode->i_size, NULL);
7580 7585