diff options
author | Dave Kleikamp <shaggy@linux.vnet.ibm.com> | 2009-01-30 15:09:06 -0500 |
---|---|---|
committer | Dave Kleikamp <shaggy@linux.vnet.ibm.com> | 2009-01-30 15:09:06 -0500 |
commit | 1ad53a98c927a9b5b1b57288ac0edec562fbcf8d (patch) | |
tree | f8de5c192927fd2594437018a6489798dbafcbed | |
parent | b5c816a4f177604ae708892bba074b1d534fcbee (diff) |
jfs: Fix error handling in metapage_writepage()
Improved error handling so that last_write_complete(), and thus
end_page_writeback(), gets called only once.
Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Reported-by: Eric Sesterhenn <snakebyte@gmx.de>
-rw-r--r-- | fs/jfs/jfs_metapage.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index c350057087dd..07b6c5dfb4b6 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c | |||
@@ -369,6 +369,7 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc) | |||
369 | unsigned long bio_bytes = 0; | 369 | unsigned long bio_bytes = 0; |
370 | unsigned long bio_offset = 0; | 370 | unsigned long bio_offset = 0; |
371 | int offset; | 371 | int offset; |
372 | int bad_blocks = 0; | ||
372 | 373 | ||
373 | page_start = (sector_t)page->index << | 374 | page_start = (sector_t)page->index << |
374 | (PAGE_CACHE_SHIFT - inode->i_blkbits); | 375 | (PAGE_CACHE_SHIFT - inode->i_blkbits); |
@@ -394,6 +395,7 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc) | |||
394 | } | 395 | } |
395 | 396 | ||
396 | clear_bit(META_dirty, &mp->flag); | 397 | clear_bit(META_dirty, &mp->flag); |
398 | set_bit(META_io, &mp->flag); | ||
397 | block_offset = offset >> inode->i_blkbits; | 399 | block_offset = offset >> inode->i_blkbits; |
398 | lblock = page_start + block_offset; | 400 | lblock = page_start + block_offset; |
399 | if (bio) { | 401 | if (bio) { |
@@ -402,7 +404,6 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc) | |||
402 | len = min(xlen, blocks_per_mp); | 404 | len = min(xlen, blocks_per_mp); |
403 | xlen -= len; | 405 | xlen -= len; |
404 | bio_bytes += len << inode->i_blkbits; | 406 | bio_bytes += len << inode->i_blkbits; |
405 | set_bit(META_io, &mp->flag); | ||
406 | continue; | 407 | continue; |
407 | } | 408 | } |
408 | /* Not contiguous */ | 409 | /* Not contiguous */ |
@@ -424,12 +425,14 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc) | |||
424 | xlen = (PAGE_CACHE_SIZE - offset) >> inode->i_blkbits; | 425 | xlen = (PAGE_CACHE_SIZE - offset) >> inode->i_blkbits; |
425 | pblock = metapage_get_blocks(inode, lblock, &xlen); | 426 | pblock = metapage_get_blocks(inode, lblock, &xlen); |
426 | if (!pblock) { | 427 | if (!pblock) { |
427 | /* Need better error handling */ | ||
428 | printk(KERN_ERR "JFS: metapage_get_blocks failed\n"); | 428 | printk(KERN_ERR "JFS: metapage_get_blocks failed\n"); |
429 | dec_io(page, last_write_complete); | 429 | /* |
430 | * We already called inc_io(), but can't cancel it | ||
431 | * with dec_io() until we're done with the page | ||
432 | */ | ||
433 | bad_blocks++; | ||
430 | continue; | 434 | continue; |
431 | } | 435 | } |
432 | set_bit(META_io, &mp->flag); | ||
433 | len = min(xlen, (int)JFS_SBI(inode->i_sb)->nbperpage); | 436 | len = min(xlen, (int)JFS_SBI(inode->i_sb)->nbperpage); |
434 | 437 | ||
435 | bio = bio_alloc(GFP_NOFS, 1); | 438 | bio = bio_alloc(GFP_NOFS, 1); |
@@ -459,6 +462,9 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc) | |||
459 | 462 | ||
460 | unlock_page(page); | 463 | unlock_page(page); |
461 | 464 | ||
465 | if (bad_blocks) | ||
466 | goto err_out; | ||
467 | |||
462 | if (nr_underway == 0) | 468 | if (nr_underway == 0) |
463 | end_page_writeback(page); | 469 | end_page_writeback(page); |
464 | 470 | ||
@@ -474,7 +480,9 @@ skip: | |||
474 | bio_put(bio); | 480 | bio_put(bio); |
475 | unlock_page(page); | 481 | unlock_page(page); |
476 | dec_io(page, last_write_complete); | 482 | dec_io(page, last_write_complete); |
477 | 483 | err_out: | |
484 | while (bad_blocks--) | ||
485 | dec_io(page, last_write_complete); | ||
478 | return -EIO; | 486 | return -EIO; |
479 | } | 487 | } |
480 | 488 | ||