Print this page
Revert exi_zone to exi_zoneid, and install exi_ne backpointer


 148 struct exportinfo *
 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);


 625  *  (d)      (e)      f         m EXPORT,f1(f2)    p
 626  *  EXPORT   EXPORT             |                  |
 627  *  f1       f2                 |                  |
 628  *           |                  |                  |
 629  *           j                 (o) EXPORT,f2       q EXPORT f2
 630  *
 631  */
 632 int
 633 treeclimb_export(struct exportinfo *exip)
 634 {
 635         vnode_t *dvp, *vp;
 636         fid_t fid;
 637         int error;
 638         int exportdir;
 639         struct exportinfo *new_exi = exip;
 640         struct exp_visible *visp;
 641         struct exp_visible *vis_head = NULL;
 642         struct vattr va;
 643         treenode_t *tree_head = NULL;
 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 
 722                         /*


 825 
 826 /*
 827  * Walk up the tree and:
 828  * 1. release pseudo exportinfo if it has no child
 829  * 2. release visible in parent's exportinfo
 830  * 3. delete non-exported leaf nodes from tree
 831  *
 832  * Deleting of nodes will start only if the unshared
 833  * node was a leaf node.
 834  * Deleting of nodes will finish when we reach a node which
 835  * has children or is a real export, then we might still need
 836  * to continue releasing visibles, until we reach VROOT or zone's root node.
 837  */
 838 void
 839 treeclimb_unexport(nfs_export_t *ne, struct exportinfo *exip)
 840 {
 841         treenode_t *tnode, *old_nd;
 842         treenode_t *connect_point = NULL;
 843 
 844         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
 845         ASSERT(curzone == exip->exi_zone || curzone == global_zone);

 846 
 847         /*
 848          * exi_tree can be null for the zone root
 849          * which means we're already at the "top"
 850          * and there's nothing more to "climb".
 851          */
 852         tnode = exip->exi_tree;
 853         if (tnode == NULL) {
 854                 /* Should only happen for... */
 855                 ASSERT(exip == ne->exi_root);
 856                 return;
 857         }
 858 
 859         /*
 860          * The unshared exportinfo was unlinked in unexport().
 861          * Zeroing tree_exi ensures that we will skip it.
 862          */
 863         tnode->tree_exi = NULL;
 864 
 865         if (tnode->tree_vis != NULL) /* system root has tree_vis == NULL */


 988         return (exi);
 989 }
 990 
 991 /*
 992  * Return true if the supplied vnode has a sub-directory exported.
 993  */
 994 int
 995 has_visible(struct exportinfo *exi, vnode_t *vp)
 996 {
 997         struct exp_visible *visp;
 998         fid_t fid;
 999         bool_t vp_is_exported;
1000 
1001         vp_is_exported = VN_CMP(vp, exi->exi_vp);
1002 
1003         /*
1004          * An exported root vnode has a sub-dir shared if it has a visible
1005          * list.  i.e. if it does not have a visible list, then there is no
1006          * node in this filesystem leads to any other shared node.
1007          */
1008         ASSERT3P(curzone, ==, exi->exi_zone);
1009         if (vp_is_exported &&
1010             ((vp->v_flag & VROOT) || VN_IS_CURZONEROOT(vp))) {
1011                 return (exi->exi_visible ? 1 : 0);
1012         }
1013 
1014         /*
1015          * Only the exportinfo of a fs root node may have a visible list.
1016          * Either it is a pseudo root node, or a real exported root node.
1017          */
1018         exi = get_root_export(exi);
1019 
1020         if (!exi->exi_visible)
1021                 return (0);
1022 
1023         /* Get the fid of the vnode */
1024         bzero(&fid, sizeof (fid));
1025         fid.fid_len = MAXFIDSZ;
1026         if (vop_fid_pseudo(vp, &fid) != 0) {
1027                 return (0);
1028         }




 148 struct exportinfo *
 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         exi->exi_zoneid = ne->ne_globals->nfs_zoneid;


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


 623  *  (d)      (e)      f         m EXPORT,f1(f2)    p
 624  *  EXPORT   EXPORT             |                  |
 625  *  f1       f2                 |                  |
 626  *           |                  |                  |
 627  *           j                 (o) EXPORT,f2       q EXPORT f2
 628  *
 629  */
 630 int
 631 treeclimb_export(struct exportinfo *exip)
 632 {
 633         vnode_t *dvp, *vp;
 634         fid_t fid;
 635         int error;
 636         int exportdir;
 637         struct exportinfo *new_exi = exip;
 638         struct exp_visible *visp;
 639         struct exp_visible *vis_head = NULL;
 640         struct vattr va;
 641         treenode_t *tree_head = NULL;
 642         timespec_t now;
 643         nfs_export_t *ne;
 644 
 645         ne = exip->exi_ne;
 646         ASSERT3P(ne, ==, nfs_get_export());     /* curzone reality check */
 647         ASSERT(RW_WRITE_HELD(&ne->exported_lock));

 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                 /* XXX KEBE ASKS DO WE NEED THIS?!? */
 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 || vp == EXI_TO_ZONEROOTVP(exip)) {
 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                                 vis_head = NULL;
 702                         }
 703 
 704                         if (VN_IS_CURZONEROOT(vp)) {
 705                                 /* at system root */
 706                                 /*
 707                                  * If sharing "/", new_exi is shared exportinfo
 708                                  * (exip). Otherwise, new_exi is exportinfo
 709                                  * created by pseudo_exportfs() above.
 710                                  */
 711                                 ne->ns_root = tree_prepend_node(tree_head, NULL,
 712                                     new_exi);
 713 
 714                                 /* Update the change timestamp */
 715                                 tree_update_change(ne, ne->ns_root, &now);
 716 
 717                                 break;
 718                         }
 719 
 720                         /*


 823 
 824 /*
 825  * Walk up the tree and:
 826  * 1. release pseudo exportinfo if it has no child
 827  * 2. release visible in parent's exportinfo
 828  * 3. delete non-exported leaf nodes from tree
 829  *
 830  * Deleting of nodes will start only if the unshared
 831  * node was a leaf node.
 832  * Deleting of nodes will finish when we reach a node which
 833  * has children or is a real export, then we might still need
 834  * to continue releasing visibles, until we reach VROOT or zone's root node.
 835  */
 836 void
 837 treeclimb_unexport(nfs_export_t *ne, struct exportinfo *exip)
 838 {
 839         treenode_t *tnode, *old_nd;
 840         treenode_t *connect_point = NULL;
 841 
 842         ASSERT(RW_WRITE_HELD(&ne->exported_lock));
 843         ASSERT(curzone->zone_id == exip->exi_zoneid ||
 844             curzone->zone_id == global_zone->zone_id);
 845 
 846         /*
 847          * exi_tree can be null for the zone root
 848          * which means we're already at the "top"
 849          * and there's nothing more to "climb".
 850          */
 851         tnode = exip->exi_tree;
 852         if (tnode == NULL) {
 853                 /* Should only happen for... */
 854                 ASSERT(exip == ne->exi_root);
 855                 return;
 856         }
 857 
 858         /*
 859          * The unshared exportinfo was unlinked in unexport().
 860          * Zeroing tree_exi ensures that we will skip it.
 861          */
 862         tnode->tree_exi = NULL;
 863 
 864         if (tnode->tree_vis != NULL) /* system root has tree_vis == NULL */


 987         return (exi);
 988 }
 989 
 990 /*
 991  * Return true if the supplied vnode has a sub-directory exported.
 992  */
 993 int
 994 has_visible(struct exportinfo *exi, vnode_t *vp)
 995 {
 996         struct exp_visible *visp;
 997         fid_t fid;
 998         bool_t vp_is_exported;
 999 
1000         vp_is_exported = VN_CMP(vp, exi->exi_vp);
1001 
1002         /*
1003          * An exported root vnode has a sub-dir shared if it has a visible
1004          * list.  i.e. if it does not have a visible list, then there is no
1005          * node in this filesystem leads to any other shared node.
1006          */
1007         ASSERT3P(curzone->zone_id, ==, exi->exi_zoneid);
1008         if (vp_is_exported &&
1009             ((vp->v_flag & VROOT) || VN_IS_CURZONEROOT(vp))) {
1010                 return (exi->exi_visible ? 1 : 0);
1011         }
1012 
1013         /*
1014          * Only the exportinfo of a fs root node may have a visible list.
1015          * Either it is a pseudo root node, or a real exported root node.
1016          */
1017         exi = get_root_export(exi);
1018 
1019         if (!exi->exi_visible)
1020                 return (0);
1021 
1022         /* Get the fid of the vnode */
1023         bzero(&fid, sizeof (fid));
1024         fid.fid_len = MAXFIDSZ;
1025         if (vop_fid_pseudo(vp, &fid) != 0) {
1026                 return (0);
1027         }