aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2011-01-10 12:46:59 -0500
committerTheodore Ts'o <tytso@mit.edu>2011-01-10 12:46:59 -0500
commitb40971426a837e9dc9c66e1b6bbcb3874eafe4e0 (patch)
tree34b2a745719ed18bd1f0c81cfad200b9d8b2e309
parentca6e909f9bebe709bc65a3ee605ce32969db0452 (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>
-rw-r--r--fs/ext4/inode.c21
-rw-r--r--fs/ext4/namei.c32
-rw-r--r--fs/ext4/resize.c64
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);
269exit_bh: 279exit_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
472exit_inode: 496exit_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);
475exit_dindj: 499exit_dindj:
476 /* ext4_journal_release_buffer(handle, dind); */ 500 /* ext4_journal_release_buffer(handle, dind); */
477exit_primary:
478 /* ext4_journal_release_buffer(handle, *primary); */
479exit_sbh: 501exit_sbh:
480 /* ext4_journal_release_buffer(handle, *primary); */ 502 /* ext4_journal_release_buffer(handle, EXT4_SB(sb)->s_sbh); */
481exit_dind: 503exit_dind:
482 brelse(dind); 504 brelse(dind);
483exit_bh: 505exit_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. */