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,155 ****
   * 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
   * 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)
  {
          struct exportinfo *exi;
          struct exportdata *kex;
          fsid_t fsid;
          int vpathlen;
--- 140,155 ----
   * 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, 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)
  {
          struct exportinfo *exi;
          struct exportdata *kex;
          fsid_t fsid;
          int vpathlen;
*** 163,176 ****
          exi->exi_fid = *fid;
          exi->exi_vp = vp;
          VN_HOLD(exi->exi_vp);
          exi->exi_visible = vis_head;
          exi->exi_count = 1;
          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;
--- 163,176 ----
          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);
  
          /*
           * Build up the template fhandle
           */
          exi->exi_fh.fh_fsid = fsid;
*** 638,649 ****
          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();
  
          ASSERT(RW_WRITE_HELD(&ne->exported_lock));
  
          gethrestime(&now);
  
          vp = exip->exi_vp;
--- 638,651 ----
          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;
  
+         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,670 ****
                  fid.fid_len = MAXFIDSZ;
                  error = vop_fid_pseudo(vp, &fid);
                  if (error)
                          break;
  
                  /*
!                  * The root of the file system needs special handling
                   */
!                 if (vp->v_flag & VROOT) {
!                         if (! exportdir) {
                                  struct exportinfo *exi;
  
                                  /*
                                   * Check if this VROOT dir is already exported.
                                   * If so, then attach the pseudonodes.  If not,
--- 658,675 ----
                  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, or the zone's root for
!                  * in-zone NFS service needs special handling
                   */
!                 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,704 ****
                                  new_exi = pseudo_exportfs(ne, vp, &fid,
                                      vis_head, NULL);
                                  vis_head = NULL;
                          }
  
!                         if (VN_CMP(vp, ZONE_ROOTVP())) {
                                  /* at system root */
                                  /*
                                   * If sharing "/", new_exi is shared exportinfo
                                   * (exip). Otherwise, new_exi is exportinfo
                                   * created by pseudo_exportfs() above.
--- 699,709 ----
                                  new_exi = pseudo_exportfs(ne, vp, &fid,
                                      vis_head, NULL);
                                  vis_head = NULL;
                          }
  
!                         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,842 ****
   *
   * 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.
   */
  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));
  
          /*
           * exi_tree can be null for the zone root
           * which means we're already at the "top"
           * and there's nothing more to "climb".
--- 829,849 ----
   *
   * 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 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,867 ****
          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 */
                  if (TREE_ROOT(tnode) &&
                      (TREE_EXPORTED(tnode) || tnode->tree_child_first != NULL))
                          break;
  
                  /* Release pseudo export if it has no child */
--- 864,877 ----
          if (tnode->tree_vis != NULL) /* system root has tree_vis == NULL */
                  tnode->tree_vis->vis_exported = 0;
  
          while (tnode != NULL) {
  
!                 /*
!                  * 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,879 ****
--- 880,890 ----
                          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,915 ****
  
  /*
   * Traverse backward across mountpoint from the
   * root vnode of a filesystem to its mounted-on
   * vnode.
   */
  vnode_t *
  untraverse(vnode_t *vp)
  {
          vnode_t *tvp, *nextvp;
  
          tvp = vp;
          for (;;) {
!                 if (! (tvp->v_flag & VROOT))
                          break;
  
                  /* lock vfs to prevent unmount of this vfs */
                  vfs_lock_wait(tvp->v_vfsp);
  
--- 908,928 ----
  
  /*
   * 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) && !VN_IS_CURZONEROOT(tvp))
                          break;
  
                  /* lock vfs to prevent unmount of this vfs */
                  vfs_lock_wait(tvp->v_vfsp);
  
*** 936,946 ****
          return (tvp);
  }
  
  /*
   * Given an exportinfo, climb up to find the exportinfo for the VROOT
!  * of the filesystem.
   *
   * e.g.         /
   *              |
   *              a (VROOT) pseudo-exportinfo
   *              |
--- 949,959 ----
          return (tvp);
  }
  
  /*
   * Given an exportinfo, climb up to find the exportinfo for the VROOT
!  * (or zone root) of the filesystem.
   *
   * e.g.         /
   *              |
   *              a (VROOT) pseudo-exportinfo
   *              |
*** 953,963 ****
   * 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.
   */
  struct exportinfo *
  get_root_export(struct exportinfo *exip)
  {
          treenode_t *tnode = exip->exi_tree;
--- 966,976 ----
   * 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.  Returned exi does NOT have a new hold.
   */
  struct exportinfo *
  get_root_export(struct exportinfo *exip)
  {
          treenode_t *tnode = exip->exi_tree;
*** 985,1000 ****
          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.
           */
!         if (vp_is_exported && (vp->v_flag & VROOT))
                  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.
           */
--- 998,1016 ----
          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.
           */
!         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,1073 ****
  
          /*
           * Only a PSEUDO node has a visible list or an exported VROOT
           * node may have a visible list.
           */
!         if (! PSEUDO(exi))
                  exi = get_root_export(exi);
  
          /* Get the fid of the vnode */
  
          bzero(&fid, sizeof (fid));
--- 1079,1089 ----
  
          /*
           * Only a PSEUDO node has a visible list or an exported VROOT
           * node may have a visible list.
           */
!         if (!PSEUDO(exi))
                  exi = get_root_export(exi);
  
          /* Get the fid of the vnode */
  
          bzero(&fid, sizeof (fid));
*** 1171,1181 ****
  {
          /*
           * Only a PSEUDO node has a visible list or an exported VROOT
           * node may have a visible list.
           */
!         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);
--- 1187,1197 ----
  {
          /*
           * Only a PSEUDO node has a visible list or an exported VROOT
           * node may have a visible list.
           */
!         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);