From: Chris Mason <mason@suse.com>
To: linux-kernel@vger.kernel.org
Subject: [PATCH] 2.5.x write_super is not for syncing
Date: 16 Oct 2002 14:00:06 -0400 [thread overview]
Message-ID: <1034791206.18503.68.camel@tiny> (raw)
Hello all,
This patch adds a commit_super super operation that allows the journaled
filesystems to do something different for the periodic write_super calls
and sync.
Based on comments from Al about my last patch, alloc_super sets a
default empty super_operations struct on each super. This allows us to
get rid of all checks for sb->s_ops == NULL.
sync_supers is changed so that it doesn't loop on a single FS if the
write_super call leaves sb->s_dirt set. I did this by changing
generic_shutdown_super to use list_del_init(&sb->s_list), which allows
us to check for supers that have been removed from the super_blocks list
while we slept. The idea came from an sgi patch Hugh Dickins sent me.
Anyway, this is against 2.5.43, please review:
--- 1.161/fs/buffer.c Tue Oct 8 14:40:47 2002
+++ edited/fs/buffer.c Wed Oct 16 11:39:04 2002
@@ -217,8 +217,10 @@
sync_inodes_sb(sb, 0);
DQUOT_SYNC(sb);
lock_super(sb);
- if (sb->s_dirt && sb->s_op && sb->s_op->write_super)
+ if (sb->s_dirt && sb->s_op->write_super)
sb->s_op->write_super(sb);
+ if (sb->s_dirt && sb->s_op->commit_super)
+ sb->s_op->commit_super(sb);
unlock_super(sb);
sync_blockdev(sb->s_bdev);
sync_inodes_sb(sb, 1);
@@ -251,7 +253,7 @@
wakeup_bdflush(0);
sync_inodes(0); /* All mappings and inodes, including block devices */
DQUOT_SYNC(NULL);
- sync_supers(); /* Write the superblocks */
+ commit_supers(); /* Write the superblocks */
sync_inodes(1); /* All the mappings and inodes, again. */
return 0;
}
@@ -274,7 +276,7 @@
/* sync the superblock to buffers */
sb = inode->i_sb;
lock_super(sb);
- if (sb->s_op && sb->s_op->write_super)
+ if (sb->s_op->write_super)
sb->s_op->write_super(sb);
unlock_super(sb);
--- 1.22/fs/fs-writeback.c Sun Sep 22 17:26:49 2002
+++ edited/fs/fs-writeback.c Wed Oct 16 13:29:51 2002
@@ -57,7 +57,7 @@
* dirty the inode itself
*/
if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
- if (sb->s_op && sb->s_op->dirty_inode)
+ if (sb->s_op->dirty_inode)
sb->s_op->dirty_inode(inode);
}
@@ -103,8 +103,7 @@
static void write_inode(struct inode *inode, int sync)
{
- if (inode->i_sb->s_op && inode->i_sb->s_op->write_inode &&
- !is_bad_inode(inode))
+ if (inode->i_sb->s_op->write_inode && !is_bad_inode(inode))
inode->i_sb->s_op->write_inode(inode, sync);
}
--- 1.83/fs/super.c Mon Sep 9 17:00:57 2002
+++ edited/fs/super.c Wed Oct 16 10:36:09 2002
@@ -48,6 +48,8 @@
*/
static struct super_block *alloc_super(void)
{
+ static struct super_operations default_op = {};
+
struct super_block *s = kmalloc(sizeof(struct super_block), GFP_USER);
if (s) {
memset(s, 0, sizeof(struct super_block));
@@ -72,6 +74,7 @@
s->s_maxbytes = MAX_NON_LFS;
s->dq_op = sb_dquot_ops;
s->s_qcop = sb_quotactl_ops;
+ s->s_op = &default_op;
}
out:
return s;
@@ -203,7 +206,12 @@
unlock_super(sb);
}
spin_lock(&sb_lock);
- list_del(&sb->s_list);
+
+ /*
+ * use list_del_init so we can tell later if a super with an
+ * incremented count has been removed from all lists
+ */
+ list_del_init(&sb->s_list);
list_del(&sb->s_instances);
spin_unlock(&sb_lock);
up_write(&sb->s_umount);
@@ -267,35 +275,65 @@
{
lock_super(sb);
if (sb->s_root && sb->s_dirt)
- if (sb->s_op && sb->s_op->write_super)
+ if (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->write_super)
+ sb->s_op->write_super(sb);
+ if (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(void)
+void dirty_super_op(void (*func)(struct super_block *))
{
struct super_block * sb;
-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 (list_empty(&sb->s_list)) {
+ goto restart;
+ }
+ }
+ sb = sb_entry(sb->s_list.next);
+ }
spin_unlock(&sb_lock);
}
+void sync_supers(void)
+{
+ dirty_super_op(write_super);
+}
+
+void commit_supers(void)
+{
+ dirty_super_op(commit_super);
+}
+
/**
* get_super - get the superblock of a device
* @dev: device to get the superblock for
@@ -396,7 +434,7 @@
if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
if (!fs_may_remount_ro(sb))
return -EBUSY;
- if (sb->s_op && sb->s_op->remount_fs) {
+ if (sb->s_op->remount_fs) {
lock_super(sb);
retval = sb->s_op->remount_fs(sb, &flags, data);
unlock_super(sb);
--- 1.170/include/linux/fs.h Fri Oct 11 04:49:46 2002
+++ edited/include/linux/fs.h Wed Oct 16 10:42:16 2002
@@ -818,6 +818,7 @@
void (*umount_begin) (struct super_block *);
int (*show_options)(struct seq_file *, struct vfsmount *);
+ void (*commit_super) (struct super_block *);
};
/* Inode state bits. Protected by inode_lock. */
@@ -1141,6 +1142,7 @@
extern int filemap_fdatawrite(struct address_space *);
extern int filemap_fdatawait(struct address_space *);
extern void sync_supers(void);
+extern void commit_supers(void);
extern sector_t bmap(struct inode *, sector_t);
extern int notify_change(struct dentry *, struct iattr *);
extern int permission(struct inode *, int);
next reply other threads:[~2002-10-16 17:53 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-10-16 18:00 Chris Mason [this message]
2002-12-02 22:07 ` [PATCH] 2.5.x write_super is not for syncing Andrew Morton
2002-12-02 23:40 ` Chris Mason
2002-12-03 0:03 ` Andrew Morton
2002-12-03 1:10 ` Chris Mason
2002-12-03 1:40 ` Andrew Morton
2002-12-03 3:09 ` Andrew Morton
2002-12-03 19:36 ` Bryan Henderson
2002-12-03 20:06 ` Andrew Morton
2002-12-03 21:41 ` Bryan Henderson
2002-12-03 22:13 ` Andrew Morton
2002-12-04 2:05 ` Bryan Henderson
2002-12-04 4:29 ` Andrew Morton
2002-12-04 19:00 ` Bryan Henderson
2002-12-04 19:23 ` Matthew Wilcox
2002-12-04 22:17 ` Bryan Henderson
2002-12-05 10:36 ` Arnaldo Carvalho de Melo
2002-12-05 16:31 ` Stephen C. Tweedie
2002-12-05 17:24 ` girish
2002-12-04 21:10 ` Stephen C. Tweedie
2002-12-04 22:46 ` Bryan Henderson
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=1034791206.18503.68.camel@tiny \
--to=mason@suse.com \
--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.