Commit 9ca92389 authored by Theodore Ts'o's avatar Theodore Ts'o

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: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent 7234ab2a
...@@ -995,7 +995,6 @@ static const struct super_operations ext4_sops = { ...@@ -995,7 +995,6 @@ static const struct super_operations ext4_sops = {
.dirty_inode = ext4_dirty_inode, .dirty_inode = ext4_dirty_inode,
.delete_inode = ext4_delete_inode, .delete_inode = ext4_delete_inode,
.put_super = ext4_put_super, .put_super = ext4_put_super,
.write_super = ext4_write_super,
.sync_fs = ext4_sync_fs, .sync_fs = ext4_sync_fs,
.freeze_fs = ext4_freeze, .freeze_fs = ext4_freeze,
.unfreeze_fs = ext4_unfreeze, .unfreeze_fs = ext4_unfreeze,
...@@ -1010,6 +1009,25 @@ static const struct super_operations ext4_sops = { ...@@ -1010,6 +1009,25 @@ static const struct super_operations ext4_sops = {
.bdev_try_to_free_page = bdev_try_to_free_page, .bdev_try_to_free_page = bdev_try_to_free_page,
}; };
static const struct super_operations ext4_nojournal_sops = {
.alloc_inode = ext4_alloc_inode,
.destroy_inode = ext4_destroy_inode,
.write_inode = ext4_write_inode,
.dirty_inode = ext4_dirty_inode,
.delete_inode = ext4_delete_inode,
.write_super = ext4_write_super,
.put_super = ext4_put_super,
.statfs = ext4_statfs,
.remount_fs = ext4_remount,
.clear_inode = ext4_clear_inode,
.show_options = ext4_show_options,
#ifdef CONFIG_QUOTA
.quota_read = ext4_quota_read,
.quota_write = ext4_quota_write,
#endif
.bdev_try_to_free_page = bdev_try_to_free_page,
};
static const struct export_operations ext4_export_ops = { static const struct export_operations ext4_export_ops = {
.fh_to_dentry = ext4_fh_to_dentry, .fh_to_dentry = ext4_fh_to_dentry,
.fh_to_parent = ext4_fh_to_parent, .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,7 +2633,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
/* /*
* set up enough so that it can read an inode * set up enough so that it can read an inode
*/ */
sb->s_op = &ext4_sops; if (!test_opt(sb, NOLOAD) &&
EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
sb->s_op = &ext4_sops;
else
sb->s_op = &ext4_nojournal_sops;
sb->s_export_op = &ext4_export_ops; sb->s_export_op = &ext4_export_ops;
sb->s_xattr = ext4_xattr_handlers; sb->s_xattr = ext4_xattr_handlers;
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
...@@ -3275,19 +3297,9 @@ int ext4_force_commit(struct super_block *sb) ...@@ -3275,19 +3297,9 @@ int ext4_force_commit(struct super_block *sb)
return ret; return ret;
} }
/*
* Ext4 always journals updates to the superblock itself, so we don't
* have to propagate any other updates to the superblock on disk at this
* point if the journalling is enabled.
*/
static void ext4_write_super(struct super_block *sb) static void ext4_write_super(struct super_block *sb)
{ {
if (EXT4_SB(sb)->s_journal) { ext4_commit_super(sb, 1);
if (mutex_trylock(&sb->s_lock) != 0)
BUG();
} else {
ext4_commit_super(sb, 1);
}
} }
static int ext4_sync_fs(struct super_block *sb, int wait) 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,15 +3308,9 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
tid_t target; tid_t target;
trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait); trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait);
if (EXT4_SB(sb)->s_journal) { if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, if (wait)
&target)) { jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target);
if (wait)
jbd2_log_wait_commit(EXT4_SB(sb)->s_journal,
target);
}
} else {
ext4_commit_super(sb, wait);
} }
return ret; return ret;
} }
...@@ -3318,32 +3324,31 @@ static int ext4_freeze(struct super_block *sb) ...@@ -3318,32 +3324,31 @@ static int ext4_freeze(struct super_block *sb)
int error = 0; int error = 0;
journal_t *journal; journal_t *journal;
if (!(sb->s_flags & MS_RDONLY)) { if (sb->s_flags & MS_RDONLY)
journal = EXT4_SB(sb)->s_journal; return 0;
if (journal) { journal = EXT4_SB(sb)->s_journal;
/* Now we set up the journal barrier. */
jbd2_journal_lock_updates(journal);
/* /* Now we set up the journal barrier. */
* We don't want to clear needs_recovery flag when we jbd2_journal_lock_updates(journal);
* failed to flush the journal.
*/
error = jbd2_journal_flush(journal);
if (error < 0)
goto out;
}
/* Journal blocked and flushed, clear needs_recovery flag. */ /*
EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); * Don't clear the needs_recovery flag if we failed to flush
error = ext4_commit_super(sb, 1); * the journal.
if (error) */
goto out; error = jbd2_journal_flush(journal);
if (error < 0) {
out:
jbd2_journal_unlock_updates(journal);
return error;
} }
/* Journal blocked and flushed, clear needs_recovery flag. */
EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
error = ext4_commit_super(sb, 1);
if (error)
goto out;
return 0; return 0;
out:
jbd2_journal_unlock_updates(journal);
return error;
} }
/* /*
...@@ -3352,14 +3357,15 @@ static int ext4_freeze(struct super_block *sb) ...@@ -3352,14 +3357,15 @@ static int ext4_freeze(struct super_block *sb)
*/ */
static int ext4_unfreeze(struct super_block *sb) static int ext4_unfreeze(struct super_block *sb)
{ {
if (EXT4_SB(sb)->s_journal && !(sb->s_flags & MS_RDONLY)) { if (sb->s_flags & MS_RDONLY)
lock_super(sb); return 0;
/* Reser the needs_recovery flag before the fs is unlocked. */
EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); lock_super(sb);
ext4_commit_super(sb, 1); /* Reset the needs_recovery flag before the fs is unlocked. */
unlock_super(sb); EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); ext4_commit_super(sb, 1);
} unlock_super(sb);
jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment