Print this page
*** NO COMMENTS ***
@@ -324,10 +324,55 @@
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,23 +442,32 @@
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, &exi,
+ 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,10 +475,15 @@
}
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,17 +508,13 @@
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.
+ /* The passed argument exportinfo is 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.