Commit 85d18365 authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] kNFSd: Convert export-table to use new cache code

This introduces two caches, svc_export_cache (nfsd.exports) and
svc_expkey_cache (nfsd.fh).
nfsd.exports maps client+directory  ->  export options.
nfsd.fh maps client + filehandle-fragment -> directory.

A major part of this change is that export entries are now reference counted,
so we have to be careful  to keep those counts correct.
parent df821d2c
This diff is collapsed.
...@@ -86,7 +86,7 @@ u32 ...@@ -86,7 +86,7 @@ u32
fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
{ {
struct knfsd_fh *fh = &fhp->fh_handle; struct knfsd_fh *fh = &fhp->fh_handle;
struct svc_export *exp; struct svc_export *exp = NULL;
struct dentry *dentry; struct dentry *dentry;
struct inode *inode; struct inode *inode;
u32 error = 0; u32 error = 0;
...@@ -144,13 +144,12 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ...@@ -144,13 +144,12 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
exp = exp_find(rqstp->rq_client, 0, tfh); exp = exp_find(rqstp->rq_client, 0, tfh);
} }
/* error = nfserr_dropit;
* Look up the export entry. if (IS_ERR(exp))
*/ goto out;
error = nfserr_stale;
error = nfserr_stale;
if (!exp) if (!exp)
/* export entry revoked */
goto out; goto out;
/* Check if the request originated from a secure port. */ /* Check if the request originated from a secure port. */
...@@ -221,6 +220,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ...@@ -221,6 +220,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
dentry = fhp->fh_dentry; dentry = fhp->fh_dentry;
exp = fhp->fh_export; exp = fhp->fh_export;
} }
cache_get(&exp->h);
inode = dentry->d_inode; inode = dentry->d_inode;
...@@ -263,6 +263,8 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ...@@ -263,6 +263,8 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
} }
#endif #endif
out: out:
if (exp && !IS_ERR(exp))
exp_put(exp);
if (error == nfserr_stale) if (error == nfserr_stale)
nfsdstats.fh_stale++; nfsdstats.fh_stale++;
return error; return error;
...@@ -344,6 +346,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st ...@@ -344,6 +346,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
fhp->fh_dentry = dentry; /* our internal copy */ fhp->fh_dentry = dentry; /* our internal copy */
fhp->fh_export = exp; fhp->fh_export = exp;
cache_get(&exp->h);
if (ref_fh_version == 0xca) { if (ref_fh_version == 0xca) {
/* old style filehandle please */ /* old style filehandle please */
...@@ -442,6 +445,7 @@ void ...@@ -442,6 +445,7 @@ void
fh_put(struct svc_fh *fhp) fh_put(struct svc_fh *fhp)
{ {
struct dentry * dentry = fhp->fh_dentry; struct dentry * dentry = fhp->fh_dentry;
struct svc_export * exp = fhp->fh_export;
if (dentry) { if (dentry) {
fh_unlock(fhp); fh_unlock(fhp);
fhp->fh_dentry = NULL; fhp->fh_dentry = NULL;
...@@ -452,6 +456,10 @@ fh_put(struct svc_fh *fhp) ...@@ -452,6 +456,10 @@ fh_put(struct svc_fh *fhp)
#endif #endif
nfsd_nr_put++; nfsd_nr_put++;
} }
if (exp) {
svc_export_put(&exp->h, &svc_export_cache);
fhp->fh_export = NULL;
}
return; return;
} }
...@@ -135,6 +135,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, ...@@ -135,6 +135,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
dput(dentry); dput(dentry);
dentry = dget(dparent); dentry = dget(dparent);
} else { } else {
exp_put(exp);
exp = exp2; exp = exp2;
} }
mntput(mnt); mntput(mnt);
...@@ -157,11 +158,14 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, ...@@ -157,11 +158,14 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
exp2 = exp_get_by_name(exp->ex_client, mnt, mounts); exp2 = exp_get_by_name(exp->ex_client, mnt, mounts);
if (exp2 && EX_CROSSMNT(exp2)) { if (exp2 && EX_CROSSMNT(exp2)) {
/* successfully crossed mount point */ /* successfully crossed mount point */
exp_put(exp);
exp = exp2; exp = exp2;
dput(dentry); dput(dentry);
dentry = mounts; dentry = mounts;
} else } else {
if (exp2) exp_put(exp2);
dput(mounts); dput(mounts);
}
mntput(mnt); mntput(mnt);
} }
} }
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
struct svc_export { struct svc_export {
struct list_head ex_hash; struct cache_head h;
struct auth_domain * ex_client; struct auth_domain * ex_client;
int ex_flags; int ex_flags;
struct vfsmount * ex_mnt; struct vfsmount * ex_mnt;
...@@ -61,7 +61,7 @@ struct svc_export { ...@@ -61,7 +61,7 @@ struct svc_export {
* for type 0 (dev/ino), one for type 1 (fsid) * for type 0 (dev/ino), one for type 1 (fsid)
*/ */
struct svc_expkey { struct svc_expkey {
struct list_head ek_hash; struct cache_head h;
struct auth_domain * ek_client; struct auth_domain * ek_client;
int ek_fsidtype; int ek_fsidtype;
...@@ -98,14 +98,30 @@ int exp_rootfh(struct auth_domain *, ...@@ -98,14 +98,30 @@ int exp_rootfh(struct auth_domain *,
int exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp); int exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp);
int nfserrno(int errno); int nfserrno(int errno);
extern void expkey_put(struct cache_head *item, struct cache_detail *cd);
extern void svc_export_put(struct cache_head *item, struct cache_detail *cd);
extern struct cache_detail svc_export_cache, svc_expkey_cache;
static inline void exp_put(struct svc_export *exp)
{
svc_export_put(&exp->h, &svc_export_cache);
}
static inline struct svc_export * static inline struct svc_export *
exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv) exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv)
{ {
struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv); struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv);
if (ek) if (ek && !IS_ERR(ek)) {
return ek->ek_export; struct svc_export *exp = ek->ek_export;
else int err;
return NULL; cache_get(&exp->h);
expkey_put(&ek->h, &svc_expkey_cache);
if (exp &&
(err = cache_check(&svc_export_cache, &exp->h)))
exp = ERR_PTR(err);
return exp;
} else
return ERR_PTR(PTR_ERR(ek));
} }
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment