aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2009-05-01 12:52:25 -0400
committerTheodore Ts'o <tytso@mit.edu>2009-05-01 12:52:25 -0400
commit9ca92389c5312a51e819c15c762f0abdc7f3129b (patch)
tree0f99256a5632614134573283853c577676cb1b99 /fs/ext4
parent7234ab2a55e77784b44cf2d862136d9e41b8d98a (diff)
ext4: Use separate super_operations structure for no_journal filesystems
By using a separate super_operations structure for filesystems that have and don't have journals, we can simply ext4_write_super() --- which is only needed when no journal is present --- and ext4_freeze(), ext4_unfreeze(), and ext4_sync_fs(), which are only needed when the journal is present. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/super.c108
1 files changed, 57 insertions, 51 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 7c7a08af1200..68c3a44c4a97 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -995,7 +995,6 @@ static const struct super_operations ext4_sops = {
995 .dirty_inode = ext4_dirty_inode, 995 .dirty_inode = ext4_dirty_inode,
996 .delete_inode = ext4_delete_inode, 996 .delete_inode = ext4_delete_inode,
997 .put_super = ext4_put_super, 997 .put_super = ext4_put_super,
998 .write_super = ext4_write_super,
999 .sync_fs = ext4_sync_fs, 998 .sync_fs = ext4_sync_fs,
1000 .freeze_fs = ext4_freeze, 999 .freeze_fs = ext4_freeze,
1001 .unfreeze_fs = ext4_unfreeze, 1000 .unfreeze_fs = ext4_unfreeze,
@@ -1010,6 +1009,25 @@ static const struct super_operations ext4_sops = {
1010 .bdev_try_to_free_page = bdev_try_to_free_page, 1009 .bdev_try_to_free_page = bdev_try_to_free_page,
1011}; 1010};
1012 1011
1012static const struct super_operations ext4_nojournal_sops = {
1013 .alloc_inode = ext4_alloc_inode,
1014 .destroy_inode = ext4_destroy_inode,
1015 .write_inode = ext4_write_inode,
1016 .dirty_inode = ext4_dirty_inode,
1017 .delete_inode = ext4_delete_inode,
1018 .write_super = ext4_write_super,
1019 .put_super = ext4_put_super,
1020 .statfs = ext4_statfs,
1021 .remount_fs = ext4_remount,
1022 .clear_inode = ext4_clear_inode,
1023 .show_options = ext4_show_options,
1024#ifdef CONFIG_QUOTA
1025 .quota_read = ext4_quota_read,
1026 .quota_write = ext4_quota_write,
1027#endif
1028 .bdev_try_to_free_page = bdev_try_to_free_page,
1029};
1030
1013static const struct export_operations ext4_export_ops = { 1031static const struct export_operations ext4_export_ops = {
1014 .fh_to_dentry = ext4_fh_to_dentry, 1032 .fh_to_dentry = ext4_fh_to_dentry,
1015 .fh_to_parent = ext4_fh_to_parent, 1033 .fh_to_parent = ext4_fh_to_parent,
@@ -2615,7 +2633,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
2615 /* 2633 /*
2616 * set up enough so that it can read an inode 2634 * set up enough so that it can read an inode
2617 */ 2635 */
2618 sb->s_op = &ext4_sops; 2636 if (!test_opt(sb, NOLOAD) &&
2637 EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
2638 sb->s_op = &ext4_sops;
2639 else
2640 sb->s_op = &ext4_nojournal_sops;
2619 sb->s_export_op = &ext4_export_ops; 2641 sb->s_export_op = &ext4_export_ops;
2620 sb->s_xattr = ext4_xattr_handlers; 2642 sb->s_xattr = ext4_xattr_handlers;
2621#ifdef CONFIG_QUOTA 2643#ifdef CONFIG_QUOTA
@@ -3275,19 +3297,9 @@ int ext4_force_commit(struct super_block *sb)
3275 return ret; 3297 return ret;
3276} 3298}
3277 3299
3278/*
3279 * Ext4 always journals updates to the superblock itself, so we don't
3280 * have to propagate any other updates to the superblock on disk at this
3281 * point if the journalling is enabled.
3282 */
3283static void ext4_write_super(struct super_block *sb) 3300static void ext4_write_super(struct super_block *sb)
3284{ 3301{
3285 if (EXT4_SB(sb)->s_journal) { 3302 ext4_commit_super(sb, 1);
3286 if (mutex_trylock(&sb->s_lock) != 0)
3287 BUG();
3288 } else {
3289 ext4_commit_super(sb, 1);
3290 }
3291} 3303}
3292 3304
3293static int ext4_sync_fs(struct super_block *sb, int wait) 3305static int ext4_sync_fs(struct super_block *sb, int wait)
@@ -3296,15 +3308,9 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
3296 tid_t target; 3308 tid_t target;
3297 3309
3298 trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait); 3310 trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait);
3299 if (EXT4_SB(sb)->s_journal) { 3311 if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
3300 if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, 3312 if (wait)
3301 &target)) { 3313 jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target);
3302 if (wait)
3303 jbd2_log_wait_commit(EXT4_SB(sb)->s_journal,
3304 target);
3305 }
3306 } else {
3307 ext4_commit_super(sb, wait);
3308 } 3314 }
3309 return ret; 3315 return ret;
3310} 3316}
@@ -3318,32 +3324,31 @@ static int ext4_freeze(struct super_block *sb)
3318 int error = 0; 3324 int error = 0;
3319 journal_t *journal; 3325 journal_t *journal;
3320 3326
3321 if (!(sb->s_flags & MS_RDONLY)) { 3327 if (sb->s_flags & MS_RDONLY)
3322 journal = EXT4_SB(sb)->s_journal; 3328 return 0;
3323 3329
3324 if (journal) { 3330 journal = EXT4_SB(sb)->s_journal;
3325 /* Now we set up the journal barrier. */
3326 jbd2_journal_lock_updates(journal);
3327 3331
3328 /* 3332 /* Now we set up the journal barrier. */
3329 * We don't want to clear needs_recovery flag when we 3333 jbd2_journal_lock_updates(journal);
3330 * failed to flush the journal.
3331 */
3332 error = jbd2_journal_flush(journal);
3333 if (error < 0)
3334 goto out;
3335 }
3336 3334
3337 /* Journal blocked and flushed, clear needs_recovery flag. */ 3335 /*
3338 EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); 3336 * Don't clear the needs_recovery flag if we failed to flush
3339 error = ext4_commit_super(sb, 1); 3337 * the journal.
3340 if (error) 3338 */
3341 goto out; 3339 error = jbd2_journal_flush(journal);
3340 if (error < 0) {
3341 out:
3342 jbd2_journal_unlock_updates(journal);
3343 return error;
3342 } 3344 }
3345
3346 /* Journal blocked and flushed, clear needs_recovery flag. */
3347 EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
3348 error = ext4_commit_super(sb, 1);
3349 if (error)
3350 goto out;
3343 return 0; 3351 return 0;
3344out:
3345 jbd2_journal_unlock_updates(journal);
3346 return error;
3347} 3352}
3348 3353
3349/* 3354/*
@@ -3352,14 +3357,15 @@ out:
3352 */ 3357 */
3353static int ext4_unfreeze(struct super_block *sb) 3358static int ext4_unfreeze(struct super_block *sb)
3354{ 3359{
3355 if (EXT4_SB(sb)->s_journal && !(sb->s_flags & MS_RDONLY)) { 3360 if (sb->s_flags & MS_RDONLY)
3356 lock_super(sb); 3361 return 0;
3357 /* Reser the needs_recovery flag before the fs is unlocked. */ 3362
3358 EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); 3363 lock_super(sb);
3359 ext4_commit_super(sb, 1); 3364 /* Reset the needs_recovery flag before the fs is unlocked. */
3360 unlock_super(sb); 3365 EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
3361 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 3366 ext4_commit_super(sb, 1);
3362 } 3367 unlock_super(sb);
3368 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
3363 return 0; 3369 return 0;
3364} 3370}
3365 3371