diff options
| author | Theodore Ts'o <tytso@mit.edu> | 2010-10-27 21:30:09 -0400 |
|---|---|---|
| committer | Theodore Ts'o <tytso@mit.edu> | 2010-10-27 21:30:09 -0400 |
| commit | 5a87b7a5da250c9be6d757758425dfeaf8ed3179 (patch) | |
| tree | efd1ca776e184101cb20ba4606bc35103385bcb5 | |
| parent | 16828088f9e518158edecb6cde7e6fa38e4c889b (diff) | |
ext4: call mpage_da_submit_io() from mpage_da_map_blocks()
Eventually we need to completely reorganize the ext4 writepage
callpath, but for now, we simplify things a little by calling
mpage_da_submit_io() from mpage_da_map_blocks(), since all of the
places where we call mpage_da_map_blocks() it is followed up by a call
to mpage_da_submit_io().
We're also a wee bit better with respect to error handling, but there
are still a number of issues where it's not clear what the right thing
is to do with ext4 functions deep in the writeback codepath fails.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
| -rw-r--r-- | fs/ext4/inode.c | 66 |
1 files changed, 33 insertions, 33 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 670ab15e4f9a..55961ff4efc2 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -60,6 +60,7 @@ static inline int ext4_begin_ordered_truncate(struct inode *inode, | |||
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | static void ext4_invalidatepage(struct page *page, unsigned long offset); | 62 | static void ext4_invalidatepage(struct page *page, unsigned long offset); |
| 63 | static int ext4_writepage(struct page *page, struct writeback_control *wbc); | ||
| 63 | 64 | ||
| 64 | /* | 65 | /* |
| 65 | * Test whether an inode is a fast symlink. | 66 | * Test whether an inode is a fast symlink. |
| @@ -2033,7 +2034,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd) | |||
| 2033 | BUG_ON(PageWriteback(page)); | 2034 | BUG_ON(PageWriteback(page)); |
| 2034 | 2035 | ||
| 2035 | pages_skipped = mpd->wbc->pages_skipped; | 2036 | pages_skipped = mpd->wbc->pages_skipped; |
| 2036 | err = mapping->a_ops->writepage(page, mpd->wbc); | 2037 | err = ext4_writepage(page, mpd->wbc); |
| 2037 | if (!err && (pages_skipped == mpd->wbc->pages_skipped)) | 2038 | if (!err && (pages_skipped == mpd->wbc->pages_skipped)) |
| 2038 | /* | 2039 | /* |
| 2039 | * have successfully written the page | 2040 | * have successfully written the page |
| @@ -2189,14 +2190,15 @@ static void ext4_print_free_blocks(struct inode *inode) | |||
| 2189 | } | 2190 | } |
| 2190 | 2191 | ||
| 2191 | /* | 2192 | /* |
| 2192 | * mpage_da_map_blocks - go through given space | 2193 | * mpage_da_map_and_submit - go through given space, map them |
| 2194 | * if necessary, and then submit them for I/O | ||
| 2193 | * | 2195 | * |
| 2194 | * @mpd - bh describing space | 2196 | * @mpd - bh describing space |
| 2195 | * | 2197 | * |
| 2196 | * The function skips space we know is already mapped to disk blocks. | 2198 | * The function skips space we know is already mapped to disk blocks. |
| 2197 | * | 2199 | * |
| 2198 | */ | 2200 | */ |
| 2199 | static int mpage_da_map_blocks(struct mpage_da_data *mpd) | 2201 | static void mpage_da_map_and_submit(struct mpage_da_data *mpd) |
| 2200 | { | 2202 | { |
| 2201 | int err, blks, get_blocks_flags; | 2203 | int err, blks, get_blocks_flags; |
| 2202 | struct ext4_map_blocks map; | 2204 | struct ext4_map_blocks map; |
| @@ -2206,18 +2208,14 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) | |||
| 2206 | handle_t *handle = NULL; | 2208 | handle_t *handle = NULL; |
| 2207 | 2209 | ||
| 2208 | /* | 2210 | /* |
| 2209 | * We consider only non-mapped and non-allocated blocks | 2211 | * If the blocks are mapped already, or we couldn't accumulate |
| 2212 | * any blocks, then proceed immediately to the submission stage. | ||
| 2210 | */ | 2213 | */ |
| 2211 | if ((mpd->b_state & (1 << BH_Mapped)) && | 2214 | if ((mpd->b_size == 0) || |
| 2212 | !(mpd->b_state & (1 << BH_Delay)) && | 2215 | ((mpd->b_state & (1 << BH_Mapped)) && |
| 2213 | !(mpd->b_state & (1 << BH_Unwritten))) | 2216 | !(mpd->b_state & (1 << BH_Delay)) && |
| 2214 | return 0; | 2217 | !(mpd->b_state & (1 << BH_Unwritten)))) |
| 2215 | 2218 | goto submit_io; | |
| 2216 | /* | ||
| 2217 | * If we didn't accumulate anything to write simply return | ||
| 2218 | */ | ||
| 2219 | if (!mpd->b_size) | ||
| 2220 | return 0; | ||
| 2221 | 2219 | ||
| 2222 | handle = ext4_journal_current_handle(); | 2220 | handle = ext4_journal_current_handle(); |
| 2223 | BUG_ON(!handle); | 2221 | BUG_ON(!handle); |
| @@ -2254,17 +2252,18 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) | |||
| 2254 | 2252 | ||
| 2255 | err = blks; | 2253 | err = blks; |
| 2256 | /* | 2254 | /* |
| 2257 | * If get block returns with error we simply | 2255 | * If get block returns EAGAIN or ENOSPC and there |
| 2258 | * return. Later writepage will redirty the page and | 2256 | * appears to be free blocks we will call |
| 2259 | * writepages will find the dirty page again | 2257 | * ext4_writepage() for all of the pages which will |
| 2258 | * just redirty the pages. | ||
| 2260 | */ | 2259 | */ |
| 2261 | if (err == -EAGAIN) | 2260 | if (err == -EAGAIN) |
| 2262 | return 0; | 2261 | goto submit_io; |
| 2263 | 2262 | ||
| 2264 | if (err == -ENOSPC && | 2263 | if (err == -ENOSPC && |
| 2265 | ext4_count_free_blocks(sb)) { | 2264 | ext4_count_free_blocks(sb)) { |
| 2266 | mpd->retval = err; | 2265 | mpd->retval = err; |
| 2267 | return 0; | 2266 | goto submit_io; |
| 2268 | } | 2267 | } |
| 2269 | 2268 | ||
| 2270 | /* | 2269 | /* |
| @@ -2289,7 +2288,7 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) | |||
| 2289 | /* invalidate all the pages */ | 2288 | /* invalidate all the pages */ |
| 2290 | ext4_da_block_invalidatepages(mpd, next, | 2289 | ext4_da_block_invalidatepages(mpd, next, |
| 2291 | mpd->b_size >> mpd->inode->i_blkbits); | 2290 | mpd->b_size >> mpd->inode->i_blkbits); |
| 2292 | return err; | 2291 | return; |
| 2293 | } | 2292 | } |
| 2294 | BUG_ON(blks == 0); | 2293 | BUG_ON(blks == 0); |
| 2295 | 2294 | ||
| @@ -2312,7 +2311,8 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) | |||
| 2312 | if (ext4_should_order_data(mpd->inode)) { | 2311 | if (ext4_should_order_data(mpd->inode)) { |
| 2313 | err = ext4_jbd2_file_inode(handle, mpd->inode); | 2312 | err = ext4_jbd2_file_inode(handle, mpd->inode); |
| 2314 | if (err) | 2313 | if (err) |
| 2315 | return err; | 2314 | /* This only happens if the journal is aborted */ |
| 2315 | return; | ||
| 2316 | } | 2316 | } |
| 2317 | 2317 | ||
| 2318 | /* | 2318 | /* |
| @@ -2323,10 +2323,16 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) | |||
| 2323 | disksize = i_size_read(mpd->inode); | 2323 | disksize = i_size_read(mpd->inode); |
| 2324 | if (disksize > EXT4_I(mpd->inode)->i_disksize) { | 2324 | if (disksize > EXT4_I(mpd->inode)->i_disksize) { |
| 2325 | ext4_update_i_disksize(mpd->inode, disksize); | 2325 | ext4_update_i_disksize(mpd->inode, disksize); |
| 2326 | return ext4_mark_inode_dirty(handle, mpd->inode); | 2326 | err = ext4_mark_inode_dirty(handle, mpd->inode); |
| 2327 | if (err) | ||
| 2328 | ext4_error(mpd->inode->i_sb, | ||
| 2329 | "Failed to mark inode %lu dirty", | ||
| 2330 | mpd->inode->i_ino); | ||
| 2327 | } | 2331 | } |
| 2328 | 2332 | ||
| 2329 | return 0; | 2333 | submit_io: |
| 2334 | mpage_da_submit_io(mpd); | ||
| 2335 | mpd->io_done = 1; | ||
| 2330 | } | 2336 | } |
| 2331 | 2337 | ||
| 2332 | #define BH_FLAGS ((1 << BH_Uptodate) | (1 << BH_Mapped) | \ | 2338 | #define BH_FLAGS ((1 << BH_Uptodate) | (1 << BH_Mapped) | \ |
| @@ -2403,9 +2409,7 @@ flush_it: | |||
| 2403 | * We couldn't merge the block to our extent, so we | 2409 | * We couldn't merge the block to our extent, so we |
| 2404 | * need to flush current extent and start new one | 2410 | * need to flush current extent and start new one |
| 2405 | */ | 2411 | */ |
| 2406 | if (mpage_da_map_blocks(mpd) == 0) | 2412 | mpage_da_map_and_submit(mpd); |
| 2407 | mpage_da_submit_io(mpd); | ||
| 2408 | mpd->io_done = 1; | ||
| 2409 | return; | 2413 | return; |
| 2410 | } | 2414 | } |
| 2411 | 2415 | ||
| @@ -2437,15 +2441,13 @@ static int __mpage_da_writepage(struct page *page, | |||
| 2437 | if (mpd->next_page != page->index) { | 2441 | if (mpd->next_page != page->index) { |
| 2438 | /* | 2442 | /* |
| 2439 | * Nope, we can't. So, we map non-allocated blocks | 2443 | * Nope, we can't. So, we map non-allocated blocks |
| 2440 | * and start IO on them using writepage() | 2444 | * and start IO on them |
| 2441 | */ | 2445 | */ |
| 2442 | if (mpd->next_page != mpd->first_page) { | 2446 | if (mpd->next_page != mpd->first_page) { |
| 2443 | if (mpage_da_map_blocks(mpd) == 0) | 2447 | mpage_da_map_and_submit(mpd); |
| 2444 | mpage_da_submit_io(mpd); | ||
| 2445 | /* | 2448 | /* |
| 2446 | * skip rest of the page in the page_vec | 2449 | * skip rest of the page in the page_vec |
| 2447 | */ | 2450 | */ |
| 2448 | mpd->io_done = 1; | ||
| 2449 | redirty_page_for_writepage(wbc, page); | 2451 | redirty_page_for_writepage(wbc, page); |
| 2450 | unlock_page(page); | 2452 | unlock_page(page); |
| 2451 | return MPAGE_DA_EXTENT_TAIL; | 2453 | return MPAGE_DA_EXTENT_TAIL; |
| @@ -3071,9 +3073,7 @@ retry: | |||
| 3071 | * them for I/O. | 3073 | * them for I/O. |
| 3072 | */ | 3074 | */ |
| 3073 | if (!mpd.io_done && mpd.next_page != mpd.first_page) { | 3075 | if (!mpd.io_done && mpd.next_page != mpd.first_page) { |
| 3074 | if (mpage_da_map_blocks(&mpd) == 0) | 3076 | mpage_da_map_and_submit(&mpd); |
| 3075 | mpage_da_submit_io(&mpd); | ||
| 3076 | mpd.io_done = 1; | ||
| 3077 | ret = MPAGE_DA_EXTENT_TAIL; | 3077 | ret = MPAGE_DA_EXTENT_TAIL; |
| 3078 | } | 3078 | } |
| 3079 | trace_ext4_da_write_pages(inode, &mpd); | 3079 | trace_ext4_da_write_pages(inode, &mpd); |
