aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHidehiro Kawai <hidehiro.kawai.ez@hitachi.com>2008-10-10 20:29:21 -0400
committerTheodore Ts'o <tytso@mit.edu>2008-10-10 20:29:21 -0400
commit7ffe1ea8949c75ecffb7a4d988bb881a9fa62fbe (patch)
tree42dc4e7dd16a33ba4c9b74cda41934e1fe27beb5
parent44519faf22ad6ce924ad0352d3dc200d9e0b66e8 (diff)
ext4: add checks for errors from jbd2
If the journal has aborted due to a checkpointing failure, we have to keep the contents of the journal space. Otherwise, the filesystem will lose uncheckpointed metadata completely and become inconsistent. To avoid this, we need to keep needs_recovery flag if checkpoint has failed. With this patch, ext4_put_super() detects a checkpointing failure from the return value of journal_destroy(), then it invokes ext4_abort() to make the filesystem read only and keep needs_recovery flag. Errors from jbd2_journal_flush() are also handled by this patch in some places. Signed-off-by: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--fs/ext4/ioctl.c12
-rw-r--r--fs/ext4/super.c23
2 files changed, 27 insertions, 8 deletions
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index ea27eaa0cfe5..dc99b4776d58 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -192,7 +192,7 @@ setversion_out:
192 case EXT4_IOC_GROUP_EXTEND: { 192 case EXT4_IOC_GROUP_EXTEND: {
193 ext4_fsblk_t n_blocks_count; 193 ext4_fsblk_t n_blocks_count;
194 struct super_block *sb = inode->i_sb; 194 struct super_block *sb = inode->i_sb;
195 int err; 195 int err, err2;
196 196
197 if (!capable(CAP_SYS_RESOURCE)) 197 if (!capable(CAP_SYS_RESOURCE))
198 return -EPERM; 198 return -EPERM;
@@ -206,8 +206,10 @@ setversion_out:
206 206
207 err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count); 207 err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count);
208 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); 208 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
209 jbd2_journal_flush(EXT4_SB(sb)->s_journal); 209 err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
210 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 210 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
211 if (err == 0)
212 err = err2;
211 mnt_drop_write(filp->f_path.mnt); 213 mnt_drop_write(filp->f_path.mnt);
212 214
213 return err; 215 return err;
@@ -215,7 +217,7 @@ setversion_out:
215 case EXT4_IOC_GROUP_ADD: { 217 case EXT4_IOC_GROUP_ADD: {
216 struct ext4_new_group_data input; 218 struct ext4_new_group_data input;
217 struct super_block *sb = inode->i_sb; 219 struct super_block *sb = inode->i_sb;
218 int err; 220 int err, err2;
219 221
220 if (!capable(CAP_SYS_RESOURCE)) 222 if (!capable(CAP_SYS_RESOURCE))
221 return -EPERM; 223 return -EPERM;
@@ -230,8 +232,10 @@ setversion_out:
230 232
231 err = ext4_group_add(sb, &input); 233 err = ext4_group_add(sb, &input);
232 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); 234 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
233 jbd2_journal_flush(EXT4_SB(sb)->s_journal); 235 err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
234 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 236 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
237 if (err == 0)
238 err = err2;
235 mnt_drop_write(filp->f_path.mnt); 239 mnt_drop_write(filp->f_path.mnt);
236 240
237 return err; 241 return err;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 0e661c569660..79bd3989e84f 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -507,7 +507,8 @@ static void ext4_put_super(struct super_block *sb)
507 ext4_mb_release(sb); 507 ext4_mb_release(sb);
508 ext4_ext_release(sb); 508 ext4_ext_release(sb);
509 ext4_xattr_put_super(sb); 509 ext4_xattr_put_super(sb);
510 jbd2_journal_destroy(sbi->s_journal); 510 if (jbd2_journal_destroy(sbi->s_journal) < 0)
511 ext4_abort(sb, __func__, "Couldn't clean up the journal");
511 sbi->s_journal = NULL; 512 sbi->s_journal = NULL;
512 if (!(sb->s_flags & MS_RDONLY)) { 513 if (!(sb->s_flags & MS_RDONLY)) {
513 EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); 514 EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
@@ -2853,7 +2854,9 @@ static void ext4_mark_recovery_complete(struct super_block *sb,
2853 journal_t *journal = EXT4_SB(sb)->s_journal; 2854 journal_t *journal = EXT4_SB(sb)->s_journal;
2854 2855
2855 jbd2_journal_lock_updates(journal); 2856 jbd2_journal_lock_updates(journal);
2856 jbd2_journal_flush(journal); 2857 if (jbd2_journal_flush(journal) < 0)
2858 goto out;
2859
2857 lock_super(sb); 2860 lock_super(sb);
2858 if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) && 2861 if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) &&
2859 sb->s_flags & MS_RDONLY) { 2862 sb->s_flags & MS_RDONLY) {
@@ -2862,6 +2865,8 @@ static void ext4_mark_recovery_complete(struct super_block *sb,
2862 ext4_commit_super(sb, es, 1); 2865 ext4_commit_super(sb, es, 1);
2863 } 2866 }
2864 unlock_super(sb); 2867 unlock_super(sb);
2868
2869out:
2865 jbd2_journal_unlock_updates(journal); 2870 jbd2_journal_unlock_updates(journal);
2866} 2871}
2867 2872
@@ -2962,7 +2967,13 @@ static void ext4_write_super_lockfs(struct super_block *sb)
2962 2967
2963 /* Now we set up the journal barrier. */ 2968 /* Now we set up the journal barrier. */
2964 jbd2_journal_lock_updates(journal); 2969 jbd2_journal_lock_updates(journal);
2965 jbd2_journal_flush(journal); 2970
2971 /*
2972 * We don't want to clear needs_recovery flag when we failed
2973 * to flush the journal.
2974 */
2975 if (jbd2_journal_flush(journal) < 0)
2976 return;
2966 2977
2967 /* Journal blocked and flushed, clear needs_recovery flag. */ 2978 /* Journal blocked and flushed, clear needs_recovery flag. */
2968 EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); 2979 EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
@@ -3402,8 +3413,12 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
3402 * otherwise be livelocked... 3413 * otherwise be livelocked...
3403 */ 3414 */
3404 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); 3415 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
3405 jbd2_journal_flush(EXT4_SB(sb)->s_journal); 3416 err = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
3406 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 3417 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
3418 if (err) {
3419 path_put(&nd.path);
3420 return err;
3421 }
3407 } 3422 }
3408 3423
3409 err = vfs_quota_on_path(sb, type, format_id, &nd.path); 3424 err = vfs_quota_on_path(sb, type, format_id, &nd.path);