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