aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/super.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-05-16 16:53:28 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-07-10 23:40:48 -0400
commit275a5d24bf56b2d9dd4644c54a56366b89a028f1 (patch)
tree2c429fc9480ef292b8cfdc81be05f3ff2b2c02a5 /fs/nfs/super.c
parent75180df2ed467866ada839fe73cf7cc7d75c0a22 (diff)
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: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r--fs/nfs/super.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 1b555cd41e3b..a2b1af89ca1a 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1317,7 +1317,9 @@ static int nfs_compare_super(struct super_block *sb, void *data)
1317{ 1317{
1318 struct nfs_server *server = data, *old = NFS_SB(sb); 1318 struct nfs_server *server = data, *old = NFS_SB(sb);
1319 1319
1320 if (old->nfs_client != server->nfs_client) 1320 if (memcmp(&old->nfs_client->cl_addr,
1321 &server->nfs_client->cl_addr,
1322 sizeof(old->nfs_client->cl_addr)) != 0)
1321 return 0; 1323 return 0;
1322 /* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */ 1324 /* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */
1323 if (old->flags & NFS_MOUNT_UNSHARED) 1325 if (old->flags & NFS_MOUNT_UNSHARED)
@@ -1327,6 +1329,39 @@ static int nfs_compare_super(struct super_block *sb, void *data)
1327 return 1; 1329 return 1;
1328} 1330}
1329 1331
1332#define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS)
1333
1334static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b, int flags)
1335{
1336 const struct nfs_server *a = s->s_fs_info;
1337 const struct rpc_clnt *clnt_a = a->client;
1338 const struct rpc_clnt *clnt_b = b->client;
1339
1340 if ((s->s_flags & NFS_MS_MASK) != (flags & NFS_MS_MASK))
1341 goto Ebusy;
1342 if (a->nfs_client != b->nfs_client)
1343 goto Ebusy;
1344 if (a->flags != b->flags)
1345 goto Ebusy;
1346 if (a->wsize != b->wsize)
1347 goto Ebusy;
1348 if (a->rsize != b->rsize)
1349 goto Ebusy;
1350 if (a->acregmin != b->acregmin)
1351 goto Ebusy;
1352 if (a->acregmax != b->acregmax)
1353 goto Ebusy;
1354 if (a->acdirmin != b->acdirmin)
1355 goto Ebusy;
1356 if (a->acdirmax != b->acdirmax)
1357 goto Ebusy;
1358 if (clnt_a->cl_auth->au_flavor != clnt_b->cl_auth->au_flavor)
1359 goto Ebusy;
1360 return 0;
1361Ebusy:
1362 return -EBUSY;
1363}
1364
1330static int nfs_get_sb(struct file_system_type *fs_type, 1365static int nfs_get_sb(struct file_system_type *fs_type,
1331 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) 1366 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
1332{ 1367{
@@ -1361,8 +1396,11 @@ static int nfs_get_sb(struct file_system_type *fs_type,
1361 } 1396 }
1362 1397
1363 if (s->s_fs_info != server) { 1398 if (s->s_fs_info != server) {
1399 error = nfs_compare_mount_options(s, server, flags);
1364 nfs_free_server(server); 1400 nfs_free_server(server);
1365 server = NULL; 1401 server = NULL;
1402 if (error < 0)
1403 goto error_splat_super;
1366 } 1404 }
1367 1405
1368 if (!s->s_root) { 1406 if (!s->s_root) {
@@ -1442,8 +1480,11 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
1442 } 1480 }
1443 1481
1444 if (s->s_fs_info != server) { 1482 if (s->s_fs_info != server) {
1483 error = nfs_compare_mount_options(s, server, flags);
1445 nfs_free_server(server); 1484 nfs_free_server(server);
1446 server = NULL; 1485 server = NULL;
1486 if (error < 0)
1487 goto error_splat_super;
1447 } 1488 }
1448 1489
1449 if (!s->s_root) { 1490 if (!s->s_root) {