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);