diff options
author | Pavel Filipensky <Pavel.Filipensky@Sun.COM> | 2010-02-28 14:10:13 +0000 |
---|---|---|
committer | Pavel Filipensky <Pavel.Filipensky@Sun.COM> | 2010-02-28 14:10:13 +0000 |
commit | 3f2383012abdf005e860f5afa06cb2e0044a424f (patch) | |
tree | 71c69c62fec067b9c94c91dce252deb378fbb44d /usr | |
parent | ea1b934f6e05788b68ee3d5f5d2c6c35683854db (diff) | |
download | illumos-gate-3f2383012abdf005e860f5afa06cb2e0044a424f.tar.gz |
6901748 mvfs and nfs pseudo namespace tree do not work together
6926015 dead code in exportfs()
Diffstat (limited to 'usr')
-rw-r--r-- | usr/src/uts/common/fs/nfs/nfs4_srv_ns.c | 142 | ||||
-rw-r--r-- | usr/src/uts/common/fs/nfs/nfs_export.c | 16 | ||||
-rw-r--r-- | usr/src/uts/common/nfs/export.h | 23 |
3 files changed, 91 insertions, 90 deletions
diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c b/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c index 40ef94e16b..922c24a260 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c +++ b/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c @@ -18,7 +18,7 @@ * * CDDL HEADER END * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -270,7 +270,6 @@ tree_prepend_node(treenode_t *n, exp_visible_t *v, exportinfo_t *e) } if (v) { tnode->tree_vis = v; - v->vis_tree = tnode; } if (e) { tnode->tree_exi = e; @@ -309,8 +308,6 @@ tree_remove_node(treenode_t *node) } /* - * Add a list of visible directories to a pseudo exportfs. - * * When we export a new directory we need to add a new * path segment through the pseudofs to reach the new * directory. This new path is reflected in a list of @@ -323,19 +320,70 @@ tree_remove_node(treenode_t *node) * the lists so there's no duplicate entries. Where a common * path component is found, the vis_count field is bumped. * - * When the addition is complete, the supplied list is freed. + * This example shows that the treenode chain (tree_head) and + * exp_visible chain (vis_head) can differ in length. The latter + * can be shorter. The outer loop must loop over the vis_head chain. + * + * share /x/a + * mount -F ufs /dev/dsk/... /x/y + * mkdir -p /x/y/a/b + * share /x/y/a/b + * + * When more_visible() is called during the second share, + * the existing namespace is folowing: + * exp_visible_t + * treenode_t exportinfo_t v0 v1 + * ns_root+---+ +------------+ +---+ +---+ + * t0| / |........| E0 pseudo |->| x |->| a | + * +---+ +------------+ +---+ +---+ + * | / / + * +---+ / / + * t1| x |------------------------ / + * +---+ / + * | / + * +---+ / + * t2| a |------------------------- + * +---+........+------------+ + * | E1 real | + * +------------+ + * + * This is being added: + * + * tree_head vis_head + * +---+ +---+ + * t3| x |->| x |v2 + * +---+ +---+ + * | | + * +---+ +---+ v4 v5 + * t4| y |->| y |v3 +------------+ +---+ +---+ + * +---+\ +---+ | E2 pseudo |->| a |->| b | + * | \....... >+------------+ +---+ +---+ + * +---+ / / + * t5| a |--------------------------- / + * +---+ / + * | / + * +---+------------------------------- + * t6| b | +------------+ + * +---+..........>| E3 real | + * +------------+ + * + * more_visible() will: + * - add t3 (with t4,t5,t6) as a child of t0 (t3 will become sibling of t1) + * - t3->tree_vis = v0 (plus bump vis_count for v0) and free v2 + * - add v3 to the end of E0->exi_visible + * + * Note that v4 and v5 were already proccesed in pseudo_exportfs() and + * added to E2. The outer loop of more_visible() will loop only over v2 + * and v3. The inner loop of more_visible() always loops over v0 and v1. */ - static void -more_visible(struct exportinfo *exi, struct exp_visible *vis_head) +more_visible(struct exportinfo *exi, treenode_t *tree_head) { - struct exp_visible *vp1, *vp2; - struct exp_visible *tail, *new; - treenode_t *subtree_head, *dupl, *dest; + struct exp_visible *vp1, *vp2, *vis_head, *tail, *next; int found; - dest = exi->exi_tree; - subtree_head = vis_head->vis_tree; + vis_head = tree_head->tree_vis; + tree_add_child(exi->exi_tree, tree_head); /* * If exportinfo doesn't already have a visible @@ -343,39 +391,23 @@ more_visible(struct exportinfo *exi, struct exp_visible *vis_head) */ if (exi->exi_visible == NULL) { exi->exi_visible = vis_head; - tree_add_child(dest, subtree_head); return; } - /* - * The outer loop traverses the supplied list. - */ - for (vp1 = vis_head; vp1; vp1 = vp1->vis_next) { - - /* - * Given an element from the list to be added, - * search the exportinfo visible list looking for a match. - * If a match is found, increment the reference count. - */ + /* The outer loop traverses the supplied list. */ + for (vp1 = vis_head; vp1; vp1 = next) { found = 0; + next = vp1->vis_next; + /* The inner loop searches the exportinfo visible list. */ for (vp2 = exi->exi_visible; vp2; vp2 = vp2->vis_next) { - tail = vp2; - if (EQFID(&vp1->vis_fid, &vp2->vis_fid)) { found = 1; vp2->vis_count++; VN_RELE(vp1->vis_vp); - vp1->vis_vp = NULL; - /* - * If the visible struct we want to add - * (vp1) has vis_exported set to 1, then - * the matching visible struct we just found - * must also have it's vis_exported field - * set to 1. - * + * Transfer vis_exported from vp1 to vp2. * For example, if /export/home was shared * (and a mountpoint), then "export" and * "home" would each have visible structs in @@ -386,51 +418,23 @@ more_visible(struct exportinfo *exi, struct exp_visible *vis_head) * existing visible struct for export, and * see that vis_exported was 0. The code * below will set it to 1. - * - * vp1 is from vis list passed in (vis_head) - * vp2 is from vis list on pseudo exportinfo */ if (vp1->vis_exported && !vp2->vis_exported) vp2->vis_exported = 1; - /* - * Assuming that visibles in vis_head are sorted - * in same order as they appear in the shared - * path. If /a/b/c/d is being shared we will - * see 'a' before 'b' etc. - */ - dupl = vp1->vis_tree; - dest = vp2->vis_tree; - /* If node is shared, transfer exportinfo ptr */ - if (dupl->tree_exi) { - dest->tree_exi = dupl->tree_exi; - dest->tree_exi->exi_tree = dest; - } - subtree_head = dupl->tree_child_first; - kmem_free(dupl, sizeof (*dupl)); + + kmem_free(vp1, sizeof (*vp1)); + tree_head->tree_vis = vp2; break; } } /* If not found - add to the end of the list */ if (! found) { - new = kmem_zalloc(sizeof (*new), KM_SLEEP); - *new = *vp1; - tail->vis_next = new; - new->vis_next = NULL; - vp1->vis_vp = NULL; - /* Tell treenode that new visible is kmem_zalloc-ated */ - new->vis_tree->tree_vis = new; + tail->vis_next = vp1; + vp1->vis_next = NULL; } + tree_head = tree_head->tree_child_first; } - - /* - * Throw away the path list. vis_vp pointers in vis_head list - * are either VN_RELEed or reassigned, and are set to NULL. - * There is no need to VN_RELE in free_visible for this vis_head. - */ - free_visible(vis_head); - if (subtree_head) - tree_add_child(dest, subtree_head); } /* @@ -595,7 +599,7 @@ treeclimb_export(struct exportinfo *exip) * directories whether it's a pseudo * or a real export. */ - more_visible(exi, vis_head); + more_visible(exi, tree_head); break; /* and climb no further */ } } @@ -778,7 +782,7 @@ treeclimb_unexport(struct exportinfo *exip) /* Release visible in parent's exportinfo */ if (tnode->tree_vis) { - exi = vis2exi(tnode->tree_vis); + exi = vis2exi(tnode); less_visible(exi, tnode->tree_vis); } diff --git a/usr/src/uts/common/fs/nfs/nfs_export.c b/usr/src/uts/common/fs/nfs/nfs_export.c index 6bd69dc5c3..53f9f97294 100644 --- a/usr/src/uts/common/fs/nfs/nfs_export.c +++ b/usr/src/uts/common/fs/nfs/nfs_export.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -695,18 +695,17 @@ srv_secinfo_exp2pseu(exportdata_t *curdata, exportdata_t *olddata) } /* - * Find for given exp_visible the exportinfo which has it - * linked on its exi_visible list. + * Find for given treenode the exportinfo which has its + * exp_visible linked on its exi_visible list. * * Note: We could add new pointer either to treenode or * to exp_visible, which will point there directly. * This would buy some speed for some memory. */ exportinfo_t * -vis2exi(struct exp_visible *vis) +vis2exi(treenode_t *tnode) { exportinfo_t *exi_ret = NULL; - treenode_t *tnode = vis->vis_tree; for (;;) { tnode = tnode->tree_parent; @@ -1570,13 +1569,8 @@ exi_scan_end: return (0); out7: - /* - * Unlink and re-link the new and old export in exptable. - */ + /* Unlink the new export in exptable. */ (void) export_unlink(&exi->exi_fsid, &exi->exi_fid, exi->exi_vp, NULL); - if (ex != NULL) - export_link(ex); - rw_exit(&exported_lock); out6: if (kex->ex_flags & EX_INDEX) diff --git a/usr/src/uts/common/nfs/export.h b/usr/src/uts/common/nfs/export.h index 79c605a21e..9bc35d0a6a 100644 --- a/usr/src/uts/common/nfs/export.h +++ b/usr/src/uts/common/nfs/export.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -301,11 +301,15 @@ struct svc_req; /* * Treenodes are used to build tree representing every node which is part - * of nfs server pseudo namespace. - * This tree is interconnected with both exportinfo and exp_visible struct. - * When there is a need to walk the namespace (either starting in - * exportinfo or in exp_visible) we first make a step aside (to the left), - * walk up or down as needed, and then we step back (to the right). + * of nfs server pseudo namespace. They are connected with both exportinfo + * and exp_visible struct. They were introduced to avoid lookup of ".." + * in the underlying file system during unshare, which was failing if the + * file system was forcibly unmounted or if the directory was removed. + * One exp_visible_t can be shared via several treenode_t, i.e. + * different tree_vis can point to the same exp_visible_t. + * This will happen if some directory is on two different shared paths: + * E.g. after share /tmp/a/b1 and share /tmp/a/b2 there will be two treenodes + * corresponding to /tmp/a and both will have same value in tree_vis. * * * @@ -349,9 +353,9 @@ struct svc_req; * * * Bi-directional interconnect: - * * treenode_t::tree_exi --------- exportinfo_t::exi_tree - * treenode_t::tree_vis ......... exp_visible_t::vis_tree + * One-way direction connection: + * treenode_t::tree_vis .........> exp_visible_t */ /* Access to treenode_t is under protection of exported_lock RW_LOCK */ typedef struct treenode { @@ -457,7 +461,6 @@ struct exp_visible { int vis_count; int vis_exported; struct exp_visible *vis_next; - struct treenode *vis_tree; struct secinfo *vis_secinfo; int vis_seccnt; }; @@ -523,7 +526,7 @@ extern char *build_symlink(vnode_t *, cred_t *, size_t *); /* * Functions that handle the NFSv4 server namespace */ -extern exportinfo_t *vis2exi(struct exp_visible *); +extern exportinfo_t *vis2exi(treenode_t *); extern int treeclimb_export(struct exportinfo *); extern void treeclimb_unexport(struct exportinfo *); extern int nfs_visible(struct exportinfo *, vnode_t *, int *); |