Merge branch 'for-3.5-take-2' of git://linux-nfs.org/~bfields/linux
Pull nfsd update from Bruce Fields. * 'for-3.5-take-2' of git://linux-nfs.org/~bfields/linux: (23 commits) nfsd: trivial: use SEEK_SET instead of 0 in vfs_llseek SUNRPC: split upcall function to extract reusable parts nfsd: allocate id-to-name and name-to-id caches in per-net operations. nfsd: make name-to-id cache allocated per network namespace context nfsd: make id-to-name cache allocated per network namespace context nfsd: pass network context to idmap init/exit functions nfsd: allocate export and expkey caches in per-net operations. nfsd: make expkey cache allocated per network namespace context nfsd: make export cache allocated per network namespace context nfsd: pass pointer to export cache down to stack wherever possible. nfsd: pass network context to export caches init/shutdown routines Lockd: pass network namespace to creation and destruction routines NFSd: remove hard-coded dereferences to name-to-id and id-to-name caches nfsd: pass pointer to expkey cache down to stack wherever possible. nfsd: use hash table from cache detail in nfsd export seq ops nfsd: pass svc_export_cache pointer as private data to "exports" seq file ops nfsd: use exp_put() for svc_export_cache put nfsd: use cache detail pointer from svc_export structure on cache put nfsd: add link to owner cache detail to svc_export structure nfsd: use passed cache_detail pointer expkey_parse() ...
This commit is contained in:
175
fs/nfsd/export.c
175
fs/nfsd/export.c
@@ -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);
|
||||
|
||||
rv = cache_register_net(&svc_export_cache, &init_net);
|
||||
dprintk("nfsd: initializing export module (net: %p).\n", 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);
|
||||
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);
|
||||
}
|
||||
|
@@ -42,14 +42,14 @@
|
||||
#define IDMAP_NAMESZ 128
|
||||
|
||||
#ifdef CONFIG_NFSD_V4
|
||||
int nfsd_idmap_init(void);
|
||||
void nfsd_idmap_shutdown(void);
|
||||
int nfsd_idmap_init(struct net *);
|
||||
void nfsd_idmap_shutdown(struct net *);
|
||||
#else
|
||||
static inline int nfsd_idmap_init(void)
|
||||
static inline int nfsd_idmap_init(struct net *net)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void nfsd_idmap_shutdown(void)
|
||||
static inline void nfsd_idmap_shutdown(struct net *net)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
@@ -28,6 +28,12 @@ struct cld_net;
|
||||
|
||||
struct nfsd_net {
|
||||
struct cld_net *cld_net;
|
||||
|
||||
struct cache_detail *svc_expkey_cache;
|
||||
struct cache_detail *svc_export_cache;
|
||||
|
||||
struct cache_detail *idtoname_cache;
|
||||
struct cache_detail *nametoid_cache;
|
||||
};
|
||||
|
||||
extern int nfsd_net_id;
|
||||
|
@@ -36,9 +36,11 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sunrpc/svc_xprt.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include "idmap.h"
|
||||
#include "nfsd.h"
|
||||
#include "netns.h"
|
||||
|
||||
/*
|
||||
* Turn off idmapping when using AUTH_SYS.
|
||||
@@ -107,8 +109,6 @@ ent_alloc(void)
|
||||
* ID -> Name cache
|
||||
*/
|
||||
|
||||
static struct cache_head *idtoname_table[ENT_HASHMAX];
|
||||
|
||||
static uint32_t
|
||||
idtoname_hash(struct ent *ent)
|
||||
{
|
||||
@@ -183,13 +183,13 @@ warn_no_idmapd(struct cache_detail *detail, int has_died)
|
||||
|
||||
|
||||
static int idtoname_parse(struct cache_detail *, char *, int);
|
||||
static struct ent *idtoname_lookup(struct ent *);
|
||||
static struct ent *idtoname_update(struct ent *, struct ent *);
|
||||
static struct ent *idtoname_lookup(struct cache_detail *, struct ent *);
|
||||
static struct ent *idtoname_update(struct cache_detail *, struct ent *,
|
||||
struct ent *);
|
||||
|
||||
static struct cache_detail idtoname_cache = {
|
||||
static struct cache_detail idtoname_cache_template = {
|
||||
.owner = THIS_MODULE,
|
||||
.hash_size = ENT_HASHMAX,
|
||||
.hash_table = idtoname_table,
|
||||
.name = "nfs4.idtoname",
|
||||
.cache_put = ent_put,
|
||||
.cache_upcall = idtoname_upcall,
|
||||
@@ -244,7 +244,7 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
|
||||
goto out;
|
||||
|
||||
error = -ENOMEM;
|
||||
res = idtoname_lookup(&ent);
|
||||
res = idtoname_lookup(cd, &ent);
|
||||
if (!res)
|
||||
goto out;
|
||||
|
||||
@@ -260,11 +260,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
|
||||
else
|
||||
memcpy(ent.name, buf1, sizeof(ent.name));
|
||||
error = -ENOMEM;
|
||||
res = idtoname_update(&ent, res);
|
||||
res = idtoname_update(cd, &ent, res);
|
||||
if (res == NULL)
|
||||
goto out;
|
||||
|
||||
cache_put(&res->h, &idtoname_cache);
|
||||
cache_put(&res->h, cd);
|
||||
|
||||
error = 0;
|
||||
out:
|
||||
@@ -275,10 +275,9 @@ out:
|
||||
|
||||
|
||||
static struct ent *
|
||||
idtoname_lookup(struct ent *item)
|
||||
idtoname_lookup(struct cache_detail *cd, struct ent *item)
|
||||
{
|
||||
struct cache_head *ch = sunrpc_cache_lookup(&idtoname_cache,
|
||||
&item->h,
|
||||
struct cache_head *ch = sunrpc_cache_lookup(cd, &item->h,
|
||||
idtoname_hash(item));
|
||||
if (ch)
|
||||
return container_of(ch, struct ent, h);
|
||||
@@ -287,10 +286,9 @@ idtoname_lookup(struct ent *item)
|
||||
}
|
||||
|
||||
static struct ent *
|
||||
idtoname_update(struct ent *new, struct ent *old)
|
||||
idtoname_update(struct cache_detail *cd, struct ent *new, struct ent *old)
|
||||
{
|
||||
struct cache_head *ch = sunrpc_cache_update(&idtoname_cache,
|
||||
&new->h, &old->h,
|
||||
struct cache_head *ch = sunrpc_cache_update(cd, &new->h, &old->h,
|
||||
idtoname_hash(new));
|
||||
if (ch)
|
||||
return container_of(ch, struct ent, h);
|
||||
@@ -303,8 +301,6 @@ idtoname_update(struct ent *new, struct ent *old)
|
||||
* Name -> ID cache
|
||||
*/
|
||||
|
||||
static struct cache_head *nametoid_table[ENT_HASHMAX];
|
||||
|
||||
static inline int
|
||||
nametoid_hash(struct ent *ent)
|
||||
{
|
||||
@@ -359,14 +355,14 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ent *nametoid_lookup(struct ent *);
|
||||
static struct ent *nametoid_update(struct ent *, struct ent *);
|
||||
static struct ent *nametoid_lookup(struct cache_detail *, struct ent *);
|
||||
static struct ent *nametoid_update(struct cache_detail *, struct ent *,
|
||||
struct ent *);
|
||||
static int nametoid_parse(struct cache_detail *, char *, int);
|
||||
|
||||
static struct cache_detail nametoid_cache = {
|
||||
static struct cache_detail nametoid_cache_template = {
|
||||
.owner = THIS_MODULE,
|
||||
.hash_size = ENT_HASHMAX,
|
||||
.hash_table = nametoid_table,
|
||||
.name = "nfs4.nametoid",
|
||||
.cache_put = ent_put,
|
||||
.cache_upcall = nametoid_upcall,
|
||||
@@ -426,14 +422,14 @@ nametoid_parse(struct cache_detail *cd, char *buf, int buflen)
|
||||
set_bit(CACHE_NEGATIVE, &ent.h.flags);
|
||||
|
||||
error = -ENOMEM;
|
||||
res = nametoid_lookup(&ent);
|
||||
res = nametoid_lookup(cd, &ent);
|
||||
if (res == NULL)
|
||||
goto out;
|
||||
res = nametoid_update(&ent, res);
|
||||
res = nametoid_update(cd, &ent, res);
|
||||
if (res == NULL)
|
||||
goto out;
|
||||
|
||||
cache_put(&res->h, &nametoid_cache);
|
||||
cache_put(&res->h, cd);
|
||||
error = 0;
|
||||
out:
|
||||
kfree(buf1);
|
||||
@@ -443,10 +439,9 @@ out:
|
||||
|
||||
|
||||
static struct ent *
|
||||
nametoid_lookup(struct ent *item)
|
||||
nametoid_lookup(struct cache_detail *cd, struct ent *item)
|
||||
{
|
||||
struct cache_head *ch = sunrpc_cache_lookup(&nametoid_cache,
|
||||
&item->h,
|
||||
struct cache_head *ch = sunrpc_cache_lookup(cd, &item->h,
|
||||
nametoid_hash(item));
|
||||
if (ch)
|
||||
return container_of(ch, struct ent, h);
|
||||
@@ -455,10 +450,9 @@ nametoid_lookup(struct ent *item)
|
||||
}
|
||||
|
||||
static struct ent *
|
||||
nametoid_update(struct ent *new, struct ent *old)
|
||||
nametoid_update(struct cache_detail *cd, struct ent *new, struct ent *old)
|
||||
{
|
||||
struct cache_head *ch = sunrpc_cache_update(&nametoid_cache,
|
||||
&new->h, &old->h,
|
||||
struct cache_head *ch = sunrpc_cache_update(cd, &new->h, &old->h,
|
||||
nametoid_hash(new));
|
||||
if (ch)
|
||||
return container_of(ch, struct ent, h);
|
||||
@@ -471,34 +465,55 @@ nametoid_update(struct ent *new, struct ent *old)
|
||||
*/
|
||||
|
||||
int
|
||||
nfsd_idmap_init(void)
|
||||
nfsd_idmap_init(struct net *net)
|
||||
{
|
||||
int rv;
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
|
||||
rv = cache_register_net(&idtoname_cache, &init_net);
|
||||
nn->idtoname_cache = cache_create_net(&idtoname_cache_template, net);
|
||||
if (IS_ERR(nn->idtoname_cache))
|
||||
return PTR_ERR(nn->idtoname_cache);
|
||||
rv = cache_register_net(nn->idtoname_cache, net);
|
||||
if (rv)
|
||||
return rv;
|
||||
rv = cache_register_net(&nametoid_cache, &init_net);
|
||||
goto destroy_idtoname_cache;
|
||||
nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net);
|
||||
if (IS_ERR(nn->nametoid_cache)) {
|
||||
rv = PTR_ERR(nn->idtoname_cache);
|
||||
goto unregister_idtoname_cache;
|
||||
}
|
||||
rv = cache_register_net(nn->nametoid_cache, net);
|
||||
if (rv)
|
||||
cache_unregister_net(&idtoname_cache, &init_net);
|
||||
goto destroy_nametoid_cache;
|
||||
return 0;
|
||||
|
||||
destroy_nametoid_cache:
|
||||
cache_destroy_net(nn->nametoid_cache, net);
|
||||
unregister_idtoname_cache:
|
||||
cache_unregister_net(nn->idtoname_cache, net);
|
||||
destroy_idtoname_cache:
|
||||
cache_destroy_net(nn->idtoname_cache, net);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nfsd_idmap_shutdown(void)
|
||||
nfsd_idmap_shutdown(struct net *net)
|
||||
{
|
||||
cache_unregister_net(&idtoname_cache, &init_net);
|
||||
cache_unregister_net(&nametoid_cache, &init_net);
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
|
||||
cache_unregister_net(nn->idtoname_cache, net);
|
||||
cache_unregister_net(nn->nametoid_cache, net);
|
||||
cache_destroy_net(nn->idtoname_cache, net);
|
||||
cache_destroy_net(nn->nametoid_cache, net);
|
||||
}
|
||||
|
||||
static int
|
||||
idmap_lookup(struct svc_rqst *rqstp,
|
||||
struct ent *(*lookup_fn)(struct ent *), struct ent *key,
|
||||
struct cache_detail *detail, struct ent **item)
|
||||
struct ent *(*lookup_fn)(struct cache_detail *, struct ent *),
|
||||
struct ent *key, struct cache_detail *detail, struct ent **item)
|
||||
{
|
||||
int ret;
|
||||
|
||||
*item = lookup_fn(key);
|
||||
*item = lookup_fn(detail, key);
|
||||
if (!*item)
|
||||
return -ENOMEM;
|
||||
retry:
|
||||
@@ -506,7 +521,7 @@ idmap_lookup(struct svc_rqst *rqstp,
|
||||
|
||||
if (ret == -ETIMEDOUT) {
|
||||
struct ent *prev_item = *item;
|
||||
*item = lookup_fn(key);
|
||||
*item = lookup_fn(detail, key);
|
||||
if (*item != prev_item)
|
||||
goto retry;
|
||||
cache_put(&(*item)->h, detail);
|
||||
@@ -531,19 +546,20 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen
|
||||
.type = type,
|
||||
};
|
||||
int ret;
|
||||
struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id);
|
||||
|
||||
if (namelen + 1 > sizeof(key.name))
|
||||
return nfserr_badowner;
|
||||
memcpy(key.name, name, namelen);
|
||||
key.name[namelen] = '\0';
|
||||
strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
|
||||
ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item);
|
||||
ret = idmap_lookup(rqstp, nametoid_lookup, &key, nn->nametoid_cache, &item);
|
||||
if (ret == -ENOENT)
|
||||
return nfserr_badowner;
|
||||
if (ret)
|
||||
return nfserrno(ret);
|
||||
*id = item->id;
|
||||
cache_put(&item->h, &nametoid_cache);
|
||||
cache_put(&item->h, nn->nametoid_cache);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -555,9 +571,10 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
|
||||
.type = type,
|
||||
};
|
||||
int ret;
|
||||
struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id);
|
||||
|
||||
strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
|
||||
ret = idmap_lookup(rqstp, idtoname_lookup, &key, &idtoname_cache, &item);
|
||||
ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item);
|
||||
if (ret == -ENOENT)
|
||||
return sprintf(name, "%u", id);
|
||||
if (ret)
|
||||
@@ -565,7 +582,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
|
||||
ret = strlen(item->name);
|
||||
BUG_ON(ret > IDMAP_NAMESZ);
|
||||
memcpy(name, item->name, ret);
|
||||
cache_put(&item->h, &idtoname_cache);
|
||||
cache_put(&item->h, nn->idtoname_cache);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -3155,10 +3155,17 @@ out:
|
||||
static struct lock_manager nfsd4_manager = {
|
||||
};
|
||||
|
||||
static bool grace_ended;
|
||||
|
||||
static void
|
||||
nfsd4_end_grace(void)
|
||||
{
|
||||
/* do nothing if grace period already ended */
|
||||
if (grace_ended)
|
||||
return;
|
||||
|
||||
dprintk("NFSD: end of grace period\n");
|
||||
grace_ended = true;
|
||||
nfsd4_record_grace_done(&init_net, boot_time);
|
||||
locks_end_grace(&nfsd4_manager);
|
||||
/*
|
||||
@@ -3183,8 +3190,7 @@ nfs4_laundromat(void)
|
||||
nfs4_lock_state();
|
||||
|
||||
dprintk("NFSD: laundromat service - starting\n");
|
||||
if (locks_in_grace())
|
||||
nfsd4_end_grace();
|
||||
nfsd4_end_grace();
|
||||
INIT_LIST_HEAD(&reaplist);
|
||||
spin_lock(&client_lock);
|
||||
list_for_each_safe(pos, next, &client_lru) {
|
||||
@@ -4055,7 +4061,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
struct nfs4_openowner *open_sop = NULL;
|
||||
struct nfs4_lockowner *lock_sop = NULL;
|
||||
struct nfs4_ol_stateid *lock_stp;
|
||||
struct nfs4_file *fp;
|
||||
struct file *filp = NULL;
|
||||
struct file_lock file_lock;
|
||||
struct file_lock conflock;
|
||||
@@ -4123,7 +4128,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
goto out;
|
||||
}
|
||||
lock_sop = lockowner(lock_stp->st_stateowner);
|
||||
fp = lock_stp->st_file;
|
||||
|
||||
lkflg = setlkflg(lock->lk_type);
|
||||
status = nfs4_check_openmode(lock_stp, lkflg);
|
||||
@@ -4715,6 +4719,7 @@ nfs4_state_start(void)
|
||||
nfsd4_client_tracking_init(&init_net);
|
||||
boot_time = get_seconds();
|
||||
locks_start_grace(&nfsd4_manager);
|
||||
grace_ended = false;
|
||||
printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
|
||||
nfsd4_grace);
|
||||
ret = set_callback_cred();
|
||||
|
@@ -127,7 +127,17 @@ static const struct file_operations transaction_ops = {
|
||||
|
||||
static int exports_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &nfs_exports_op);
|
||||
int err;
|
||||
struct seq_file *seq;
|
||||
struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
|
||||
|
||||
err = seq_open(file, &nfs_exports_op);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
seq = file->private_data;
|
||||
seq->private = nn->svc_export_cache;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations exports_operations = {
|
||||
@@ -345,7 +355,7 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
|
||||
if (!dom)
|
||||
return -ENOMEM;
|
||||
|
||||
len = exp_rootfh(dom, path, &fh, maxsize);
|
||||
len = exp_rootfh(&init_net, dom, path, &fh, maxsize);
|
||||
auth_domain_put(dom);
|
||||
if (len)
|
||||
return len;
|
||||
@@ -1127,7 +1137,34 @@ static int create_proc_exports_entry(void)
|
||||
#endif
|
||||
|
||||
int nfsd_net_id;
|
||||
|
||||
static __net_init int nfsd_init_net(struct net *net)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = nfsd_export_init(net);
|
||||
if (retval)
|
||||
goto out_export_error;
|
||||
retval = nfsd_idmap_init(net);
|
||||
if (retval)
|
||||
goto out_idmap_error;
|
||||
return 0;
|
||||
|
||||
out_idmap_error:
|
||||
nfsd_export_shutdown(net);
|
||||
out_export_error:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static __net_exit void nfsd_exit_net(struct net *net)
|
||||
{
|
||||
nfsd_idmap_shutdown(net);
|
||||
nfsd_export_shutdown(net);
|
||||
}
|
||||
|
||||
static struct pernet_operations nfsd_net_ops = {
|
||||
.init = nfsd_init_net,
|
||||
.exit = nfsd_exit_net,
|
||||
.id = &nfsd_net_id,
|
||||
.size = sizeof(struct nfsd_net),
|
||||
};
|
||||
@@ -1154,16 +1191,10 @@ static int __init init_nfsd(void)
|
||||
retval = nfsd_reply_cache_init();
|
||||
if (retval)
|
||||
goto out_free_stat;
|
||||
retval = nfsd_export_init();
|
||||
if (retval)
|
||||
goto out_free_cache;
|
||||
nfsd_lockd_init(); /* lockd->nfsd callbacks */
|
||||
retval = nfsd_idmap_init();
|
||||
if (retval)
|
||||
goto out_free_lockd;
|
||||
retval = create_proc_exports_entry();
|
||||
if (retval)
|
||||
goto out_free_idmap;
|
||||
goto out_free_lockd;
|
||||
retval = register_filesystem(&nfsd_fs_type);
|
||||
if (retval)
|
||||
goto out_free_all;
|
||||
@@ -1171,12 +1202,8 @@ static int __init init_nfsd(void)
|
||||
out_free_all:
|
||||
remove_proc_entry("fs/nfs/exports", NULL);
|
||||
remove_proc_entry("fs/nfs", NULL);
|
||||
out_free_idmap:
|
||||
nfsd_idmap_shutdown();
|
||||
out_free_lockd:
|
||||
nfsd_lockd_shutdown();
|
||||
nfsd_export_shutdown();
|
||||
out_free_cache:
|
||||
nfsd_reply_cache_shutdown();
|
||||
out_free_stat:
|
||||
nfsd_stat_shutdown();
|
||||
@@ -1192,13 +1219,11 @@ out_unregister_notifier:
|
||||
|
||||
static void __exit exit_nfsd(void)
|
||||
{
|
||||
nfsd_export_shutdown();
|
||||
nfsd_reply_cache_shutdown();
|
||||
remove_proc_entry("fs/nfs/exports", NULL);
|
||||
remove_proc_entry("fs/nfs", NULL);
|
||||
nfsd_stat_shutdown();
|
||||
nfsd_lockd_shutdown();
|
||||
nfsd_idmap_shutdown();
|
||||
nfsd4_free_slabs();
|
||||
nfsd_fault_inject_cleanup();
|
||||
unregister_filesystem(&nfsd_fs_type);
|
||||
|
@@ -636,7 +636,7 @@ fh_put(struct svc_fh *fhp)
|
||||
#endif
|
||||
}
|
||||
if (exp) {
|
||||
cache_put(&exp->h, &svc_export_cache);
|
||||
exp_put(exp);
|
||||
fhp->fh_export = NULL;
|
||||
}
|
||||
return;
|
||||
|
@@ -220,7 +220,7 @@ static int nfsd_startup(unsigned short port, int nrservs)
|
||||
ret = nfsd_init_socks(port);
|
||||
if (ret)
|
||||
goto out_racache;
|
||||
ret = lockd_up();
|
||||
ret = lockd_up(&init_net);
|
||||
if (ret)
|
||||
goto out_racache;
|
||||
ret = nfs4_state_start();
|
||||
@@ -229,7 +229,7 @@ static int nfsd_startup(unsigned short port, int nrservs)
|
||||
nfsd_up = true;
|
||||
return 0;
|
||||
out_lockd:
|
||||
lockd_down();
|
||||
lockd_down(&init_net);
|
||||
out_racache:
|
||||
nfsd_racache_shutdown();
|
||||
return ret;
|
||||
@@ -246,7 +246,7 @@ static void nfsd_shutdown(void)
|
||||
if (!nfsd_up)
|
||||
return;
|
||||
nfs4_state_shutdown();
|
||||
lockd_down();
|
||||
lockd_down(&init_net);
|
||||
nfsd_racache_shutdown();
|
||||
nfsd_up = false;
|
||||
}
|
||||
@@ -261,7 +261,7 @@ static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
|
||||
|
||||
printk(KERN_WARNING "nfsd: last server has exited, flushing export "
|
||||
"cache\n");
|
||||
nfsd_export_flush();
|
||||
nfsd_export_flush(net);
|
||||
}
|
||||
|
||||
void nfsd_reset_versions(void)
|
||||
|
@@ -2039,7 +2039,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
offset = vfs_llseek(file, offset, 0);
|
||||
offset = vfs_llseek(file, offset, SEEK_SET);
|
||||
if (offset < 0) {
|
||||
err = nfserrno((int)offset);
|
||||
goto out_close;
|
||||
|
Reference in New Issue
Block a user