Commit 03550fac authored by J. Bruce Fields's avatar J. Bruce Fields

nfsd: move most of fh_verify to separate function

Move the code that actually parses the filehandle and looks up the
dentry and export to a separate function.  This simplifies the reference
counting a little and moves fh_verify() a little closer to the kernel
ideal of small, minimally-indentended functions.  Clean up a few other
minor style sins along the way.
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
Cc: Neil Brown <neilb@suse.de>
parent c3bb257d
...@@ -113,28 +113,19 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp, ...@@ -113,28 +113,19 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
} }
/* /*
* Perform sanity checks on the dentry in a client's file handle. * Use the given filehandle to look up the corresponding export and
* * dentry. On success, the results are used to set fh_export and
* Note that the file handle dentry may need to be freed even after * fh_dentry.
* an error return.
*
* This is only called at the start of an nfsproc call, so fhp points to
* a svc_fh which is all 0 except for the over-the-wire file handle.
*/ */
__be32 static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
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 = NULL;
struct dentry *dentry;
__be32 error = 0;
dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
if (!fhp->fh_dentry) {
struct fid *fid = NULL, sfid; struct fid *fid = NULL, sfid;
struct svc_export *exp;
struct dentry *dentry;
int fileid_type; int fileid_type;
int data_left = fh->fh_size/4; int data_left = fh->fh_size/4;
__be32 error;
error = nfserr_stale; error = nfserr_stale;
if (rqstp->rq_vers > 2) if (rqstp->rq_vers > 2)
...@@ -144,13 +135,14 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ...@@ -144,13 +135,14 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
if (fh->fh_version == 1) { if (fh->fh_version == 1) {
int len; int len;
if (--data_left<0) goto out;
switch (fh->fh_auth_type) { if (--data_left < 0)
case 0: break; return error;
default: goto out; if (fh->fh_auth_type != 0)
} return error;
len = key_len(fh->fh_fsid_type) / 4; len = key_len(fh->fh_fsid_type) / 4;
if (len == 0) goto out; if (len == 0)
return error;
if (fh->fh_fsid_type == FSID_MAJOR_MINOR) { if (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
/* deprecated, convert to type 3 */ /* deprecated, convert to type 3 */
len = key_len(FSID_ENCODE_DEV)/4; len = key_len(FSID_ENCODE_DEV)/4;
...@@ -158,16 +150,18 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ...@@ -158,16 +150,18 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1]))); fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1])));
fh->fh_fsid[1] = fh->fh_fsid[2]; fh->fh_fsid[1] = fh->fh_fsid[2];
} }
if ((data_left -= len)<0) goto out; data_left -= len;
exp = rqst_exp_find(rqstp, fh->fh_fsid_type, if (data_left < 0)
fh->fh_auth); return error;
exp = rqst_exp_find(rqstp, fh->fh_fsid_type, fh->fh_auth);
fid = (struct fid *)(fh->fh_auth + len); fid = (struct fid *)(fh->fh_auth + len);
} else { } else {
__u32 tfh[2]; __u32 tfh[2];
dev_t xdev; dev_t xdev;
ino_t xino; ino_t xino;
if (fh->fh_size != NFS_FHSIZE) if (fh->fh_size != NFS_FHSIZE)
goto out; return error;
/* assume old filehandle format */ /* assume old filehandle format */
xdev = old_decode_dev(fh->ofh_xdev); xdev = old_decode_dev(fh->ofh_xdev);
xino = u32_to_ino_t(fh->ofh_xino); xino = u32_to_ino_t(fh->ofh_xino);
...@@ -177,12 +171,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ...@@ -177,12 +171,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
error = nfserr_stale; error = nfserr_stale;
if (PTR_ERR(exp) == -ENOENT) if (PTR_ERR(exp) == -ENOENT)
goto out; return error;
if (IS_ERR(exp)) { if (IS_ERR(exp))
error = nfserrno(PTR_ERR(exp)); return nfserrno(PTR_ERR(exp));
goto out;
}
error = nfsd_setuser_and_check_port(rqstp, exp); error = nfsd_setuser_and_check_port(rqstp, exp);
if (error) if (error)
...@@ -232,7 +224,36 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ...@@ -232,7 +224,36 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
fhp->fh_dentry = dentry; fhp->fh_dentry = dentry;
fhp->fh_export = exp; fhp->fh_export = exp;
nfsd_nr_verified++; nfsd_nr_verified++;
cache_get(&exp->h); return 0;
out:
exp_put(exp);
return error;
}
/*
* Perform sanity checks on the dentry in a client's file handle.
*
* Note that the file handle dentry may need to be freed even after
* an error return.
*
* This is only called at the start of an nfsproc call, so fhp points to
* a svc_fh which is all 0 except for the over-the-wire file handle.
*/
__be32
fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
{
struct svc_export *exp;
struct dentry *dentry;
__be32 error;
dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
if (!fhp->fh_dentry) {
error = nfsd_set_fh_dentry(rqstp, fhp);
if (error)
goto out;
dentry = fhp->fh_dentry;
exp = fhp->fh_export;
} else { } else {
/* /*
* just rechecking permissions * just rechecking permissions
...@@ -242,7 +263,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ...@@ -242,7 +263,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
dprintk("nfsd: fh_verify - just checking\n"); dprintk("nfsd: fh_verify - just checking\n");
dentry = fhp->fh_dentry; dentry = fhp->fh_dentry;
exp = fhp->fh_export; exp = fhp->fh_export;
cache_get(&exp->h);
/* /*
* Set user creds for this exportpoint; necessary even * Set user creds for this exportpoint; necessary even
* in the "just checking" case because this may be a * in the "just checking" case because this may be a
...@@ -281,8 +301,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ...@@ -281,8 +301,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
access, ntohl(error)); access, ntohl(error));
} }
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;
......
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