676          * Done. Update curdata.
 677          * Free up the existing secinfo list in curdata and
 678          * set the new value.
 679          */
 680         curdata->ex_seccnt = tcnt;
 681         curdata->ex_secinfo = msec;
 682 }
 683 
 684 /*
 685  * Find for given treenode the exportinfo which has its
 686  * exp_visible linked on its exi_visible list.
 687  *
 688  * Note: We could add new pointer either to treenode or
 689  * to exp_visible, which will point there directly.
 690  * This would buy some speed for some memory.
 691  */
 692 exportinfo_t *
 693 vis2exi(treenode_t *tnode)
 694 {
 695         exportinfo_t *exi_ret = NULL;
 696 #ifdef DEBUG
 697         zone_t *zone = NULL;
 698 #endif
 699 
 700         for (;;) {
 701                 tnode = tnode->tree_parent;
 702 #ifdef DEBUG
 703                 if (zone == NULL && tnode->tree_exi != NULL)
 704                         zone = tnode->tree_exi->exi_zone;
 705 #endif
 706                 if (TREE_ROOT(tnode)) {
 707                         ASSERT3P(zone, ==, tnode->tree_exi->exi_zone);
 708                         exi_ret = tnode->tree_exi;
 709                         break;
 710                 }
 711         }
 712 
 713         ASSERT(exi_ret); /* Every visible should have its home exportinfo */
 714         return (exi_ret);
 715 }
 716 
 717 /*
 718  * For NFS V4.
 719  * Add or remove the newly exported or unexported security flavors of the
 720  * given exportinfo from its ancestors upto the system root.
 721  */
 722 static void
 723 srv_secinfo_treeclimb(nfs_export_t *ne, exportinfo_t *exip, secinfo_t *sec,
 724     int seccnt, bool_t isadd)
 725 {
 726         treenode_t *tnode;
 727 
 728         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
 729         ASSERT3U(exip->exi_zoneid, ==, curzone->zone_id);
 730 
 731         /*
 732          * exi_tree can be null for the zone root
 733          * which means we're already at the "top"
 734          * and there's nothing more to "climb".
 735          */
 736         tnode = exip->exi_tree;
 737         if (tnode == NULL) {
 738                 /* Should only happen for... */
 739                 ASSERT(exip == ne->exi_root);
 740                 return;
 741         }
 742 
 743         if (seccnt == 0)
 744                 return;
 745 
 746         /*
 747          * If flavors are being added and the new export root isn't
 748          * also VROOT, its implicitly allowed flavors are inherited from
 749          * its pseudonode.
 750          * Note - for VROOT exports the implicitly allowed flavors were
 751          * transferred from the PSEUDO export in exportfs()
 752          */
 753         if (isadd && !(exip->exi_vp->v_flag & VROOT) &&
 754             !VN_IS_CURZONEROOT(exip->exi_vp) &&
 755             tnode->tree_vis->vis_seccnt > 0) {
 756                 srv_secinfo_add(&exip->exi_export.ex_secinfo,
 757                     &exip->exi_export.ex_seccnt, tnode->tree_vis->vis_secinfo,
 758                     tnode->tree_vis->vis_seccnt, FALSE);
 759         }
 760 
 761         /*
 762          * Move to parent node and propagate sec flavor
 763          * to exportinfo and to visible structures.
 764          */
 765         tnode = tnode->tree_parent;
 766 
 767         while (tnode != NULL) {
 768 
 769                 /* If there is exportinfo, update it */
 770                 if (tnode->tree_exi != NULL) {
 771                         secinfo_t **pxsec =
 772                             &tnode->tree_exi->exi_export.ex_secinfo;
 773                         int *pxcnt = &tnode->tree_exi->exi_export.ex_seccnt;
 774                         int is_pseudo = PSEUDO(tnode->tree_exi);
 
 807         (exi)->hash_name.bckt = (bucket); \
 808         (exi)->hash_name.prev = NULL; \
 809         (exi)->hash_name.next = *(bucket); \
 810         if ((exi)->hash_name.next) \
 811                 (exi)->hash_name.next->hash_name.prev = (exi); \
 812         *(bucket) = (exi);
 813 
 814 void
 815 export_link(nfs_export_t *ne, exportinfo_t *exi)
 816 {
 817         exportinfo_t **bckt;
 818 
 819         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
 820 
 821         bckt = &ne->exptable[exptablehash(&exi->exi_fsid, &exi->exi_fid)];
 822         exp_hash_link(exi, fid_hash, bckt);
 823 
 824         bckt = &ne->exptable_path_hash[pkp_tab_hash(exi->exi_export.ex_path,
 825             strlen(exi->exi_export.ex_path))];
 826         exp_hash_link(exi, path_hash, bckt);
 827 }
 828 
 829 /*
 830  * Helper functions for exi_id handling
 831  */
 832 static int
 833 exi_id_compar(const void *v1, const void *v2)
 834 {
 835         const struct exportinfo *e1 = v1;
 836         const struct exportinfo *e2 = v2;
 837 
 838         if (e1->exi_id < e2->exi_id)
 839                 return (-1);
 840         if (e1->exi_id > e2->exi_id)
 841                 return (1);
 842 
 843         return (0);
 844 }
 845 
 846 int
 
 913          * is all zeroes. It is initially set to the root filesystem.
 914          */
 915         ne->exi_root = kmem_zalloc(sizeof (*ne->exi_root), KM_SLEEP);
 916         ne->exi_public = ne->exi_root;
 917 
 918         ne->exi_root->exi_export.ex_flags = EX_PUBLIC;
 919         ne->exi_root->exi_export.ex_pathlen = 1;  /* length of "/" */
 920         ne->exi_root->exi_export.ex_path =
 921             kmem_alloc(ne->exi_root->exi_export.ex_pathlen + 1, KM_SLEEP);
 922         ne->exi_root->exi_export.ex_path[0] = '/';
 923         ne->exi_root->exi_export.ex_path[1] = '\0';
 924 
 925         ne->exi_root->exi_count = 1;
 926         mutex_init(&ne->exi_root->exi_lock, NULL, MUTEX_DEFAULT, NULL);
 927 
 928         /*
 929          * Because we cannot:
 930          *      ASSERT(curzone->zone_id == ng->nfs_zoneid);
 931          * We grab the zone pointer explicitly (like netstacks do) and
 932          * set the rootvp here.
 933          */
 934         zone = zone_find_by_id_nolock(ng->nfs_zoneid);
 935         ne->exi_root->exi_vp = zone->zone_rootvp;
 936         ne->exi_root->exi_zone = zone;    /* XXX KEBE SAYS lose me, and... */
 937         /* ne->exi_root->exi_zoneid = ng->nfs_zoneid; */ /* use me instead! */
 938 
 939         /*
 940          * Fill in ne->exi_rootfid later, in nfs_export_get_rootfid
 941          * because we can't correctly return errors here.
 942          */
 943 
 944         /* Initialize auth cache and auth cache lock */
 945         for (i = 0; i < AUTH_TABLESIZE; i++) {
 946                 ne->exi_root->exi_cache[i] = kmem_alloc(sizeof (avl_tree_t),
 947                     KM_SLEEP);
 948                 avl_create(ne->exi_root->exi_cache[i],
 949                     nfsauth_cache_clnt_compar, sizeof (struct auth_cache_clnt),
 950                     offsetof(struct auth_cache_clnt, authc_link));
 951         }
 952         rw_init(&ne->exi_root->exi_cache_lock, NULL, RW_DEFAULT, NULL);
 953 
 954         /* setup exi_fh later, in nfs_export_get_rootfid */
 955 
 956         rw_enter(&ne->exported_lock, RW_WRITER);
 957 
 
1395                     VN_CMP(ex2->exi_vp, vp) &&
1396                     strcmp(ex2->exi_export.ex_path, lookpn.pn_path) != 0) {
1397                         DTRACE_PROBE(nfss__i__exported_lock2_stop);
1398                         rw_exit(&ne->exported_lock);
1399                         VN_RELE(vp);
1400                         if (dvp != NULL)
1401                                 VN_RELE(dvp);
1402                         pn_free(&lookpn);
1403                         return (EEXIST);
1404                 }
1405         }
1406         DTRACE_PROBE(nfss__i__exported_lock2_stop);
1407         rw_exit(&ne->exported_lock);
1408         pn_free(&lookpn);
1409 
1410         exi = kmem_zalloc(sizeof (*exi), KM_SLEEP);
1411         exi->exi_fsid = fsid;
1412         exi->exi_fid = fid;
1413         exi->exi_vp = vp;
1414         exi->exi_count = 1;
1415         exi->exi_zone = crgetzone(cr);
1416         ASSERT(exi->exi_zone != NULL);               /* XXX KEBE ASKS... */
1417         ASSERT3P(exi->exi_zone, ==, curzone);        /* ... are these legit? */
1418         exi->exi_volatile_dev = (vfssw[vp->v_vfsp->vfs_fstype].vsw_flag &
1419             VSW_VOLATILEDEV) ? 1 : 0;
1420         mutex_init(&exi->exi_lock, NULL, MUTEX_DEFAULT, NULL);
1421         exi->exi_dvp = dvp;
1422 
1423         /*
1424          * Initialize auth cache and auth cache lock
1425          */
1426         for (i = 0; i < AUTH_TABLESIZE; i++) {
1427                 exi->exi_cache[i] = kmem_alloc(sizeof (avl_tree_t), KM_SLEEP);
1428                 avl_create(exi->exi_cache[i], nfsauth_cache_clnt_compar,
1429                     sizeof (struct auth_cache_clnt),
1430                     offsetof(struct auth_cache_clnt, authc_link));
1431         }
1432         rw_init(&exi->exi_cache_lock, NULL, RW_DEFAULT, NULL);
1433 
1434         /*
1435          * Build up the template fhandle
1436          */
1437         exi->exi_fh.fh_fsid = fsid;
 
1867         for (i = 0; i < AUTH_TABLESIZE; i++) {
1868                 avl_destroy(exi->exi_cache[i]);
1869                 kmem_free(exi->exi_cache[i], sizeof (avl_tree_t));
1870         }
1871 
1872         kmem_free(exi, sizeof (*exi));
1873 
1874         return (error);
1875 }
1876 
1877 /*
1878  * Remove the exportinfo from the export list
1879  */
1880 void
1881 export_unlink(nfs_export_t *ne, struct exportinfo *exi)
1882 {
1883         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
1884 
1885         exp_hash_unlink(exi, fid_hash);
1886         exp_hash_unlink(exi, path_hash);
1887 }
1888 
1889 /*
1890  * Unexport an exported filesystem
1891  */
1892 static int
1893 unexport(nfs_export_t *ne, struct exportinfo *exi)
1894 {
1895         struct secinfo cursec[MAX_FLAVORS];
1896         int curcnt;
1897 
1898         rw_enter(&ne->exported_lock, RW_WRITER);
1899 
1900         /* Check if exi is still linked in the export table */
1901         if (!EXP_LINKED(exi) || PSEUDO(exi)) {
1902                 rw_exit(&ne->exported_lock);
1903                 return (EINVAL);
1904         }
1905 
1906         mutex_enter(&nfs_exi_id_lock);
 
1911         /*
1912          * Remove security flavors before treeclimb_unexport() is called
1913          * because srv_secinfo_treeclimb needs the namespace tree
1914          */
1915         curcnt = build_seclist_nodups(&exi->exi_export, cursec, TRUE);
1916         srv_secinfo_treeclimb(ne, exi, cursec, curcnt, FALSE);
1917 
1918         /*
1919          * If there's a visible list, then need to leave
1920          * a pseudo export here to retain the visible list
1921          * for paths to exports below.
1922          */
1923         if (exi->exi_visible != NULL) {
1924                 struct exportinfo *newexi;
1925 
1926                 newexi = pseudo_exportfs(ne, exi->exi_vp, &exi->exi_fid,
1927                     exi->exi_visible, &exi->exi_export);
1928                 exi->exi_visible = NULL;
1929 
1930                 /* interconnect the existing treenode with the new exportinfo */
1931                 newexi->exi_zone = exi->exi_zone; /* XXX KEBE SAYS LOSE ME */
1932                 newexi->exi_tree = exi->exi_tree;
1933                 newexi->exi_tree->tree_exi = newexi;
1934 
1935                 /* Update the change timestamp */
1936                 tree_update_change(ne, exi->exi_tree, NULL);
1937         } else {
1938                 treeclimb_unexport(ne, exi);
1939         }
1940 
1941         rw_exit(&ne->exported_lock);
1942 
1943         /*
1944          * Need to call into the NFSv4 server and release all data
1945          * held on this particular export.  This is important since
1946          * the v4 server may be holding file locks or vnodes under
1947          * this export.
1948          */
1949         rfs4_clean_state_exi(ne, exi);
1950 
1951         /*
 
 | 
 
 
 676          * Done. Update curdata.
 677          * Free up the existing secinfo list in curdata and
 678          * set the new value.
 679          */
 680         curdata->ex_seccnt = tcnt;
 681         curdata->ex_secinfo = msec;
 682 }
 683 
 684 /*
 685  * Find for given treenode the exportinfo which has its
 686  * exp_visible linked on its exi_visible list.
 687  *
 688  * Note: We could add new pointer either to treenode or
 689  * to exp_visible, which will point there directly.
 690  * This would buy some speed for some memory.
 691  */
 692 exportinfo_t *
 693 vis2exi(treenode_t *tnode)
 694 {
 695         exportinfo_t *exi_ret = NULL;
 696 
 697         for (;;) {
 698                 tnode = tnode->tree_parent;
 699                 if (TREE_ROOT(tnode)) {
 700                         exi_ret = tnode->tree_exi;
 701                         break;
 702                 }
 703         }
 704 
 705         /* Every visible should have its home exportinfo */
 706         ASSERT(exi_ret != NULL);
 707         return (exi_ret);
 708 }
 709 
 710 /*
 711  * For NFS V4.
 712  * Add or remove the newly exported or unexported security flavors of the
 713  * given exportinfo from its ancestors upto the system root.
 714  */
 715 static void
 716 srv_secinfo_treeclimb(nfs_export_t *ne, exportinfo_t *exip, secinfo_t *sec,
 717     int seccnt, bool_t isadd)
 718 {
 719         treenode_t *tnode;
 720 
 721         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
 722 
 723         /*
 724          * exi_tree can be null for the zone root
 725          * which means we're already at the "top"
 726          * and there's nothing more to "climb".
 727          */
 728         tnode = exip->exi_tree;
 729         if (tnode == NULL) {
 730                 /* Should only happen for... */
 731                 ASSERT(exip == ne->exi_root);
 732                 return;
 733         }
 734 
 735         if (seccnt == 0)
 736                 return;
 737 
 738         /*
 739          * If flavors are being added and the new export root isn't
 740          * also VROOT, its implicitly allowed flavors are inherited from
 741          * its pseudonode.
 742          * Note - for VROOT exports the implicitly allowed flavors were
 743          * transferred from the PSEUDO export in exportfs()
 744          */
 745         if (isadd && !(exip->exi_vp->v_flag & VROOT) &&
 746             !VN_CMP(exip->exi_vp, EXI_TO_ZONEROOTVP(exip)) &&
 747             tnode->tree_vis->vis_seccnt > 0) {
 748                 srv_secinfo_add(&exip->exi_export.ex_secinfo,
 749                     &exip->exi_export.ex_seccnt, tnode->tree_vis->vis_secinfo,
 750                     tnode->tree_vis->vis_seccnt, FALSE);
 751         }
 752 
 753         /*
 754          * Move to parent node and propagate sec flavor
 755          * to exportinfo and to visible structures.
 756          */
 757         tnode = tnode->tree_parent;
 758 
 759         while (tnode != NULL) {
 760 
 761                 /* If there is exportinfo, update it */
 762                 if (tnode->tree_exi != NULL) {
 763                         secinfo_t **pxsec =
 764                             &tnode->tree_exi->exi_export.ex_secinfo;
 765                         int *pxcnt = &tnode->tree_exi->exi_export.ex_seccnt;
 766                         int is_pseudo = PSEUDO(tnode->tree_exi);
 
 799         (exi)->hash_name.bckt = (bucket); \
 800         (exi)->hash_name.prev = NULL; \
 801         (exi)->hash_name.next = *(bucket); \
 802         if ((exi)->hash_name.next) \
 803                 (exi)->hash_name.next->hash_name.prev = (exi); \
 804         *(bucket) = (exi);
 805 
 806 void
 807 export_link(nfs_export_t *ne, exportinfo_t *exi)
 808 {
 809         exportinfo_t **bckt;
 810 
 811         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
 812 
 813         bckt = &ne->exptable[exptablehash(&exi->exi_fsid, &exi->exi_fid)];
 814         exp_hash_link(exi, fid_hash, bckt);
 815 
 816         bckt = &ne->exptable_path_hash[pkp_tab_hash(exi->exi_export.ex_path,
 817             strlen(exi->exi_export.ex_path))];
 818         exp_hash_link(exi, path_hash, bckt);
 819         exi->exi_ne = ne;
 820 }
 821 
 822 /*
 823  * Helper functions for exi_id handling
 824  */
 825 static int
 826 exi_id_compar(const void *v1, const void *v2)
 827 {
 828         const struct exportinfo *e1 = v1;
 829         const struct exportinfo *e2 = v2;
 830 
 831         if (e1->exi_id < e2->exi_id)
 832                 return (-1);
 833         if (e1->exi_id > e2->exi_id)
 834                 return (1);
 835 
 836         return (0);
 837 }
 838 
 839 int
 
 906          * is all zeroes. It is initially set to the root filesystem.
 907          */
 908         ne->exi_root = kmem_zalloc(sizeof (*ne->exi_root), KM_SLEEP);
 909         ne->exi_public = ne->exi_root;
 910 
 911         ne->exi_root->exi_export.ex_flags = EX_PUBLIC;
 912         ne->exi_root->exi_export.ex_pathlen = 1;  /* length of "/" */
 913         ne->exi_root->exi_export.ex_path =
 914             kmem_alloc(ne->exi_root->exi_export.ex_pathlen + 1, KM_SLEEP);
 915         ne->exi_root->exi_export.ex_path[0] = '/';
 916         ne->exi_root->exi_export.ex_path[1] = '\0';
 917 
 918         ne->exi_root->exi_count = 1;
 919         mutex_init(&ne->exi_root->exi_lock, NULL, MUTEX_DEFAULT, NULL);
 920 
 921         /*
 922          * Because we cannot:
 923          *      ASSERT(curzone->zone_id == ng->nfs_zoneid);
 924          * We grab the zone pointer explicitly (like netstacks do) and
 925          * set the rootvp here.
 926          *
 927          * Subsequent exportinfo_t's that get export_link()ed to "ne" also
 928          * will backpoint to "ne" such that exi->exi_ne->exi_root->exi_vp
 929          * will get the zone's rootvp for a given exportinfo_t.
 930          */
 931         zone = zone_find_by_id_nolock(ng->nfs_zoneid);
 932         ne->exi_root->exi_vp = zone->zone_rootvp;
 933         ne->exi_root->exi_zoneid = ng->nfs_zoneid;
 934 
 935         /*
 936          * Fill in ne->exi_rootfid later, in nfs_export_get_rootfid
 937          * because we can't correctly return errors here.
 938          */
 939 
 940         /* Initialize auth cache and auth cache lock */
 941         for (i = 0; i < AUTH_TABLESIZE; i++) {
 942                 ne->exi_root->exi_cache[i] = kmem_alloc(sizeof (avl_tree_t),
 943                     KM_SLEEP);
 944                 avl_create(ne->exi_root->exi_cache[i],
 945                     nfsauth_cache_clnt_compar, sizeof (struct auth_cache_clnt),
 946                     offsetof(struct auth_cache_clnt, authc_link));
 947         }
 948         rw_init(&ne->exi_root->exi_cache_lock, NULL, RW_DEFAULT, NULL);
 949 
 950         /* setup exi_fh later, in nfs_export_get_rootfid */
 951 
 952         rw_enter(&ne->exported_lock, RW_WRITER);
 953 
 
1391                     VN_CMP(ex2->exi_vp, vp) &&
1392                     strcmp(ex2->exi_export.ex_path, lookpn.pn_path) != 0) {
1393                         DTRACE_PROBE(nfss__i__exported_lock2_stop);
1394                         rw_exit(&ne->exported_lock);
1395                         VN_RELE(vp);
1396                         if (dvp != NULL)
1397                                 VN_RELE(dvp);
1398                         pn_free(&lookpn);
1399                         return (EEXIST);
1400                 }
1401         }
1402         DTRACE_PROBE(nfss__i__exported_lock2_stop);
1403         rw_exit(&ne->exported_lock);
1404         pn_free(&lookpn);
1405 
1406         exi = kmem_zalloc(sizeof (*exi), KM_SLEEP);
1407         exi->exi_fsid = fsid;
1408         exi->exi_fid = fid;
1409         exi->exi_vp = vp;
1410         exi->exi_count = 1;
1411         exi->exi_zoneid = crgetzoneid(cr);
1412         ASSERT3U(exi->exi_zoneid, ==, curzone->zone_id);
1413         exi->exi_volatile_dev = (vfssw[vp->v_vfsp->vfs_fstype].vsw_flag &
1414             VSW_VOLATILEDEV) ? 1 : 0;
1415         mutex_init(&exi->exi_lock, NULL, MUTEX_DEFAULT, NULL);
1416         exi->exi_dvp = dvp;
1417 
1418         /*
1419          * Initialize auth cache and auth cache lock
1420          */
1421         for (i = 0; i < AUTH_TABLESIZE; i++) {
1422                 exi->exi_cache[i] = kmem_alloc(sizeof (avl_tree_t), KM_SLEEP);
1423                 avl_create(exi->exi_cache[i], nfsauth_cache_clnt_compar,
1424                     sizeof (struct auth_cache_clnt),
1425                     offsetof(struct auth_cache_clnt, authc_link));
1426         }
1427         rw_init(&exi->exi_cache_lock, NULL, RW_DEFAULT, NULL);
1428 
1429         /*
1430          * Build up the template fhandle
1431          */
1432         exi->exi_fh.fh_fsid = fsid;
 
1862         for (i = 0; i < AUTH_TABLESIZE; i++) {
1863                 avl_destroy(exi->exi_cache[i]);
1864                 kmem_free(exi->exi_cache[i], sizeof (avl_tree_t));
1865         }
1866 
1867         kmem_free(exi, sizeof (*exi));
1868 
1869         return (error);
1870 }
1871 
1872 /*
1873  * Remove the exportinfo from the export list
1874  */
1875 void
1876 export_unlink(nfs_export_t *ne, struct exportinfo *exi)
1877 {
1878         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
1879 
1880         exp_hash_unlink(exi, fid_hash);
1881         exp_hash_unlink(exi, path_hash);
1882         ASSERT3P(exi->exi_ne, ==, ne);
1883         exi->exi_ne = NULL;
1884 }
1885 
1886 /*
1887  * Unexport an exported filesystem
1888  */
1889 static int
1890 unexport(nfs_export_t *ne, struct exportinfo *exi)
1891 {
1892         struct secinfo cursec[MAX_FLAVORS];
1893         int curcnt;
1894 
1895         rw_enter(&ne->exported_lock, RW_WRITER);
1896 
1897         /* Check if exi is still linked in the export table */
1898         if (!EXP_LINKED(exi) || PSEUDO(exi)) {
1899                 rw_exit(&ne->exported_lock);
1900                 return (EINVAL);
1901         }
1902 
1903         mutex_enter(&nfs_exi_id_lock);
 
1908         /*
1909          * Remove security flavors before treeclimb_unexport() is called
1910          * because srv_secinfo_treeclimb needs the namespace tree
1911          */
1912         curcnt = build_seclist_nodups(&exi->exi_export, cursec, TRUE);
1913         srv_secinfo_treeclimb(ne, exi, cursec, curcnt, FALSE);
1914 
1915         /*
1916          * If there's a visible list, then need to leave
1917          * a pseudo export here to retain the visible list
1918          * for paths to exports below.
1919          */
1920         if (exi->exi_visible != NULL) {
1921                 struct exportinfo *newexi;
1922 
1923                 newexi = pseudo_exportfs(ne, exi->exi_vp, &exi->exi_fid,
1924                     exi->exi_visible, &exi->exi_export);
1925                 exi->exi_visible = NULL;
1926 
1927                 /* interconnect the existing treenode with the new exportinfo */
1928                 newexi->exi_tree = exi->exi_tree;
1929                 newexi->exi_tree->tree_exi = newexi;
1930 
1931                 /* Update the change timestamp */
1932                 tree_update_change(ne, exi->exi_tree, NULL);
1933         } else {
1934                 treeclimb_unexport(ne, exi);
1935         }
1936 
1937         rw_exit(&ne->exported_lock);
1938 
1939         /*
1940          * Need to call into the NFSv4 server and release all data
1941          * held on this particular export.  This is important since
1942          * the v4 server may be holding file locks or vnodes under
1943          * this export.
1944          */
1945         rfs4_clean_state_exi(ne, exi);
1946 
1947         /*
 
 |