From: Artem Bityutskiy <dedekind1@gmail.com>
To: Ted Tso <tytso@mit.edu>
Cc: Ext4 Mailing List <linux-ext4@vger.kernel.org>,
Linux FS Maling List <linux-fsdevel@vger.kernel.org>,
Linux Kernel Maling List <linux-kernel@vger.kernel.org>
Subject: [PATCH v1 7/9] ext4: stop using VFS for dirty superblock management
Date: Tue, 20 Mar 2012 16:41:27 +0200 [thread overview]
Message-ID: <1332254489-2300-8-git-send-email-dedekind1@gmail.com> (raw)
In-Reply-To: <1332254489-2300-1-git-send-email-dedekind1@gmail.com>
From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Do not use VFS for managing dirty superblock but do it inside ext4. Remove the
'ext4_write_super()' VFS callback and instead, schedule a delayed work when the
superblock is marked as dirty. Use the 'dio_unwritten_wq' which we already have
for these purposes.
We add memory barriers to make sure the 's_dirt' flag changes are visible to
other CPUs as soon as possible to avoid queuing unnecessary works.
The big changes comparing to the previous behavior:
1. We use 'dio_unwritten' queue, so the superblock will be written by
per-filesystem 'ext4-dio-unwrit' thread, instead of 'sync_supers' thread.
2. We allocate memory in 'ext4_mark_super_dirty()'.
Note: the final goal is to get rid of the 'sync_supers()' kernel thread which
wakes up every 5 seconds and even if there is nothing to do. Thus, we are
pushing superblock management from VFS down to file-systems.
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
---
fs/ext4/super.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 63 insertions(+), 10 deletions(-)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index d9543f3..7d453f7 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -73,7 +73,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);
static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *data);
@@ -1294,7 +1293,6 @@ static const struct super_operations ext4_nojournal_sops = {
.dirty_inode = ext4_dirty_inode,
.drop_inode = ext4_drop_inode,
.evict_inode = ext4_evict_inode,
- .write_super = ext4_write_super,
.put_super = ext4_put_super,
.statfs = ext4_statfs,
.remount_fs = ext4_remount,
@@ -4140,6 +4138,14 @@ static int ext4_commit_super(struct super_block *sb, int sync)
if (!sbh || block_device_ejected(sb))
return error;
+
+ sb->s_dirt = 0;
+ /*
+ * Make sure we first mark the superblock as clean and then start
+ * writing it out.
+ */
+ smp_wmb();
+
if (buffer_write_io_error(sbh)) {
/*
* Oh, dear. A previous attempt to write the
@@ -4180,7 +4186,6 @@ static int ext4_commit_super(struct super_block *sb, int sync)
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) {
@@ -4199,9 +4204,64 @@ static int ext4_commit_super(struct super_block *sb, int sync)
return error;
}
+struct sb_delayed_work {
+ struct delayed_work dwork;
+ struct super_block *sb;
+};
+
+static struct sb_delayed_work *work_to_sbwork(struct work_struct *work)
+{
+ struct delayed_work *dwork;
+
+ dwork = container_of(work, struct delayed_work, work);
+ return container_of(dwork, struct sb_delayed_work, dwork);
+}
+
+static void write_super(struct work_struct *work)
+{
+ struct sb_delayed_work *sbwork = work_to_sbwork(work);
+ struct super_block *sb = sbwork->sb;
+
+ kfree(sbwork);
+
+ smp_rmb();
+ if (!sb->s_dirt)
+ return;
+
+ lock_super(sb);
+ ext4_commit_super(sb, 1);
+ unlock_super(sb);
+}
+
void __ext4_mark_super_dirty(struct super_block *sb)
{
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
+ struct sb_delayed_work *sbwork;
+ unsigned long delay;
+
+ /* Make sure we see 's_dirt' changes ASAP */
+ smp_rmb();
+ if (sb->s_dirt == 1)
+ return;
sb->s_dirt = 1;
+ /* Make other CPUs see the 's_dirt' change as soon as possible */
+ smp_wmb();
+
+ sbwork = kmalloc(sizeof(struct sb_delayed_work), GFP_NOFS);
+ if (!sbwork) {
+ /*
+ * Well, should not be a big deal - the system must be in
+ * trouble anyway, and the SB will be written out on unmount or
+ * we may be luckier next time it is marked as dirty.
+ */
+ sb->s_dirt = 2;
+ return;
+ }
+
+ INIT_DELAYED_WORK(&sbwork->dwork, write_super);
+ sbwork->sb = sb;
+ delay = msecs_to_jiffies(dirty_writeback_interval * 10);
+ queue_delayed_work(sbi->dio_unwritten_wq, &sbwork->dwork, delay);
}
/*
@@ -4291,13 +4351,6 @@ int ext4_force_commit(struct super_block *sb)
return ret;
}
-static void ext4_write_super(struct super_block *sb)
-{
- lock_super(sb);
- ext4_commit_super(sb, 1);
- unlock_super(sb);
-}
next prev parent reply other threads:[~2012-03-20 14:41 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-20 14:41 [PATCH v1 0/9] do not use s_dirt in ext4 Artem Bityutskiy
2012-03-20 14:41 ` [PATCH v1 1/9] ext4: do not mark superblock as dirty unnecessarily Artem Bityutskiy
2012-03-22 9:58 ` Jan Kara
2012-03-20 14:41 ` [PATCH v1 2/9] ext4: write superblock only once on unmount Artem Bityutskiy
2012-03-22 9:59 ` Jan Kara
2012-03-20 14:41 ` [PATCH v1 3/9] ext4: remove useless s_dirt assignment Artem Bityutskiy
2012-03-22 10:02 ` Jan Kara
2012-03-20 14:41 ` [PATCH v1 4/9] mm: export dirty_writeback_interval Artem Bityutskiy
2012-03-20 14:41 ` [PATCH v1 5/9] VFS: remove unused superblock helpers Artem Bityutskiy
2012-03-20 14:41 ` [PATCH v1 6/9] ext4: introduce __ext4_mark_super_dirty Artem Bityutskiy
2012-03-20 14:41 ` Artem Bityutskiy [this message]
2012-03-21 8:26 ` [PATCH v1 7/9] ext4: stop using VFS for dirty superblock management Artem Bityutskiy
2012-03-20 14:41 ` [PATCH v1 8/9] ext4: small cleanup in ext4_commit_super Artem Bityutskiy
2012-03-22 10:11 ` Jan Kara
2012-03-20 14:41 ` [PATCH v1 9/9] ext4: introduce own superblock dirty flag Artem Bityutskiy
2012-03-22 9:53 ` [PATCH v1 0/9] do not use s_dirt in ext4 Jan Kara
2012-03-22 10:05 ` Artem Bityutskiy
2012-03-22 10:33 ` Jan Kara
2012-03-22 11:25 ` Artem Bityutskiy
2012-03-22 13:42 ` Jan Kara
2012-03-22 13:59 ` Artem Bityutskiy
2012-03-27 13:29 ` Artem Bityutskiy
2012-03-27 20:14 ` Jan Kara
2012-03-28 8:44 ` Artem Bityutskiy
2012-03-28 10:15 ` Jan Kara
2012-03-30 15:23 ` Artem Bityutskiy
2012-03-30 15:35 ` Jan Kara
2012-03-30 15:43 ` Artem Bityutskiy
2012-03-31 11:49 ` Jan Kara
2012-04-02 13:46 ` Artem Bityutskiy
2012-03-31 12:25 ` Artem Bityutskiy
2012-03-22 13:35 ` Ted Ts'o
2012-03-22 13:56 ` Artem Bityutskiy
2012-03-22 15:06 ` Ted Ts'o
2012-03-23 8:55 ` Artem Bityutskiy
2012-03-23 14:23 ` Ted Ts'o
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1332254489-2300-8-git-send-email-dedekind1@gmail.com \
--to=dedekind1@gmail.com \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=tytso@mit.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).