aboutsummaryrefslogtreecommitdiffstats
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
commit75180df2ed467866ada839fe73cf7cc7d75c0a22 (patch)
tree35966d0b22e58cc49ddee5b5f8d0e64c577dc576
parent8007122520f0a3599bdc4df47358a5d83b2574aa (diff)
NFS: Add the mount option "nosharecache"
Prior to David Howell's mount changes in 2.6.18, users who mounted different directories which happened to be from the same filesystem on the server would get different super blocks, and hence could choose different mount options. As long as there were no hard linked files that crossed from one subtree to another, this was quite safe. Post the changes, if the two directories are on the same filesystem (have the same 'fsid'), they will share the same super block, and hence the same mount options. Add a flag to allow users to elect not to share the NFS super block with another mount point, even if the fsids are the same. This will allow users to set different mount options for the two different super blocks, as was previously possible. It is still up to the user to ensure that there are no cache coherency issues when doing this, however the default behaviour will be to share super blocks whenever two paths result in the same fsid. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/super.c43
-rw-r--r--include/linux/nfs4_mount.h3
-rw-r--r--include/linux/nfs_mount.h1
3 files changed, 41 insertions, 6 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 064e69d2fdde..1b555cd41e3b 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -100,6 +100,7 @@ enum {
100 Opt_udp, Opt_tcp, 100 Opt_udp, Opt_tcp,
101 Opt_acl, Opt_noacl, 101 Opt_acl, Opt_noacl,
102 Opt_rdirplus, Opt_nordirplus, 102 Opt_rdirplus, Opt_nordirplus,
103 Opt_sharecache, Opt_nosharecache,
103 104
104 /* Mount options that take integer arguments */ 105 /* Mount options that take integer arguments */
105 Opt_port, 106 Opt_port,
@@ -146,6 +147,8 @@ static match_table_t nfs_mount_option_tokens = {
146 { Opt_noacl, "noacl" }, 147 { Opt_noacl, "noacl" },
147 { Opt_rdirplus, "rdirplus" }, 148 { Opt_rdirplus, "rdirplus" },
148 { Opt_nordirplus, "nordirplus" }, 149 { Opt_nordirplus, "nordirplus" },
150 { Opt_sharecache, "sharecache" },
151 { Opt_nosharecache, "nosharecache" },
149 152
150 { Opt_port, "port=%u" }, 153 { Opt_port, "port=%u" },
151 { Opt_rsize, "rsize=%u" }, 154 { Opt_rsize, "rsize=%u" },
@@ -450,6 +453,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
450 { NFS_MOUNT_NONLM, ",nolock", "" }, 453 { NFS_MOUNT_NONLM, ",nolock", "" },
451 { NFS_MOUNT_NOACL, ",noacl", "" }, 454 { NFS_MOUNT_NOACL, ",noacl", "" },
452 { NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" }, 455 { NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" },
456 { NFS_MOUNT_UNSHARED, ",nosharecache", ""},
453 { 0, NULL, NULL } 457 { 0, NULL, NULL }
454 }; 458 };
455 const struct proc_nfs_info *nfs_infop; 459 const struct proc_nfs_info *nfs_infop;
@@ -714,6 +718,12 @@ static int nfs_parse_mount_options(char *raw,
714 case Opt_nordirplus: 718 case Opt_nordirplus:
715 mnt->flags |= NFS_MOUNT_NORDIRPLUS; 719 mnt->flags |= NFS_MOUNT_NORDIRPLUS;
716 break; 720 break;
721 case Opt_sharecache:
722 mnt->flags &= ~NFS_MOUNT_UNSHARED;
723 break;
724 case Opt_nosharecache:
725 mnt->flags |= NFS_MOUNT_UNSHARED;
726 break;
717 727
718 case Opt_port: 728 case Opt_port:
719 if (match_int(args, &option)) 729 if (match_int(args, &option))
@@ -1309,6 +1319,9 @@ static int nfs_compare_super(struct super_block *sb, void *data)
1309 1319
1310 if (old->nfs_client != server->nfs_client) 1320 if (old->nfs_client != server->nfs_client)
1311 return 0; 1321 return 0;
1322 /* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */
1323 if (old->flags & NFS_MOUNT_UNSHARED)
1324 return 0;
1312 if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0) 1325 if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0)
1313 return 0; 1326 return 0;
1314 return 1; 1327 return 1;
@@ -1322,6 +1335,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
1322 struct nfs_fh mntfh; 1335 struct nfs_fh mntfh;
1323 struct nfs_mount_data *data = raw_data; 1336 struct nfs_mount_data *data = raw_data;
1324 struct dentry *mntroot; 1337 struct dentry *mntroot;
1338 int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
1325 int error; 1339 int error;
1326 1340
1327 /* Validate the mount data */ 1341 /* Validate the mount data */
@@ -1336,8 +1350,11 @@ static int nfs_get_sb(struct file_system_type *fs_type,
1336 goto out; 1350 goto out;
1337 } 1351 }
1338 1352
1353 if (server->flags & NFS_MOUNT_UNSHARED)
1354 compare_super = NULL;
1355
1339 /* Get a superblock - note that we may end up sharing one that already exists */ 1356 /* Get a superblock - note that we may end up sharing one that already exists */
1340 s = sget(fs_type, nfs_compare_super, nfs_set_super, server); 1357 s = sget(fs_type, compare_super, nfs_set_super, server);
1341 if (IS_ERR(s)) { 1358 if (IS_ERR(s)) {
1342 error = PTR_ERR(s); 1359 error = PTR_ERR(s);
1343 goto out_err_nosb; 1360 goto out_err_nosb;
@@ -1402,6 +1419,7 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
1402 struct super_block *s; 1419 struct super_block *s;
1403 struct nfs_server *server; 1420 struct nfs_server *server;
1404 struct dentry *mntroot; 1421 struct dentry *mntroot;
1422 int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
1405 int error; 1423 int error;
1406 1424
1407 dprintk("--> nfs_xdev_get_sb()\n"); 1425 dprintk("--> nfs_xdev_get_sb()\n");
@@ -1413,8 +1431,11 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
1413 goto out_err_noserver; 1431 goto out_err_noserver;
1414 } 1432 }
1415 1433
1434 if (server->flags & NFS_MOUNT_UNSHARED)
1435 compare_super = NULL;
1436
1416 /* Get a superblock - note that we may end up sharing one that already exists */ 1437 /* Get a superblock - note that we may end up sharing one that already exists */
1417 s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); 1438 s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
1418 if (IS_ERR(s)) { 1439 if (IS_ERR(s)) {
1419 error = PTR_ERR(s); 1440 error = PTR_ERR(s);
1420 goto out_err_nosb; 1441 goto out_err_nosb;
@@ -1657,6 +1678,7 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
1657 struct nfs_fh mntfh; 1678 struct nfs_fh mntfh;
1658 struct dentry *mntroot; 1679 struct dentry *mntroot;
1659 char *mntpath = NULL, *hostname = NULL, *ip_addr = NULL; 1680 char *mntpath = NULL, *hostname = NULL, *ip_addr = NULL;
1681 int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
1660 int error; 1682 int error;
1661 1683
1662 /* Validate the mount data */ 1684 /* Validate the mount data */
@@ -1673,8 +1695,11 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
1673 goto out; 1695 goto out;
1674 } 1696 }
1675 1697
1698 if (server->flags & NFS4_MOUNT_UNSHARED)
1699 compare_super = NULL;
1700
1676 /* Get a superblock - note that we may end up sharing one that already exists */ 1701 /* Get a superblock - note that we may end up sharing one that already exists */
1677 s = sget(fs_type, nfs_compare_super, nfs_set_super, server); 1702 s = sget(fs_type, compare_super, nfs_set_super, server);
1678 if (IS_ERR(s)) { 1703 if (IS_ERR(s)) {
1679 error = PTR_ERR(s); 1704 error = PTR_ERR(s);
1680 goto out_free; 1705 goto out_free;
@@ -1740,6 +1765,7 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
1740 struct super_block *s; 1765 struct super_block *s;
1741 struct nfs_server *server; 1766 struct nfs_server *server;
1742 struct dentry *mntroot; 1767 struct dentry *mntroot;
1768 int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
1743 int error; 1769 int error;
1744 1770
1745 dprintk("--> nfs4_xdev_get_sb()\n"); 1771 dprintk("--> nfs4_xdev_get_sb()\n");
@@ -1751,8 +1777,11 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
1751 goto out_err_noserver; 1777 goto out_err_noserver;
1752 } 1778 }
1753 1779
1780 if (server->flags & NFS4_MOUNT_UNSHARED)
1781 compare_super = NULL;
1782
1754 /* Get a superblock - note that we may end up sharing one that already exists */ 1783 /* Get a superblock - note that we may end up sharing one that already exists */
1755 s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); 1784 s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
1756 if (IS_ERR(s)) { 1785 if (IS_ERR(s)) {
1757 error = PTR_ERR(s); 1786 error = PTR_ERR(s);
1758 goto out_err_nosb; 1787 goto out_err_nosb;
@@ -1807,6 +1836,7 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
1807 struct nfs_server *server; 1836 struct nfs_server *server;
1808 struct dentry *mntroot; 1837 struct dentry *mntroot;
1809 struct nfs_fh mntfh; 1838 struct nfs_fh mntfh;
1839 int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
1810 int error; 1840 int error;
1811 1841
1812 dprintk("--> nfs4_referral_get_sb()\n"); 1842 dprintk("--> nfs4_referral_get_sb()\n");
@@ -1818,8 +1848,11 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
1818 goto out_err_noserver; 1848 goto out_err_noserver;
1819 } 1849 }
1820 1850
1851 if (server->flags & NFS4_MOUNT_UNSHARED)
1852 compare_super = NULL;
1853
1821 /* Get a superblock - note that we may end up sharing one that already exists */ 1854 /* Get a superblock - note that we may end up sharing one that already exists */
1822 s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); 1855 s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
1823 if (IS_ERR(s)) { 1856 if (IS_ERR(s)) {
1824 error = PTR_ERR(s); 1857 error = PTR_ERR(s);
1825 goto out_err_nosb; 1858 goto out_err_nosb;
diff --git a/include/linux/nfs4_mount.h b/include/linux/nfs4_mount.h
index d8d7480e5a47..a0dcf6655657 100644
--- a/include/linux/nfs4_mount.h
+++ b/include/linux/nfs4_mount.h
@@ -65,6 +65,7 @@ struct nfs4_mount_data {
65#define NFS4_MOUNT_NOCTO 0x0010 /* 1 */ 65#define NFS4_MOUNT_NOCTO 0x0010 /* 1 */
66#define NFS4_MOUNT_NOAC 0x0020 /* 1 */ 66#define NFS4_MOUNT_NOAC 0x0020 /* 1 */
67#define NFS4_MOUNT_STRICTLOCK 0x1000 /* 1 */ 67#define NFS4_MOUNT_STRICTLOCK 0x1000 /* 1 */
68#define NFS4_MOUNT_FLAGMASK 0x1033 68#define NFS4_MOUNT_UNSHARED 0x8000 /* 1 */
69#define NFS4_MOUNT_FLAGMASK 0x9033
69 70
70#endif 71#endif
diff --git a/include/linux/nfs_mount.h b/include/linux/nfs_mount.h
index 0b82a17c705b..a3ade89a64d2 100644
--- a/include/linux/nfs_mount.h
+++ b/include/linux/nfs_mount.h
@@ -62,6 +62,7 @@ struct nfs_mount_data {
62#define NFS_MOUNT_STRICTLOCK 0x1000 /* reserved for NFSv4 */ 62#define NFS_MOUNT_STRICTLOCK 0x1000 /* reserved for NFSv4 */
63#define NFS_MOUNT_SECFLAVOUR 0x2000 /* 5 */ 63#define NFS_MOUNT_SECFLAVOUR 0x2000 /* 5 */
64#define NFS_MOUNT_NORDIRPLUS 0x4000 /* 5 */ 64#define NFS_MOUNT_NORDIRPLUS 0x4000 /* 5 */
65#define NFS_MOUNT_UNSHARED 0x8000 /* 5 */
65#define NFS_MOUNT_FLAGMASK 0xFFFF 66#define NFS_MOUNT_FLAGMASK 0xFFFF
66 67
67#endif 68#endif