[PATCH] write_super is not for syncing (take 3)

Chris Mason (mason@suse.com)
05 Aug 2002 13:34:53 -0400


Hello everyone,

This patch has been floating around for some time, and I've been
building other reiserfs speedups on top of it. It does two things:

1) allows the FS write_super function to leave the super dirty without
looping endlessly in sync_supers(). This is based on code sent to me by
Hugh Dickins, and it helps all the filesystems avoid looping in
sync_supers() under load.

2) adds a commit_super() call to struct super_operations(). This allows
the journaled filesystems to differentiate between calls from sync() and
calls from kupdated.

Below are just the hunks that change VFS code, against 2.4.19-final.
The reiserfs bits will come once this gets accepted. Please review and
throw something blunt at me if you don't want this in the kernel.

-chris

diff -urN --exclude *.orig --exclude *.rej parent/fs/buffer.c comp/fs/buffer.c
--- parent/fs/buffer.c Sun Jun 2 23:14:55 2002
+++ comp/fs/buffer.c Sun Jun 2 23:14:47 2002
@@ -328,6 +328,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();

@@ -347,7 +349,7 @@
lock_kernel();
sync_inodes(dev);
DQUOT_SYNC(dev);
- sync_supers(dev);
+ commit_supers(dev);
unlock_kernel();

return sync_buffers(dev, 1);
diff -urN --exclude *.orig --exclude *.rej parent/fs/super.c comp/fs/super.c
--- parent/fs/super.c Sun Jun 2 23:14:54 2002
+++ comp/fs/super.c Sun Jun 2 23:14:47 2002
@@ -396,6 +396,7 @@
struct file_system_type *fs = s->s_type;

spin_lock(&sb_lock);
+ s->s_type = NULL;
list_del(&s->s_list);
list_del(&s->s_instances);
spin_unlock(&sb_lock);
@@ -440,12 +441,23 @@
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);
+}
+
/*
* Note: check the dirty flag before waiting, so we don't
* hold up the sync while mounting a device. (The newly
* mounted device won't need syncing.)
*/
-void sync_supers(kdev_t dev)
+static void dirty_super_op(kdev_t dev, void (*func)(struct super_block *))
{
struct super_block * sb;

@@ -453,25 +465,41 @@
sb = get_super(dev);
if (sb) {
if (sb->s_dirt)
- write_super(sb);
+ func(sb);
drop_super(sb);
}
return;
}
-restart:
spin_lock(&sb_lock);
+restart:
sb = sb_entry(super_blocks.next);
- while (sb != sb_entry(&super_blocks))
+ while (sb != sb_entry(&super_blocks)) {
if (sb->s_dirt) {
sb->s_count++;
spin_unlock(&sb_lock);
down_read(&sb->s_umount);
- write_super(sb);
- drop_super(sb);
- goto restart;
- } else
- sb = sb_entry(sb->s_list.next);
+ func(sb);
+ up_read(&sb->s_umount);
+ spin_lock(&sb_lock);
+ if (!--sb->s_count) {
+ destroy_super(sb);
+ goto restart;
+ } else if (!sb->s_type)
+ goto restart;
+ }
+ sb = sb_entry(sb->s_list.next);
+ }
spin_unlock(&sb_lock);
+}
+
+void sync_supers(kdev_t dev)
+{
+ dirty_super_op(dev, write_super);
+}
+
+void commit_supers(kdev_t dev)
+{
+ dirty_super_op(dev, commit_super);
}

/**
diff -urN --exclude *.orig --exclude *.rej parent/include/linux/fs.h comp/include/linux/fs.h
--- parent/include/linux/fs.h Sun Jun 2 23:14:55 2002
+++ comp/include/linux/fs.h Sun Jun 2 23:14:47 2002
@@ -920,6 +920,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.. */
@@ -1236,6 +1237,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);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/