* [PATCH 1/3] ext4: Simplify ext4_commit_super()'s function signature
@ 2009-05-01 4:37 Theodore Ts'o
2009-05-01 4:37 ` [PATCH 2/3] ext4: Fix and simplify s_dirt handling Theodore Ts'o
0 siblings, 1 reply; 12+ messages in thread
From: Theodore Ts'o @ 2009-05-01 4:37 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
The ext4_commit_super() function took both a struct super_block * and
a struct ext4_super_block *, but the struct ext4_super_block can be
derived from the struct super_block.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/super.c | 33 ++++++++++++++++-----------------
1 files changed, 16 insertions(+), 17 deletions(-)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 3e509bc..ad4c9be 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -54,8 +54,7 @@ static struct kset *ext4_kset;
static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
unsigned long journal_devnum);
-static int ext4_commit_super(struct super_block *sb,
- struct ext4_super_block *es, int sync);
+static int ext4_commit_super(struct super_block *sb, int sync);
static void ext4_mark_recovery_complete(struct super_block *sb,
struct ext4_super_block *es);
static void ext4_clear_journal_err(struct super_block *sb,
@@ -306,7 +305,7 @@ static void ext4_handle_error(struct super_block *sb)
printk(KERN_CRIT "Remounting filesystem read-only\n");
sb->s_flags |= MS_RDONLY;
}
- ext4_commit_super(sb, es, 1);
+ ext4_commit_super(sb, 1);
if (test_opt(sb, ERRORS_PANIC))
panic("EXT4-fs (device %s): panic forced after error\n",
sb->s_id);
@@ -448,7 +447,7 @@ __acquires(bitlock)
if (test_opt(sb, ERRORS_CONT)) {
EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
- ext4_commit_super(sb, es, 0);
+ ext4_commit_super(sb, 0);
return;
}
ext4_unlock_group(sb, grp);
@@ -577,7 +576,7 @@ static void ext4_put_super(struct super_block *sb)
if (!(sb->s_flags & MS_RDONLY)) {
EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
es->s_state = cpu_to_le16(sbi->s_mount_state);
- ext4_commit_super(sb, es, 1);
+ ext4_commit_super(sb, 1);
}
if (sbi->s_proc) {
remove_proc_entry(sb->s_id, ext4_proc_root);
@@ -1596,7 +1595,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
if (sbi->s_journal)
EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
- ext4_commit_super(sb, es, 1);
+ ext4_commit_super(sb, 1);
if (test_opt(sb, DEBUG))
printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, "
"bpg=%lu, ipg=%lu, mo=%04lx]\n",
@@ -2655,7 +2654,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
if (test_opt(sb, ERRORS_PANIC)) {
EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
- ext4_commit_super(sb, es, 1);
+ ext4_commit_super(sb, 1);
goto failed_mount4;
}
}
@@ -3132,15 +3131,15 @@ static int ext4_load_journal(struct super_block *sb,
sb->s_dirt = 1;
/* Make sure we flush the recovery flag to disk. */
- ext4_commit_super(sb, es, 1);
+ ext4_commit_super(sb, 1);
}
return 0;
}
-static int ext4_commit_super(struct super_block *sb,
- struct ext4_super_block *es, int sync)
+static int ext4_commit_super(struct super_block *sb, int sync)
{
+ struct ext4_super_block *es = EXT4_SB(sb)->s_es;
struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
int error = 0;
@@ -3212,7 +3211,7 @@ static void ext4_mark_recovery_complete(struct super_block *sb,
sb->s_flags & MS_RDONLY) {
EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
sb->s_dirt = 0;
- ext4_commit_super(sb, es, 1);
+ ext4_commit_super(sb, 1);
}
unlock_super(sb);
@@ -3253,7 +3252,7 @@ static void ext4_clear_journal_err(struct super_block *sb,
EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
- ext4_commit_super(sb, es, 1);
+ ext4_commit_super(sb, 1);
jbd2_journal_clear_err(journal);
}
@@ -3293,7 +3292,7 @@ static void ext4_write_super(struct super_block *sb)
BUG();
sb->s_dirt = 0;
} else {
- ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
+ ext4_commit_super(sb, 1);
}
}
@@ -3312,7 +3311,7 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
target);
}
} else {
- ext4_commit_super(sb, EXT4_SB(sb)->s_es, wait);
+ ext4_commit_super(sb, wait);
}
return ret;
}
@@ -3345,7 +3344,7 @@ static int ext4_freeze(struct super_block *sb)
/* Journal blocked and flushed, clear needs_recovery flag. */
EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
- error = ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
+ error = ext4_commit_super(sb, 1);
if (error)
goto out;
}
@@ -3365,7 +3364,7 @@ static int ext4_unfreeze(struct super_block *sb)
lock_super(sb);
/* Reser the needs_recovery flag before the fs is unlocked. */
EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
- ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1);
+ ext4_commit_super(sb, 1);
unlock_super(sb);
jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
}
@@ -3520,7 +3519,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
}
}
if (sbi->s_journal == NULL)
- ext4_commit_super(sb, es, 1);
+ ext4_commit_super(sb, 1);
#ifdef CONFIG_QUOTA
/* Release old quota file names */
--
1.6.0.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/3] ext4: Fix and simplify s_dirt handling
2009-05-01 4:37 [PATCH 1/3] ext4: Simplify ext4_commit_super()'s function signature Theodore Ts'o
@ 2009-05-01 4:37 ` Theodore Ts'o
2009-05-01 4:37 ` [PATCH 3/3] ext4: Use separate super_operations structure for no_journal filesystems Theodore Ts'o
2009-05-01 7:02 ` [PATCH 2/3] ext4: Fix and simplify s_dirt handling Christoph Hellwig
0 siblings, 2 replies; 12+ messages in thread
From: Theodore Ts'o @ 2009-05-01 4:37 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
The s_dirt flag wasn't completely handled correctly, but it didn't
really matter when journalling was enabled. It turns out that when
ext4 runs without a journal, we don't clear s_dirt in places where we
should have, with the result that the high-level write_super()
function was writing the superblock when it wasn't necessary.
So we fix this by making ext4_commit_super() clear the s_dirt flag,
and removing many of the other places where s_dirt is manipulated.
When journalling is enabled, the s_dirt flag might be left set more
often, but s_dirt really doesn't matter when journalling is enabled.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
fs/ext4/super.c | 14 +++-----------
1 files changed, 3 insertions(+), 11 deletions(-)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index ad4c9be..7c7a08a 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3128,7 +3128,6 @@ static int ext4_load_journal(struct super_block *sb,
if (journal_devnum &&
journal_devnum != le32_to_cpu(es->s_journal_dev)) {
es->s_journal_dev = cpu_to_le32(journal_devnum);
- sb->s_dirt = 1;
/* Make sure we flush the recovery flag to disk. */
ext4_commit_super(sb, 1);
@@ -3168,7 +3167,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
&EXT4_SB(sb)->s_freeblocks_counter));
es->s_free_inodes_count = cpu_to_le32(percpu_counter_sum_positive(
&EXT4_SB(sb)->s_freeinodes_counter));
-
+ sb->s_dirt = 0;
BUFFER_TRACE(sbh, "marking dirty");
mark_buffer_dirty(sbh);
if (sync) {
@@ -3210,7 +3209,6 @@ static void ext4_mark_recovery_complete(struct super_block *sb,
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) &&
sb->s_flags & MS_RDONLY) {
EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
- sb->s_dirt = 0;
ext4_commit_super(sb, 1);
}
unlock_super(sb);
@@ -3271,10 +3269,8 @@ int ext4_force_commit(struct super_block *sb)
return 0;
journal = EXT4_SB(sb)->s_journal;
- if (journal) {
- sb->s_dirt = 0;
+ if (journal)
ret = ext4_journal_force_commit(journal);
- }
return ret;
}
@@ -3282,15 +3278,13 @@ int ext4_force_commit(struct super_block *sb)
/*
* 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. (We can probably nuke this function altogether, and remove
- * any mention to sb->s_dirt in all of fs/ext4; eventual cleanup...)
+ * point if the journalling is enabled.
*/
static void ext4_write_super(struct super_block *sb)
{
if (EXT4_SB(sb)->s_journal) {
if (mutex_trylock(&sb->s_lock) != 0)
BUG();
- sb->s_dirt = 0;
} else {
ext4_commit_super(sb, 1);
}
@@ -3302,7 +3296,6 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
tid_t target;
trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait);
- sb->s_dirt = 0;
if (EXT4_SB(sb)->s_journal) {
if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal,
&target)) {
@@ -3324,7 +3317,6 @@ static int ext4_freeze(struct super_block *sb)
{
int error = 0;
journal_t *journal;
- sb->s_dirt = 0;
if (!(sb->s_flags & MS_RDONLY)) {
journal = EXT4_SB(sb)->s_journal;
--
1.6.0.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/3] ext4: Use separate super_operations structure for no_journal filesystems
2009-05-01 4:37 ` [PATCH 2/3] ext4: Fix and simplify s_dirt handling Theodore Ts'o
@ 2009-05-01 4:37 ` Theodore Ts'o
2009-05-01 7:04 ` Christoph Hellwig
2009-05-01 10:42 ` Andreas Dilger
2009-05-01 7:02 ` [PATCH 2/3] ext4: Fix and simplify s_dirt handling Christoph Hellwig
1 sibling, 2 replies; 12+ messages in thread
From: Theodore Ts'o @ 2009-05-01 4:37 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
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>
---
fs/ext4/super.c | 98 ++++++++++++++++++++++++++-----------------------------
1 files changed, 46 insertions(+), 52 deletions(-)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 7c7a08a..241a81e 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -65,7 +65,6 @@ static const char *ext4_decode_error(struct super_block *sb, int errno,
static int ext4_remount(struct super_block *sb, int *flags, char *data);
static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf);
static int ext4_unfreeze(struct super_block *sb);
-static void ext4_write_super(struct super_block *sb);
static int ext4_freeze(struct super_block *sb);
@@ -995,7 +994,6 @@ static const struct super_operations ext4_sops = {
.dirty_inode = ext4_dirty_inode,
.delete_inode = ext4_delete_inode,
.put_super = ext4_put_super,
- .write_super = ext4_write_super,
.sync_fs = ext4_sync_fs,
.freeze_fs = ext4_freeze,
.unfreeze_fs = ext4_unfreeze,
@@ -1010,6 +1008,8 @@ static const struct super_operations ext4_sops = {
.bdev_try_to_free_page = bdev_try_to_free_page,
};
+static struct super_operations ext4_nojournal_sops;
+
static const struct export_operations ext4_export_ops = {
.fh_to_dentry = ext4_fh_to_dentry,
.fh_to_parent = ext4_fh_to_parent,
@@ -2615,7 +2615,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
/*
* 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_xattr = ext4_xattr_handlers;
#ifdef CONFIG_QUOTA
@@ -3275,19 +3279,9 @@ int ext4_force_commit(struct super_block *sb)
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)
{
- if (EXT4_SB(sb)->s_journal) {
- if (mutex_trylock(&sb->s_lock) != 0)
- BUG();
- } else {
- ext4_commit_super(sb, 1);
- }
+ ext4_commit_super(sb, 1);
}
static int ext4_sync_fs(struct super_block *sb, int wait)
@@ -3296,15 +3290,9 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
tid_t target;
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 (wait)
- jbd2_log_wait_commit(EXT4_SB(sb)->s_journal,
- target);
- }
- } else {
- ext4_commit_super(sb, wait);
+ if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
+ if (wait)
+ jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target);
}
return ret;
}
@@ -3318,32 +3306,31 @@ static int ext4_freeze(struct super_block *sb)
int error = 0;
journal_t *journal;
- if (!(sb->s_flags & MS_RDONLY)) {
- journal = EXT4_SB(sb)->s_journal;
+ if (sb->s_flags & MS_RDONLY)
+ return 0;
- if (journal) {
- /* Now we set up the journal barrier. */
- jbd2_journal_lock_updates(journal);
+ journal = EXT4_SB(sb)->s_journal;
- /*
- * We don't want to clear needs_recovery flag when we
- * failed to flush the journal.
- */
- error = jbd2_journal_flush(journal);
- if (error < 0)
- goto out;
- }
+ /* Now we set up the journal barrier. */
+ jbd2_journal_lock_updates(journal);
- /* 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;
+ /*
+ * Don't clear the needs_recovery flag if we failed to flush
+ * the journal.
+ */
+ 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;
-out:
- jbd2_journal_unlock_updates(journal);
- return error;
}
/*
@@ -3352,14 +3339,15 @@ out:
*/
static int ext4_unfreeze(struct super_block *sb)
{
- if (EXT4_SB(sb)->s_journal && !(sb->s_flags & MS_RDONLY)) {
- lock_super(sb);
- /* Reser the needs_recovery flag before the fs is unlocked. */
- EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
- ext4_commit_super(sb, 1);
- unlock_super(sb);
- jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
- }
+ if (sb->s_flags & MS_RDONLY)
+ return 0;
+
+ lock_super(sb);
+ /* Reset the needs_recovery flag before the fs is unlocked. */
+ EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+ ext4_commit_super(sb, 1);
+ unlock_super(sb);
+ jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
return 0;
}
@@ -3923,6 +3911,12 @@ static int __init init_ext4_fs(void)
{
int err;
+ ext4_nojournal_sops = ext4_sops;
+ ext4_nojournal_sops.write_super = ext4_write_super;
+ ext4_nojournal_sops.sync_fs = 0;
+ ext4_nojournal_sops.freeze_fs = 0;
+ ext4_nojournal_sops.unfreeze_fs = 0;
+
ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj);
if (!ext4_kset)
return -ENOMEM;
--
1.6.0.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 2/3] ext4: Fix and simplify s_dirt handling
2009-05-01 4:37 ` [PATCH 2/3] ext4: Fix and simplify s_dirt handling Theodore Ts'o
2009-05-01 4:37 ` [PATCH 3/3] ext4: Use separate super_operations structure for no_journal filesystems Theodore Ts'o
@ 2009-05-01 7:02 ` Christoph Hellwig
2009-05-01 13:45 ` Theodore Tso
1 sibling, 1 reply; 12+ messages in thread
From: Christoph Hellwig @ 2009-05-01 7:02 UTC (permalink / raw)
To: Theodore Ts'o; +Cc: Ext4 Developers List
On Fri, May 01, 2009 at 12:37:16AM -0400, Theodore Ts'o wrote:
> The s_dirt flag wasn't completely handled correctly, but it didn't
> really matter when journalling was enabled. It turns out that when
> ext4 runs without a journal, we don't clear s_dirt in places where we
> should have, with the result that the high-level write_super()
> function was writing the superblock when it wasn't necessary.
>
> So we fix this by making ext4_commit_super() clear the s_dirt flag,
> and removing many of the other places where s_dirt is manipulated.
> When journalling is enabled, the s_dirt flag might be left set more
> often, but s_dirt really doesn't matter when journalling is enabled.
Btw, you might want to move all s_dirt setting into a wrapper, so that
it never gets set for journal mode. That way we can avoid superflous
calls into the filesystem in that default mode.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/3] ext4: Use separate super_operations structure for no_journal filesystems
2009-05-01 4:37 ` [PATCH 3/3] ext4: Use separate super_operations structure for no_journal filesystems Theodore Ts'o
@ 2009-05-01 7:04 ` Christoph Hellwig
2009-05-01 13:48 ` Theodore Tso
2009-05-01 10:42 ` Andreas Dilger
1 sibling, 1 reply; 12+ messages in thread
From: Christoph Hellwig @ 2009-05-01 7:04 UTC (permalink / raw)
To: Theodore Ts'o; +Cc: Ext4 Developers List
On Fri, May 01, 2009 at 12:37:17AM -0400, Theodore Ts'o wrote:
> 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.
FYI: I will make ->sync_fs mandatory pretty soon. At that point
->write_super will only be left for d_dirt-induced periodic writeback.
(Still have to figure out what to do about file_fsync, but that won't
affect ext4)
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/3] ext4: Use separate super_operations structure for no_journal filesystems
2009-05-01 4:37 ` [PATCH 3/3] ext4: Use separate super_operations structure for no_journal filesystems Theodore Ts'o
2009-05-01 7:04 ` Christoph Hellwig
@ 2009-05-01 10:42 ` Andreas Dilger
2009-05-01 13:49 ` Theodore Tso
` (2 more replies)
1 sibling, 3 replies; 12+ messages in thread
From: Andreas Dilger @ 2009-05-01 10:42 UTC (permalink / raw)
To: Theodore Ts'o; +Cc: Ext4 Developers List
On May 01, 2009 00:37 -0400, Theodore Ts'o wrote:
> @@ -3923,6 +3911,12 @@ static int __init init_ext4_fs(void)
> + ext4_nojournal_sops = ext4_sops;
> + ext4_nojournal_sops.write_super = ext4_write_super;
> + ext4_nojournal_sops.sync_fs = 0;
> + ext4_nojournal_sops.freeze_fs = 0;
> + ext4_nojournal_sops.unfreeze_fs = 0;
I thought the general policy these days was to make a static const
ops struct so that it cannot be changed (correctly or incorrectly)?
Cheers, Andreas
--
Andreas Dilger
Sr. Staff Engineer, Lustre Group
Sun Microsystems of Canada, Inc.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/3] ext4: Fix and simplify s_dirt handling
2009-05-01 7:02 ` [PATCH 2/3] ext4: Fix and simplify s_dirt handling Christoph Hellwig
@ 2009-05-01 13:45 ` Theodore Tso
0 siblings, 0 replies; 12+ messages in thread
From: Theodore Tso @ 2009-05-01 13:45 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Ext4 Developers List
On Fri, May 01, 2009 at 03:02:55AM -0400, Christoph Hellwig wrote:
> On Fri, May 01, 2009 at 12:37:16AM -0400, Theodore Ts'o wrote:
> > The s_dirt flag wasn't completely handled correctly, but it didn't
> > really matter when journalling was enabled. It turns out that when
> > ext4 runs without a journal, we don't clear s_dirt in places where we
> > should have, with the result that the high-level write_super()
> > function was writing the superblock when it wasn't necessary.
> >
> > So we fix this by making ext4_commit_super() clear the s_dirt flag,
> > and removing many of the other places where s_dirt is manipulated.
> > When journalling is enabled, the s_dirt flag might be left set more
> > often, but s_dirt really doesn't matter when journalling is enabled.
>
> Btw, you might want to move all s_dirt setting into a wrapper, so that
> it never gets set for journal mode. That way we can avoid superflous
> calls into the filesystem in that default mode.
I thought about doing this, but currently the VFS core checks for the
presence for the write_super method function before it checks for
s_dirt, so it didn't seem to matter much whether or not s_dirt was set
if the filesystem doesn't have a NULL write_super function.
- Ted
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/3] ext4: Use separate super_operations structure for no_journal filesystems
2009-05-01 7:04 ` Christoph Hellwig
@ 2009-05-01 13:48 ` Theodore Tso
2009-05-01 14:24 ` Christoph Hellwig
0 siblings, 1 reply; 12+ messages in thread
From: Theodore Tso @ 2009-05-01 13:48 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Ext4 Developers List
On Fri, May 01, 2009 at 03:04:22AM -0400, Christoph Hellwig wrote:
> On Fri, May 01, 2009 at 12:37:17AM -0400, Theodore Ts'o wrote:
> > 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.
>
> FYI: I will make ->sync_fs mandatory pretty soon. At that point
> ->write_super will only be left for d_dirt-induced periodic writeback.
> (Still have to figure out what to do about file_fsync, but that won't
> affect ext4)
So I'm guessing your plans are to have sys_sync() no longer call
write_super(), but to only call sync_fs()? If that's the case, I
think all we need to do is set ext4_nojournal_sops.sync_fs to be
ext4_commit_super.
I assume the idea is so that the filesystem can distinguish between
periodic s_dirt writeback versus a request to write the superblock
caused by an explicit fsync or sync system call?
- Ted
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/3] ext4: Use separate super_operations structure for no_journal filesystems
2009-05-01 10:42 ` Andreas Dilger
@ 2009-05-01 13:49 ` Theodore Tso
2009-05-01 14:47 ` Christoph Hellwig
2009-05-01 16:55 ` [PATCH v2] " Theodore Ts'o
2 siblings, 0 replies; 12+ messages in thread
From: Theodore Tso @ 2009-05-01 13:49 UTC (permalink / raw)
To: Andreas Dilger; +Cc: Ext4 Developers List
On Fri, May 01, 2009 at 04:42:53AM -0600, Andreas Dilger wrote:
> On May 01, 2009 00:37 -0400, Theodore Ts'o wrote:
> > @@ -3923,6 +3911,12 @@ static int __init init_ext4_fs(void)
> > + ext4_nojournal_sops = ext4_sops;
> > + ext4_nojournal_sops.write_super = ext4_write_super;
> > + ext4_nojournal_sops.sync_fs = 0;
> > + ext4_nojournal_sops.freeze_fs = 0;
> > + ext4_nojournal_sops.unfreeze_fs = 0;
>
> I thought the general policy these days was to make a static const
> ops struct so that it cannot be changed (correctly or incorrectly)?
The tradeoff is this makes it much easier from a maintenance point of
view to see what the differences are between ext4_nojournal_sops and
ext4_journal_sops.
- Ted
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/3] ext4: Use separate super_operations structure for no_journal filesystems
2009-05-01 13:48 ` Theodore Tso
@ 2009-05-01 14:24 ` Christoph Hellwig
0 siblings, 0 replies; 12+ messages in thread
From: Christoph Hellwig @ 2009-05-01 14:24 UTC (permalink / raw)
To: Theodore Tso; +Cc: Christoph Hellwig, Ext4 Developers List
On Fri, May 01, 2009 at 09:48:04AM -0400, Theodore Tso wrote:
> So I'm guessing your plans are to have sys_sync() no longer call
> write_super(), but to only call sync_fs()? If that's the case, I
> think all we need to do is set ext4_nojournal_sops.sync_fs to be
> ext4_commit_super.
>
> I assume the idea is so that the filesystem can distinguish between
> periodic s_dirt writeback versus a request to write the superblock
> caused by an explicit fsync or sync system call?
Exactly. The plan is to use write_super only for peridoic writeback,
everything that is used for data integrity will go through ->sync_fs.
We'll grow a couple more ->sync_fs instances, but I think the result
is a lot more logic. We'll also avoid the mostly useless double
sb writes due to ->write_super being called for both the wait = 0 and
wait = 1 cases in sync.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/3] ext4: Use separate super_operations structure for no_journal filesystems
2009-05-01 10:42 ` Andreas Dilger
2009-05-01 13:49 ` Theodore Tso
@ 2009-05-01 14:47 ` Christoph Hellwig
2009-05-01 16:55 ` [PATCH v2] " Theodore Ts'o
2 siblings, 0 replies; 12+ messages in thread
From: Christoph Hellwig @ 2009-05-01 14:47 UTC (permalink / raw)
To: Andreas Dilger; +Cc: Theodore Ts'o, Ext4 Developers List
On Fri, May 01, 2009 at 04:42:53AM -0600, Andreas Dilger wrote:
> On May 01, 2009 00:37 -0400, Theodore Ts'o wrote:
> > @@ -3923,6 +3911,12 @@ static int __init init_ext4_fs(void)
> > + ext4_nojournal_sops = ext4_sops;
> > + ext4_nojournal_sops.write_super = ext4_write_super;
> > + ext4_nojournal_sops.sync_fs = 0;
> > + ext4_nojournal_sops.freeze_fs = 0;
> > + ext4_nojournal_sops.unfreeze_fs = 0;
>
> I thought the general policy these days was to make a static const
> ops struct so that it cannot be changed (correctly or incorrectly)?
Yeah. Having the super ops in the normal style would be a lot more
readable. We don't copy mostly the same inode or file operations
either.
And to be super-pedantic NULL pointer should be initialized as NULL, not
0.
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2] ext4: Use separate super_operations structure for no_journal filesystems
2009-05-01 10:42 ` Andreas Dilger
2009-05-01 13:49 ` Theodore Tso
2009-05-01 14:47 ` Christoph Hellwig
@ 2009-05-01 16:55 ` Theodore Ts'o
2 siblings, 0 replies; 12+ messages in thread
From: Theodore Ts'o @ 2009-05-01 16:55 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Andreas Dilger, Theodore Ts'o
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>
---
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 7c7a08a..68c3a44 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -995,7 +995,6 @@ static const struct super_operations ext4_sops = {
.dirty_inode = ext4_dirty_inode,
.delete_inode = ext4_delete_inode,
.put_super = ext4_put_super,
- .write_super = ext4_write_super,
.sync_fs = ext4_sync_fs,
.freeze_fs = ext4_freeze,
.unfreeze_fs = ext4_unfreeze,
@@ -1010,6 +1009,25 @@ static const struct super_operations ext4_sops = {
.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 = {
.fh_to_dentry = ext4_fh_to_dentry,
.fh_to_parent = ext4_fh_to_parent,
@@ -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
*/
- 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_xattr = ext4_xattr_handlers;
#ifdef CONFIG_QUOTA
@@ -3275,19 +3297,9 @@ int ext4_force_commit(struct super_block *sb)
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)
{
- if (EXT4_SB(sb)->s_journal) {
- if (mutex_trylock(&sb->s_lock) != 0)
- BUG();
- } else {
- ext4_commit_super(sb, 1);
- }
+ ext4_commit_super(sb, 1);
}
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;
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 (wait)
- jbd2_log_wait_commit(EXT4_SB(sb)->s_journal,
- target);
- }
- } else {
- ext4_commit_super(sb, wait);
+ if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
+ if (wait)
+ jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target);
}
return ret;
}
@@ -3318,32 +3324,31 @@ static int ext4_freeze(struct super_block *sb)
int error = 0;
journal_t *journal;
- if (!(sb->s_flags & MS_RDONLY)) {
- journal = EXT4_SB(sb)->s_journal;
+ if (sb->s_flags & MS_RDONLY)
+ return 0;
- if (journal) {
- /* Now we set up the journal barrier. */
- jbd2_journal_lock_updates(journal);
+ journal = EXT4_SB(sb)->s_journal;
- /*
- * We don't want to clear needs_recovery flag when we
- * failed to flush the journal.
- */
- error = jbd2_journal_flush(journal);
- if (error < 0)
- goto out;
- }
+ /* Now we set up the journal barrier. */
+ jbd2_journal_lock_updates(journal);
- /* 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;
+ /*
+ * Don't clear the needs_recovery flag if we failed to flush
+ * the journal.
+ */
+ 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;
-out:
- jbd2_journal_unlock_updates(journal);
- return error;
}
/*
@@ -3352,14 +3357,15 @@ out:
*/
static int ext4_unfreeze(struct super_block *sb)
{
- if (EXT4_SB(sb)->s_journal && !(sb->s_flags & MS_RDONLY)) {
- lock_super(sb);
- /* Reser the needs_recovery flag before the fs is unlocked. */
- EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
- ext4_commit_super(sb, 1);
- unlock_super(sb);
- jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
- }
+ if (sb->s_flags & MS_RDONLY)
+ return 0;
+
+ lock_super(sb);
+ /* Reset the needs_recovery flag before the fs is unlocked. */
+ EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+ ext4_commit_super(sb, 1);
+ unlock_super(sb);
+ jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
return 0;
}
--
1.6.0.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
end of thread, other threads:[~2009-05-01 16:56 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-01 4:37 [PATCH 1/3] ext4: Simplify ext4_commit_super()'s function signature Theodore Ts'o
2009-05-01 4:37 ` [PATCH 2/3] ext4: Fix and simplify s_dirt handling Theodore Ts'o
2009-05-01 4:37 ` [PATCH 3/3] ext4: Use separate super_operations structure for no_journal filesystems Theodore Ts'o
2009-05-01 7:04 ` Christoph Hellwig
2009-05-01 13:48 ` Theodore Tso
2009-05-01 14:24 ` Christoph Hellwig
2009-05-01 10:42 ` Andreas Dilger
2009-05-01 13:49 ` Theodore Tso
2009-05-01 14:47 ` Christoph Hellwig
2009-05-01 16:55 ` [PATCH v2] " Theodore Ts'o
2009-05-01 7:02 ` [PATCH 2/3] ext4: Fix and simplify s_dirt handling Christoph Hellwig
2009-05-01 13:45 ` Theodore Tso
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).