From: Valerie Aurora <vaurora@xxxxxxxxxx> While we can check if a file system is currently read-only, we can't guarantee that it will stay read-only. The file system can be mounted or remounted read-write at any time. This is a problem for union mounts, which require the underlying file system be read-only for the entire duration of the union mount. Add a hard read-only users count to the superblock. When this count is non-zero, don't allow any read-write mounts of this super, or any read-write remounts of existing mounts. --- fs/super.c | 11 +++++++++++ include/linux/fs.h | 7 +++++++ 2 files changed, 18 insertions(+), 0 deletions(-) diff --git a/fs/super.c b/fs/super.c index ab3d672..511f657 100644 --- a/fs/super.c +++ b/fs/super.c @@ -130,6 +130,7 @@ static inline void destroy_super(struct super_block *s) #ifdef CONFIG_SMP free_percpu(s->s_files); #endif + BUG_ON(s->s_hard_readonly_users); security_sb_free(s); kfree(s->s_subtype); kfree(s->s_options); @@ -587,6 +588,9 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) return -EBUSY; } + if (!(flags & MS_RDONLY) && sb->s_hard_readonly_users) + return -EROFS; + if (sb->s_op->remount_fs) { retval = sb->s_op->remount_fs(sb, &flags, data); if (retval) @@ -956,9 +960,16 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data) WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to " "negative value (%lld)\n", type->name, sb->s_maxbytes); + if (!(flags & MS_RDONLY) && sb->s_hard_readonly_users) + goto out_sb_is_hard_ro; + up_write(&sb->s_umount); free_secdata(secdata); return root; + +out_sb_is_hard_ro: + up_write(&sb->s_umount); + error = -EROFS; out_sb: dput(root); deactivate_locked_super(sb); diff --git a/include/linux/fs.h b/include/linux/fs.h index 1c77787..43c17d0 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1437,6 +1437,13 @@ struct super_block { * Saved pool identifier for cleancache (-1 means none) */ int cleancache_poolid; + + /* + * Number of mounts requiring that the underlying file system never + * transition to read-write. Protected by s_umount. Decremented by + * free_vfsmnt() if MNT_HARD_READONLY is set. + */ + int s_hard_readonly_users; }; extern struct timespec current_fs_time(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