Print this page
Try to remove assumption that zone's root vnode is marked VROOT

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c
          +++ new/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c
↓ open down ↓ 134 lines elided ↑ open up ↑
 135  135   * mountpoint along the path, then it calls this
 136  136   * function to export it.
 137  137   *
 138  138   * This pseudo export differs from a real export in that
 139  139   * it only allows read-only access.  A "visible" list of
 140  140   * directories is added to filter lookup and readdir results
 141  141   * to only contain dirnames which lead to descendant shares.
 142  142   *
 143  143   * A visible list has a per-file-system scope.  Any exportinfo
 144  144   * struct (real or pseudo) can have a visible list as long as
 145      - * a) its export root is VROOT
      145 + * a) its export root is VROOT, or is the zone's root for in-zone NFS service
 146  146   * b) a descendant of the export root is shared
 147  147   */
 148  148  struct exportinfo *
 149  149  pseudo_exportfs(nfs_export_t *ne, vnode_t *vp, fid_t *fid, struct exp_visible *vis_head,
 150  150      struct exportdata *exdata)
 151  151  {
 152  152          struct exportinfo *exi;
 153  153          struct exportdata *kex;
 154  154          fsid_t fsid;
 155  155          int vpathlen;
↓ open down ↓ 495 lines elided ↑ open up ↑
 651  651  
 652  652          for (;;) {
 653  653  
 654  654                  bzero(&fid, sizeof (fid));
 655  655                  fid.fid_len = MAXFIDSZ;
 656  656                  error = vop_fid_pseudo(vp, &fid);
 657  657                  if (error)
 658  658                          break;
 659  659  
 660  660                  /*
 661      -                 * The root of the file system needs special handling
      661 +                 * The root of the file system, or the zone's root for
      662 +                 * in-zone NFS service needs special handling
 662  663                   */
 663      -                if (vp->v_flag & VROOT) {
 664      -                        if (! exportdir) {
      664 +                if (vp->v_flag & VROOT || VN_IS_CURZONEROOT(vp)) {
      665 +                        if (!exportdir) {
 665  666                                  struct exportinfo *exi;
 666  667  
 667  668                                  /*
 668  669                                   * Check if this VROOT dir is already exported.
 669  670                                   * If so, then attach the pseudonodes.  If not,
 670  671                                   * then continue .. traversal until we hit a
 671  672                                   * VROOT export (pseudo or real).
 672  673                                   */
 673  674                                  exi = checkexport4(&vp->v_vfsp->vfs_fsid, &fid,
 674  675                                      vp);
↓ open down ↓ 13 lines elided ↑ open up ↑
 688  689                                   * Found the root directory of a filesystem
 689  690                                   * that isn't exported.  Need to export
 690  691                                   * this as a pseudo export so that an NFS v4
 691  692                                   * client can do lookups in it.
 692  693                                   */
 693  694                                  new_exi = pseudo_exportfs(ne, vp, &fid,
 694  695                                      vis_head, NULL);
 695  696                                  vis_head = NULL;
 696  697                          }
 697  698  
 698      -                        if (VN_CMP(vp, ZONE_ROOTVP())) {
      699 +                        if (VN_IS_CURZONEROOT(vp)) {
 699  700                                  /* at system root */
 700  701                                  /*
 701  702                                   * If sharing "/", new_exi is shared exportinfo
 702  703                                   * (exip). Otherwise, new_exi is exportinfo
 703  704                                   * created by pseudo_exportfs() above.
 704  705                                   */
 705  706                                  ne->ns_root = tree_prepend_node(tree_head, NULL,
 706  707                                      new_exi);
 707  708  
 708  709                                  /* Update the change timestamp */
↓ open down ↓ 109 lines elided ↑ open up ↑
 818  819  /*
 819  820   * Walk up the tree and:
 820  821   * 1. release pseudo exportinfo if it has no child
 821  822   * 2. release visible in parent's exportinfo
 822  823   * 3. delete non-exported leaf nodes from tree
 823  824   *
 824  825   * Deleting of nodes will start only if the unshared
 825  826   * node was a leaf node.
 826  827   * Deleting of nodes will finish when we reach a node which
 827  828   * has children or is a real export, then we might still need
 828      - * to continue releasing visibles, until we reach VROOT node.
      829 + * to continue releasing visibles, until we reach VROOT or zone's root node.
 829  830   */
 830  831  void
 831  832  treeclimb_unexport(nfs_export_t *ne, struct exportinfo *exip)
 832  833  {
 833  834          treenode_t *tnode, *old_nd;
 834  835          treenode_t *connect_point = NULL;
 835  836  
 836  837          ASSERT(RW_WRITE_HELD(&ne->exported_lock));
 837  838  
 838  839          tnode = exip->exi_tree;
↓ open down ↓ 1 lines elided ↑ open up ↑
 840  841           * The unshared exportinfo was unlinked in unexport().
 841  842           * Zeroing tree_exi ensures that we will skip it.
 842  843           */
 843  844          tnode->tree_exi = NULL;
 844  845  
 845  846          if (tnode->tree_vis != NULL) /* system root has tree_vis == NULL */
 846  847                  tnode->tree_vis->vis_exported = 0;
 847  848  
 848  849          while (tnode != NULL) {
 849  850  
 850      -                /* Stop at VROOT node which is exported or has child */
      851 +                /*
      852 +                 * Stop at VROOT (or zone root) node which is exported or has
      853 +                 * child.
      854 +                 */
 851  855                  if (TREE_ROOT(tnode) &&
 852  856                      (TREE_EXPORTED(tnode) || tnode->tree_child_first != NULL))
 853  857                          break;
 854  858  
 855  859                  /* Release pseudo export if it has no child */
 856  860                  if (TREE_ROOT(tnode) && !TREE_EXPORTED(tnode) &&
 857  861                      tnode->tree_child_first == NULL) {
 858  862                          mutex_enter(&nfs_exi_id_lock);
 859  863                          avl_remove(&exi_id_tree, tnode->tree_exi);
 860  864                          mutex_exit(&nfs_exi_id_lock);
↓ open down ↓ 27 lines elided ↑ open up ↑
 888  892   * root vnode of a filesystem to its mounted-on
 889  893   * vnode.
 890  894   */
 891  895  vnode_t *
 892  896  untraverse(vnode_t *vp)
 893  897  {
 894  898          vnode_t *tvp, *nextvp;
 895  899  
 896  900          tvp = vp;
 897  901          for (;;) {
 898      -                if (! (tvp->v_flag & VROOT))
      902 +                if (!(tvp->v_flag & VROOT) && !VN_IS_CURZONEROOT(tvp))
 899  903                          break;
 900  904  
 901  905                  /* lock vfs to prevent unmount of this vfs */
 902  906                  vfs_lock_wait(tvp->v_vfsp);
 903  907  
 904  908                  if ((nextvp = tvp->v_vfsp->vfs_vnodecovered) == NULL) {
 905  909                          vfs_unlock(tvp->v_vfsp);
 906  910                          break;
 907  911                  }
 908  912  
↓ open down ↓ 10 lines elided ↑ open up ↑
 919  923                  vfs_unlock(tvp->v_vfsp);
 920  924                  VN_RELE(tvp);
 921  925                  tvp = nextvp;
 922  926          }
 923  927  
 924  928          return (tvp);
 925  929  }
 926  930  
 927  931  /*
 928  932   * Given an exportinfo, climb up to find the exportinfo for the VROOT
 929      - * of the filesystem.
      933 + * (or zone root) of the filesystem.
 930  934   *
 931  935   * e.g.         /
 932  936   *              |
 933  937   *              a (VROOT) pseudo-exportinfo
 934  938   *              |
 935  939   *              b
 936  940   *              |
 937  941   *              c  #share /a/b/c
 938  942   *              |
 939  943   *              d
↓ open down ↓ 28 lines elided ↑ open up ↑
 968  972  int
 969  973  has_visible(struct exportinfo *exi, vnode_t *vp)
 970  974  {
 971  975          struct exp_visible *visp;
 972  976          fid_t fid;
 973  977          bool_t vp_is_exported;
 974  978  
 975  979          vp_is_exported = VN_CMP(vp, exi->exi_vp);
 976  980  
 977  981          /*
 978      -         * An exported root vnode has a sub-dir shared if it has a visible list.
 979      -         * i.e. if it does not have a visible list, then there is no node in
 980      -         * this filesystem leads to any other shared node.
      982 +         * An exported root vnode has a sub-dir shared if it has a visible
      983 +         * list.  i.e. if it does not have a visible list, then there is no
      984 +         * node in this filesystem leads to any other shared node.
 981  985           */
 982      -        if (vp_is_exported && (vp->v_flag & VROOT))
      986 +        if (vp_is_exported &&
      987 +            ((vp->v_flag & VROOT) || VN_IS_CURZONEROOT(vp))) {
 983  988                  return (exi->exi_visible ? 1 : 0);
      989 +        }
 984  990  
 985  991          /*
 986  992           * Only the exportinfo of a fs root node may have a visible list.
 987  993           * Either it is a pseudo root node, or a real exported root node.
 988  994           */
 989  995          exi = get_root_export(exi);
 990  996  
 991  997          if (!exi->exi_visible)
 992  998                  return (0);
 993  999  
↓ open down ↓ 52 lines elided ↑ open up ↑
1046 1052           */
1047 1053          if (VN_CMP(vp, exi->exi_vp)) {
1048 1054                  *expseudo = 0;
1049 1055                  return (1);
1050 1056          }
1051 1057  
1052 1058          /*
1053 1059           * Only a PSEUDO node has a visible list or an exported VROOT
1054 1060           * node may have a visible list.
1055 1061           */
1056      -        if (! PSEUDO(exi))
     1062 +        if (!PSEUDO(exi))
1057 1063                  exi = get_root_export(exi);
1058 1064  
1059 1065          /* Get the fid of the vnode */
1060 1066  
1061 1067          bzero(&fid, sizeof (fid));
1062 1068          fid.fid_len = MAXFIDSZ;
1063 1069          if (vop_fid_pseudo(vp, &fid) != 0) {
1064 1070                  *expseudo = 0;
1065 1071                  return (0);
1066 1072          }
↓ open down ↓ 87 lines elided ↑ open up ↑
1154 1160   * skips . and .. entries.
1155 1161   */
1156 1162  int
1157 1163  nfs_visible_inode(struct exportinfo *exi, ino64_t ino,
1158 1164      struct exp_visible **visp)
1159 1165  {
1160 1166          /*
1161 1167           * Only a PSEUDO node has a visible list or an exported VROOT
1162 1168           * node may have a visible list.
1163 1169           */
1164      -        if (! PSEUDO(exi))
     1170 +        if (!PSEUDO(exi))
1165 1171                  exi = get_root_export(exi);
1166 1172  
1167 1173          for (*visp = exi->exi_visible; *visp != NULL; *visp = (*visp)->vis_next)
1168 1174                  if ((u_longlong_t)ino == (*visp)->vis_ino) {
1169 1175                          return (1);
1170 1176                  }
1171 1177  
1172 1178          return (0);
1173 1179  }
1174 1180  
↓ open down ↓ 89 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX