aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3
diff options
context:
space:
mode:
authorHidehiro Kawai <hidehiro.kawai.ez@hitachi.com>2008-10-22 17:15:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-23 11:55:01 -0400
commit2d7c820e56ce83b23daee9eb5343730fb309418e (patch)
treea64db3f90c8826a03c591be492faaf64ab7bf14a /fs/ext3
parent4afe978530702c934dfdb11f54073136818b2119 (diff)
ext3: add checks for errors from jbd
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, ext3_put_super() detects a checkpointing failure from the return value of journal_destroy(), then it invokes ext3_abort() to make the filesystem read only and keep needs_recovery flag. Errors from journal_flush() are also handled by this patch in some places. Signed-off-by: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com> Cc: Jan Kara <jack@ucw.cz> Cc: Stephen Rothwell <sfr@canb.auug.org.au> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: <linux-ext4@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ext3')
-rw-r--r--fs/ext3/ioctl.c12
-rw-r--r--fs/ext3/super.c23
2 files changed, 27 insertions, 8 deletions
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index 0d0c70151642..b7394d05ee8e 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -239,7 +239,7 @@ setrsvsz_out:
239 case EXT3_IOC_GROUP_EXTEND: { 239 case EXT3_IOC_GROUP_EXTEND: {
240 ext3_fsblk_t n_blocks_count; 240 ext3_fsblk_t n_blocks_count;
241 struct super_block *sb = inode->i_sb; 241 struct super_block *sb = inode->i_sb;
242 int err; 242 int err, err2;
243 243
244 if (!capable(CAP_SYS_RESOURCE)) 244 if (!capable(CAP_SYS_RESOURCE))
245 return -EPERM; 245 return -EPERM;
@@ -254,8 +254,10 @@ setrsvsz_out:
254 } 254 }
255 err = ext3_group_extend(sb, EXT3_SB(sb)->s_es, n_blocks_count); 255 err = ext3_group_extend(sb, EXT3_SB(sb)->s_es, n_blocks_count);
256 journal_lock_updates(EXT3_SB(sb)->s_journal); 256 journal_lock_updates(EXT3_SB(sb)->s_journal);
257 journal_flush(EXT3_SB(sb)->s_journal); 257 err2 = journal_flush(EXT3_SB(sb)->s_journal);
258 journal_unlock_updates(EXT3_SB(sb)->s_journal); 258 journal_unlock_updates(EXT3_SB(sb)->s_journal);
259 if (err == 0)
260 err = err2;
259group_extend_out: 261group_extend_out:
260 mnt_drop_write(filp->f_path.mnt); 262 mnt_drop_write(filp->f_path.mnt);
261 return err; 263 return err;
@@ -263,7 +265,7 @@ group_extend_out:
263 case EXT3_IOC_GROUP_ADD: { 265 case EXT3_IOC_GROUP_ADD: {
264 struct ext3_new_group_data input; 266 struct ext3_new_group_data input;
265 struct super_block *sb = inode->i_sb; 267 struct super_block *sb = inode->i_sb;
266 int err; 268 int err, err2;
267 269
268 if (!capable(CAP_SYS_RESOURCE)) 270 if (!capable(CAP_SYS_RESOURCE))
269 return -EPERM; 271 return -EPERM;
@@ -280,8 +282,10 @@ group_extend_out:
280 282
281 err = ext3_group_add(sb, &input); 283 err = ext3_group_add(sb, &input);
282 journal_lock_updates(EXT3_SB(sb)->s_journal); 284 journal_lock_updates(EXT3_SB(sb)->s_journal);
283 journal_flush(EXT3_SB(sb)->s_journal); 285 err2 = journal_flush(EXT3_SB(sb)->s_journal);
284 journal_unlock_updates(EXT3_SB(sb)->s_journal); 286 journal_unlock_updates(EXT3_SB(sb)->s_journal);
287 if (err == 0)
288 err = err2;
285group_add_out: 289group_add_out:
286 mnt_drop_write(filp->f_path.mnt); 290 mnt_drop_write(filp->f_path.mnt);
287 return err; 291 return err;
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 3a260af5544d..cac29ee3b14a 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -393,7 +393,8 @@ static void ext3_put_super (struct super_block * sb)
393 int i; 393 int i;
394 394
395 ext3_xattr_put_super(sb); 395 ext3_xattr_put_super(sb);
396 journal_destroy(sbi->s_journal); 396 if (journal_destroy(sbi->s_journal) < 0)
397 ext3_abort(sb, __func__, "Couldn't clean up the journal");
397 if (!(sb->s_flags & MS_RDONLY)) { 398 if (!(sb->s_flags & MS_RDONLY)) {
398 EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); 399 EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
399 es->s_state = cpu_to_le16(sbi->s_mount_state); 400 es->s_state = cpu_to_le16(sbi->s_mount_state);
@@ -2296,7 +2297,9 @@ static void ext3_mark_recovery_complete(struct super_block * sb,
2296 journal_t *journal = EXT3_SB(sb)->s_journal; 2297 journal_t *journal = EXT3_SB(sb)->s_journal;
2297 2298
2298 journal_lock_updates(journal); 2299 journal_lock_updates(journal);
2299 journal_flush(journal); 2300 if (journal_flush(journal) < 0)
2301 goto out;
2302
2300 lock_super(sb); 2303 lock_super(sb);
2301 if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) && 2304 if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) &&
2302 sb->s_flags & MS_RDONLY) { 2305 sb->s_flags & MS_RDONLY) {
@@ -2305,6 +2308,8 @@ static void ext3_mark_recovery_complete(struct super_block * sb,
2305 ext3_commit_super(sb, es, 1); 2308 ext3_commit_super(sb, es, 1);
2306 } 2309 }
2307 unlock_super(sb); 2310 unlock_super(sb);
2311
2312out:
2308 journal_unlock_updates(journal); 2313 journal_unlock_updates(journal);
2309} 2314}
2310 2315
@@ -2404,7 +2409,13 @@ static void ext3_write_super_lockfs(struct super_block *sb)
2404 2409
2405 /* Now we set up the journal barrier. */ 2410 /* Now we set up the journal barrier. */
2406 journal_lock_updates(journal); 2411 journal_lock_updates(journal);
2407 journal_flush(journal); 2412
2413 /*
2414 * We don't want to clear needs_recovery flag when we failed
2415 * to flush the journal.
2416 */
2417 if (journal_flush(journal) < 0)
2418 return;
2408 2419
2409 /* Journal blocked and flushed, clear needs_recovery flag. */ 2420 /* Journal blocked and flushed, clear needs_recovery flag. */
2410 EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); 2421 EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
@@ -2822,8 +2833,12 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
2822 * otherwise be livelocked... 2833 * otherwise be livelocked...
2823 */ 2834 */
2824 journal_lock_updates(EXT3_SB(sb)->s_journal); 2835 journal_lock_updates(EXT3_SB(sb)->s_journal);
2825 journal_flush(EXT3_SB(sb)->s_journal); 2836 err = journal_flush(EXT3_SB(sb)->s_journal);
2826 journal_unlock_updates(EXT3_SB(sb)->s_journal); 2837 journal_unlock_updates(EXT3_SB(sb)->s_journal);
2838 if (err) {
2839 path_put(&nd.path);
2840 return err;
2841 }
2827 } 2842 }
2828 2843
2829 err = vfs_quota_on_path(sb, type, format_id, &nd.path); 2844 err = vfs_quota_on_path(sb, type, format_id, &nd.path);