aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jfs
diff options
context:
space:
mode:
authorDave Kleikamp <shaggy@linux.vnet.ibm.com>2009-01-30 15:09:06 -0500
committerDave Kleikamp <shaggy@linux.vnet.ibm.com>2009-01-30 15:09:06 -0500
commit1ad53a98c927a9b5b1b57288ac0edec562fbcf8d (patch)
treef8de5c192927fd2594437018a6489798dbafcbed /fs/jfs
parentb5c816a4f177604ae708892bba074b1d534fcbee (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>
Diffstat (limited to 'fs/jfs')
-rw-r--r--fs/jfs/jfs_metapage.c18
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 483err_out:
484 while (bad_blocks--)
485 dec_io(page, last_write_complete);
478 return -EIO; 486 return -EIO;
479} 487}
480 488