* sync_fs for 2.5
@ 2002-12-10 20:01 Andrew Morton
0 siblings, 0 replies; only message in thread
From: Andrew Morton @ 2002-12-10 20:01 UTC (permalink / raw)
To: linux-fsdevel@vger.kernel.org
Here's my shot at a 2.5 version of the sync_fs() superblock operation.
It is more elaborate than in 2.4 - it is independent of s_dirt, and
does a two pass operation. The first to get IO underway, the second
to wait on it.
Seeking comments...
Documentation/filesystems/Locking | 2 +
fs/buffer.c | 11 ++++++--
fs/super.c | 48 +++++++++++++++++++++++++++++++++++---
include/linux/fs.h | 3 ++
4 files changed, 58 insertions(+), 6 deletions(-)
--- 25/fs/buffer.c~sync_fs Fri Dec 6 12:54:47 2002
+++ 25-akpm/fs/buffer.c Fri Dec 6 13:23:32 2002
@@ -222,6 +222,9 @@ int fsync_super(struct super_block *sb)
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->sync_fs) {
+ sb->s_op->sync_fs(sb, 1);
+ }
unlock_super(sb);
sync_blockdev(sb->s_bdev);
sync_inodes_sb(sb, 1);
@@ -252,10 +255,12 @@ int fsync_bdev(struct block_device *bdev
asmlinkage long sys_sync(void)
{
wakeup_bdflush(0);
- sync_inodes(0); /* All mappings and inodes, including block devices */
+ sync_inodes(0); /* All mappings, inodes and their blockdevs */
DQUOT_SYNC(NULL);
- sync_supers(); /* Write the superblocks */
- sync_inodes(1); /* All the mappings and inodes, again. */
+ sync_supers(); /* Write the superblocks */
+ sync_filesystems(0); /* Start syncing the filesystems */
+ sync_filesystems(1); /* Waitingly sync the filesystems */
+ sync_inodes(1); /* Mappings, inodes and blockdevs, again. */
return 0;
}
--- 25/include/linux/fs.h~sync_fs Fri Dec 6 12:54:47 2002
+++ 25-akpm/include/linux/fs.h Fri Dec 6 13:23:56 2002
@@ -632,6 +632,7 @@ struct super_block {
struct semaphore s_lock;
int s_count;
int s_syncing;
+ int s_need_sync_fs;
atomic_t s_active;
void *s_security;
@@ -810,6 +811,7 @@ struct super_operations {
void (*delete_inode) (struct inode *);
void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *);
+ int (*sync_fs)(struct super_block *sb, int wait);
void (*write_super_lockfs) (struct super_block *);
void (*unlockfs) (struct super_block *);
int (*statfs) (struct super_block *, struct statfs *);
@@ -1143,6 +1145,7 @@ extern void write_inode_now(struct inode
extern int filemap_fdatawrite(struct address_space *);
extern int filemap_fdatawait(struct address_space *);
extern void sync_supers(void);
+extern void sync_filesystems(int wait);
extern sector_t bmap(struct inode *, sector_t);
extern int setattr_mask(unsigned int);
extern int notify_change(struct dentry *, struct iattr *);
--- 25/fs/super.c~sync_fs Fri Dec 6 12:54:47 2002
+++ 25-akpm/fs/super.c Fri Dec 6 13:27:10 2002
@@ -189,6 +189,8 @@ void generic_shutdown_super(struct super
if (sop) {
if (sop->write_super && sb->s_dirt)
sop->write_super(sb);
+ if (sop->sync_fs)
+ sop->sync_fs(sb, 1);
if (sop->put_super)
sop->put_super(sb);
}
@@ -266,8 +268,8 @@ void drop_super(struct super_block *sb)
static inline void write_super(struct super_block *sb)
{
lock_super(sb);
- if (sb->s_root && sb->s_dirt)
- if (sb->s_op && sb->s_op->write_super)
+ if (sb->s_op && sb->s_root && sb->s_dirt)
+ if (sb->s_op->write_super)
sb->s_op->write_super(sb);
unlock_super(sb);
}
@@ -277,7 +279,7 @@ static inline void write_super(struct su
* hold up the sync while mounting a device. (The newly
* mounted device won't need syncing.)
*/
-void sync_supers(void)
+void sync_supers()
{
struct super_block * sb;
restart:
@@ -296,6 +298,46 @@ restart:
spin_unlock(&sb_lock);
}
+/*
+ * Call the ->sync_fs super_op against all filesytems which are r/w and
+ * which implement it.
+ */
+void sync_filesystems(int wait)
+{
+ struct super_block * sb;
+
+ spin_lock(&sb_lock);
+ for (sb = sb_entry(super_blocks.next); sb != sb_entry(&super_blocks);
+ sb = sb_entry(sb->s_list.next)) {
+ if (!sb->s_op)
+ continue;
+ if (!sb->s_op->sync_fs);
+ continue;
+ if (sb->s_flags & MS_RDONLY)
+ continue;
+ sb->s_need_sync_fs = 1;
+ }
+ spin_unlock(&sb_lock);
+
+restart:
+ spin_lock(&sb_lock);
+ for (sb = sb_entry(super_blocks.next); sb != sb_entry(&super_blocks);
+ sb = sb_entry(sb->s_list.next)) {
+ if (!sb->s_need_sync_fs)
+ continue;
+ sb->s_need_sync_fs = 0;
+ if (sb->s_flags & MS_RDONLY)
+ continue; /* hm. Was remounted r/w meanwhile */
+ sb->s_count++;
+ spin_unlock(&sb_lock);
+ down_read(&sb->s_umount);
+ sb->s_op->sync_fs(sb, wait);
+ drop_super(sb);
+ goto restart;
+ }
+ spin_unlock(&sb_lock);
+}
+
/**
* get_super - get the superblock of a device
* @dev: device to get the superblock for
--- 25/Documentation/filesystems/Locking~sync_fs Fri Dec 6 12:54:47 2002
+++ 25-akpm/Documentation/filesystems/Locking Fri Dec 6 12:54:47 2002
@@ -92,6 +92,7 @@ prototypes:
void (*delete_inode) (struct inode *);
void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *);
+ void (*sync_fs) (struct super_block *);
int (*statfs) (struct super_block *, struct statfs *);
int (*remount_fs) (struct super_block *, int *, char *);
void (*clear_inode) (struct inode *);
@@ -108,6 +109,7 @@ delete_inode: no
clear_inode: no
put_super: yes yes maybe (see below)
write_super: no yes maybe (see below)
+sync_fs: no no maybe (see below)
statfs: no no no
remount_fs: yes yes maybe (see below)
umount_begin: yes no maybe (see below)
_
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2002-12-10 20:02 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-12-10 20:01 sync_fs for 2.5 Andrew Morton
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).