|
@@ -15,11 +15,13 @@
|
|
|
#include <linux/namei.h>
|
|
|
#include <linux/module.h>
|
|
|
#include <linux/exportfs.h>
|
|
|
+#include <linux/sunrpc/svc_xprt.h>
|
|
|
|
|
|
#include <net/ipv6.h>
|
|
|
|
|
|
#include "nfsd.h"
|
|
|
#include "nfsfh.h"
|
|
|
+#include "netns.h"
|
|
|
|
|
|
#define NFSDDBG_FACILITY NFSDDBG_EXPORT
|
|
|
|
|
@@ -38,7 +40,6 @@ typedef struct svc_export svc_export;
|
|
|
#define EXPKEY_HASHBITS 8
|
|
|
#define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS)
|
|
|
#define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
|
|
|
-static struct cache_head *expkey_table[EXPKEY_HASHMAX];
|
|
|
|
|
|
static void expkey_put(struct kref *ref)
|
|
|
{
|
|
@@ -71,9 +72,9 @@ static int expkey_upcall(struct cache_detail *cd, struct cache_head *h)
|
|
|
return sunrpc_cache_pipe_upcall(cd, h, expkey_request);
|
|
|
}
|
|
|
|
|
|
-static struct svc_expkey *svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old);
|
|
|
-static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *);
|
|
|
-static struct cache_detail svc_expkey_cache;
|
|
|
+static struct svc_expkey *svc_expkey_update(struct cache_detail *cd, struct svc_expkey *new,
|
|
|
+ struct svc_expkey *old);
|
|
|
+static struct svc_expkey *svc_expkey_lookup(struct cache_detail *cd, struct svc_expkey *);
|
|
|
|
|
|
static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
|
|
|
{
|
|
@@ -131,7 +132,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
|
|
|
key.ek_fsidtype = fsidtype;
|
|
|
memcpy(key.ek_fsid, buf, len);
|
|
|
|
|
|
- ek = svc_expkey_lookup(&key);
|
|
|
+ ek = svc_expkey_lookup(cd, &key);
|
|
|
err = -ENOMEM;
|
|
|
if (!ek)
|
|
|
goto out;
|
|
@@ -145,7 +146,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
|
|
|
err = 0;
|
|
|
if (len == 0) {
|
|
|
set_bit(CACHE_NEGATIVE, &key.h.flags);
|
|
|
- ek = svc_expkey_update(&key, ek);
|
|
|
+ ek = svc_expkey_update(cd, &key, ek);
|
|
|
if (!ek)
|
|
|
err = -ENOMEM;
|
|
|
} else {
|
|
@@ -155,7 +156,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
|
|
|
|
|
|
dprintk("Found the path %s\n", buf);
|
|
|
|
|
|
- ek = svc_expkey_update(&key, ek);
|
|
|
+ ek = svc_expkey_update(cd, &key, ek);
|
|
|
if (!ek)
|
|
|
err = -ENOMEM;
|
|
|
path_put(&key.ek_path);
|
|
@@ -163,7 +164,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
|
|
|
cache_flush();
|
|
|
out:
|
|
|
if (ek)
|
|
|
- cache_put(&ek->h, &svc_expkey_cache);
|
|
|
+ cache_put(&ek->h, cd);
|
|
|
if (dom)
|
|
|
auth_domain_put(dom);
|
|
|
kfree(buf);
|
|
@@ -239,10 +240,9 @@ static struct cache_head *expkey_alloc(void)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-static struct cache_detail svc_expkey_cache = {
|
|
|
+static struct cache_detail svc_expkey_cache_template = {
|
|
|
.owner = THIS_MODULE,
|
|
|
.hash_size = EXPKEY_HASHMAX,
|
|
|
- .hash_table = expkey_table,
|
|
|
.name = "nfsd.fh",
|
|
|
.cache_put = expkey_put,
|
|
|
.cache_upcall = expkey_upcall,
|
|
@@ -268,13 +268,12 @@ svc_expkey_hash(struct svc_expkey *item)
|
|
|
}
|
|
|
|
|
|
static struct svc_expkey *
|
|
|
-svc_expkey_lookup(struct svc_expkey *item)
|
|
|
+svc_expkey_lookup(struct cache_detail *cd, struct svc_expkey *item)
|
|
|
{
|
|
|
struct cache_head *ch;
|
|
|
int hash = svc_expkey_hash(item);
|
|
|
|
|
|
- ch = sunrpc_cache_lookup(&svc_expkey_cache, &item->h,
|
|
|
- hash);
|
|
|
+ ch = sunrpc_cache_lookup(cd, &item->h, hash);
|
|
|
if (ch)
|
|
|
return container_of(ch, struct svc_expkey, h);
|
|
|
else
|
|
@@ -282,13 +281,13 @@ svc_expkey_lookup(struct svc_expkey *item)
|
|
|
}
|
|
|
|
|
|
static struct svc_expkey *
|
|
|
-svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old)
|
|
|
+svc_expkey_update(struct cache_detail *cd, struct svc_expkey *new,
|
|
|
+ struct svc_expkey *old)
|
|
|
{
|
|
|
struct cache_head *ch;
|
|
|
int hash = svc_expkey_hash(new);
|
|
|
|
|
|
- ch = sunrpc_cache_update(&svc_expkey_cache, &new->h,
|
|
|
- &old->h, hash);
|
|
|
+ ch = sunrpc_cache_update(cd, &new->h, &old->h, hash);
|
|
|
if (ch)
|
|
|
return container_of(ch, struct svc_expkey, h);
|
|
|
else
|
|
@@ -299,8 +298,6 @@ svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old)
|
|
|
#define EXPORT_HASHBITS 8
|
|
|
#define EXPORT_HASHMAX (1<< EXPORT_HASHBITS)
|
|
|
|
|
|
-static struct cache_head *export_table[EXPORT_HASHMAX];
|
|
|
-
|
|
|
static void nfsd4_fslocs_free(struct nfsd4_fs_locations *fsloc)
|
|
|
{
|
|
|
int i;
|
|
@@ -525,6 +522,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
|
|
|
goto out1;
|
|
|
|
|
|
exp.ex_client = dom;
|
|
|
+ exp.cd = cd;
|
|
|
|
|
|
/* expiry */
|
|
|
err = -EINVAL;
|
|
@@ -672,6 +670,7 @@ static void svc_export_init(struct cache_head *cnew, struct cache_head *citem)
|
|
|
new->ex_fslocs.locations = NULL;
|
|
|
new->ex_fslocs.locations_count = 0;
|
|
|
new->ex_fslocs.migrated = 0;
|
|
|
+ new->cd = item->cd;
|
|
|
}
|
|
|
|
|
|
static void export_update(struct cache_head *cnew, struct cache_head *citem)
|
|
@@ -707,10 +706,9 @@ static struct cache_head *svc_export_alloc(void)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-struct cache_detail svc_export_cache = {
|
|
|
+struct cache_detail svc_export_cache_template = {
|
|
|
.owner = THIS_MODULE,
|
|
|
.hash_size = EXPORT_HASHMAX,
|
|
|
- .hash_table = export_table,
|
|
|
.name = "nfsd.export",
|
|
|
.cache_put = svc_export_put,
|
|
|
.cache_upcall = svc_export_upcall,
|
|
@@ -739,8 +737,7 @@ svc_export_lookup(struct svc_export *exp)
|
|
|
struct cache_head *ch;
|
|
|
int hash = svc_export_hash(exp);
|
|
|
|
|
|
- ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h,
|
|
|
- hash);
|
|
|
+ ch = sunrpc_cache_lookup(exp->cd, &exp->h, hash);
|
|
|
if (ch)
|
|
|
return container_of(ch, struct svc_export, h);
|
|
|
else
|
|
@@ -753,9 +750,7 @@ svc_export_update(struct svc_export *new, struct svc_export *old)
|
|
|
struct cache_head *ch;
|
|
|
int hash = svc_export_hash(old);
|
|
|
|
|
|
- ch = sunrpc_cache_update(&svc_export_cache, &new->h,
|
|
|
- &old->h,
|
|
|
- hash);
|
|
|
+ ch = sunrpc_cache_update(old->cd, &new->h, &old->h, hash);
|
|
|
if (ch)
|
|
|
return container_of(ch, struct svc_export, h);
|
|
|
else
|
|
@@ -764,7 +759,8 @@ svc_export_update(struct svc_export *new, struct svc_export *old)
|
|
|
|
|
|
|
|
|
static struct svc_expkey *
|
|
|
-exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
|
|
|
+exp_find_key(struct cache_detail *cd, svc_client *clp, int fsid_type,
|
|
|
+ u32 *fsidv, struct cache_req *reqp)
|
|
|
{
|
|
|
struct svc_expkey key, *ek;
|
|
|
int err;
|
|
@@ -776,18 +772,18 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
|
|
|
key.ek_fsidtype = fsid_type;
|
|
|
memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
|
|
|
|
|
|
- ek = svc_expkey_lookup(&key);
|
|
|
+ ek = svc_expkey_lookup(cd, &key);
|
|
|
if (ek == NULL)
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
- err = cache_check(&svc_expkey_cache, &ek->h, reqp);
|
|
|
+ err = cache_check(cd, &ek->h, reqp);
|
|
|
if (err)
|
|
|
return ERR_PTR(err);
|
|
|
return ek;
|
|
|
}
|
|
|
|
|
|
|
|
|
-static svc_export *exp_get_by_name(svc_client *clp, const struct path *path,
|
|
|
- struct cache_req *reqp)
|
|
|
+static svc_export *exp_get_by_name(struct cache_detail *cd, svc_client *clp,
|
|
|
+ const struct path *path, struct cache_req *reqp)
|
|
|
{
|
|
|
struct svc_export *exp, key;
|
|
|
int err;
|
|
@@ -797,11 +793,12 @@ static svc_export *exp_get_by_name(svc_client *clp, const struct path *path,
|
|
|
|
|
|
key.ex_client = clp;
|
|
|
key.ex_path = *path;
|
|
|
+ key.cd = cd;
|
|
|
|
|
|
exp = svc_export_lookup(&key);
|
|
|
if (exp == NULL)
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
- err = cache_check(&svc_export_cache, &exp->h, reqp);
|
|
|
+ err = cache_check(cd, &exp->h, reqp);
|
|
|
if (err)
|
|
|
return ERR_PTR(err);
|
|
|
return exp;
|
|
@@ -810,16 +807,17 @@ static svc_export *exp_get_by_name(svc_client *clp, const struct path *path,
|
|
|
/*
|
|
|
* Find the export entry for a given dentry.
|
|
|
*/
|
|
|
-static struct svc_export *exp_parent(svc_client *clp, struct path *path)
|
|
|
+static struct svc_export *exp_parent(struct cache_detail *cd, svc_client *clp,
|
|
|
+ struct path *path)
|
|
|
{
|
|
|
struct dentry *saved = dget(path->dentry);
|
|
|
- svc_export *exp = exp_get_by_name(clp, path, NULL);
|
|
|
+ svc_export *exp = exp_get_by_name(cd, clp, path, NULL);
|
|
|
|
|
|
while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) {
|
|
|
struct dentry *parent = dget_parent(path->dentry);
|
|
|
dput(path->dentry);
|
|
|
path->dentry = parent;
|
|
|
- exp = exp_get_by_name(clp, path, NULL);
|
|
|
+ exp = exp_get_by_name(cd, clp, path, NULL);
|
|
|
}
|
|
|
dput(path->dentry);
|
|
|
path->dentry = saved;
|
|
@@ -834,13 +832,16 @@ static struct svc_export *exp_parent(svc_client *clp, struct path *path)
|
|
|
* since its harder to fool a kernel module than a user space program.
|
|
|
*/
|
|
|
int
|
|
|
-exp_rootfh(svc_client *clp, char *name, struct knfsd_fh *f, int maxsize)
|
|
|
+exp_rootfh(struct net *net, svc_client *clp, char *name,
|
|
|
+ struct knfsd_fh *f, int maxsize)
|
|
|
{
|
|
|
struct svc_export *exp;
|
|
|
struct path path;
|
|
|
struct inode *inode;
|
|
|
struct svc_fh fh;
|
|
|
int err;
|
|
|
+ struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
|
|
+ struct cache_detail *cd = nn->svc_export_cache;
|
|
|
|
|
|
err = -EPERM;
|
|
|
/* NB: we probably ought to check that it's NUL-terminated */
|
|
@@ -853,7 +854,7 @@ exp_rootfh(svc_client *clp, char *name, struct knfsd_fh *f, int maxsize)
|
|
|
dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n",
|
|
|
name, path.dentry, clp->name,
|
|
|
inode->i_sb->s_id, inode->i_ino);
|
|
|
- exp = exp_parent(clp, &path);
|
|
|
+ exp = exp_parent(cd, clp, &path);
|
|
|
if (IS_ERR(exp)) {
|
|
|
err = PTR_ERR(exp);
|
|
|
goto out;
|
|
@@ -875,16 +876,18 @@ out:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static struct svc_export *exp_find(struct auth_domain *clp, int fsid_type,
|
|
|
+static struct svc_export *exp_find(struct cache_detail *cd,
|
|
|
+ struct auth_domain *clp, int fsid_type,
|
|
|
u32 *fsidv, struct cache_req *reqp)
|
|
|
{
|
|
|
struct svc_export *exp;
|
|
|
- struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp);
|
|
|
+ struct nfsd_net *nn = net_generic(cd->net, nfsd_net_id);
|
|
|
+ struct svc_expkey *ek = exp_find_key(nn->svc_expkey_cache, clp, fsid_type, fsidv, reqp);
|
|
|
if (IS_ERR(ek))
|
|
|
return ERR_CAST(ek);
|
|
|
|
|
|
- exp = exp_get_by_name(clp, &ek->ek_path, reqp);
|
|
|
- cache_put(&ek->h, &svc_expkey_cache);
|
|
|
+ exp = exp_get_by_name(cd, clp, &ek->ek_path, reqp);
|
|
|
+ cache_put(&ek->h, nn->svc_expkey_cache);
|
|
|
|
|
|
if (IS_ERR(exp))
|
|
|
return ERR_CAST(exp);
|
|
@@ -926,12 +929,14 @@ struct svc_export *
|
|
|
rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path)
|
|
|
{
|
|
|
struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
|
|
|
+ struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id);
|
|
|
+ struct cache_detail *cd = nn->svc_export_cache;
|
|
|
|
|
|
if (rqstp->rq_client == NULL)
|
|
|
goto gss;
|
|
|
|
|
|
/* First try the auth_unix client: */
|
|
|
- exp = exp_get_by_name(rqstp->rq_client, path, &rqstp->rq_chandle);
|
|
|
+ exp = exp_get_by_name(cd, rqstp->rq_client, path, &rqstp->rq_chandle);
|
|
|
if (PTR_ERR(exp) == -ENOENT)
|
|
|
goto gss;
|
|
|
if (IS_ERR(exp))
|
|
@@ -943,7 +948,7 @@ gss:
|
|
|
/* Otherwise, try falling back on gss client */
|
|
|
if (rqstp->rq_gssclient == NULL)
|
|
|
return exp;
|
|
|
- gssexp = exp_get_by_name(rqstp->rq_gssclient, path, &rqstp->rq_chandle);
|
|
|
+ gssexp = exp_get_by_name(cd, rqstp->rq_gssclient, path, &rqstp->rq_chandle);
|
|
|
if (PTR_ERR(gssexp) == -ENOENT)
|
|
|
return exp;
|
|
|
if (!IS_ERR(exp))
|
|
@@ -955,12 +960,15 @@ struct svc_export *
|
|
|
rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
|
|
|
{
|
|
|
struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
|
|
|
+ struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id);
|
|
|
+ struct cache_detail *cd = nn->svc_export_cache;
|
|
|
|
|
|
if (rqstp->rq_client == NULL)
|
|
|
goto gss;
|
|
|
|
|
|
/* First try the auth_unix client: */
|
|
|
- exp = exp_find(rqstp->rq_client, fsid_type, fsidv, &rqstp->rq_chandle);
|
|
|
+ exp = exp_find(cd, rqstp->rq_client, fsid_type,
|
|
|
+ fsidv, &rqstp->rq_chandle);
|
|
|
if (PTR_ERR(exp) == -ENOENT)
|
|
|
goto gss;
|
|
|
if (IS_ERR(exp))
|
|
@@ -972,7 +980,7 @@ gss:
|
|
|
/* Otherwise, try falling back on gss client */
|
|
|
if (rqstp->rq_gssclient == NULL)
|
|
|
return exp;
|
|
|
- gssexp = exp_find(rqstp->rq_gssclient, fsid_type, fsidv,
|
|
|
+ gssexp = exp_find(cd, rqstp->rq_gssclient, fsid_type, fsidv,
|
|
|
&rqstp->rq_chandle);
|
|
|
if (PTR_ERR(gssexp) == -ENOENT)
|
|
|
return exp;
|
|
@@ -1029,13 +1037,15 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
|
|
|
/* Iterator */
|
|
|
|
|
|
static void *e_start(struct seq_file *m, loff_t *pos)
|
|
|
- __acquires(svc_export_cache.hash_lock)
|
|
|
+ __acquires(((struct cache_detail *)m->private)->hash_lock)
|
|
|
{
|
|
|
loff_t n = *pos;
|
|
|
unsigned hash, export;
|
|
|
struct cache_head *ch;
|
|
|
-
|
|
|
- read_lock(&svc_export_cache.hash_lock);
|
|
|
+ struct cache_detail *cd = m->private;
|
|
|
+ struct cache_head **export_table = cd->hash_table;
|
|
|
+
|
|
|
+ read_lock(&cd->hash_lock);
|
|
|
if (!n--)
|
|
|
return SEQ_START_TOKEN;
|
|
|
hash = n >> 32;
|
|
@@ -1060,6 +1070,8 @@ static void *e_next(struct seq_file *m, void *p, loff_t *pos)
|
|
|
{
|
|
|
struct cache_head *ch = p;
|
|
|
int hash = (*pos >> 32);
|
|
|
+ struct cache_detail *cd = m->private;
|
|
|
+ struct cache_head **export_table = cd->hash_table;
|
|
|
|
|
|
if (p == SEQ_START_TOKEN)
|
|
|
hash = 0;
|
|
@@ -1082,9 +1094,11 @@ static void *e_next(struct seq_file *m, void *p, loff_t *pos)
|
|
|
}
|
|
|
|
|
|
static void e_stop(struct seq_file *m, void *p)
|
|
|
- __releases(svc_export_cache.hash_lock)
|
|
|
+ __releases(((struct cache_detail *)m->private)->hash_lock)
|
|
|
{
|
|
|
- read_unlock(&svc_export_cache.hash_lock);
|
|
|
+ struct cache_detail *cd = m->private;
|
|
|
+
|
|
|
+ read_unlock(&cd->hash_lock);
|
|
|
}
|
|
|
|
|
|
static struct flags {
|
|
@@ -1195,6 +1209,7 @@ static int e_show(struct seq_file *m, void *p)
|
|
|
{
|
|
|
struct cache_head *cp = p;
|
|
|
struct svc_export *exp = container_of(cp, struct svc_export, h);
|
|
|
+ struct cache_detail *cd = m->private;
|
|
|
|
|
|
if (p == SEQ_START_TOKEN) {
|
|
|
seq_puts(m, "# Version 1.1\n");
|
|
@@ -1203,10 +1218,10 @@ static int e_show(struct seq_file *m, void *p)
|
|
|
}
|
|
|
|
|
|
cache_get(&exp->h);
|
|
|
- if (cache_check(&svc_export_cache, &exp->h, NULL))
|
|
|
+ if (cache_check(cd, &exp->h, NULL))
|
|
|
return 0;
|
|
|
- cache_put(&exp->h, &svc_export_cache);
|
|
|
- return svc_export_show(m, &svc_export_cache, cp);
|
|
|
+ exp_put(exp);
|
|
|
+ return svc_export_show(m, cd, cp);
|
|
|
}
|
|
|
|
|
|
const struct seq_operations nfs_exports_op = {
|
|
@@ -1216,48 +1231,70 @@ const struct seq_operations nfs_exports_op = {
|
|
|
.show = e_show,
|
|
|
};
|
|
|
|
|
|
-
|
|
|
/*
|
|
|
* Initialize the exports module.
|
|
|
*/
|
|
|
int
|
|
|
-nfsd_export_init(void)
|
|
|
+nfsd_export_init(struct net *net)
|
|
|
{
|
|
|
int rv;
|
|
|
- dprintk("nfsd: initializing export module.\n");
|
|
|
+ struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
|
|
+
|
|
|
+ dprintk("nfsd: initializing export module (net: %p).\n", net);
|
|
|
|
|
|
- rv = cache_register_net(&svc_export_cache, &init_net);
|
|
|
+ nn->svc_export_cache = cache_create_net(&svc_export_cache_template, net);
|
|
|
+ if (IS_ERR(nn->svc_export_cache))
|
|
|
+ return PTR_ERR(nn->svc_export_cache);
|
|
|
+ rv = cache_register_net(nn->svc_export_cache, net);
|
|
|
if (rv)
|
|
|
- return rv;
|
|
|
- rv = cache_register_net(&svc_expkey_cache, &init_net);
|
|
|
+ goto destroy_export_cache;
|
|
|
+
|
|
|
+ nn->svc_expkey_cache = cache_create_net(&svc_expkey_cache_template, net);
|
|
|
+ if (IS_ERR(nn->svc_expkey_cache)) {
|
|
|
+ rv = PTR_ERR(nn->svc_expkey_cache);
|
|
|
+ goto unregister_export_cache;
|
|
|
+ }
|
|
|
+ rv = cache_register_net(nn->svc_expkey_cache, net);
|
|
|
if (rv)
|
|
|
- cache_unregister_net(&svc_export_cache, &init_net);
|
|
|
- return rv;
|
|
|
+ goto destroy_expkey_cache;
|
|
|
+ return 0;
|
|
|
|
|
|
+destroy_expkey_cache:
|
|
|
+ cache_destroy_net(nn->svc_expkey_cache, net);
|
|
|
+unregister_export_cache:
|
|
|
+ cache_unregister_net(nn->svc_export_cache, net);
|
|
|
+destroy_export_cache:
|
|
|
+ cache_destroy_net(nn->svc_export_cache, net);
|
|
|
+ return rv;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Flush exports table - called when last nfsd thread is killed
|
|
|
*/
|
|
|
void
|
|
|
-nfsd_export_flush(void)
|
|
|
+nfsd_export_flush(struct net *net)
|
|
|
{
|
|
|
- cache_purge(&svc_expkey_cache);
|
|
|
- cache_purge(&svc_export_cache);
|
|
|
+ struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
|
|
+
|
|
|
+ cache_purge(nn->svc_expkey_cache);
|
|
|
+ cache_purge(nn->svc_export_cache);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Shutdown the exports module.
|
|
|
*/
|
|
|
void
|
|
|
-nfsd_export_shutdown(void)
|
|
|
+nfsd_export_shutdown(struct net *net)
|
|
|
{
|
|
|
+ struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
|
|
|
|
|
- dprintk("nfsd: shutting down export module.\n");
|
|
|
+ dprintk("nfsd: shutting down export module (net: %p).\n", net);
|
|
|
|
|
|
- cache_unregister_net(&svc_expkey_cache, &init_net);
|
|
|
- cache_unregister_net(&svc_export_cache, &init_net);
|
|
|
- svcauth_unix_purge();
|
|
|
+ cache_unregister_net(nn->svc_expkey_cache, net);
|
|
|
+ cache_unregister_net(nn->svc_export_cache, net);
|
|
|
+ cache_destroy_net(nn->svc_expkey_cache, net);
|
|
|
+ cache_destroy_net(nn->svc_export_cache, net);
|
|
|
+ svcauth_unix_purge(net);
|
|
|
|
|
|
- dprintk("nfsd: export shutdown complete.\n");
|
|
|
+ dprintk("nfsd: export shutdown complete (net: %p).\n", net);
|
|
|
}
|