Beispiel #1
0
/*
 * Walk up the tree and:
 * 1. release pseudo exportinfo if it has no child
 * 2. release visible in parent's exportinfo
 * 3. delete non-exported leaf nodes from tree
 *
 * 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(struct exportinfo *exip)
{
	treenode_t *tnode, *old_nd;
	treenode_t *connect_point = NULL;

	ASSERT(RW_WRITE_HELD(&exported_lock));

	tnode = exip->exi_tree;
	/*
	 * The unshared exportinfo was unlinked in unexport().
	 * Zeroing tree_exi ensures that we will skip it.
	 */
	tnode->tree_exi = NULL;

	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 */
		if (TREE_ROOT(tnode) && !TREE_EXPORTED(tnode) &&
		    tnode->tree_child_first == NULL) {
			export_unlink(tnode->tree_exi);
			exi_rele(tnode->tree_exi);
		}

		/* Release visible in parent's exportinfo */
		if (tnode->tree_vis != NULL)
			less_visible(vis2exi(tnode), tnode->tree_vis);

		/* Continue with parent */
		old_nd = tnode;
		tnode = tnode->tree_parent;

		/* Remove itself, if this is a leaf and non-exported node */
		if (old_nd->tree_child_first == NULL &&
		    !TREE_EXPORTED(old_nd)) {
			tree_remove_node(old_nd);
			connect_point = tnode;
		}
	}

	/* Update the change timestamp */
	if (connect_point != NULL)
		tree_update_change(connect_point, NULL);
}
Beispiel #2
0
/*
 * Given an exportinfo, climb up to find the exportinfo for the VROOT
 * of the filesystem.
 *
 * e.g.         /
 *              |
 *              a (VROOT) pseudo-exportinfo
 *		|
 *		b
 *		|
 *		c  #share /a/b/c
 *		|
 *		d
 *
 * 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;
	exportinfo_t *exi = NULL;

	while (tnode) {
		if (TREE_ROOT(tnode)) {
			exi = tnode->tree_exi;
			break;
		}
		tnode = tnode->tree_parent;
	}
	ASSERT(exi);
	return (exi);
}