On Fri, 22 Oct 2010, Miklos Szeredi wrote: > > Or, more subtle, tries to > > update atime on some opened struct file on that sb. > > Hmm, load_nls() will apparently do that. Drat. > > Plan B: remount all vfsmounts read-only before ->remount_fs() but > remember which ones were read-write and restore on failure. Will > result in ugly transient write failures if remount_fs() fails, but I > don't think anybody would care in practice. And it's actually a pretty simple change. Here's the incremental patch to "vfs: protect remounting superblock read-only", with "vfs: allow mnt_want_write() to sleep" reverted. The full, updated patch with follow. Thanks, Miklos Index: linux-2.6/fs/namespace.c =================================================================== --- linux-2.6.orig/fs/namespace.c 2010-10-22 16:24:41.000000000 +0200 +++ linux-2.6/fs/namespace.c 2010-10-22 16:17:59.000000000 +0200 @@ -435,11 +435,17 @@ int sb_prepare_remount_readonly(struct s } } } + list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) { + if (mnt->mnt_flags & MNT_WRITE_HOLD) { + if (!err) { + mnt->mnt_flags |= MNT_READONLY | MNT_WAS_WRITE; + smp_wmb(); + } + mnt->mnt_flags &= ~MNT_WRITE_HOLD; + } + } br_write_unlock(vfsmount_lock); - if (err) - sb_cancel_remount_readonly(sb); - return err; } @@ -449,12 +455,11 @@ void sb_cancel_remount_readonly(struct s br_write_lock(vfsmount_lock); list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) { - if (mnt->mnt_flags & MNT_WRITE_HOLD) - mnt->mnt_flags &= ~MNT_WRITE_HOLD; + if (mnt->mnt_flags & MNT_WAS_WRITE) + mnt->mnt_flags &= ~(MNT_WAS_WRITE | MNT_READONLY); } br_write_unlock(vfsmount_lock); - wake_up_all(&sb->s_wait_remount_readonly); } void sb_finish_remount_readonly(struct super_block *sb) @@ -463,15 +468,11 @@ void sb_finish_remount_readonly(struct s br_write_lock(vfsmount_lock); list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) { - if (!(mnt->mnt_flags & MNT_READONLY)) { - mnt->mnt_flags |= MNT_READONLY; - smp_wmb(); - mnt->mnt_flags &= ~MNT_WRITE_HOLD; - } + if (mnt->mnt_flags & MNT_WAS_WRITE) + mnt->mnt_flags &= ~MNT_WAS_WRITE; } sb->s_flags |= MS_RDONLY; br_write_unlock(vfsmount_lock); - wake_up_all(&sb->s_wait_remount_readonly); } void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb) Index: linux-2.6/include/linux/mount.h =================================================================== --- linux-2.6.orig/include/linux/mount.h 2010-10-22 16:02:14.000000000 +0200 +++ linux-2.6/include/linux/mount.h 2010-10-22 16:20:26.000000000 +0200 @@ -30,6 +30,7 @@ struct mnt_namespace; #define MNT_SHRINKABLE 0x100 #define MNT_WRITE_HOLD 0x200 +#define MNT_WAS_WRITE 0x400 /* used by remount to remember write mounts */ #define MNT_SHARED 0x1000 /* if the vfsmount is a shared mount */ #define MNT_UNBINDABLE 0x2000 /* if the vfsmount is a unbindable mount */ -- 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