Opt_udp, Opt_tcp,
Opt_acl, Opt_noacl,
Opt_rdirplus, Opt_nordirplus,
+ Opt_sharecache, Opt_nosharecache,
/* Mount options that take integer arguments */
Opt_port,
{ Opt_noacl, "noacl" },
{ Opt_rdirplus, "rdirplus" },
{ Opt_nordirplus, "nordirplus" },
+ { Opt_sharecache, "sharecache" },
+ { Opt_nosharecache, "nosharecache" },
{ Opt_port, "port=%u" },
{ Opt_rsize, "rsize=%u" },
};
#endif
-static struct shrinker *acl_shrinker;
+static struct shrinker acl_shrinker = {
+ .shrink = nfs_access_cache_shrinker,
+ .seeks = DEFAULT_SEEKS,
+};
/*
* Register the NFS filesystems
if (ret < 0)
goto error_2;
#endif
- acl_shrinker = set_shrinker(DEFAULT_SEEKS, nfs_access_cache_shrinker);
+ register_shrinker(&acl_shrinker);
return 0;
#ifdef CONFIG_NFS_V4
*/
void __exit unregister_nfs_fs(void)
{
- if (acl_shrinker != NULL)
- remove_shrinker(acl_shrinker);
+ unregister_shrinker(&acl_shrinker);
#ifdef CONFIG_NFS_V4
unregister_filesystem(&nfs4_fs_type);
- nfs_unregister_sysctl();
#endif
+ nfs_unregister_sysctl();
unregister_filesystem(&nfs_fs_type);
}
{ 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;
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))
return 0;
if (option < 0 || option > 65535)
return 0;
- mnt->nfs_server.address.sin_port = htonl(option);
+ mnt->nfs_server.address.sin_port = htons(option);
break;
case Opt_rsize:
if (match_int(args, &mnt->rsize))
kfree(string);
switch (token) {
- case Opt_udp:
+ case Opt_xprt_udp:
mnt->flags &= ~NFS_MOUNT_TCP;
mnt->nfs_server.protocol = IPPROTO_UDP;
mnt->timeo = 7;
mnt->retrans = 5;
break;
- case Opt_tcp:
+ case Opt_xprt_tcp:
mnt->flags |= NFS_MOUNT_TCP;
mnt->nfs_server.protocol = IPPROTO_TCP;
mnt->timeo = 600;
kfree(string);
switch (token) {
- case Opt_udp:
+ case Opt_xprt_udp:
mnt->mount_server.protocol = IPPROTO_UDP;
break;
- case Opt_tcp:
+ case Opt_xprt_tcp:
mnt->mount_server.protocol = IPPROTO_TCP;
break;
default:
c = strchr(dev_name, ':');
if (c == NULL)
return -EINVAL;
- len = c - dev_name - 1;
+ len = c - dev_name;
if (len > sizeof(data->hostname))
- return -EINVAL;
+ return -ENAMETOOLONG;
strncpy(data->hostname, dev_name, len);
args.nfs_server.hostname = data->hostname;
c++;
if (strlen(c) > NFS_MAXPATHLEN)
- return -EINVAL;
+ return -ENAMETOOLONG;
args.nfs_server.export_path = c;
status = nfs_try_mount(&args, mntfh);
if (status)
- return -EINVAL;
+ return status;
/*
* Translate to nfs_mount_data, which nfs_fill_super
nfs_initialise_sb(sb);
}
-static int nfs_set_super(struct super_block *s, void *_server)
+#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 1;
+Ebusy:
+ return 0;
+}
+
+struct nfs_sb_mountdata {
+ struct nfs_server *server;
+ int mntflags;
+};
+
+static int nfs_set_super(struct super_block *s, void *data)
{
- struct nfs_server *server = _server;
+ struct nfs_sb_mountdata *sb_mntdata = data;
+ struct nfs_server *server = sb_mntdata->server;
int ret;
+ s->s_flags = sb_mntdata->mntflags;
s->s_fs_info = server;
ret = set_anon_super(s, server);
if (ret == 0)
static int nfs_compare_super(struct super_block *sb, void *data)
{
- struct nfs_server *server = data, *old = NFS_SB(sb);
+ struct nfs_sb_mountdata *sb_mntdata = data;
+ struct nfs_server *server = sb_mntdata->server, *old = NFS_SB(sb);
+ int mntflags = sb_mntdata->mntflags;
- 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)
return 0;
if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0)
return 0;
- return 1;
+ return nfs_compare_mount_options(sb, server, mntflags);
}
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;
+ struct nfs_sb_mountdata sb_mntdata = {
+ .mntflags = flags,
+ };
int error;
/* Validate the mount data */
error = PTR_ERR(server);
goto out;
}
+ sb_mntdata.server = server;
+
+ 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, &sb_mntdata);
if (IS_ERR(s)) {
error = PTR_ERR(s);
goto out_err_nosb;
if (!s->s_root) {
/* initial superblock/root creation */
- s->s_flags = flags;
nfs_fill_super(s, data);
}
struct super_block *s;
struct nfs_server *server;
struct dentry *mntroot;
+ int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
+ struct nfs_sb_mountdata sb_mntdata = {
+ .mntflags = flags,
+ };
int error;
dprintk("--> nfs_xdev_get_sb()\n");
error = PTR_ERR(server);
goto out_err_noserver;
}
+ sb_mntdata.server = server;
+
+ 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, &sb_mntdata);
if (IS_ERR(s)) {
error = PTR_ERR(s);
goto out_err_nosb;
if (!s->s_root) {
/* initial superblock/root creation */
- s->s_flags = flags;
nfs_clone_super(s, data->sb);
}
/* while calculating len, pretend ':' is '\0' */
len = c - dev_name;
if (len > NFS4_MAXNAMLEN)
- return -EINVAL;
+ return -ENAMETOOLONG;
*hostname = kzalloc(len, GFP_KERNEL);
if (*hostname == NULL)
return -ENOMEM;
c++; /* step over the ':' */
len = strlen(c);
if (len > NFS4_MAXPATHLEN)
- return -EINVAL;
+ return -ENAMETOOLONG;
*mntpath = kzalloc(len + 1, GFP_KERNEL);
if (*mntpath == NULL)
return -ENOMEM;
dprintk("MNTPATH: %s\n", *mntpath);
+ if (args.client_address == NULL)
+ goto out_no_client_address;
+
*ip_addr = args.client_address;
break;
out_no_address:
dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
return -EINVAL;
+
+out_no_client_address:
+ dfprintk(MOUNT, "NFS4: mount program didn't pass callback address\n");
+ return -EINVAL;
}
/*
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;
+ struct nfs_sb_mountdata sb_mntdata = {
+ .mntflags = flags,
+ };
int error;
/* Validate the mount data */
error = PTR_ERR(server);
goto out;
}
+ sb_mntdata.server = server;
+
+ 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, &sb_mntdata);
if (IS_ERR(s)) {
error = PTR_ERR(s);
goto out_free;
if (!s->s_root) {
/* initial superblock/root creation */
- s->s_flags = flags;
nfs4_fill_super(s);
}
struct super_block *s;
struct nfs_server *server;
struct dentry *mntroot;
+ int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
+ struct nfs_sb_mountdata sb_mntdata = {
+ .mntflags = flags,
+ };
int error;
dprintk("--> nfs4_xdev_get_sb()\n");
error = PTR_ERR(server);
goto out_err_noserver;
}
+ sb_mntdata.server = server;
+
+ 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, &sb_mntdata);
if (IS_ERR(s)) {
error = PTR_ERR(s);
goto out_err_nosb;
if (!s->s_root) {
/* initial superblock/root creation */
- s->s_flags = flags;
nfs4_clone_super(s, data->sb);
}
struct nfs_server *server;
struct dentry *mntroot;
struct nfs_fh mntfh;
+ int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
+ struct nfs_sb_mountdata sb_mntdata = {
+ .mntflags = flags,
+ };
int error;
dprintk("--> nfs4_referral_get_sb()\n");
error = PTR_ERR(server);
goto out_err_noserver;
}
+ sb_mntdata.server = server;
+
+ 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, &sb_mntdata);
if (IS_ERR(s)) {
error = PTR_ERR(s);
goto out_err_nosb;
if (!s->s_root) {
/* initial superblock/root creation */
- s->s_flags = flags;
nfs4_fill_super(s);
}