From: Chris Mason <mason@suse.com>
To: linux-kernel@vger.kernel.org
Cc: aviro@math.psu.edu, akpm@zip.com.au
Subject: [RFC] write_super is for syncing
Date: Tue, 12 Mar 2002 17:00:53 -0500 [thread overview]
Message-ID: <205630000.1015970453@tiny> (raw)
Hi everyone,
The fact that write_super gets called for both syncs and periodic
commits causes problems for the journaled filesystems, since we
need to trigger commits on write_super to have sync() behave
properly.
So, this patch adds a new super operation called commit_super,
and extends struct super.s_dirt a little so the filesystem
can say: call me on sync() but don't call me from kupdate.
if (s_dirt & S_SUPER_DIRTY) call me from kupdate and on sync
if (s_dirt & S_SUPER_DIRTY_COMMIT) call me on sync only.
If the commit_super operation is not provided, fs/super.c goes
back to the old s_dirt usage.
I've got reiserfs bits to make use of this, they increase our
streaming write performance by ~30%. This patch is against 2.4.19-pre1,
it applies cleanly to pre3 but I haven't tested that yet. I'll port
to 2.5 if we agree the patch is a good idea.
-chris
--- linus.25/fs/super.c Mon, 28 Jan 2002 09:51:50 -0500
+++ speedup.1/fs/super.c Sun, 12 May 2002 10:54:29 -0400
@@ -453,15 +453,68 @@
put_super(sb);
}
+/* since we've added the idea of comit_dirty vs regular dirty with
+ * commit_super operation, only use the S_SUPER_DIRTY mask if
+ * the FS has a commit_super op.
+ */
+static inline int super_dirty(struct super_block *sb)
+{
+ if (sb->s_op && sb->s_op->commit_super) {
+ return sb->s_dirt & S_SUPER_DIRTY;
+ }
+ return sb->s_dirt;
+}
+
+
static inline void write_super(struct super_block *sb)
{
lock_super(sb);
- if (sb->s_root && sb->s_dirt)
+ if (sb->s_root && super_dirty(sb))
if (sb->s_op && sb->s_op->write_super)
sb->s_op->write_super(sb);
unlock_super(sb);
}
+static inline void commit_super(struct super_block *sb)
+{
+ lock_super(sb);
+ if (sb->s_root && sb->s_dirt) {
+ if (sb->s_op && sb->s_op->write_super)
+ sb->s_op->write_super(sb);
+ if (sb->s_op && sb->s_op->commit_super)
+ sb->s_op->commit_super(sb);
+ }
+ unlock_super(sb);
+}
+
+void commit_supers(kdev_t dev)
+{
+ struct super_block * sb;
+
+ if (dev) {
+ sb = get_super(dev);
+ if (sb) {
+ if (sb->s_dirt)
+ commit_super(sb);
+ drop_super(sb);
+ }
+ }
+restart:
+ spin_lock(&sb_lock);
+ sb = sb_entry(super_blocks.next);
+ while (sb != sb_entry(&super_blocks))
+ if (sb->s_dirt) {
+ sb->s_count++;
+ spin_unlock(&sb_lock);
+ down_read(&sb->s_umount);
+ commit_super(sb);
+ drop_super(sb);
+ goto restart;
+ } else
+ sb = sb_entry(sb->s_list.next);
+ spin_unlock(&sb_lock);
+}
+
/*
* Note: check the dirty flag before waiting, so we don't
* hold up the sync while mounting a device. (The newly
@@ -484,7 +537,7 @@
spin_lock(&sb_lock);
sb = sb_entry(super_blocks.next);
while (sb != sb_entry(&super_blocks))
- if (sb->s_dirt) {
+ if (super_dirty(sb)) {
sb->s_count++;
spin_unlock(&sb_lock);
down_read(&sb->s_umount);
--- linus.25/fs/buffer.c Mon, 11 Feb 2002 12:21:42 -0500
+++ speedup.1/fs/buffer.c Sun, 12 May 2002 10:54:29 -0400
@@ -327,6 +327,8 @@
lock_super(sb);
if (sb->s_dirt && sb->s_op && sb->s_op->write_super)
sb->s_op->write_super(sb);
+ if (sb->s_op && sb->s_op->commit_super)
+ sb->s_op->commit_super(sb);
unlock_super(sb);
unlock_kernel();
@@ -346,7 +348,7 @@
lock_kernel();
sync_inodes(dev);
DQUOT_SYNC(dev);
- sync_supers(dev);
+ commit_supers(dev);
unlock_kernel();
return sync_buffers(dev, 1);
--- linus.25/include/linux/fs.h Mon, 28 Jan 2002 09:51:50 -0500
+++ speedup.1/include/linux/fs.h Sun, 12 May 2002 10:54:29 -0400
@@ -697,6 +697,10 @@
#define sb_entry(list) list_entry((list), struct super_block, s_list)
#define S_BIAS (1<<30)
+
+/* flags for the s_dirt field */
+#define S_SUPER_DIRTY 1
+#define S_SUPER_DIRTY_COMMIT 2
struct super_block {
struct list_head s_list; /* Keep this first */
kdev_t s_dev;
@@ -909,6 +913,7 @@
struct dentry * (*fh_to_dentry)(struct super_block *sb, __u32 *fh, int len, int fhtype, int parent);
int (*dentry_to_fh)(struct dentry *, __u32 *fh, int *lenp, int need_parent);
int (*show_options)(struct seq_file *, struct vfsmount *);
+ void (*commit_super) (struct super_block *);
};
/* Inode state bits.. */
@@ -1216,6 +1221,7 @@
extern int filemap_fdatasync(struct address_space *);
extern int filemap_fdatawait(struct address_space *);
extern void sync_supers(kdev_t);
+extern void commit_supers(kdev_t);
extern int bmap(struct inode *, int);
extern int notify_change(struct dentry *, struct iattr *);
extern int permission(struct inode *, int);
next reply other threads:[~2002-03-12 22:02 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-03-12 22:00 Chris Mason [this message]
2002-03-12 22:15 ` [RFC] write_super is for syncing Andrew Morton
2002-03-12 22:48 ` Chris Mason
2002-03-12 23:11 ` Chris Mason
2002-03-13 20:49 ` Hugh Dickins
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=205630000.1015970453@tiny \
--to=mason@suse.com \
--cc=akpm@zip.com.au \
--cc=aviro@math.psu.edu \
--cc=linux-kernel@vger.kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.