Skip to content

Commit 75180df

Browse files
Trond MyklebustTrond Myklebust
authored andcommitted
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>
1 parent 8007122 commit 75180df

File tree

3 files changed

+41
-6
lines changed

3 files changed

+41
-6
lines changed

fs/nfs/super.c

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ enum {
100100
Opt_udp, Opt_tcp,
101101
Opt_acl, Opt_noacl,
102102
Opt_rdirplus, Opt_nordirplus,
103+
Opt_sharecache, Opt_nosharecache,
103104

104105
/* Mount options that take integer arguments */
105106
Opt_port,
@@ -146,6 +147,8 @@ static match_table_t nfs_mount_option_tokens = {
146147
{ Opt_noacl, "noacl" },
147148
{ Opt_rdirplus, "rdirplus" },
148149
{ Opt_nordirplus, "nordirplus" },
150+
{ Opt_sharecache, "sharecache" },
151+
{ Opt_nosharecache, "nosharecache" },
149152

150153
{ Opt_port, "port=%u" },
151154
{ Opt_rsize, "rsize=%u" },
@@ -450,6 +453,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
450453
{ NFS_MOUNT_NONLM, ",nolock", "" },
451454
{ NFS_MOUNT_NOACL, ",noacl", "" },
452455
{ NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" },
456+
{ NFS_MOUNT_UNSHARED, ",nosharecache", ""},
453457
{ 0, NULL, NULL }
454458
};
455459
const struct proc_nfs_info *nfs_infop;
@@ -714,6 +718,12 @@ static int nfs_parse_mount_options(char *raw,
714718
case Opt_nordirplus:
715719
mnt->flags |= NFS_MOUNT_NORDIRPLUS;
716720
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;
717727

718728
case Opt_port:
719729
if (match_int(args, &option))
@@ -1309,6 +1319,9 @@ static int nfs_compare_super(struct super_block *sb, void *data)
13091319

13101320
if (old->nfs_client != server->nfs_client)
13111321
return 0;
1322+
/* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */
1323+
if (old->flags & NFS_MOUNT_UNSHARED)
1324+
return 0;
13121325
if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0)
13131326
return 0;
13141327
return 1;
@@ -1322,6 +1335,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
13221335
struct nfs_fh mntfh;
13231336
struct nfs_mount_data *data = raw_data;
13241337
struct dentry *mntroot;
1338+
int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
13251339
int error;
13261340

13271341
/* Validate the mount data */
@@ -1336,8 +1350,11 @@ static int nfs_get_sb(struct file_system_type *fs_type,
13361350
goto out;
13371351
}
13381352

1353+
if (server->flags & NFS_MOUNT_UNSHARED)
1354+
compare_super = NULL;
1355+
13391356
/* 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);
13411358
if (IS_ERR(s)) {
13421359
error = PTR_ERR(s);
13431360
goto out_err_nosb;
@@ -1402,6 +1419,7 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
14021419
struct super_block *s;
14031420
struct nfs_server *server;
14041421
struct dentry *mntroot;
1422+
int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
14051423
int error;
14061424

14071425
dprintk("--> nfs_xdev_get_sb()\n");
@@ -1413,8 +1431,11 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
14131431
goto out_err_noserver;
14141432
}
14151433

1434+
if (server->flags & NFS_MOUNT_UNSHARED)
1435+
compare_super = NULL;
1436+
14161437
/* 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);
14181439
if (IS_ERR(s)) {
14191440
error = PTR_ERR(s);
14201441
goto out_err_nosb;
@@ -1657,6 +1678,7 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
16571678
struct nfs_fh mntfh;
16581679
struct dentry *mntroot;
16591680
char *mntpath = NULL, *hostname = NULL, *ip_addr = NULL;
1681+
int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
16601682
int error;
16611683

16621684
/* Validate the mount data */
@@ -1673,8 +1695,11 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
16731695
goto out;
16741696
}
16751697

1698+
if (server->flags & NFS4_MOUNT_UNSHARED)
1699+
compare_super = NULL;
1700+
16761701
/* 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);
16781703
if (IS_ERR(s)) {
16791704
error = PTR_ERR(s);
16801705
goto out_free;
@@ -1740,6 +1765,7 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
17401765
struct super_block *s;
17411766
struct nfs_server *server;
17421767
struct dentry *mntroot;
1768+
int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
17431769
int error;
17441770

17451771
dprintk("--> nfs4_xdev_get_sb()\n");
@@ -1751,8 +1777,11 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
17511777
goto out_err_noserver;
17521778
}
17531779

1780+
if (server->flags & NFS4_MOUNT_UNSHARED)
1781+
compare_super = NULL;
1782+
17541783
/* 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);
17561785
if (IS_ERR(s)) {
17571786
error = PTR_ERR(s);
17581787
goto out_err_nosb;
@@ -1807,6 +1836,7 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
18071836
struct nfs_server *server;
18081837
struct dentry *mntroot;
18091838
struct nfs_fh mntfh;
1839+
int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
18101840
int error;
18111841

18121842
dprintk("--> nfs4_referral_get_sb()\n");
@@ -1818,8 +1848,11 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
18181848
goto out_err_noserver;
18191849
}
18201850

1851+
if (server->flags & NFS4_MOUNT_UNSHARED)
1852+
compare_super = NULL;
1853+
18211854
/* 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);
18231856
if (IS_ERR(s)) {
18241857
error = PTR_ERR(s);
18251858
goto out_err_nosb;

include/linux/nfs4_mount.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ struct nfs4_mount_data {
6565
#define NFS4_MOUNT_NOCTO 0x0010 /* 1 */
6666
#define NFS4_MOUNT_NOAC 0x0020 /* 1 */
6767
#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
6970

7071
#endif

include/linux/nfs_mount.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ struct nfs_mount_data {
6262
#define NFS_MOUNT_STRICTLOCK 0x1000 /* reserved for NFSv4 */
6363
#define NFS_MOUNT_SECFLAVOUR 0x2000 /* 5 */
6464
#define NFS_MOUNT_NORDIRPLUS 0x4000 /* 5 */
65+
#define NFS_MOUNT_UNSHARED 0x8000 /* 5 */
6566
#define NFS_MOUNT_FLAGMASK 0xFFFF
6667

6768
#endif

0 commit comments

Comments
 (0)