diff options
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 55 |
1 files changed, 11 insertions, 44 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 240f6e2dc7ee..92655fd89657 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1339,8 +1339,11 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, | |||
1339 | clear_buffer_unwritten(bh); | 1339 | clear_buffer_unwritten(bh); |
1340 | } | 1340 | } |
1341 | 1341 | ||
1342 | /* skip page if block allocation undone */ | 1342 | /* |
1343 | if (buffer_delay(bh) || buffer_unwritten(bh)) | 1343 | * skip page if block allocation undone and |
1344 | * block is dirty | ||
1345 | */ | ||
1346 | if (ext4_bh_delay_or_unwritten(NULL, bh)) | ||
1344 | skip_page = 1; | 1347 | skip_page = 1; |
1345 | bh = bh->b_this_page; | 1348 | bh = bh->b_this_page; |
1346 | block_start += bh->b_size; | 1349 | block_start += bh->b_size; |
@@ -2270,6 +2273,7 @@ retry: | |||
2270 | ext4_msg(inode->i_sb, KERN_CRIT, "%s: jbd2_start: " | 2273 | ext4_msg(inode->i_sb, KERN_CRIT, "%s: jbd2_start: " |
2271 | "%ld pages, ino %lu; err %d", __func__, | 2274 | "%ld pages, ino %lu; err %d", __func__, |
2272 | wbc->nr_to_write, inode->i_ino, ret); | 2275 | wbc->nr_to_write, inode->i_ino, ret); |
2276 | blk_finish_plug(&plug); | ||
2273 | goto out_writepages; | 2277 | goto out_writepages; |
2274 | } | 2278 | } |
2275 | 2279 | ||
@@ -2386,7 +2390,6 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, | |||
2386 | pgoff_t index; | 2390 | pgoff_t index; |
2387 | struct inode *inode = mapping->host; | 2391 | struct inode *inode = mapping->host; |
2388 | handle_t *handle; | 2392 | handle_t *handle; |
2389 | loff_t page_len; | ||
2390 | 2393 | ||
2391 | index = pos >> PAGE_CACHE_SHIFT; | 2394 | index = pos >> PAGE_CACHE_SHIFT; |
2392 | 2395 | ||
@@ -2433,13 +2436,6 @@ retry: | |||
2433 | */ | 2436 | */ |
2434 | if (pos + len > inode->i_size) | 2437 | if (pos + len > inode->i_size) |
2435 | ext4_truncate_failed_write(inode); | 2438 | ext4_truncate_failed_write(inode); |
2436 | } else { | ||
2437 | page_len = pos & (PAGE_CACHE_SIZE - 1); | ||
2438 | if (page_len > 0) { | ||
2439 | ret = ext4_discard_partial_page_buffers_no_lock(handle, | ||
2440 | inode, page, pos - page_len, page_len, | ||
2441 | EXT4_DISCARD_PARTIAL_PG_ZERO_UNMAPPED); | ||
2442 | } | ||
2443 | } | 2439 | } |
2444 | 2440 | ||
2445 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) | 2441 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) |
@@ -2482,7 +2478,6 @@ static int ext4_da_write_end(struct file *file, | |||
2482 | loff_t new_i_size; | 2478 | loff_t new_i_size; |
2483 | unsigned long start, end; | 2479 | unsigned long start, end; |
2484 | int write_mode = (int)(unsigned long)fsdata; | 2480 | int write_mode = (int)(unsigned long)fsdata; |
2485 | loff_t page_len; | ||
2486 | 2481 | ||
2487 | if (write_mode == FALL_BACK_TO_NONDELALLOC) { | 2482 | if (write_mode == FALL_BACK_TO_NONDELALLOC) { |
2488 | if (ext4_should_order_data(inode)) { | 2483 | if (ext4_should_order_data(inode)) { |
@@ -2507,7 +2502,7 @@ static int ext4_da_write_end(struct file *file, | |||
2507 | */ | 2502 | */ |
2508 | 2503 | ||
2509 | new_i_size = pos + copied; | 2504 | new_i_size = pos + copied; |
2510 | if (new_i_size > EXT4_I(inode)->i_disksize) { | 2505 | if (copied && new_i_size > EXT4_I(inode)->i_disksize) { |
2511 | if (ext4_da_should_update_i_disksize(page, end)) { | 2506 | if (ext4_da_should_update_i_disksize(page, end)) { |
2512 | down_write(&EXT4_I(inode)->i_data_sem); | 2507 | down_write(&EXT4_I(inode)->i_data_sem); |
2513 | if (new_i_size > EXT4_I(inode)->i_disksize) { | 2508 | if (new_i_size > EXT4_I(inode)->i_disksize) { |
@@ -2531,16 +2526,6 @@ static int ext4_da_write_end(struct file *file, | |||
2531 | } | 2526 | } |
2532 | ret2 = generic_write_end(file, mapping, pos, len, copied, | 2527 | ret2 = generic_write_end(file, mapping, pos, len, copied, |
2533 | page, fsdata); | 2528 | page, fsdata); |
2534 | |||
2535 | page_len = PAGE_CACHE_SIZE - | ||
2536 | ((pos + copied - 1) & (PAGE_CACHE_SIZE - 1)); | ||
2537 | |||
2538 | if (page_len > 0) { | ||
2539 | ret = ext4_discard_partial_page_buffers_no_lock(handle, | ||
2540 | inode, page, pos + copied - 1, page_len, | ||
2541 | EXT4_DISCARD_PARTIAL_PG_ZERO_UNMAPPED); | ||
2542 | } | ||
2543 | |||
2544 | copied = ret2; | 2529 | copied = ret2; |
2545 | if (ret2 < 0) | 2530 | if (ret2 < 0) |
2546 | ret = ret2; | 2531 | ret = ret2; |
@@ -2780,10 +2765,11 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, | |||
2780 | iocb->private, io_end->inode->i_ino, iocb, offset, | 2765 | iocb->private, io_end->inode->i_ino, iocb, offset, |
2781 | size); | 2766 | size); |
2782 | 2767 | ||
2768 | iocb->private = NULL; | ||
2769 | |||
2783 | /* if not aio dio with unwritten extents, just free io and return */ | 2770 | /* if not aio dio with unwritten extents, just free io and return */ |
2784 | if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { | 2771 | if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { |
2785 | ext4_free_io_end(io_end); | 2772 | ext4_free_io_end(io_end); |
2786 | iocb->private = NULL; | ||
2787 | out: | 2773 | out: |
2788 | if (is_async) | 2774 | if (is_async) |
2789 | aio_complete(iocb, ret, 0); | 2775 | aio_complete(iocb, ret, 0); |
@@ -2807,7 +2793,6 @@ out: | |||
2807 | 2793 | ||
2808 | /* queue the work to convert unwritten extents to written */ | 2794 | /* queue the work to convert unwritten extents to written */ |
2809 | queue_work(wq, &io_end->work); | 2795 | queue_work(wq, &io_end->work); |
2810 | iocb->private = NULL; | ||
2811 | 2796 | ||
2812 | /* XXX: probably should move into the real I/O completion handler */ | 2797 | /* XXX: probably should move into the real I/O completion handler */ |
2813 | inode_dio_done(inode); | 2798 | inode_dio_done(inode); |
@@ -3202,26 +3187,8 @@ int ext4_discard_partial_page_buffers_no_lock(handle_t *handle, | |||
3202 | 3187 | ||
3203 | iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); | 3188 | iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); |
3204 | 3189 | ||
3205 | if (!page_has_buffers(page)) { | 3190 | if (!page_has_buffers(page)) |
3206 | /* | 3191 | create_empty_buffers(page, blocksize, 0); |
3207 | * If the range to be discarded covers a partial block | ||
3208 | * we need to get the page buffers. This is because | ||
3209 | * partial blocks cannot be released and the page needs | ||
3210 | * to be updated with the contents of the block before | ||
3211 | * we write the zeros on top of it. | ||
3212 | */ | ||
3213 | if ((from & (blocksize - 1)) || | ||
3214 | ((from + length) & (blocksize - 1))) { | ||
3215 | create_empty_buffers(page, blocksize, 0); | ||
3216 | } else { | ||
3217 | /* | ||
3218 | * If there are no partial blocks, | ||
3219 | * there is nothing to update, | ||
3220 | * so we can return now | ||
3221 | */ | ||
3222 | return 0; | ||
3223 | } | ||
3224 | } | ||
3225 | 3192 | ||
3226 | /* Find the buffer that contains "offset" */ | 3193 | /* Find the buffer that contains "offset" */ |
3227 | bh = page_buffers(page); | 3194 | bh = page_buffers(page); |