Commit 981d3487 authored by Neil Brown's avatar Neil Brown Committed by David S. Miller

[PATCH] kNFSd 14: Filehandle lookup makes use of new export table structure.

Filehandle lookup currently breaks out the interesting pieces of
a filehandle and passes them to exp_get or exp_get_fsid, which put the
pieces back into a filehandle fragment.

We define a new interface "exp_find" which does a lookup based on
a filehandle fragment to avoid this double handling.

In the process, common code in exp_get_key and exp_get_fsid_key is united
into exp_find_key.

Also, filehandle composition now uses the mk_fsid_v? inline functions.
parent 6d0f7b03
...@@ -88,32 +88,39 @@ static int export_hash(svc_client *clp, struct dentry *dentry) ...@@ -88,32 +88,39 @@ static int export_hash(svc_client *clp, struct dentry *dentry)
return rv & EXPORT_HASHMASK; return rv & EXPORT_HASHMASK;
} }
/*
* Find the client's export entry matching xdev/xino.
*/
struct svc_expkey * struct svc_expkey *
exp_get_key(svc_client *clp, dev_t dev, ino_t ino) exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv)
{ {
struct list_head *head; struct list_head *head;
struct svc_expkey *ek; struct svc_expkey *ek;
u32 fsidv[2];
if (!clp) if (!clp)
return NULL; return NULL;
mk_fsid_v0(fsidv, dev, ino); head = &clp->cl_export[expkey_hash(fsid_type, fsidv)];
head = &clp->cl_export[expkey_hash(0, fsidv)];
list_for_each_entry(ek, head, ek_hash) list_for_each_entry(ek, head, ek_hash)
if (ek->ek_fsidtype == 0 && if (ek->ek_fsidtype == fsid_type &&
fsidv[0] == ek->ek_fsid[0] && fsidv[0] == ek->ek_fsid[0] &&
fsidv[1] == ek->ek_fsid[1] && (fsid_type == 1 || fsidv[1] == ek->ek_fsid[1]) &&
clp == ek->ek_client) clp == ek->ek_client)
return ek; return ek;
return NULL; return NULL;
} }
inline svc_export *
/*
* Find the client's export entry matching xdev/xino.
*/
static inline struct svc_expkey *
exp_get_key(svc_client *clp, dev_t dev, ino_t ino)
{
u32 fsidv[2];
mk_fsid_v0(fsidv, dev, ino);
return exp_find_key(clp, 0, fsidv);
}
static inline svc_export *
exp_get(svc_client *clp, dev_t dev, ino_t ino) exp_get(svc_client *clp, dev_t dev, ino_t ino)
{ {
struct svc_expkey *ek; struct svc_expkey *ek;
...@@ -128,28 +135,17 @@ exp_get(svc_client *clp, dev_t dev, ino_t ino) ...@@ -128,28 +135,17 @@ exp_get(svc_client *clp, dev_t dev, ino_t ino)
/* /*
* Find the client's export entry matching fsid * Find the client's export entry matching fsid
*/ */
struct svc_expkey * static inline struct svc_expkey *
exp_get_fsid_key(svc_client *clp, int fsid) exp_get_fsid_key(svc_client *clp, int fsid)
{ {
struct list_head *head;
struct svc_expkey *ek;
u32 fsidv[2]; u32 fsidv[2];
if (!clp)
return NULL;
mk_fsid_v1(fsidv, fsid); mk_fsid_v1(fsidv, fsid);
head = &clp->cl_export[expkey_hash(1, fsidv)]; return exp_find_key(clp, 1, fsidv);
list_for_each_entry(ek, head, ek_hash) {
if (ek->ek_fsidtype == 1 &&
fsidv[0] == ek->ek_fsid[0] &&
clp == ek->ek_client)
return ek;
}
return NULL;
} }
inline svc_export *
static inline svc_export *
exp_get_fsid(svc_client *clp, int fsid) exp_get_fsid(svc_client *clp, int fsid)
{ {
struct svc_expkey *ek; struct svc_expkey *ek;
......
...@@ -97,14 +97,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ...@@ -97,14 +97,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
rqstp->rq_reffh = fh; rqstp->rq_reffh = fh;
if (!fhp->fh_dentry) { if (!fhp->fh_dentry) {
dev_t xdev = 0;
ino_t xino = 0;
__u32 *datap=NULL; __u32 *datap=NULL;
__u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */ __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */
int fileid_type; int fileid_type;
int data_left = fh->fh_size/4; int data_left = fh->fh_size/4;
int nfsdev;
int fsid = 0;
error = nfserr_stale; error = nfserr_stale;
if (rqstp->rq_vers > 2) if (rqstp->rq_vers > 2)
...@@ -113,6 +109,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ...@@ -113,6 +109,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
return nfserr_nofilehandle; return nfserr_nofilehandle;
if (fh->fh_version == 1) { if (fh->fh_version == 1) {
int len;
datap = fh->fh_auth; datap = fh->fh_auth;
if (--data_left<0) goto out; if (--data_left<0) goto out;
switch (fh->fh_auth_type) { switch (fh->fh_auth_type) {
...@@ -122,39 +119,37 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ...@@ -122,39 +119,37 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
switch (fh->fh_fsid_type) { switch (fh->fh_fsid_type) {
case 0: case 0:
if ((data_left-=2)<0) goto out; len = 2;
nfsdev = ntohl(*datap++);
xdev = MKDEV(nfsdev>>16, nfsdev&0xFFFF);
xino = *datap++;
break; break;
case 1: case 1:
if ((data_left-=1)<0) goto out; len = 1;
fsid = *datap++;
break; break;
default: default:
goto out; goto out;
} }
if ((data_left -= len)<0) goto out;
exp = exp_find(rqstp->rq_client, fh->fh_fsid_type, datap);
datap += len;
} else { } else {
dev_t xdev;
ino_t xino;
if (fh->fh_size != NFS_FHSIZE) if (fh->fh_size != NFS_FHSIZE)
goto out; goto out;
/* assume old filehandle format */ /* assume old filehandle format */
xdev = u32_to_dev_t(fh->ofh_xdev); xdev = u32_to_dev_t(fh->ofh_xdev);
xino = u32_to_ino_t(fh->ofh_xino); xino = u32_to_ino_t(fh->ofh_xino);
mk_fsid_v0(tfh, xdev, xino);
exp = exp_find(rqstp->rq_client, 0, tfh);
} }
/* /*
* Look up the export entry. * Look up the export entry.
*/ */
error = nfserr_stale; error = nfserr_stale;
if (fh->fh_version == 1 && fh->fh_fsid_type == 1)
exp = exp_get_fsid(rqstp->rq_client, fsid);
else
exp = exp_get(rqstp->rq_client, xdev, xino);
if (!exp) { if (!exp)
/* export entry revoked */ /* 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. */
error = nfserr_perm; error = nfserr_perm;
...@@ -367,13 +362,14 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st ...@@ -367,13 +362,14 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
(ref_fh_fsid_type == 1)) { (ref_fh_fsid_type == 1)) {
fhp->fh_handle.fh_fsid_type = 1; fhp->fh_handle.fh_fsid_type = 1;
/* fsid_type 1 == 4 bytes filesystem id */ /* fsid_type 1 == 4 bytes filesystem id */
*datap++ = exp->ex_fsid; mk_fsid_v1(datap, exp->ex_fsid);
datap += 1;
fhp->fh_handle.fh_size = 2*4; fhp->fh_handle.fh_size = 2*4;
} else { } else {
fhp->fh_handle.fh_fsid_type = 0; fhp->fh_handle.fh_fsid_type = 0;
/* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */ /* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */
*datap++ = htonl((MAJOR(ex_dev)<<16)| MINOR(ex_dev)); mk_fsid_v0(datap, ex_dev, exp->ex_dentry->d_inode->i_ino);
*datap++ = ino_t_to_u32(exp->ex_dentry->d_inode->i_ino); datap += 2;
fhp->fh_handle.fh_size = 3*4; fhp->fh_handle.fh_size = 3*4;
} }
if (inode) { if (inode) {
......
...@@ -98,8 +98,7 @@ void exp_readlock(void); ...@@ -98,8 +98,7 @@ void exp_readlock(void);
void exp_readunlock(void); void exp_readunlock(void);
struct svc_client * exp_getclient(struct sockaddr_in *sin); struct svc_client * exp_getclient(struct sockaddr_in *sin);
void exp_putclient(struct svc_client *clp); void exp_putclient(struct svc_client *clp);
struct svc_export * exp_get(struct svc_client *clp, dev_t dev, ino_t ino); struct svc_expkey * exp_find_key(struct svc_client *clp, int fsid_type, u32 *fsidv);
struct svc_export * exp_get_fsid(struct svc_client *clp, int fsid);
struct svc_export * exp_get_by_name(struct svc_client *clp, struct svc_export * exp_get_by_name(struct svc_client *clp,
struct vfsmount *mnt, struct vfsmount *mnt,
struct dentry *dentry); struct dentry *dentry);
...@@ -109,6 +108,15 @@ int exp_rootfh(struct svc_client *, ...@@ -109,6 +108,15 @@ int exp_rootfh(struct svc_client *,
char *path, struct knfsd_fh *, int maxsize); char *path, struct knfsd_fh *, int maxsize);
int nfserrno(int errno); int nfserrno(int errno);
static inline struct svc_export *
exp_find(struct svc_client *clp, int fsid_type, u32 *fsidv)
{
struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv);
if (ek)
return ek->ek_export;
else
return NULL;
}
#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