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

Commit 275a5d24 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFS: Error when mounting the same filesystem with different options



Unless the user sets the NFS_MOUNT_NOSHAREDCACHE mount flag, we should
return EBUSY if the filesystem is already mounted on a superblock that
has set conflicting mount options.

Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 75180df2
Loading
Loading
Loading
Loading
+42 −1
Original line number Diff line number Diff line
@@ -1317,7 +1317,9 @@ static int nfs_compare_super(struct super_block *sb, void *data)
{
	struct nfs_server *server = data, *old = NFS_SB(sb);

	if (old->nfs_client != server->nfs_client)
	if (memcmp(&old->nfs_client->cl_addr,
				&server->nfs_client->cl_addr,
				sizeof(old->nfs_client->cl_addr)) != 0)
		return 0;
	/* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */
	if (old->flags & NFS_MOUNT_UNSHARED)
@@ -1327,6 +1329,39 @@ static int nfs_compare_super(struct super_block *sb, void *data)
	return 1;
}

#define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS)

static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b, int flags)
{
	const struct nfs_server *a = s->s_fs_info;
	const struct rpc_clnt *clnt_a = a->client;
	const struct rpc_clnt *clnt_b = b->client;

	if ((s->s_flags & NFS_MS_MASK) != (flags & NFS_MS_MASK))
		goto Ebusy;
	if (a->nfs_client != b->nfs_client)
		goto Ebusy;
	if (a->flags != b->flags)
		goto Ebusy;
	if (a->wsize != b->wsize)
		goto Ebusy;
	if (a->rsize != b->rsize)
		goto Ebusy;
	if (a->acregmin != b->acregmin)
		goto Ebusy;
	if (a->acregmax != b->acregmax)
		goto Ebusy;
	if (a->acdirmin != b->acdirmin)
		goto Ebusy;
	if (a->acdirmax != b->acdirmax)
		goto Ebusy;
	if (clnt_a->cl_auth->au_flavor != clnt_b->cl_auth->au_flavor)
		goto Ebusy;
	return 0;
Ebusy:
	return -EBUSY;
}

static int nfs_get_sb(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
{
@@ -1361,8 +1396,11 @@ static int nfs_get_sb(struct file_system_type *fs_type,
	}

	if (s->s_fs_info != server) {
		error = nfs_compare_mount_options(s, server, flags);
		nfs_free_server(server);
		server = NULL;
		if (error < 0)
			goto error_splat_super;
	}

	if (!s->s_root) {
@@ -1442,8 +1480,11 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
	}

	if (s->s_fs_info != server) {
		error = nfs_compare_mount_options(s, server, flags);
		nfs_free_server(server);
		server = NULL;
		if (error < 0)
			goto error_splat_super;
	}

	if (!s->s_root) {