From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andrew Morton Subject: sync_fs for 2.5 Date: Tue, 10 Dec 2002 12:01:38 -0800 Sender: linux-fsdevel-owner@vger.kernel.org Message-ID: <3DF64822.D5E4CEA4@digeo.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Return-path: Received: from digeo-nav01.digeo.com (digeo-nav01.digeo.com [192.168.1.233]) by packet.digeo.com (8.9.3+Sun/8.9.3) with SMTP id MAA09015 for ; Tue, 10 Dec 2002 12:02:07 -0800 (PST) Received: from digeo-e2k04.digeo.com ([192.168.2.24]) by digeo-nav01.digeo.com (NAVGW 2.5.2.12) with SMTP id M2002121012035421471 for ; Tue, 10 Dec 2002 12:03:54 -0800 To: "linux-fsdevel@vger.kernel.org" List-Id: 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) _