Print this page
*** NO COMMENTS ***
*** 324,333 ****
--- 324,378 ----
rfs_setattr_getfh(struct nfssaargs *args)
{
return (&args->saa_fh);
}
+ /* Change and release @exip and @vpp only in success */
+ int
+ rfs_cross_mnt(vnode_t **vpp, struct exportinfo **exip)
+ {
+ struct exportinfo *exi;
+ vnode_t *vp;
+ fid_t fid;
+ int error;
+
+ vp = *vpp;
+
+ /* traverse() releases argument in success */
+ VN_HOLD(*vpp);
+
+ if ((error = traverse(&vp)) != 0) {
+ VN_RELE(*vpp);
+ return (error);
+ }
+
+ bzero(&fid, sizeof (fid));
+ fid.fid_len = MAXFIDSZ;
+ error = VOP_FID(vp, &fid, NULL);
+ if (error) {
+ VN_RELE(vp);
+ return (error);
+ }
+
+ exi = checkexport(&vp->v_vfsp->vfs_fsid, &fid);
+ if (exi == NULL ||
+ (exi->exi_export.ex_flags & EX_NOHIDE) == 0) {
+ /* It is not error, just subdir is not exported
+ * or "nohide" is not set
+ */
+ VN_RELE(vp);
+ } else {
+ /* go to submount */
+ exi_rele(*exip);
+ *exip = exi;
+
+ VN_RELE(*vpp);
+ *vpp = vp;
+ }
+ return (0);
+ }
+
/*
* Directory lookup.
* Returns an fhandle and file attributes for file name in a directory.
*/
/* ARGSUSED */
*** 397,419 ****
if (name == NULL) {
dr->dr_status = NFSERR_ACCES;
return;
}
/*
* If the public filehandle is used then allow
* a multi-component lookup, i.e. evaluate
* a pathname and follow symbolic links if
* necessary.
*
* This may result in a vnode in another filesystem
* which is OK as long as the filesystem is exported.
*/
if (PUBLIC_FH2(fhp)) {
publicfh_flag = TRUE;
! error = rfs_publicfh_mclookup(name, dvp, cr, &vp, &exi,
&sec);
} else {
/*
* Do a normal single component lookup.
*/
error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr,
--- 442,473 ----
if (name == NULL) {
dr->dr_status = NFSERR_ACCES;
return;
}
+ exi_hold(exi);
+
/*
* If the public filehandle is used then allow
* a multi-component lookup, i.e. evaluate
* a pathname and follow symbolic links if
* necessary.
*
* This may result in a vnode in another filesystem
* which is OK as long as the filesystem is exported.
*/
if (PUBLIC_FH2(fhp)) {
+ struct exportinfo *new;
+
publicfh_flag = TRUE;
! error = rfs_publicfh_mclookup(name, dvp, cr, &vp, &new,
&sec);
+
+ if (error == 0) {
+ exi_rele(exi);
+ exi = new;
+ }
} else {
/*
* Do a normal single component lookup.
*/
error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr,
*** 421,430 ****
--- 475,489 ----
}
if (name != da->da_name)
kmem_free(name, MAXPATHLEN);
+ if (error == 0 && vn_ismntpt(vp)) {
+ error = rfs_cross_mnt(&vp, &exi);
+ if (error)
+ VN_RELE(vp);
+ }
if (!error) {
va.va_mask = AT_ALL; /* we want everything */
error = rfs4_delegated_getattr(vp, &va, 0, cr);
*** 449,465 ****
VN_RELE(vp);
}
VN_RELE(dvp);
! /*
! * If publicfh_flag is true then we have called rfs_publicfh_mclookup
! * and have obtained a new exportinfo in exi which needs to be
! * released. Note the the original exportinfo pointed to by exi
! * will be released by the caller, comon_dispatch.
*/
- if (publicfh_flag && exi != NULL)
exi_rele(exi);
/*
* If it's public fh, no 0x81, and client's flavor is
* invalid, set WebNFS status to WNFSERR_CLNT_FLAVOR now.
--- 508,520 ----
VN_RELE(vp);
}
VN_RELE(dvp);
! /* The passed argument exportinfo is released by the
! * caller, comon_dispatch
*/
exi_rele(exi);
/*
* If it's public fh, no 0x81, and client's flavor is
* invalid, set WebNFS status to WNFSERR_CLNT_FLAVOR now.