Print this page
Hyperaggressive asserts pt 1/N
Ooops exi_zoneid isn't a variable again yet
Be far more judicious in the use of curzone-using macros.


 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 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 
 730         /*
 731          * exi_tree can be null for the zone root
 732          * which means we're already at the "top"
 733          * and there's nothing more to "climb".
 734          */
 735         tnode = exip->exi_tree;
 736         if (tnode == NULL) {
 737                 /* Should only happen for... */
 738                 ASSERT(exip == ne->exi_root);
 739                 return;
 740         }
 741 
 742         if (seccnt == 0)
 743                 return;
 744 
 745         /*
 746          * If flavors are being added and the new export root isn't
 747          * also VROOT, its implicitly allowed flavors are inherited from
 748          * its pseudonode.


 799         if ((exi)->hash_name.prev) \
 800                 (exi)->hash_name.prev->hash_name.next = (exi)->hash_name.next; \
 801         if ((exi)->hash_name.next) \
 802                 (exi)->hash_name.next->hash_name.prev = (exi)->hash_name.prev; \
 803         (exi)->hash_name.bckt = NULL;
 804 
 805 #define exp_hash_link(exi, hash_name, bucket) \
 806         (exi)->hash_name.bckt = (bucket); \
 807         (exi)->hash_name.prev = NULL; \
 808         (exi)->hash_name.next = *(bucket); \
 809         if ((exi)->hash_name.next) \
 810                 (exi)->hash_name.next->hash_name.prev = (exi); \
 811         *(bucket) = (exi);
 812 
 813 void
 814 export_link(nfs_export_t *ne, exportinfo_t *exi)
 815 {
 816         exportinfo_t **bckt;
 817 
 818         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
 819         ASSERT(exi->exi_zoneid == ne->ne_globals->nfs_zoneid);
 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);


 883         if (err != 0) {
 884                 ne->exi_rootfid.fid_len = 0;
 885                 return (err);
 886         }
 887 
 888         /* Setup the fhandle template exi_fh */
 889         ne->exi_root->exi_fh.fh_fsid = rootdir->v_vfsp->vfs_fsid;
 890         ne->exi_root->exi_fh.fh_xlen = ne->exi_rootfid.fid_len;
 891         bcopy(ne->exi_rootfid.fid_data, ne->exi_root->exi_fh.fh_xdata,
 892             ne->exi_rootfid.fid_len);
 893         ne->exi_root->exi_fh.fh_len = sizeof (ne->exi_root->exi_fh.fh_data);
 894 
 895         return (0);
 896 }
 897 
 898 void
 899 nfs_export_zone_init(nfs_globals_t *ng)
 900 {
 901         int i;
 902         nfs_export_t *ne;

 903 
 904         ne = kmem_zalloc(sizeof (*ne), KM_SLEEP);
 905 
 906         rw_init(&ne->exported_lock, NULL, RW_DEFAULT, NULL);
 907 
 908         ne->ne_globals = ng; /* "up" pointer */
 909 
 910         /*
 911          * Allocate the place holder for the public file handle, which
 912          * is all zeroes. It is initially set to the root filesystem.
 913          */
 914         ne->exi_root = kmem_zalloc(sizeof (*ne->exi_root), KM_SLEEP);
 915         ne->exi_public = ne->exi_root;
 916 
 917         ne->exi_root->exi_export.ex_flags = EX_PUBLIC;
 918         ne->exi_root->exi_export.ex_pathlen = 1;  /* length of "/" */
 919         ne->exi_root->exi_export.ex_path =
 920             kmem_alloc(ne->exi_root->exi_export.ex_pathlen + 1, KM_SLEEP);
 921         ne->exi_root->exi_export.ex_path[0] = '/';
 922         ne->exi_root->exi_export.ex_path[1] = '\0';
 923 
 924         ne->exi_root->exi_count = 1;
 925         mutex_init(&ne->exi_root->exi_lock, NULL, MUTEX_DEFAULT, NULL);
 926 
 927         ASSERT(curzone->zone_id == ng->nfs_zoneid);
 928         ne->exi_root->exi_vp = ZONE_ROOTVP();
 929         ne->exi_root->exi_zoneid = ng->nfs_zoneid;







 930 
 931         /*
 932          * Fill in ne->exi_rootfid later, in nfs_export_get_rootfid
 933          * because we can't correctly return errors here.
 934          */
 935 
 936         /* Initialize auth cache and auth cache lock */
 937         for (i = 0; i < AUTH_TABLESIZE; i++) {
 938                 ne->exi_root->exi_cache[i] = kmem_alloc(sizeof (avl_tree_t),
 939                     KM_SLEEP);
 940                 avl_create(ne->exi_root->exi_cache[i],
 941                     nfsauth_cache_clnt_compar, sizeof (struct auth_cache_clnt),
 942                     offsetof(struct auth_cache_clnt, authc_link));
 943         }
 944         rw_init(&ne->exi_root->exi_cache_lock, NULL, RW_DEFAULT, NULL);
 945 
 946         /* setup exi_fh later, in nfs_export_get_rootfid */
 947 
 948         rw_enter(&ne->exported_lock, RW_WRITER);
 949 


1903         /*
1904          * Remove security flavors before treeclimb_unexport() is called
1905          * because srv_secinfo_treeclimb needs the namespace tree
1906          */
1907         curcnt = build_seclist_nodups(&exi->exi_export, cursec, TRUE);
1908         srv_secinfo_treeclimb(ne, exi, cursec, curcnt, FALSE);
1909 
1910         /*
1911          * If there's a visible list, then need to leave
1912          * a pseudo export here to retain the visible list
1913          * for paths to exports below.
1914          */
1915         if (exi->exi_visible != NULL) {
1916                 struct exportinfo *newexi;
1917 
1918                 newexi = pseudo_exportfs(ne, exi->exi_vp, &exi->exi_fid,
1919                     exi->exi_visible, &exi->exi_export);
1920                 exi->exi_visible = NULL;
1921 
1922                 /* interconnect the existing treenode with the new exportinfo */
1923                 newexi->exi_zone = exi->exi_zone;
1924                 newexi->exi_tree = exi->exi_tree;
1925                 newexi->exi_tree->tree_exi = newexi;
1926 
1927                 /* Update the change timestamp */
1928                 tree_update_change(ne, exi->exi_tree, NULL);
1929         } else {
1930                 treeclimb_unexport(ne, exi);
1931         }
1932 
1933         rw_exit(&ne->exported_lock);
1934 
1935         /*
1936          * Need to call into the NFSv4 server and release all data
1937          * held on this particular export.  This is important since
1938          * the v4 server may be holding file locks or vnodes under
1939          * this export.
1940          */
1941         rfs4_clean_state_exi(ne, exi);
1942 
1943         /*


2172                         break;
2173                 }
2174 
2175                 if (v4srv)
2176                         exi = checkexport4(&vp->v_vfsp->vfs_fsid, &fid, vp);
2177                 else
2178                         exi = checkexport(&vp->v_vfsp->vfs_fsid, &fid);
2179 
2180                 if (exi != NULL) {
2181                         /*
2182                          * Found the export info
2183                          */
2184                         break;
2185                 }
2186 
2187                 /*
2188                  * We have just failed finding a matching export.
2189                  * If we're at the root of this filesystem, then
2190                  * it's time to stop (with failure).
2191                  */

2192                 if ((vp->v_flag & VROOT) || VN_IS_CURZONEROOT(vp)) {
2193                         error = EINVAL;
2194                         break;
2195                 }
2196 
2197                 if (walk != NULL)
2198                         (*walk)++;
2199 
2200                 /*
2201                  * Now, do a ".." up vp. If dvp is supplied, use it,
2202                  * otherwise, look it up.
2203                  */
2204                 if (dvp == NULL) {
2205                         error = VOP_LOOKUP(vp, "..", &dvp, NULL, 0, NULL, cr,
2206                             NULL, NULL, NULL);
2207                         if (error)
2208                                 break;
2209                 }
2210                 VN_RELE(vp);
2211                 vp = dvp;




 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.


 800         if ((exi)->hash_name.prev) \
 801                 (exi)->hash_name.prev->hash_name.next = (exi)->hash_name.next; \
 802         if ((exi)->hash_name.next) \
 803                 (exi)->hash_name.next->hash_name.prev = (exi)->hash_name.prev; \
 804         (exi)->hash_name.bckt = NULL;
 805 
 806 #define exp_hash_link(exi, hash_name, bucket) \
 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);


 883         if (err != 0) {
 884                 ne->exi_rootfid.fid_len = 0;
 885                 return (err);
 886         }
 887 
 888         /* Setup the fhandle template exi_fh */
 889         ne->exi_root->exi_fh.fh_fsid = rootdir->v_vfsp->vfs_fsid;
 890         ne->exi_root->exi_fh.fh_xlen = ne->exi_rootfid.fid_len;
 891         bcopy(ne->exi_rootfid.fid_data, ne->exi_root->exi_fh.fh_xdata,
 892             ne->exi_rootfid.fid_len);
 893         ne->exi_root->exi_fh.fh_len = sizeof (ne->exi_root->exi_fh.fh_data);
 894 
 895         return (0);
 896 }
 897 
 898 void
 899 nfs_export_zone_init(nfs_globals_t *ng)
 900 {
 901         int i;
 902         nfs_export_t *ne;
 903         zone_t *zone;
 904 
 905         ne = kmem_zalloc(sizeof (*ne), KM_SLEEP);
 906 
 907         rw_init(&ne->exported_lock, NULL, RW_DEFAULT, NULL);
 908 
 909         ne->ne_globals = ng; /* "up" pointer */
 910 
 911         /*
 912          * Allocate the place holder for the public file handle, which
 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 


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         /*


2180                         break;
2181                 }
2182 
2183                 if (v4srv)
2184                         exi = checkexport4(&vp->v_vfsp->vfs_fsid, &fid, vp);
2185                 else
2186                         exi = checkexport(&vp->v_vfsp->vfs_fsid, &fid);
2187 
2188                 if (exi != NULL) {
2189                         /*
2190                          * Found the export info
2191                          */
2192                         break;
2193                 }
2194 
2195                 /*
2196                  * We have just failed finding a matching export.
2197                  * If we're at the root of this filesystem, then
2198                  * it's time to stop (with failure).
2199                  */
2200                 ASSERT3P(vp->v_vfsp->vfs_zone, ==, curzone);
2201                 if ((vp->v_flag & VROOT) || VN_IS_CURZONEROOT(vp)) {
2202                         error = EINVAL;
2203                         break;
2204                 }
2205 
2206                 if (walk != NULL)
2207                         (*walk)++;
2208 
2209                 /*
2210                  * Now, do a ".." up vp. If dvp is supplied, use it,
2211                  * otherwise, look it up.
2212                  */
2213                 if (dvp == NULL) {
2214                         error = VOP_LOOKUP(vp, "..", &dvp, NULL, 0, NULL, cr,
2215                             NULL, NULL, NULL);
2216                         if (error)
2217                                 break;
2218                 }
2219                 VN_RELE(vp);
2220                 vp = dvp;