diff options
-rw-r--r-- | fs/ext3/inode.c | 101 |
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 | ||
45 | static int ext3_writepage_trans_blocks(struct inode *inode); | 45 | static int ext3_writepage_trans_blocks(struct inode *inode); |
46 | static 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 | */ | ||
1215 | static 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 | |||
1210 | static int ext3_write_begin(struct file *file, struct address_space *mapping, | 1221 | static 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 | */ |
1974 | static int ext3_block_truncate_page(handle_t *handle, struct page *page, | 1985 | static 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 | } |
2077 | stop: | ||
2078 | if (handle) | ||
2079 | ext3_journal_stop(handle); | ||
2047 | 2080 | ||
2048 | unlock: | 2081 | unlock: |
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) && |