aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3/inode.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2011-06-03 15:58:11 -0400
committerJan Kara <jack@suse.cz>2011-06-25 11:29:52 -0400
commitee3e77f18010679a889b3831c2dd931238c12d09 (patch)
tree761c06de9b82cba8a8a2e1cd2174fe7afa59efd9 /fs/ext3/inode.c
parent9008593017069ad513cc7dc78a6c94e8dfddba31 (diff)
ext3: Improve truncate error handling
New truncate calling convention allows us to handle errors from ext3_block_truncate_page(). So reorganize the code so that ext3_block_truncate_page() is called before we change inode size. This also removes unnecessary block zeroing from error recovery after failed buffered writes (zeroing isn't needed because we could have never written non-zero data to disk). We have to be careful and keep zeroing in direct IO write error recovery because there we might have already overwritten end of the last file block. Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/ext3/inode.c')
-rw-r--r--fs/ext3/inode.c101
1 files changed, 63 insertions, 38 deletions
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index b4051c9ac5f2..d2e4547c7806 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -43,6 +43,7 @@
43#include "acl.h" 43#include "acl.h"
44 44
45static int ext3_writepage_trans_blocks(struct inode *inode); 45static int ext3_writepage_trans_blocks(struct inode *inode);
46static int ext3_block_truncate_page(struct inode *inode, loff_t from);
46 47
47/* 48/*
48 * Test whether an inode is a fast symlink. 49 * Test whether an inode is a fast symlink.
@@ -1207,6 +1208,16 @@ static void ext3_truncate_failed_write(struct inode *inode)
1207 ext3_truncate(inode); 1208 ext3_truncate(inode);
1208} 1209}
1209 1210
1211/*
1212 * Truncate blocks that were not used by direct IO write. We have to zero out
1213 * the last file block as well because direct IO might have written to it.
1214 */
1215static void ext3_truncate_failed_direct_write(struct inode *inode)
1216{
1217 ext3_block_truncate_page(inode, inode->i_size);
1218 ext3_truncate(inode);
1219}
1220
1210static int ext3_write_begin(struct file *file, struct address_space *mapping, 1221static int ext3_write_begin(struct file *file, struct address_space *mapping,
1211 loff_t pos, unsigned len, unsigned flags, 1222 loff_t pos, unsigned len, unsigned flags,
1212 struct page **pagep, void **fsdata) 1223 struct page **pagep, void **fsdata)
@@ -1847,7 +1858,7 @@ retry:
1847 loff_t end = offset + iov_length(iov, nr_segs); 1858 loff_t end = offset + iov_length(iov, nr_segs);
1848 1859
1849 if (end > isize) 1860 if (end > isize)
1850 ext3_truncate_failed_write(inode); 1861 ext3_truncate_failed_direct_write(inode);
1851 } 1862 }
1852 if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) 1863 if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
1853 goto retry; 1864 goto retry;
@@ -1861,7 +1872,7 @@ retry:
1861 /* This is really bad luck. We've written the data 1872 /* This is really bad luck. We've written the data
1862 * but cannot extend i_size. Truncate allocated blocks 1873 * but cannot extend i_size. Truncate allocated blocks
1863 * and pretend the write failed... */ 1874 * and pretend the write failed... */
1864 ext3_truncate_failed_write(inode); 1875 ext3_truncate_failed_direct_write(inode);
1865 ret = PTR_ERR(handle); 1876 ret = PTR_ERR(handle);
1866 goto out; 1877 goto out;
1867 } 1878 }
@@ -1971,17 +1982,24 @@ void ext3_set_aops(struct inode *inode)
1971 * This required during truncate. We need to physically zero the tail end 1982 * This required during truncate. We need to physically zero the tail end
1972 * of that block so it doesn't yield old data if the file is later grown. 1983 * of that block so it doesn't yield old data if the file is later grown.
1973 */ 1984 */
1974static int ext3_block_truncate_page(handle_t *handle, struct page *page, 1985static int ext3_block_truncate_page(struct inode *inode, loff_t from)
1975 struct address_space *mapping, loff_t from)
1976{ 1986{
1977 ext3_fsblk_t index = from >> PAGE_CACHE_SHIFT; 1987 ext3_fsblk_t index = from >> PAGE_CACHE_SHIFT;
1978 unsigned offset = from & (PAGE_CACHE_SIZE-1); 1988 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1979 unsigned blocksize, iblock, length, pos; 1989 unsigned blocksize, iblock, length, pos;
1980 struct inode *inode = mapping->host; 1990 struct page *page;
1991 handle_t *handle = NULL;
1981 struct buffer_head *bh; 1992 struct buffer_head *bh;
1982 int err = 0; 1993 int err = 0;
1983 1994
1995 /* Truncated on block boundary - nothing to do */
1984 blocksize = inode->i_sb->s_blocksize; 1996 blocksize = inode->i_sb->s_blocksize;
1997 if ((from & (blocksize - 1)) == 0)
1998 return 0;
1999
2000 page = grab_cache_page(inode->i_mapping, index);
2001 if (!page)
2002 return -ENOMEM;
1985 length = blocksize - (offset & (blocksize - 1)); 2003 length = blocksize - (offset & (blocksize - 1));
1986 iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); 2004 iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
1987 2005
@@ -2026,11 +2044,23 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page,
2026 goto unlock; 2044 goto unlock;
2027 } 2045 }
2028 2046
2047 /* data=writeback mode doesn't need transaction to zero-out data */
2048 if (!ext3_should_writeback_data(inode)) {
2049 /* We journal at most one block */
2050 handle = ext3_journal_start(inode, 1);
2051 if (IS_ERR(handle)) {
2052 clear_highpage(page);
2053 flush_dcache_page(page);
2054 err = PTR_ERR(handle);
2055 goto unlock;
2056 }
2057 }
2058
2029 if (ext3_should_journal_data(inode)) { 2059 if (ext3_should_journal_data(inode)) {
2030 BUFFER_TRACE(bh, "get write access"); 2060 BUFFER_TRACE(bh, "get write access");
2031 err = ext3_journal_get_write_access(handle, bh); 2061 err = ext3_journal_get_write_access(handle, bh);
2032 if (err) 2062 if (err)
2033 goto unlock; 2063 goto stop;
2034 } 2064 }
2035 2065
2036 zero_user(page, offset, length); 2066 zero_user(page, offset, length);
@@ -2044,6 +2074,9 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page,
2044 err = ext3_journal_dirty_data(handle, bh); 2074 err = ext3_journal_dirty_data(handle, bh);
2045 mark_buffer_dirty(bh); 2075 mark_buffer_dirty(bh);
2046 } 2076 }
2077stop:
2078 if (handle)
2079 ext3_journal_stop(handle);
2047 2080
2048unlock: 2081unlock:
2049 unlock_page(page); 2082 unlock_page(page);
@@ -2455,7 +2488,6 @@ void ext3_truncate(struct inode *inode)
2455 struct ext3_inode_info *ei = EXT3_I(inode); 2488 struct ext3_inode_info *ei = EXT3_I(inode);
2456 __le32 *i_data = ei->i_data; 2489 __le32 *i_data = ei->i_data;
2457 int addr_per_block = EXT3_ADDR_PER_BLOCK(inode->i_sb); 2490 int addr_per_block = EXT3_ADDR_PER_BLOCK(inode->i_sb);
2458 struct address_space *mapping = inode->i_mapping;
2459 int offsets[4]; 2491 int offsets[4];
2460 Indirect chain[4]; 2492 Indirect chain[4];
2461 Indirect *partial; 2493 Indirect *partial;
@@ -2463,7 +2495,6 @@ void ext3_truncate(struct inode *inode)
2463 int n; 2495 int n;
2464 long last_block; 2496 long last_block;
2465 unsigned blocksize = inode->i_sb->s_blocksize; 2497 unsigned blocksize = inode->i_sb->s_blocksize;
2466 struct page *page;
2467 2498
2468 trace_ext3_truncate_enter(inode); 2499 trace_ext3_truncate_enter(inode);
2469 2500
@@ -2473,37 +2504,12 @@ void ext3_truncate(struct inode *inode)
2473 if (inode->i_size == 0 && ext3_should_writeback_data(inode)) 2504 if (inode->i_size == 0 && ext3_should_writeback_data(inode))
2474 ext3_set_inode_state(inode, EXT3_STATE_FLUSH_ON_CLOSE); 2505 ext3_set_inode_state(inode, EXT3_STATE_FLUSH_ON_CLOSE);
2475 2506
2476 /*
2477 * We have to lock the EOF page here, because lock_page() nests
2478 * outside journal_start().
2479 */
2480 if ((inode->i_size & (blocksize - 1)) == 0) {
2481 /* Block boundary? Nothing to do */
2482 page = NULL;
2483 } else {
2484 page = grab_cache_page(mapping,
2485 inode->i_size >> PAGE_CACHE_SHIFT);
2486 if (!page)
2487 goto out_notrans;
2488 }
2489
2490 handle = start_transaction(inode); 2507 handle = start_transaction(inode);
2491 if (IS_ERR(handle)) { 2508 if (IS_ERR(handle))
2492 if (page) {
2493 clear_highpage(page);
2494 flush_dcache_page(page);
2495 unlock_page(page);
2496 page_cache_release(page);
2497 }
2498 goto out_notrans; 2509 goto out_notrans;
2499 }
2500 2510
2501 last_block = (inode->i_size + blocksize-1) 2511 last_block = (inode->i_size + blocksize-1)
2502 >> EXT3_BLOCK_SIZE_BITS(inode->i_sb); 2512 >> EXT3_BLOCK_SIZE_BITS(inode->i_sb);
2503
2504 if (page)
2505 ext3_block_truncate_page(handle, page, mapping, inode->i_size);
2506
2507 n = ext3_block_to_path(inode, last_block, offsets, NULL); 2513 n = ext3_block_to_path(inode, last_block, offsets, NULL);
2508 if (n == 0) 2514 if (n == 0)
2509 goto out_stop; /* error */ 2515 goto out_stop; /* error */
@@ -3251,11 +3257,30 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
3251 } 3257 }
3252 3258
3253 error = ext3_orphan_add(handle, inode); 3259 error = ext3_orphan_add(handle, inode);
3260 if (error) {
3261 ext3_journal_stop(handle);
3262 goto err_out;
3263 }
3254 EXT3_I(inode)->i_disksize = attr->ia_size; 3264 EXT3_I(inode)->i_disksize = attr->ia_size;
3255 rc = ext3_mark_inode_dirty(handle, inode); 3265 error = ext3_mark_inode_dirty(handle, inode);
3256 if (!error)
3257 error = rc;
3258 ext3_journal_stop(handle); 3266 ext3_journal_stop(handle);
3267 if (error) {
3268 /* Some hard fs error must have happened. Bail out. */
3269 ext3_orphan_del(NULL, inode);
3270 goto err_out;
3271 }
3272 rc = ext3_block_truncate_page(inode, attr->ia_size);
3273 if (rc) {
3274 /* Cleanup orphan list and exit */
3275 handle = ext3_journal_start(inode, 3);
3276 if (IS_ERR(handle)) {
3277 ext3_orphan_del(NULL, inode);
3278 goto err_out;
3279 }
3280 ext3_orphan_del(handle, inode);
3281 ext3_journal_stop(handle);
3282 goto err_out;
3283 }
3259 } 3284 }
3260 3285
3261 if ((attr->ia_valid & ATTR_SIZE) && 3286 if ((attr->ia_valid & ATTR_SIZE) &&