Print this page
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.


 149 pseudo_exportfs(nfs_export_t *ne, vnode_t *vp, fid_t *fid,
 150     struct exp_visible *vis_head, struct exportdata *exdata)
 151 {
 152         struct exportinfo *exi;
 153         struct exportdata *kex;
 154         fsid_t fsid;
 155         int vpathlen;
 156         int i;
 157 
 158         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
 159 
 160         fsid = vp->v_vfsp->vfs_fsid;
 161         exi = kmem_zalloc(sizeof (*exi), KM_SLEEP);
 162         exi->exi_fsid = fsid;
 163         exi->exi_fid = *fid;
 164         exi->exi_vp = vp;
 165         VN_HOLD(exi->exi_vp);
 166         exi->exi_visible = vis_head;
 167         exi->exi_count = 1;
 168         /* Caller will set exi_zone... */


 169         exi->exi_volatile_dev = (vfssw[vp->v_vfsp->vfs_fstype].vsw_flag &
 170             VSW_VOLATILEDEV) ? 1 : 0;
 171         mutex_init(&exi->exi_lock, NULL, MUTEX_DEFAULT, NULL);
 172         exi->exi_zoneid = ne->ne_globals->nfs_zoneid;
 173 
 174         /*
 175          * Build up the template fhandle
 176          */
 177         exi->exi_fh.fh_fsid = fsid;
 178         ASSERT(exi->exi_fid.fid_len <= sizeof (exi->exi_fh.fh_xdata));
 179         exi->exi_fh.fh_xlen = exi->exi_fid.fid_len;
 180         bcopy(exi->exi_fid.fid_data, exi->exi_fh.fh_xdata,
 181             exi->exi_fid.fid_len);
 182         exi->exi_fh.fh_len = sizeof (exi->exi_fh.fh_data);
 183 
 184         kex = &exi->exi_export;
 185         kex->ex_flags = EX_PSEUDO;
 186 
 187         vpathlen = strlen(vp->v_path);
 188         kex->ex_pathlen = vpathlen + strlen(PSEUDOFS_SUFFIX);
 189         kex->ex_path = kmem_alloc(kex->ex_pathlen + 1, KM_SLEEP);
 190 
 191         if (vpathlen)
 192                 (void) strncpy(kex->ex_path, vp->v_path, vpathlen);


 643         timespec_t now;
 644         nfs_export_t *ne = nfs_get_export();
 645 
 646         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
 647         ASSERT3P(curzone, ==, exip->exi_zone);
 648 
 649         gethrestime(&now);
 650 
 651         vp = exip->exi_vp;
 652         VN_HOLD(vp);
 653         exportdir = 1;
 654 
 655         for (;;) {
 656 
 657                 bzero(&fid, sizeof (fid));
 658                 fid.fid_len = MAXFIDSZ;
 659                 error = vop_fid_pseudo(vp, &fid);
 660                 if (error)
 661                         break;
 662 

 663                 /*
 664                  * The root of the file system, or the zone's root for
 665                  * in-zone NFS service needs special handling
 666                  */
 667                 if (vp->v_flag & VROOT || VN_IS_CURZONEROOT(vp)) {
 668                         if (!exportdir) {
 669                                 struct exportinfo *exi;
 670 
 671                                 /*
 672                                  * Check if this VROOT dir is already exported.
 673                                  * If so, then attach the pseudonodes.  If not,
 674                                  * then continue .. traversal until we hit a
 675                                  * VROOT export (pseudo or real).
 676                                  */
 677                                 exi = checkexport4(&vp->v_vfsp->vfs_fsid, &fid,
 678                                     vp);
 679                                 if (exi != NULL) {
 680                                         /*
 681                                          * Found an export info
 682                                          *
 683                                          * Extend the list of visible
 684                                          * directories whether it's a pseudo
 685                                          * or a real export.
 686                                          */
 687                                         more_visible(exi, tree_head);
 688                                         break;  /* and climb no further */
 689                                 }
 690 
 691                                 /*
 692                                  * Found the root directory of a filesystem
 693                                  * that isn't exported.  Need to export
 694                                  * this as a pseudo export so that an NFS v4
 695                                  * client can do lookups in it.
 696                                  */
 697                                 new_exi = pseudo_exportfs(ne, vp, &fid,
 698                                     vis_head, NULL);

 699                                 new_exi->exi_zone = exip->exi_zone;
 700                                 vis_head = NULL;
 701                         }
 702 
 703                         if (VN_IS_CURZONEROOT(vp)) {
 704                                 /* at system root */
 705                                 /*
 706                                  * If sharing "/", new_exi is shared exportinfo
 707                                  * (exip). Otherwise, new_exi is exportinfo
 708                                  * created by pseudo_exportfs() above.
 709                                  */
 710                                 ne->ns_root = tree_prepend_node(tree_head, NULL,
 711                                     new_exi);
 712 
 713                                 /* Update the change timestamp */
 714                                 tree_update_change(ne, ne->ns_root, &now);
 715 
 716                                 break;
 717                         }
 718 


 863                 tnode->tree_vis->vis_exported = 0;
 864 
 865         while (tnode != NULL) {
 866 
 867                 /*
 868                  * Stop at VROOT (or zone root) node which is exported or has
 869                  * child.
 870                  */
 871                 if (TREE_ROOT(tnode) &&
 872                     (TREE_EXPORTED(tnode) || tnode->tree_child_first != NULL))
 873                         break;
 874 
 875                 /* Release pseudo export if it has no child */
 876                 if (TREE_ROOT(tnode) && !TREE_EXPORTED(tnode) &&
 877                     tnode->tree_child_first == NULL) {
 878                         mutex_enter(&nfs_exi_id_lock);
 879                         avl_remove(&exi_id_tree, tnode->tree_exi);
 880                         mutex_exit(&nfs_exi_id_lock);
 881                         export_unlink(ne, tnode->tree_exi);
 882                         exi_rele(tnode->tree_exi);

 883                 }
 884 
 885                 /* Release visible in parent's exportinfo */
 886                 if (tnode->tree_vis != NULL)
 887                         less_visible(vis2exi(tnode), tnode->tree_vis);
 888 
 889                 /* Continue with parent */
 890                 old_nd = tnode;
 891                 tnode = tnode->tree_parent;
 892 
 893                 /* Remove itself, if this is a leaf and non-exported node */
 894                 if (old_nd->tree_child_first == NULL &&
 895                     !TREE_EXPORTED(old_nd)) {
 896                         tree_remove_node(ne, old_nd);
 897                         connect_point = tnode;
 898                 }
 899         }
 900 
 901         /* Update the change timestamp */
 902         if (connect_point != NULL)
 903                 tree_update_change(ne, connect_point, NULL);
 904 }
 905 
 906 /*
 907  * Traverse backward across mountpoint from the
 908  * root vnode of a filesystem to its mounted-on
 909  * vnode.


 910  */
 911 vnode_t *
 912 untraverse(vnode_t *vp)
 913 {
 914         vnode_t *tvp, *nextvp;
 915 
 916         tvp = vp;
 917         for (;;) {
 918                 if (!(tvp->v_flag & VROOT) && !VN_IS_CURZONEROOT(tvp))
 919                         break;
 920 
 921                 /* lock vfs to prevent unmount of this vfs */
 922                 vfs_lock_wait(tvp->v_vfsp);
 923 
 924                 if ((nextvp = tvp->v_vfsp->vfs_vnodecovered) == NULL) {
 925                         vfs_unlock(tvp->v_vfsp);
 926                         break;
 927                 }
 928 
 929                 /*


 946 
 947 /*
 948  * Given an exportinfo, climb up to find the exportinfo for the VROOT
 949  * (or zone root) of the filesystem.
 950  *
 951  * e.g.         /
 952  *              |
 953  *              a (VROOT) pseudo-exportinfo
 954  *              |
 955  *              b
 956  *              |
 957  *              c  #share /a/b/c
 958  *              |
 959  *              d
 960  *
 961  * where c is in the same filesystem as a.
 962  * So, get_root_export(*exportinfo_for_c) returns exportinfo_for_a
 963  *
 964  * If d is shared, then c will be put into a's visible list.
 965  * Note: visible list is per filesystem and is attached to the
 966  * VROOT exportinfo.
 967  */
 968 struct exportinfo *
 969 get_root_export(struct exportinfo *exip)
 970 {
 971         treenode_t *tnode = exip->exi_tree;
 972         exportinfo_t *exi = NULL;
 973 
 974         while (tnode) {
 975                 if (TREE_ROOT(tnode)) {
 976                         exi = tnode->tree_exi;
 977                         break;
 978                 }
 979                 tnode = tnode->tree_parent;
 980         }
 981         ASSERT(exi);
 982         return (exi);
 983 }
 984 
 985 /*
 986  * Return true if the supplied vnode has a sub-directory exported.




 149 pseudo_exportfs(nfs_export_t *ne, vnode_t *vp, fid_t *fid,
 150     struct exp_visible *vis_head, struct exportdata *exdata)
 151 {
 152         struct exportinfo *exi;
 153         struct exportdata *kex;
 154         fsid_t fsid;
 155         int vpathlen;
 156         int i;
 157 
 158         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
 159 
 160         fsid = vp->v_vfsp->vfs_fsid;
 161         exi = kmem_zalloc(sizeof (*exi), KM_SLEEP);
 162         exi->exi_fsid = fsid;
 163         exi->exi_fid = *fid;
 164         exi->exi_vp = vp;
 165         VN_HOLD(exi->exi_vp);
 166         exi->exi_visible = vis_head;
 167         exi->exi_count = 1;
 168         /* Caller will set exi_zone... */
 169         /* XXX KEBE SAYS Uncomment me or fix in the caller */
 170         /* exi->exi_zoneid = ne->ne_globals->nfs_zoneid; */
 171         exi->exi_volatile_dev = (vfssw[vp->v_vfsp->vfs_fstype].vsw_flag &
 172             VSW_VOLATILEDEV) ? 1 : 0;
 173         mutex_init(&exi->exi_lock, NULL, MUTEX_DEFAULT, NULL);

 174 
 175         /*
 176          * Build up the template fhandle
 177          */
 178         exi->exi_fh.fh_fsid = fsid;
 179         ASSERT(exi->exi_fid.fid_len <= sizeof (exi->exi_fh.fh_xdata));
 180         exi->exi_fh.fh_xlen = exi->exi_fid.fid_len;
 181         bcopy(exi->exi_fid.fid_data, exi->exi_fh.fh_xdata,
 182             exi->exi_fid.fid_len);
 183         exi->exi_fh.fh_len = sizeof (exi->exi_fh.fh_data);
 184 
 185         kex = &exi->exi_export;
 186         kex->ex_flags = EX_PSEUDO;
 187 
 188         vpathlen = strlen(vp->v_path);
 189         kex->ex_pathlen = vpathlen + strlen(PSEUDOFS_SUFFIX);
 190         kex->ex_path = kmem_alloc(kex->ex_pathlen + 1, KM_SLEEP);
 191 
 192         if (vpathlen)
 193                 (void) strncpy(kex->ex_path, vp->v_path, vpathlen);


 644         timespec_t now;
 645         nfs_export_t *ne = nfs_get_export();
 646 
 647         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
 648         ASSERT3P(curzone, ==, exip->exi_zone);
 649 
 650         gethrestime(&now);
 651 
 652         vp = exip->exi_vp;
 653         VN_HOLD(vp);
 654         exportdir = 1;
 655 
 656         for (;;) {
 657 
 658                 bzero(&fid, sizeof (fid));
 659                 fid.fid_len = MAXFIDSZ;
 660                 error = vop_fid_pseudo(vp, &fid);
 661                 if (error)
 662                         break;
 663 
 664                 ASSERT3U(exip->exi_zoneid, ==, curzone->zone_id);
 665                 /*
 666                  * The root of the file system, or the zone's root for
 667                  * in-zone NFS service needs special handling
 668                  */
 669                 if (vp->v_flag & VROOT || VN_IS_CURZONEROOT(vp)) {
 670                         if (!exportdir) {
 671                                 struct exportinfo *exi;
 672 
 673                                 /*
 674                                  * Check if this VROOT dir is already exported.
 675                                  * If so, then attach the pseudonodes.  If not,
 676                                  * then continue .. traversal until we hit a
 677                                  * VROOT export (pseudo or real).
 678                                  */
 679                                 exi = checkexport4(&vp->v_vfsp->vfs_fsid, &fid,
 680                                     vp);
 681                                 if (exi != NULL) {
 682                                         /*
 683                                          * Found an export info
 684                                          *
 685                                          * Extend the list of visible
 686                                          * directories whether it's a pseudo
 687                                          * or a real export.
 688                                          */
 689                                         more_visible(exi, tree_head);
 690                                         break;  /* and climb no further */
 691                                 }
 692 
 693                                 /*
 694                                  * Found the root directory of a filesystem
 695                                  * that isn't exported.  Need to export
 696                                  * this as a pseudo export so that an NFS v4
 697                                  * client can do lookups in it.
 698                                  */
 699                                 new_exi = pseudo_exportfs(ne, vp, &fid,
 700                                     vis_head, NULL);
 701                                 /* XXX KEBE SAYS NUKE ME */
 702                                 new_exi->exi_zone = exip->exi_zone;
 703                                 vis_head = NULL;
 704                         }
 705 
 706                         if (VN_IS_CURZONEROOT(vp)) {
 707                                 /* at system root */
 708                                 /*
 709                                  * If sharing "/", new_exi is shared exportinfo
 710                                  * (exip). Otherwise, new_exi is exportinfo
 711                                  * created by pseudo_exportfs() above.
 712                                  */
 713                                 ne->ns_root = tree_prepend_node(tree_head, NULL,
 714                                     new_exi);
 715 
 716                                 /* Update the change timestamp */
 717                                 tree_update_change(ne, ne->ns_root, &now);
 718 
 719                                 break;
 720                         }
 721 


 866                 tnode->tree_vis->vis_exported = 0;
 867 
 868         while (tnode != NULL) {
 869 
 870                 /*
 871                  * Stop at VROOT (or zone root) node which is exported or has
 872                  * child.
 873                  */
 874                 if (TREE_ROOT(tnode) &&
 875                     (TREE_EXPORTED(tnode) || tnode->tree_child_first != NULL))
 876                         break;
 877 
 878                 /* Release pseudo export if it has no child */
 879                 if (TREE_ROOT(tnode) && !TREE_EXPORTED(tnode) &&
 880                     tnode->tree_child_first == NULL) {
 881                         mutex_enter(&nfs_exi_id_lock);
 882                         avl_remove(&exi_id_tree, tnode->tree_exi);
 883                         mutex_exit(&nfs_exi_id_lock);
 884                         export_unlink(ne, tnode->tree_exi);
 885                         exi_rele(tnode->tree_exi);
 886                         tnode->tree_exi = NULL;
 887                 }
 888 
 889                 /* Release visible in parent's exportinfo */
 890                 if (tnode->tree_vis != NULL)
 891                         less_visible(vis2exi(tnode), tnode->tree_vis);
 892 
 893                 /* Continue with parent */
 894                 old_nd = tnode;
 895                 tnode = tnode->tree_parent;
 896 
 897                 /* Remove itself, if this is a leaf and non-exported node */
 898                 if (old_nd->tree_child_first == NULL &&
 899                     !TREE_EXPORTED(old_nd)) {
 900                         tree_remove_node(ne, old_nd);
 901                         connect_point = tnode;
 902                 }
 903         }
 904 
 905         /* Update the change timestamp */
 906         if (connect_point != NULL)
 907                 tree_update_change(ne, connect_point, NULL);
 908 }
 909 
 910 /*
 911  * Traverse backward across mountpoint from the
 912  * root vnode of a filesystem to its mounted-on
 913  * vnode.
 914  *
 915  * Callers to this function have confirmed the use of curzone is safe here.
 916  */
 917 vnode_t *
 918 untraverse(vnode_t *vp)
 919 {
 920         vnode_t *tvp, *nextvp;
 921 
 922         tvp = vp;
 923         for (;;) {
 924                 if (!(tvp->v_flag & VROOT) && !VN_IS_CURZONEROOT(tvp))
 925                         break;
 926 
 927                 /* lock vfs to prevent unmount of this vfs */
 928                 vfs_lock_wait(tvp->v_vfsp);
 929 
 930                 if ((nextvp = tvp->v_vfsp->vfs_vnodecovered) == NULL) {
 931                         vfs_unlock(tvp->v_vfsp);
 932                         break;
 933                 }
 934 
 935                 /*


 952 
 953 /*
 954  * Given an exportinfo, climb up to find the exportinfo for the VROOT
 955  * (or zone root) of the filesystem.
 956  *
 957  * e.g.         /
 958  *              |
 959  *              a (VROOT) pseudo-exportinfo
 960  *              |
 961  *              b
 962  *              |
 963  *              c  #share /a/b/c
 964  *              |
 965  *              d
 966  *
 967  * where c is in the same filesystem as a.
 968  * So, get_root_export(*exportinfo_for_c) returns exportinfo_for_a
 969  *
 970  * If d is shared, then c will be put into a's visible list.
 971  * Note: visible list is per filesystem and is attached to the
 972  * VROOT exportinfo.  Returned exi does NOT have a new hold.
 973  */
 974 struct exportinfo *
 975 get_root_export(struct exportinfo *exip)
 976 {
 977         treenode_t *tnode = exip->exi_tree;
 978         exportinfo_t *exi = NULL;
 979 
 980         while (tnode) {
 981                 if (TREE_ROOT(tnode)) {
 982                         exi = tnode->tree_exi;
 983                         break;
 984                 }
 985                 tnode = tnode->tree_parent;
 986         }
 987         ASSERT(exi);
 988         return (exi);
 989 }
 990 
 991 /*
 992  * Return true if the supplied vnode has a sub-directory exported.