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.