]> git.karo-electronics.de Git - linux-beck.git/commitdiff
NFS: Add the mount option "nosharecache"
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 16 May 2007 20:53:28 +0000 (16:53 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 11 Jul 2007 03:40:48 +0000 (23:40 -0400)
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>
fs/nfs/super.c
include/linux/nfs4_mount.h
include/linux/nfs_mount.h

index 064e69d2fdde856fb19591dfa448c83f11743797..1b555cd41e3bae9ea5524cbdd3b3e9b1fda63099 100644 (file)
@@ -100,6 +100,7 @@ enum {
        Opt_udp, Opt_tcp,
        Opt_acl, Opt_noacl,
        Opt_rdirplus, Opt_nordirplus,
+       Opt_sharecache, Opt_nosharecache,
 
        /* Mount options that take integer arguments */
        Opt_port,
@@ -146,6 +147,8 @@ static match_table_t nfs_mount_option_tokens = {
        { Opt_noacl, "noacl" },
        { Opt_rdirplus, "rdirplus" },
        { Opt_nordirplus, "nordirplus" },
+       { Opt_sharecache, "sharecache" },
+       { Opt_nosharecache, "nosharecache" },
 
        { Opt_port, "port=%u" },
        { Opt_rsize, "rsize=%u" },
@@ -450,6 +453,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
                { NFS_MOUNT_NONLM, ",nolock", "" },
                { NFS_MOUNT_NOACL, ",noacl", "" },
                { NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" },
+               { NFS_MOUNT_UNSHARED, ",nosharecache", ""},
                { 0, NULL, NULL }
        };
        const struct proc_nfs_info *nfs_infop;
@@ -714,6 +718,12 @@ static int nfs_parse_mount_options(char *raw,
                case Opt_nordirplus:
                        mnt->flags |= NFS_MOUNT_NORDIRPLUS;
                        break;
+               case Opt_sharecache:
+                       mnt->flags &= ~NFS_MOUNT_UNSHARED;
+                       break;
+               case Opt_nosharecache:
+                       mnt->flags |= NFS_MOUNT_UNSHARED;
+                       break;
 
                case Opt_port:
                        if (match_int(args, &option))
@@ -1309,6 +1319,9 @@ static int nfs_compare_super(struct super_block *sb, void *data)
 
        if (old->nfs_client != server->nfs_client)
                return 0;
+       /* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */
+       if (old->flags & NFS_MOUNT_UNSHARED)
+               return 0;
        if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0)
                return 0;
        return 1;
@@ -1322,6 +1335,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
        struct nfs_fh mntfh;
        struct nfs_mount_data *data = raw_data;
        struct dentry *mntroot;
+       int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
        int error;
 
        /* Validate the mount data */
@@ -1336,8 +1350,11 @@ static int nfs_get_sb(struct file_system_type *fs_type,
                goto out;
        }
 
+       if (server->flags & NFS_MOUNT_UNSHARED)
+               compare_super = NULL;
+
        /* Get a superblock - note that we may end up sharing one that already exists */
-       s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
+       s = sget(fs_type, compare_super, nfs_set_super, server);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
                goto out_err_nosb;
@@ -1402,6 +1419,7 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
        struct super_block *s;
        struct nfs_server *server;
        struct dentry *mntroot;
+       int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
        int error;
 
        dprintk("--> nfs_xdev_get_sb()\n");
@@ -1413,8 +1431,11 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
                goto out_err_noserver;
        }
 
+       if (server->flags & NFS_MOUNT_UNSHARED)
+               compare_super = NULL;
+
        /* Get a superblock - note that we may end up sharing one that already exists */
-       s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+       s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
                goto out_err_nosb;
@@ -1657,6 +1678,7 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
        struct nfs_fh mntfh;
        struct dentry *mntroot;
        char *mntpath = NULL, *hostname = NULL, *ip_addr = NULL;
+       int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
        int error;
 
        /* Validate the mount data */
@@ -1673,8 +1695,11 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
                goto out;
        }
 
+       if (server->flags & NFS4_MOUNT_UNSHARED)
+               compare_super = NULL;
+
        /* Get a superblock - note that we may end up sharing one that already exists */
-       s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
+       s = sget(fs_type, compare_super, nfs_set_super, server);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
                goto out_free;
@@ -1740,6 +1765,7 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
        struct super_block *s;
        struct nfs_server *server;
        struct dentry *mntroot;
+       int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
        int error;
 
        dprintk("--> nfs4_xdev_get_sb()\n");
@@ -1751,8 +1777,11 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
                goto out_err_noserver;
        }
 
+       if (server->flags & NFS4_MOUNT_UNSHARED)
+               compare_super = NULL;
+
        /* Get a superblock - note that we may end up sharing one that already exists */
-       s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+       s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
                goto out_err_nosb;
@@ -1807,6 +1836,7 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
        struct nfs_server *server;
        struct dentry *mntroot;
        struct nfs_fh mntfh;
+       int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
        int error;
 
        dprintk("--> nfs4_referral_get_sb()\n");
@@ -1818,8 +1848,11 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
                goto out_err_noserver;
        }
 
+       if (server->flags & NFS4_MOUNT_UNSHARED)
+               compare_super = NULL;
+
        /* Get a superblock - note that we may end up sharing one that already exists */
-       s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+       s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
                goto out_err_nosb;
index d8d7480e5a47c50c01938b23bc6482df7640871b..a0dcf66556571762c0715551da7d2023d0cbe980 100644 (file)
@@ -65,6 +65,7 @@ struct nfs4_mount_data {
 #define NFS4_MOUNT_NOCTO       0x0010  /* 1 */
 #define NFS4_MOUNT_NOAC                0x0020  /* 1 */
 #define NFS4_MOUNT_STRICTLOCK  0x1000  /* 1 */
-#define NFS4_MOUNT_FLAGMASK    0x1033
+#define NFS4_MOUNT_UNSHARED    0x8000  /* 1 */
+#define NFS4_MOUNT_FLAGMASK    0x9033
 
 #endif
index 0b82a17c705bbb8a51d595364ab6631b0a33b2dd..a3ade89a64d21f68c359d35d5b179d97a93c0fcc 100644 (file)
@@ -62,6 +62,7 @@ struct nfs_mount_data {
 #define NFS_MOUNT_STRICTLOCK   0x1000  /* reserved for NFSv4 */
 #define NFS_MOUNT_SECFLAVOUR   0x2000  /* 5 */
 #define NFS_MOUNT_NORDIRPLUS   0x4000  /* 5 */
+#define NFS_MOUNT_UNSHARED     0x8000  /* 5 */
 #define NFS_MOUNT_FLAGMASK     0xFFFF
 
 #endif