On Wed, May 06, 2009 at 10:16:31PM +0200, Christoph Hellwig wrote: > Only four filesystems have both a ->write_super method and use lock_super > internally: ext4, fat, sysv, ufs. Push down lock_super into these > filesystems and remove it from the caller. Add a get_fs_excl/put_fs_excl > pair to sync_super for now to keep the current behaviour in that > respect. Calling it a second time from write_super is fine as it's > only checked for beeing non-zero. > > > Signed-off-by: Christoph Hellwig <hch@xxxxxx> Actually the patch lost two hunks due to missing quilt adds. Here's the complete one: Signed-off-by: Christoph Hellwig <hch@xxxxxx> Index: vfs-2.6/fs/ext4/super.c =================================================================== --- vfs-2.6.orig/fs/ext4/super.c 2009-05-06 22:23:00.016784345 +0200 +++ vfs-2.6/fs/ext4/super.c 2009-05-06 22:26:09.741784086 +0200 @@ -66,6 +66,7 @@ static int ext4_remount(struct super_blo static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf); static int ext4_unfreeze(struct super_block *sb); static void ext4_write_super(struct super_block *sb); +static void ext4_write_super_locked(struct super_block *sb); static int ext4_freeze(struct super_block *sb); @@ -566,7 +567,7 @@ static void ext4_put_super(struct super_ lock_super(sb); lock_kernel(); if (sb->s_dirt) - ext4_write_super(sb); + ext4_write_super_locked(sb); ext4_mb_release(sb); ext4_ext_release(sb); @@ -3273,17 +3274,22 @@ int ext4_force_commit(struct super_block * point. (We can probably nuke this function altogether, and remove * any mention to sb->s_dirt in all of fs/ext4; eventual cleanup...) */ -static void ext4_write_super(struct super_block *sb) +static void ext4_write_super_locked(struct super_block *sb) { if (EXT4_SB(sb)->s_journal) { - if (mutex_trylock(&sb->s_lock) != 0) - BUG(); sb->s_dirt = 0; } else { ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1); } } +static void ext4_write_super(struct super_block *sb) +{ + lock_super(sb); + ext4_write_super_locked(sb); + unlock_super(sb); +} + static int ext4_sync_fs(struct super_block *sb, int wait) { int ret = 0; Index: vfs-2.6/fs/fat/inode.c =================================================================== --- vfs-2.6.orig/fs/fat/inode.c 2009-05-06 22:23:00.021784213 +0200 +++ vfs-2.6/fs/fat/inode.c 2009-05-06 22:26:09.741784086 +0200 @@ -441,8 +441,10 @@ static void fat_clear_inode(struct inode static void fat_write_super(struct super_block *sb) { + lock_super(sb); sb->s_dirt = 0; fat_clusters_flush(sb); + unlock_super(sb); } static void fat_put_super(struct super_block *sb) Index: vfs-2.6/fs/super.c =================================================================== --- vfs-2.6.orig/fs/super.c 2009-05-06 22:23:00.025787586 +0200 +++ vfs-2.6/fs/super.c 2009-05-06 22:26:09.742784073 +0200 @@ -421,7 +421,6 @@ restart: spin_unlock(&sb_lock); down_read(&sb->s_umount); - lock_super(sb); if (sb->s_root) { /* * Avoid loops if a filesystem left s_dirt @@ -433,10 +432,12 @@ restart: if (sb->s_flags & MS_RDONLY) sb->s_dirt = 0; - if (sb->s_dirt) + if (sb->s_dirt) { + get_fs_excl(); sb->s_op->write_super(sb); + put_fs_excl(); + } } - unlock_super(sb); up_read(&sb->s_umount); spin_lock(&sb_lock); Index: vfs-2.6/fs/sysv/inode.c =================================================================== --- vfs-2.6.orig/fs/sysv/inode.c 2009-05-06 22:23:00.059784161 +0200 +++ vfs-2.6/fs/sysv/inode.c 2009-05-06 22:26:09.743783851 +0200 @@ -37,6 +37,7 @@ static void sysv_write_super(struct supe struct sysv_sb_info *sbi = SYSV_SB(sb); unsigned long time = get_seconds(), old_time; + lock_super(sb); lock_kernel(); /* * If we are going to write out the super block, @@ -53,6 +54,7 @@ static void sysv_write_super(struct supe sb->s_dirt = 0; unlock_kernel(); + unlock_super(sb); } static int sysv_remount(struct super_block *sb, int *flags, char *data) Index: vfs-2.6/fs/ufs/super.c =================================================================== --- vfs-2.6.orig/fs/ufs/super.c 2009-05-06 22:23:00.065784017 +0200 +++ vfs-2.6/fs/ufs/super.c 2009-05-06 22:26:09.743783851 +0200 @@ -1131,6 +1131,7 @@ static void ufs_write_super(struct super struct ufs_super_block_third * usb3; unsigned flags; + lock_super(sb); lock_kernel(); UFSD("ENTER\n"); flags = UFS_SB(sb)->s_flags; @@ -1149,6 +1150,7 @@ static void ufs_write_super(struct super sb->s_dirt = 0; UFSD("EXIT\n"); unlock_kernel(); + unlock_super(sb); } static void ufs_put_super(struct super_block *sb) Index: vfs-2.6/fs/sync.c =================================================================== --- vfs-2.6.orig/fs/sync.c 2009-05-06 22:28:49.598694594 +0200 +++ vfs-2.6/fs/sync.c 2009-05-06 22:29:48.860661341 +0200 @@ -31,10 +31,11 @@ static int __sync_filesystem(struct supe else sync_quota_sb(sb, -1); sync_inodes_sb(sb, wait); - lock_super(sb); - if (sb->s_dirt && sb->s_op->write_super) + if (sb->s_dirt && sb->s_op->write_super) { + get_fs_excl(); sb->s_op->write_super(sb); - unlock_super(sb); + put_fs_excl(); + } if (sb->s_op->sync_fs) sb->s_op->sync_fs(sb, wait); return __sync_blockdev(sb->s_bdev, wait); @@ -162,10 +163,11 @@ int file_fsync(struct file *filp, struct /* sync the superblock to buffers */ sb = inode->i_sb; - lock_super(sb); - if (sb->s_dirt && sb->s_op->write_super) + if (sb->s_dirt && sb->s_op->write_super) { + get_fs_excl(); sb->s_op->write_super(sb); - unlock_super(sb); + put_fs_excl(); + } /* .. finally sync the buffers to disk */ err = sync_blockdev(sb->s_bdev); -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html