Comments
Patch
@@ -2465,6 +2465,7 @@ static int __mpage_da_writepage(struct page *page,
*/
if (mpd->next_page != mpd->first_page) {
mpage_da_map_and_submit(mpd);
+redirty_page:
/*
* skip rest of the page in the page_vec
*/
@@ -2477,6 +2478,7 @@ static int __mpage_da_writepage(struct page *page,
* Start next extent of pages ...
*/
mpd->first_page = page->index;
+ mpd->next_page = page->index + 1;
/*
* ... and blocks
@@ -2486,7 +2488,6 @@ static int __mpage_da_writepage(struct page *page,
mpd->b_blocknr = 0;
}
- mpd->next_page = page->index + 1;
logical = (sector_t) page->index <<
(PAGE_CACHE_SHIFT - inode->i_blkbits);
@@ -2494,7 +2495,7 @@ static int __mpage_da_writepage(struct page *page,
mpage_add_bh_to_extent(mpd, logical, PAGE_CACHE_SIZE,
(1 << BH_Dirty) | (1 << BH_Uptodate));
if (mpd->io_done)
- return MPAGE_DA_EXTENT_TAIL;
+ goto redirty_page;
} else {
/*
* Page with regular buffer heads, just add all dirty ones
@@ -2514,7 +2515,7 @@ static int __mpage_da_writepage(struct page *page,
bh->b_size,
bh->b_state);
if (mpd->io_done)
- return MPAGE_DA_EXTENT_TAIL;
+ goto redirty_page;
} else if (buffer_dirty(bh) && (buffer_mapped(bh))) {
/*
* mapped dirty buffer. We need to update
@@ -2530,6 +2531,7 @@ static int __mpage_da_writepage(struct page *page,
logical++;
} while ((bh = bh->b_this_page) != head);
}
+ mpd->next_page = page->index + 1;
return 0;
}
When a page cannot be added to current extent in __mpage_da_writepage() we map current extent and send it for IO. Currently, mpage_da_submit_io() also redirtied and unlocked this page but it's not clear whether this is just a lucky accident or a well hidden intent. Actually, we get this wrong in the case when ext4_map_blocks() fails because of EIO and thus mpage_da_submit_io() doesn't get called and the page is left locked leading to deadlocks. Fix the issue by explicitely redirtying and unlocking the page in __mpage_da_writepage() whenever we see the page could not be added to the current extent. Signed-off-by: Jan Kara <jack@suse.cz> --- fs/ext4/inode.c | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-)