diff options
author | Theodore Ts'o <tytso@mit.edu> | 2011-01-10 12:46:59 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2011-01-10 12:46:59 -0500 |
commit | b40971426a837e9dc9c66e1b6bbcb3874eafe4e0 (patch) | |
tree | 34b2a745719ed18bd1f0c81cfad200b9d8b2e309 /fs | |
parent | ca6e909f9bebe709bc65a3ee605ce32969db0452 (diff) |
ext4: add error checking to calls to ext4_handle_dirty_metadata()
Call ext4_std_error() in various places when we can't bail out
cleanly, so the file system can be marked as in error.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/inode.c | 21 | ||||
-rw-r--r-- | fs/ext4/namei.c | 32 | ||||
-rw-r--r-- | fs/ext4/resize.c | 64 |
3 files changed, 89 insertions, 28 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 2693fcda30d8..84b616269265 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -4185,6 +4185,7 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode, | |||
4185 | { | 4185 | { |
4186 | __le32 *p; | 4186 | __le32 *p; |
4187 | int flags = EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_VALIDATED; | 4187 | int flags = EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_VALIDATED; |
4188 | int err; | ||
4188 | 4189 | ||
4189 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) | 4190 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) |
4190 | flags |= EXT4_FREE_BLOCKS_METADATA; | 4191 | flags |= EXT4_FREE_BLOCKS_METADATA; |
@@ -4200,11 +4201,23 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode, | |||
4200 | if (try_to_extend_transaction(handle, inode)) { | 4201 | if (try_to_extend_transaction(handle, inode)) { |
4201 | if (bh) { | 4202 | if (bh) { |
4202 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); | 4203 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); |
4203 | ext4_handle_dirty_metadata(handle, inode, bh); | 4204 | err = ext4_handle_dirty_metadata(handle, inode, bh); |
4205 | if (unlikely(err)) { | ||
4206 | ext4_std_error(inode->i_sb, err); | ||
4207 | return 1; | ||
4208 | } | ||
4209 | } | ||
4210 | err = ext4_mark_inode_dirty(handle, inode); | ||
4211 | if (unlikely(err)) { | ||
4212 | ext4_std_error(inode->i_sb, err); | ||
4213 | return 1; | ||
4214 | } | ||
4215 | err = ext4_truncate_restart_trans(handle, inode, | ||
4216 | blocks_for_truncate(inode)); | ||
4217 | if (unlikely(err)) { | ||
4218 | ext4_std_error(inode->i_sb, err); | ||
4219 | return 1; | ||
4204 | } | 4220 | } |
4205 | ext4_mark_inode_dirty(handle, inode); | ||
4206 | ext4_truncate_restart_trans(handle, inode, | ||
4207 | blocks_for_truncate(inode)); | ||
4208 | if (bh) { | 4221 | if (bh) { |
4209 | BUFFER_TRACE(bh, "retaking write access"); | 4222 | BUFFER_TRACE(bh, "retaking write access"); |
4210 | ext4_journal_get_write_access(handle, bh); | 4223 | ext4_journal_get_write_access(handle, bh); |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 6dfc5b9de3e6..5485390d32c5 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -1602,7 +1602,11 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, | |||
1602 | if (err) | 1602 | if (err) |
1603 | goto journal_error; | 1603 | goto journal_error; |
1604 | } | 1604 | } |
1605 | ext4_handle_dirty_metadata(handle, inode, frames[0].bh); | 1605 | err = ext4_handle_dirty_metadata(handle, inode, frames[0].bh); |
1606 | if (err) { | ||
1607 | ext4_std_error(inode->i_sb, err); | ||
1608 | goto cleanup; | ||
1609 | } | ||
1606 | } | 1610 | } |
1607 | de = do_split(handle, dir, &bh, frame, &hinfo, &err); | 1611 | de = do_split(handle, dir, &bh, frame, &hinfo, &err); |
1608 | if (!de) | 1612 | if (!de) |
@@ -1630,7 +1634,7 @@ static int ext4_delete_entry(handle_t *handle, | |||
1630 | { | 1634 | { |
1631 | struct ext4_dir_entry_2 *de, *pde; | 1635 | struct ext4_dir_entry_2 *de, *pde; |
1632 | unsigned int blocksize = dir->i_sb->s_blocksize; | 1636 | unsigned int blocksize = dir->i_sb->s_blocksize; |
1633 | int i; | 1637 | int i, err; |
1634 | 1638 | ||
1635 | i = 0; | 1639 | i = 0; |
1636 | pde = NULL; | 1640 | pde = NULL; |
@@ -1640,7 +1644,11 @@ static int ext4_delete_entry(handle_t *handle, | |||
1640 | return -EIO; | 1644 | return -EIO; |
1641 | if (de == de_del) { | 1645 | if (de == de_del) { |
1642 | BUFFER_TRACE(bh, "get_write_access"); | 1646 | BUFFER_TRACE(bh, "get_write_access"); |
1643 | ext4_journal_get_write_access(handle, bh); | 1647 | err = ext4_journal_get_write_access(handle, bh); |
1648 | if (unlikely(err)) { | ||
1649 | ext4_std_error(dir->i_sb, err); | ||
1650 | return err; | ||
1651 | } | ||
1644 | if (pde) | 1652 | if (pde) |
1645 | pde->rec_len = ext4_rec_len_to_disk( | 1653 | pde->rec_len = ext4_rec_len_to_disk( |
1646 | ext4_rec_len_from_disk(pde->rec_len, | 1654 | ext4_rec_len_from_disk(pde->rec_len, |
@@ -1652,7 +1660,11 @@ static int ext4_delete_entry(handle_t *handle, | |||
1652 | de->inode = 0; | 1660 | de->inode = 0; |
1653 | dir->i_version++; | 1661 | dir->i_version++; |
1654 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); | 1662 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); |
1655 | ext4_handle_dirty_metadata(handle, dir, bh); | 1663 | err = ext4_handle_dirty_metadata(handle, dir, bh); |
1664 | if (unlikely(err)) { | ||
1665 | ext4_std_error(dir->i_sb, err); | ||
1666 | return err; | ||
1667 | } | ||
1656 | return 0; | 1668 | return 0; |
1657 | } | 1669 | } |
1658 | i += ext4_rec_len_from_disk(de->rec_len, blocksize); | 1670 | i += ext4_rec_len_from_disk(de->rec_len, blocksize); |
@@ -2414,7 +2426,11 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2414 | ext4_current_time(new_dir); | 2426 | ext4_current_time(new_dir); |
2415 | ext4_mark_inode_dirty(handle, new_dir); | 2427 | ext4_mark_inode_dirty(handle, new_dir); |
2416 | BUFFER_TRACE(new_bh, "call ext4_handle_dirty_metadata"); | 2428 | BUFFER_TRACE(new_bh, "call ext4_handle_dirty_metadata"); |
2417 | ext4_handle_dirty_metadata(handle, new_dir, new_bh); | 2429 | retval = ext4_handle_dirty_metadata(handle, new_dir, new_bh); |
2430 | if (unlikely(retval)) { | ||
2431 | ext4_std_error(new_dir->i_sb, retval); | ||
2432 | goto end_rename; | ||
2433 | } | ||
2418 | brelse(new_bh); | 2434 | brelse(new_bh); |
2419 | new_bh = NULL; | 2435 | new_bh = NULL; |
2420 | } | 2436 | } |
@@ -2466,7 +2482,11 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2466 | PARENT_INO(dir_bh->b_data, new_dir->i_sb->s_blocksize) = | 2482 | PARENT_INO(dir_bh->b_data, new_dir->i_sb->s_blocksize) = |
2467 | cpu_to_le32(new_dir->i_ino); | 2483 | cpu_to_le32(new_dir->i_ino); |
2468 | BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata"); | 2484 | BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata"); |
2469 | ext4_handle_dirty_metadata(handle, old_dir, dir_bh); | 2485 | retval = ext4_handle_dirty_metadata(handle, old_dir, dir_bh); |
2486 | if (retval) { | ||
2487 | ext4_std_error(old_dir->i_sb, retval); | ||
2488 | goto end_rename; | ||
2489 | } | ||
2470 | ext4_dec_count(handle, old_dir); | 2490 | ext4_dec_count(handle, old_dir); |
2471 | if (new_inode) { | 2491 | if (new_inode) { |
2472 | /* checked empty_dir above, can't have another parent, | 2492 | /* checked empty_dir above, can't have another parent, |
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index dc963929de65..7faf47dde7fb 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -220,7 +220,11 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
220 | memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, gdb->b_size); | 220 | memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, gdb->b_size); |
221 | set_buffer_uptodate(gdb); | 221 | set_buffer_uptodate(gdb); |
222 | unlock_buffer(gdb); | 222 | unlock_buffer(gdb); |
223 | ext4_handle_dirty_metadata(handle, NULL, gdb); | 223 | err = ext4_handle_dirty_metadata(handle, NULL, gdb); |
224 | if (unlikely(err)) { | ||
225 | brelse(gdb); | ||
226 | goto exit_bh; | ||
227 | } | ||
224 | ext4_set_bit(bit, bh->b_data); | 228 | ext4_set_bit(bit, bh->b_data); |
225 | brelse(gdb); | 229 | brelse(gdb); |
226 | } | 230 | } |
@@ -253,7 +257,11 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
253 | 257 | ||
254 | ext4_mark_bitmap_end(input->blocks_count, sb->s_blocksize * 8, | 258 | ext4_mark_bitmap_end(input->blocks_count, sb->s_blocksize * 8, |
255 | bh->b_data); | 259 | bh->b_data); |
256 | ext4_handle_dirty_metadata(handle, NULL, bh); | 260 | err = ext4_handle_dirty_metadata(handle, NULL, bh); |
261 | if (unlikely(err)) { | ||
262 | ext4_std_error(sb, err); | ||
263 | goto exit_bh; | ||
264 | } | ||
257 | brelse(bh); | 265 | brelse(bh); |
258 | /* Mark unused entries in inode bitmap used */ | 266 | /* Mark unused entries in inode bitmap used */ |
259 | ext4_debug("clear inode bitmap %#04llx (+%llu)\n", | 267 | ext4_debug("clear inode bitmap %#04llx (+%llu)\n", |
@@ -265,7 +273,9 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
265 | 273 | ||
266 | ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8, | 274 | ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8, |
267 | bh->b_data); | 275 | bh->b_data); |
268 | ext4_handle_dirty_metadata(handle, NULL, bh); | 276 | err = ext4_handle_dirty_metadata(handle, NULL, bh); |
277 | if (unlikely(err)) | ||
278 | ext4_std_error(sb, err); | ||
269 | exit_bh: | 279 | exit_bh: |
270 | brelse(bh); | 280 | brelse(bh); |
271 | 281 | ||
@@ -417,17 +427,21 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
417 | goto exit_dind; | 427 | goto exit_dind; |
418 | } | 428 | } |
419 | 429 | ||
420 | if ((err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh))) | 430 | err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh); |
431 | if (unlikely(err)) | ||
421 | goto exit_dind; | 432 | goto exit_dind; |
422 | 433 | ||
423 | if ((err = ext4_journal_get_write_access(handle, *primary))) | 434 | err = ext4_journal_get_write_access(handle, *primary); |
435 | if (unlikely(err)) | ||
424 | goto exit_sbh; | 436 | goto exit_sbh; |
425 | 437 | ||
426 | if ((err = ext4_journal_get_write_access(handle, dind))) | 438 | err = ext4_journal_get_write_access(handle, dind); |
427 | goto exit_primary; | 439 | if (unlikely(err)) |
440 | ext4_std_error(sb, err); | ||
428 | 441 | ||
429 | /* ext4_reserve_inode_write() gets a reference on the iloc */ | 442 | /* ext4_reserve_inode_write() gets a reference on the iloc */ |
430 | if ((err = ext4_reserve_inode_write(handle, inode, &iloc))) | 443 | err = ext4_reserve_inode_write(handle, inode, &iloc); |
444 | if (unlikely(err)) | ||
431 | goto exit_dindj; | 445 | goto exit_dindj; |
432 | 446 | ||
433 | n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *), | 447 | n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *), |
@@ -449,12 +463,20 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
449 | * reserved inode, and will become GDT blocks (primary and backup). | 463 | * reserved inode, and will become GDT blocks (primary and backup). |
450 | */ | 464 | */ |
451 | data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)] = 0; | 465 | data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)] = 0; |
452 | ext4_handle_dirty_metadata(handle, NULL, dind); | 466 | err = ext4_handle_dirty_metadata(handle, NULL, dind); |
453 | brelse(dind); | 467 | if (unlikely(err)) { |
468 | ext4_std_error(sb, err); | ||
469 | goto exit_inode; | ||
470 | } | ||
454 | inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9; | 471 | inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9; |
455 | ext4_mark_iloc_dirty(handle, inode, &iloc); | 472 | ext4_mark_iloc_dirty(handle, inode, &iloc); |
456 | memset((*primary)->b_data, 0, sb->s_blocksize); | 473 | memset((*primary)->b_data, 0, sb->s_blocksize); |
457 | ext4_handle_dirty_metadata(handle, NULL, *primary); | 474 | err = ext4_handle_dirty_metadata(handle, NULL, *primary); |
475 | if (unlikely(err)) { | ||
476 | ext4_std_error(sb, err); | ||
477 | goto exit_inode; | ||
478 | } | ||
479 | brelse(dind); | ||
458 | 480 | ||
459 | o_group_desc = EXT4_SB(sb)->s_group_desc; | 481 | o_group_desc = EXT4_SB(sb)->s_group_desc; |
460 | memcpy(n_group_desc, o_group_desc, | 482 | memcpy(n_group_desc, o_group_desc, |
@@ -465,19 +487,19 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
465 | kfree(o_group_desc); | 487 | kfree(o_group_desc); |
466 | 488 | ||
467 | le16_add_cpu(&es->s_reserved_gdt_blocks, -1); | 489 | le16_add_cpu(&es->s_reserved_gdt_blocks, -1); |
468 | ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh); | 490 | err = ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh); |
491 | if (err) | ||
492 | ext4_std_error(sb, err); | ||
469 | 493 | ||
470 | return 0; | 494 | return err; |
471 | 495 | ||
472 | exit_inode: | 496 | exit_inode: |
473 | /* ext4_journal_release_buffer(handle, iloc.bh); */ | 497 | /* ext4_journal_release_buffer(handle, iloc.bh); */ |
474 | brelse(iloc.bh); | 498 | brelse(iloc.bh); |
475 | exit_dindj: | 499 | exit_dindj: |
476 | /* ext4_journal_release_buffer(handle, dind); */ | 500 | /* ext4_journal_release_buffer(handle, dind); */ |
477 | exit_primary: | ||
478 | /* ext4_journal_release_buffer(handle, *primary); */ | ||
479 | exit_sbh: | 501 | exit_sbh: |
480 | /* ext4_journal_release_buffer(handle, *primary); */ | 502 | /* ext4_journal_release_buffer(handle, EXT4_SB(sb)->s_sbh); */ |
481 | exit_dind: | 503 | exit_dind: |
482 | brelse(dind); | 504 | brelse(dind); |
483 | exit_bh: | 505 | exit_bh: |
@@ -660,7 +682,9 @@ static void update_backups(struct super_block *sb, | |||
660 | memset(bh->b_data + size, 0, rest); | 682 | memset(bh->b_data + size, 0, rest); |
661 | set_buffer_uptodate(bh); | 683 | set_buffer_uptodate(bh); |
662 | unlock_buffer(bh); | 684 | unlock_buffer(bh); |
663 | ext4_handle_dirty_metadata(handle, NULL, bh); | 685 | err = ext4_handle_dirty_metadata(handle, NULL, bh); |
686 | if (unlikely(err)) | ||
687 | ext4_std_error(sb, err); | ||
664 | brelse(bh); | 688 | brelse(bh); |
665 | } | 689 | } |
666 | if ((err2 = ext4_journal_stop(handle)) && !err) | 690 | if ((err2 = ext4_journal_stop(handle)) && !err) |
@@ -878,7 +902,11 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
878 | /* Update the global fs size fields */ | 902 | /* Update the global fs size fields */ |
879 | sbi->s_groups_count++; | 903 | sbi->s_groups_count++; |
880 | 904 | ||
881 | ext4_handle_dirty_metadata(handle, NULL, primary); | 905 | err = ext4_handle_dirty_metadata(handle, NULL, primary); |
906 | if (unlikely(err)) { | ||
907 | ext4_std_error(sb, err); | ||
908 | goto exit_journal; | ||
909 | } | ||
882 | 910 | ||
883 | /* Update the reserved block counts only once the new group is | 911 | /* Update the reserved block counts only once the new group is |
884 | * active. */ | 912 | * active. */ |