diff options
author | Yongqiang Yang <xiaoqiangnk@gmail.com> | 2011-12-13 22:05:05 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2011-12-13 22:05:05 -0500 |
commit | 093e6e3666f47d29763a235b404c84ee47ba8bb0 (patch) | |
tree | a337f1415bf1c98b63fa5536c42b97059309b8d1 /fs | |
parent | 13a79a4741d37fda2fbafb953f0f301dc007928f (diff) |
ext4: correctly handle pages w/o buffers in ext4_discard_partial_buffers()
If a page has been read into memory and never been written, it has no
buffers, but we should handle the page in truncate or punch hole.
VFS code of writing operations has handled holes correctly, so this
patch removes the code handling holes in writing operations.
Signed-off-by: Yongqiang Yang <xiaoqiangnk@gmail.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: stable@kernel.org
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/inode.c | 41 |
1 files changed, 2 insertions, 39 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index cf20e1fe7782..92655fd89657 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -2390,7 +2390,6 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, | |||
2390 | pgoff_t index; | 2390 | pgoff_t index; |
2391 | struct inode *inode = mapping->host; | 2391 | struct inode *inode = mapping->host; |
2392 | handle_t *handle; | 2392 | handle_t *handle; |
2393 | loff_t page_len; | ||
2394 | 2393 | ||
2395 | index = pos >> PAGE_CACHE_SHIFT; | 2394 | index = pos >> PAGE_CACHE_SHIFT; |
2396 | 2395 | ||
@@ -2437,13 +2436,6 @@ retry: | |||
2437 | */ | 2436 | */ |
2438 | if (pos + len > inode->i_size) | 2437 | if (pos + len > inode->i_size) |
2439 | ext4_truncate_failed_write(inode); | 2438 | ext4_truncate_failed_write(inode); |
2440 | } else { | ||
2441 | page_len = pos & (PAGE_CACHE_SIZE - 1); | ||
2442 | if (page_len > 0) { | ||
2443 | ret = ext4_discard_partial_page_buffers_no_lock(handle, | ||
2444 | inode, page, pos - page_len, page_len, | ||
2445 | EXT4_DISCARD_PARTIAL_PG_ZERO_UNMAPPED); | ||
2446 | } | ||
2447 | } | 2439 | } |
2448 | 2440 | ||
2449 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) | 2441 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) |
@@ -2486,7 +2478,6 @@ static int ext4_da_write_end(struct file *file, | |||
2486 | loff_t new_i_size; | 2478 | loff_t new_i_size; |
2487 | unsigned long start, end; | 2479 | unsigned long start, end; |
2488 | int write_mode = (int)(unsigned long)fsdata; | 2480 | int write_mode = (int)(unsigned long)fsdata; |
2489 | loff_t page_len; | ||
2490 | 2481 | ||
2491 | if (write_mode == FALL_BACK_TO_NONDELALLOC) { | 2482 | if (write_mode == FALL_BACK_TO_NONDELALLOC) { |
2492 | if (ext4_should_order_data(inode)) { | 2483 | if (ext4_should_order_data(inode)) { |
@@ -2535,16 +2526,6 @@ static int ext4_da_write_end(struct file *file, | |||
2535 | } | 2526 | } |
2536 | ret2 = generic_write_end(file, mapping, pos, len, copied, | 2527 | ret2 = generic_write_end(file, mapping, pos, len, copied, |
2537 | page, fsdata); | 2528 | page, fsdata); |
2538 | |||
2539 | page_len = PAGE_CACHE_SIZE - | ||
2540 | ((pos + copied - 1) & (PAGE_CACHE_SIZE - 1)); | ||
2541 | |||
2542 | if (page_len > 0) { | ||
2543 | ret = ext4_discard_partial_page_buffers_no_lock(handle, | ||
2544 | inode, page, pos + copied - 1, page_len, | ||
2545 | EXT4_DISCARD_PARTIAL_PG_ZERO_UNMAPPED); | ||
2546 | } | ||
2547 | |||
2548 | copied = ret2; | 2529 | copied = ret2; |
2549 | if (ret2 < 0) | 2530 | if (ret2 < 0) |
2550 | ret = ret2; | 2531 | ret = ret2; |
@@ -3206,26 +3187,8 @@ int ext4_discard_partial_page_buffers_no_lock(handle_t *handle, | |||
3206 | 3187 | ||
3207 | iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); | 3188 | iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); |
3208 | 3189 | ||
3209 | if (!page_has_buffers(page)) { | 3190 | if (!page_has_buffers(page)) |
3210 | /* | 3191 | create_empty_buffers(page, blocksize, 0); |
3211 | * If the range to be discarded covers a partial block | ||
3212 | * we need to get the page buffers. This is because | ||
3213 | * partial blocks cannot be released and the page needs | ||
3214 | * to be updated with the contents of the block before | ||
3215 | * we write the zeros on top of it. | ||
3216 | */ | ||
3217 | if ((from & (blocksize - 1)) || | ||
3218 | ((from + length) & (blocksize - 1))) { | ||
3219 | create_empty_buffers(page, blocksize, 0); | ||
3220 | } else { | ||
3221 | /* | ||
3222 | * If there are no partial blocks, | ||
3223 | * there is nothing to update, | ||
3224 | * so we can return now | ||
3225 | */ | ||
3226 | return 0; | ||
3227 | } | ||
3228 | } | ||
3229 | 3192 | ||
3230 | /* Find the buffer that contains "offset" */ | 3193 | /* Find the buffer that contains "offset" */ |
3231 | bh = page_buffers(page); | 3194 | bh = page_buffers(page); |