Commit 41a0466f authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] nfsd: separate a little of logic from fh_verify into new function

Separate out the little bit of logic in fh_verify that checks the i_mode into
a separate function.  This is nicely encapsulated, fh_verify() is overly long
anyway, and this change helps make a subsequent nfs4 named attribute change
clearer.
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: default avatarNeil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent cfc88944
...@@ -71,6 +71,35 @@ int nfsd_acceptable(void *expv, struct dentry *dentry) ...@@ -71,6 +71,35 @@ int nfsd_acceptable(void *expv, struct dentry *dentry)
return rv; return rv;
} }
/* Type check. The correct error return for type mismatches does not seem to be
* generally agreed upon. SunOS seems to use EISDIR if file isn't S_IFREG; a
* comment in the NFSv3 spec says this is incorrect (implementation notes for
* the write call).
*/
static inline int
nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, int type)
{
/* Type can be negative when creating hardlinks - not to a dir */
if (type > 0 && (mode & S_IFMT) != type) {
if (rqstp->rq_vers == 4 && (mode & S_IFMT) == S_IFLNK)
return nfserr_symlink;
else if (type == S_IFDIR)
return nfserr_notdir;
else if ((mode & S_IFMT) == S_IFDIR)
return nfserr_isdir;
else
return nfserr_inval;
}
if (type < 0 && (mode & S_IFMT) == -type) {
if (rqstp->rq_vers == 4 && (mode & S_IFMT) == S_IFLNK)
return nfserr_symlink;
else if (type == -S_IFDIR)
return nfserr_isdir;
else
return nfserr_notdir;
}
return 0;
}
/* /*
* Perform sanity checks on the dentry in a client's file handle. * Perform sanity checks on the dentry in a client's file handle.
...@@ -87,7 +116,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ...@@ -87,7 +116,6 @@ 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 svc_export *exp = NULL;
struct dentry *dentry; struct dentry *dentry;
struct inode *inode;
u32 error = 0; u32 error = 0;
dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
...@@ -223,37 +251,9 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ...@@ -223,37 +251,9 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
} }
cache_get(&exp->h); cache_get(&exp->h);
inode = dentry->d_inode; error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type);
if (error)
/* Type check. The correct error return for type mismatches
* does not seem to be generally agreed upon. SunOS seems to
* use EISDIR if file isn't S_IFREG; a comment in the NFSv3
* spec says this is incorrect (implementation notes for the
* write call).
*/
/* Type can be negative when creating hardlinks - not to a dir */
if (type > 0 && (inode->i_mode & S_IFMT) != type) {
if (rqstp->rq_vers == 4 && (inode->i_mode & S_IFMT) == S_IFLNK)
error = nfserr_symlink;
else if (type == S_IFDIR)
error = nfserr_notdir;
else if ((inode->i_mode & S_IFMT) == S_IFDIR)
error = nfserr_isdir;
else
error = nfserr_inval;
goto out; goto out;
}
if (type < 0 && (inode->i_mode & S_IFMT) == -type) {
if (rqstp->rq_vers == 4 && (inode->i_mode & S_IFMT) == S_IFLNK)
error = nfserr_symlink;
else if (type == -S_IFDIR)
error = nfserr_isdir;
else
error = nfserr_notdir;
goto out;
}
/* Finally, check access permissions. */ /* Finally, check access permissions. */
error = nfsd_permission(exp, dentry, access); error = nfsd_permission(exp, dentry, access);
......
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