Print this page
Revert exi_zone to exi_zoneid, and install exi_ne backpointer
Caution with use after exi_rele()
Ooops exi_zoneid isn't a variable again yet
Be far more judicious in the use of curzone-using macros.
(Merge and extra asserts by danmcd.)
curzone reality check and teardown changes to use the RIGHT zone
Try to remove assumption that zone's root vnode is marked VROOT
        
@@ -140,16 +140,16 @@
  * directories is added to filter lookup and readdir results
  * to only contain dirnames which lead to descendant shares.
  *
  * A visible list has a per-file-system scope.  Any exportinfo
  * struct (real or pseudo) can have a visible list as long as
- * a) its export root is VROOT
+ * a) its export root is VROOT, or is the zone's root for in-zone NFS service
  * b) a descendant of the export root is shared
  */
 struct exportinfo *
-pseudo_exportfs(nfs_export_t *ne, vnode_t *vp, fid_t *fid, struct exp_visible *vis_head,
-    struct exportdata *exdata)
+pseudo_exportfs(nfs_export_t *ne, vnode_t *vp, fid_t *fid,
+    struct exp_visible *vis_head, struct exportdata *exdata)
 {
         struct exportinfo *exi;
         struct exportdata *kex;
         fsid_t fsid;
         int vpathlen;
@@ -163,14 +163,14 @@
         exi->exi_fid = *fid;
         exi->exi_vp = vp;
         VN_HOLD(exi->exi_vp);
         exi->exi_visible = vis_head;
         exi->exi_count = 1;
+        exi->exi_zoneid = ne->ne_globals->nfs_zoneid;
         exi->exi_volatile_dev = (vfssw[vp->v_vfsp->vfs_fstype].vsw_flag &
             VSW_VOLATILEDEV) ? 1 : 0;
         mutex_init(&exi->exi_lock, NULL, MUTEX_DEFAULT, NULL);
-        exi->exi_zoneid = ne->ne_globals->nfs_zoneid;
 
         /*
          * Build up the template fhandle
          */
         exi->exi_fh.fh_fsid = fsid;
@@ -638,12 +638,14 @@
         struct exp_visible *visp;
         struct exp_visible *vis_head = NULL;
         struct vattr va;
         treenode_t *tree_head = NULL;
         timespec_t now;
-        nfs_export_t *ne = nfs_get_export();
+        nfs_export_t *ne;
 
+        ne = exip->exi_ne;
+        ASSERT3P(ne, ==, nfs_get_export());     /* curzone reality check */
         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
 
         gethrestime(&now);
 
         vp = exip->exi_vp;
@@ -656,15 +658,18 @@
                 fid.fid_len = MAXFIDSZ;
                 error = vop_fid_pseudo(vp, &fid);
                 if (error)
                         break;
 
+                /* XXX KEBE ASKS DO WE NEED THIS?!? */
+                ASSERT3U(exip->exi_zoneid, ==, curzone->zone_id);
                 /*
-                 * The root of the file system needs special handling
+                 * The root of the file system, or the zone's root for
+                 * in-zone NFS service needs special handling
                  */
-                if (vp->v_flag & VROOT) {
-                        if (! exportdir) {
+                if (vp->v_flag & VROOT || vp == EXI_TO_ZONEROOTVP(exip)) {
+                        if (!exportdir) {
                                 struct exportinfo *exi;
 
                                 /*
                                  * Check if this VROOT dir is already exported.
                                  * If so, then attach the pseudonodes.  If not,
@@ -694,11 +699,11 @@
                                 new_exi = pseudo_exportfs(ne, vp, &fid,
                                     vis_head, NULL);
                                 vis_head = NULL;
                         }
 
-                        if (VN_CMP(vp, ZONE_ROOTVP())) {
+                        if (VN_IS_CURZONEROOT(vp)) {
                                 /* at system root */
                                 /*
                                  * If sharing "/", new_exi is shared exportinfo
                                  * (exip). Otherwise, new_exi is exportinfo
                                  * created by pseudo_exportfs() above.
@@ -824,19 +829,21 @@
  *
  * Deleting of nodes will start only if the unshared
  * node was a leaf node.
  * Deleting of nodes will finish when we reach a node which
  * has children or is a real export, then we might still need
- * to continue releasing visibles, until we reach VROOT node.
+ * to continue releasing visibles, until we reach VROOT or zone's root node.
  */
 void
 treeclimb_unexport(nfs_export_t *ne, struct exportinfo *exip)
 {
         treenode_t *tnode, *old_nd;
         treenode_t *connect_point = NULL;
 
         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
+        ASSERT(curzone->zone_id == exip->exi_zoneid ||
+            curzone->zone_id == global_zone->zone_id);
 
         /*
          * exi_tree can be null for the zone root
          * which means we're already at the "top"
          * and there's nothing more to "climb".
@@ -857,11 +864,14 @@
         if (tnode->tree_vis != NULL) /* system root has tree_vis == NULL */
                 tnode->tree_vis->vis_exported = 0;
 
         while (tnode != NULL) {
 
-                /* Stop at VROOT node which is exported or has child */
+                /*
+                 * Stop at VROOT (or zone root) node which is exported or has
+                 * child.
+                 */
                 if (TREE_ROOT(tnode) &&
                     (TREE_EXPORTED(tnode) || tnode->tree_child_first != NULL))
                         break;
 
                 /* Release pseudo export if it has no child */
@@ -870,10 +880,11 @@
                         mutex_enter(&nfs_exi_id_lock);
                         avl_remove(&exi_id_tree, tnode->tree_exi);
                         mutex_exit(&nfs_exi_id_lock);
                         export_unlink(ne, tnode->tree_exi);
                         exi_rele(tnode->tree_exi);
+                        tnode->tree_exi = NULL;
                 }
 
                 /* Release visible in parent's exportinfo */
                 if (tnode->tree_vis != NULL)
                         less_visible(vis2exi(tnode), tnode->tree_vis);
@@ -897,19 +908,21 @@
 
 /*
  * Traverse backward across mountpoint from the
  * root vnode of a filesystem to its mounted-on
  * vnode.
+ *
+ * Callers to this function have confirmed the use of curzone is safe here.
  */
 vnode_t *
 untraverse(vnode_t *vp)
 {
         vnode_t *tvp, *nextvp;
 
         tvp = vp;
         for (;;) {
-                if (! (tvp->v_flag & VROOT))
+                if (!(tvp->v_flag & VROOT) && !VN_IS_CURZONEROOT(tvp))
                         break;
 
                 /* lock vfs to prevent unmount of this vfs */
                 vfs_lock_wait(tvp->v_vfsp);
 
@@ -936,11 +949,11 @@
         return (tvp);
 }
 
 /*
  * Given an exportinfo, climb up to find the exportinfo for the VROOT
- * of the filesystem.
+ * (or zone root) of the filesystem.
  *
  * e.g.         /
  *              |
  *              a (VROOT) pseudo-exportinfo
  *              |
@@ -953,11 +966,11 @@
  * where c is in the same filesystem as a.
  * So, get_root_export(*exportinfo_for_c) returns exportinfo_for_a
  *
  * If d is shared, then c will be put into a's visible list.
  * Note: visible list is per filesystem and is attached to the
- * VROOT exportinfo.
+ * VROOT exportinfo.  Returned exi does NOT have a new hold.
  */
 struct exportinfo *
 get_root_export(struct exportinfo *exip)
 {
         treenode_t *tnode = exip->exi_tree;
@@ -985,16 +998,19 @@
         bool_t vp_is_exported;
 
         vp_is_exported = VN_CMP(vp, exi->exi_vp);
 
         /*
-         * An exported root vnode has a sub-dir shared if it has a visible list.
-         * i.e. if it does not have a visible list, then there is no node in
-         * this filesystem leads to any other shared node.
+         * An exported root vnode has a sub-dir shared if it has a visible
+         * list.  i.e. if it does not have a visible list, then there is no
+         * node in this filesystem leads to any other shared node.
          */
-        if (vp_is_exported && (vp->v_flag & VROOT))
+        ASSERT3P(curzone->zone_id, ==, exi->exi_zoneid);
+        if (vp_is_exported &&
+            ((vp->v_flag & VROOT) || VN_IS_CURZONEROOT(vp))) {
                 return (exi->exi_visible ? 1 : 0);
+        }
 
         /*
          * Only the exportinfo of a fs root node may have a visible list.
          * Either it is a pseudo root node, or a real exported root node.
          */
@@ -1063,11 +1079,11 @@
 
         /*
          * Only a PSEUDO node has a visible list or an exported VROOT
          * node may have a visible list.
          */
-        if (! PSEUDO(exi))
+        if (!PSEUDO(exi))
                 exi = get_root_export(exi);
 
         /* Get the fid of the vnode */
 
         bzero(&fid, sizeof (fid));
@@ -1171,11 +1187,11 @@
 {
         /*
          * Only a PSEUDO node has a visible list or an exported VROOT
          * node may have a visible list.
          */
-        if (! PSEUDO(exi))
+        if (!PSEUDO(exi))
                 exi = get_root_export(exi);
 
         for (*visp = exi->exi_visible; *visp != NULL; *visp = (*visp)->vis_next)
                 if ((u_longlong_t)ino == (*visp)->vis_ino) {
                         return (1);