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> Index: vfs-2.6/fs/ext4/super.c =================================================================== --- vfs-2.6.orig/fs/ext4/super.c 2009-05-06 21:35:40.923658961 +0200 +++ vfs-2.6/fs/ext4/super.c 2009-05-06 21:37:07.337661434 +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,7 +3274,7 @@ 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) @@ -3284,6 +3285,13 @@ static void ext4_write_super(struct supe } } +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 21:37:16.737659384 +0200 +++ vfs-2.6/fs/fat/inode.c 2009-05-06 21:37:53.358661652 +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 21:41:00.805784126 +0200 +++ vfs-2.6/fs/super.c 2009-05-06 21:41:57.191661325 +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 21:39:21.263682879 +0200 +++ vfs-2.6/fs/sysv/inode.c 2009-05-06 21:39:58.219661498 +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 21:40:01.440659714 +0200 +++ vfs-2.6/fs/ufs/super.c 2009-05-06 21:40:33.502786591 +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) -- 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