Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2e4b7fcd authored by Dave Hansen's avatar Dave Hansen Committed by Al Viro
Browse files

[PATCH] r/o bind mounts: honor mount writer counts at remount



Originally from: Herbert Poetzl <herbert@13thfloor.at>

This is the core of the read-only bind mount patch set.

Note that this does _not_ add a "ro" option directly to the bind mount
operation.  If you require such a mount, you must first do the bind, then
follow it up with a 'mount -o remount,ro' operation:

If you wish to have a r/o bind mount of /foo on bar:

	mount --bind /foo /bar
	mount -o remount,ro /bar

Acked-by: default avatarAl Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: default avatarChristoph Hellwig <hch@infradead.org>
Signed-off-by: default avatarDave Hansen <haveblue@us.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 3d733633
Loading
Loading
Loading
Loading
+43 −7
Original line number Diff line number Diff line
@@ -105,7 +105,11 @@ struct vfsmount *alloc_vfsmnt(const char *name)
 */
int __mnt_is_readonly(struct vfsmount *mnt)
{
	return (mnt->mnt_sb->s_flags & MS_RDONLY);
	if (mnt->mnt_flags & MNT_READONLY)
		return 1;
	if (mnt->mnt_sb->s_flags & MS_RDONLY)
		return 1;
	return 0;
}
EXPORT_SYMBOL_GPL(__mnt_is_readonly);

@@ -305,7 +309,7 @@ void mnt_drop_write(struct vfsmount *mnt)
}
EXPORT_SYMBOL_GPL(mnt_drop_write);

int mnt_make_readonly(struct vfsmount *mnt)
static int mnt_make_readonly(struct vfsmount *mnt)
{
	int ret = 0;

@@ -318,15 +322,25 @@ int mnt_make_readonly(struct vfsmount *mnt)
		goto out;
	}
	/*
	 * actually set mount's r/o flag here to make
	 * __mnt_is_readonly() true, which keeps anyone
	 * from doing a successful mnt_want_write().
	 * nobody can do a successful mnt_want_write() with all
	 * of the counts in MNT_DENIED_WRITE and the locks held.
	 */
	spin_lock(&vfsmount_lock);
	if (!ret)
		mnt->mnt_flags |= MNT_READONLY;
	spin_unlock(&vfsmount_lock);
out:
	unlock_mnt_writers();
	return ret;
}

static void __mnt_unmake_readonly(struct vfsmount *mnt)
{
	spin_lock(&vfsmount_lock);
	mnt->mnt_flags &= ~MNT_READONLY;
	spin_unlock(&vfsmount_lock);
}

int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb)
{
	mnt->mnt_sb = sb;
@@ -693,7 +707,7 @@ static int show_vfsmnt(struct seq_file *m, void *v)
		seq_putc(m, '.');
		mangle(m, mnt->mnt_sb->s_subtype);
	}
	seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? " ro" : " rw");
	seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw");
	for (fs_infop = fs_info; fs_infop->flag; fs_infop++) {
		if (mnt->mnt_sb->s_flags & fs_infop->flag)
			seq_puts(m, fs_infop->str);
@@ -1295,6 +1309,23 @@ static noinline int do_loopback(struct nameidata *nd, char *old_name,
	return err;
}

static int change_mount_flags(struct vfsmount *mnt, int ms_flags)
{
	int error = 0;
	int readonly_request = 0;

	if (ms_flags & MS_RDONLY)
		readonly_request = 1;
	if (readonly_request == __mnt_is_readonly(mnt))
		return 0;

	if (readonly_request)
		error = mnt_make_readonly(mnt);
	else
		__mnt_unmake_readonly(mnt);
	return error;
}

/*
 * change filesystem flags. dir should be a physical root of filesystem.
 * If you've mounted a non-root directory somewhere and want to do remount
@@ -1317,6 +1348,9 @@ static noinline int do_remount(struct nameidata *nd, int flags, int mnt_flags,
		return -EINVAL;

	down_write(&sb->s_umount);
	if (flags & MS_BIND)
		err = change_mount_flags(nd->path.mnt, flags);
	else
		err = do_remount_sb(sb, flags, data, 0);
	if (!err)
		nd->path.mnt->mnt_flags = mnt_flags;
@@ -1701,6 +1735,8 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
		mnt_flags |= MNT_NODIRATIME;
	if (flags & MS_RELATIME)
		mnt_flags |= MNT_RELATIME;
	if (flags & MS_RDONLY)
		mnt_flags |= MNT_READONLY;

	flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
		   MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT);
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ struct mnt_namespace;
#define MNT_NOATIME	0x08
#define MNT_NODIRATIME	0x10
#define MNT_RELATIME	0x20
#define MNT_READONLY	0x40	/* does the user want this to be r/o? */

#define MNT_SHRINKABLE	0x100
#define MNT_IMBALANCED_WRITE_COUNT	0x200 /* just for debugging */