while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts));
- exp2 = exp_get_by_name(exp->ex_client, mnt, mounts, &rqstp->rq_chandle);
+ exp2 = rqst_exp_get_by_name(rqstp, mnt, mounts);
if (IS_ERR(exp2)) {
err = PTR_ERR(exp2);
dput(mounts);
return err;
}
-/*
- * Look up one component of a pathname.
- * N.B. After this call _both_ fhp and resfh need an fh_put
- *
- * If the lookup would cross a mountpoint, and the mounted filesystem
- * is exported to the client with NFSEXP_NOHIDE, then the lookup is
- * accepted as it stands and the mounted directory is
- * returned. Otherwise the covered directory is returned.
- * NOTE: this mountpoint crossing is not supported properly by all
- * clients and is explicitly disallowed for NFSv3
- * NeilBrown <neilb@cse.unsw.edu.au>
- */
__be32
-nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
- int len, struct svc_fh *resfh)
+nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ const char *name, int len,
+ struct svc_export **exp_ret, struct dentry **dentry_ret)
{
struct svc_export *exp;
struct dentry *dparent;
exp = fhp->fh_export;
exp_get(exp);
- err = nfserr_acces;
-
/* Lookup the name, but don't follow links */
if (isdotent(name, len)) {
if (len==1)
dput(dentry);
dentry = dp;
- exp2 = exp_parent(exp->ex_client, mnt, dentry,
- &rqstp->rq_chandle);
- if (IS_ERR(exp2)) {
+ exp2 = rqst_exp_parent(rqstp, mnt, dentry);
+ if (PTR_ERR(exp2) == -ENOENT) {
+ dput(dentry);
+ dentry = dget(dparent);
+ } else if (IS_ERR(exp2)) {
host_err = PTR_ERR(exp2);
dput(dentry);
mntput(mnt);
goto out_nfserr;
- }
- if (!exp2) {
- dput(dentry);
- dentry = dget(dparent);
} else {
exp_put(exp);
exp = exp2;
}
}
}
+ *dentry_ret = dentry;
+ *exp_ret = exp;
+ return 0;
+
+out_nfserr:
+ exp_put(exp);
+ return nfserrno(host_err);
+}
+
+/*
+ * Look up one component of a pathname.
+ * N.B. After this call _both_ fhp and resfh need an fh_put
+ *
+ * If the lookup would cross a mountpoint, and the mounted filesystem
+ * is exported to the client with NFSEXP_NOHIDE, then the lookup is
+ * accepted as it stands and the mounted directory is
+ * returned. Otherwise the covered directory is returned.
+ * NOTE: this mountpoint crossing is not supported properly by all
+ * clients and is explicitly disallowed for NFSv3
+ * NeilBrown <neilb@cse.unsw.edu.au>
+ */
+__be32
+nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
+ int len, struct svc_fh *resfh)
+{
+ struct svc_export *exp;
+ struct dentry *dentry;
+ __be32 err;
+
+ err = nfsd_lookup_dentry(rqstp, fhp, name, len, &exp, &dentry);
+ if (err)
+ return err;
/*
* Note: we compose the file handle now, but as the
* dentry may be negative, it may need to be updated.
if (!err && !dentry->d_inode)
err = nfserr_noent;
dput(dentry);
-out:
exp_put(exp);
return err;
-
-out_nfserr:
- err = nfserrno(host_err);
- goto out;
}
+
/*
* Set various file attributes.
* N.B. After this call fhp needs an fh_put
/* Get inode */
error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, MAY_SATTR);
if (error)
- goto out;
+ return error;
dentry = fhp->fh_dentry;
inode = dentry->d_inode;
host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
if (host_error == -EINVAL) {
- error = nfserr_attrnotsupp;
- goto out;
+ return nfserr_attrnotsupp;
} else if (host_error < 0)
goto out_nfserr;
host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
if (host_error < 0)
- goto out_nfserr;
+ goto out_release;
- if (S_ISDIR(inode->i_mode)) {
+ if (S_ISDIR(inode->i_mode))
host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
- if (host_error < 0)
- goto out_nfserr;
- }
-
- error = nfs_ok;
-out:
+out_release:
posix_acl_release(pacl);
posix_acl_release(dpacl);
- return (error);
out_nfserr:
if (host_error == -EOPNOTSUPP)
- error = nfserr_attrnotsupp;
+ return nfserr_attrnotsupp;
else
- error = nfserrno(host_error);
- goto out;
+ return nfserrno(host_error);
}
static struct posix_acl *
.u.data = rqstp,
};
+ rqstp->rq_resused = 1;
host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor);
} else {
oldfs = get_fs();