diff options
author | Theodore Ts'o <tytso@mit.edu> | 2009-05-01 12:52:25 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2009-05-01 12:52:25 -0400 |
commit | 9ca92389c5312a51e819c15c762f0abdc7f3129b (patch) | |
tree | 0f99256a5632614134573283853c577676cb1b99 /fs/ext4 | |
parent | 7234ab2a55e77784b44cf2d862136d9e41b8d98a (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.c | 108 |
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 | ||
1012 | static 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 | |||
1013 | static const struct export_operations ext4_export_ops = { | 1031 | static 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 | */ | ||
3283 | static void ext4_write_super(struct super_block *sb) | 3300 | static 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 | ||
3293 | static int ext4_sync_fs(struct super_block *sb, int wait) | 3305 | static 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; |
3344 | out: | ||
3345 | jbd2_journal_unlock_updates(journal); | ||
3346 | return error; | ||
3347 | } | 3352 | } |
3348 | 3353 | ||
3349 | /* | 3354 | /* |
@@ -3352,14 +3357,15 @@ out: | |||
3352 | */ | 3357 | */ |
3353 | static int ext4_unfreeze(struct super_block *sb) | 3358 | static 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 | ||