Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-16818 Add fksmbcl development tool
NEX-17264 SMB client test tp_smbutil_013 fails after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (fix ref leaks)
5404 smbfs needs mmap support
Portions contributed by: Gordon Ross <gordon.w.ross@gmail.com>
Reviewed by: C Fraire <cfraire@me.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Jason King <jason.brian.king@gmail.com>
Reviewed by: Andrew Stormont <andyjstormont@gmail.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
2552 smbfs: add support for NFS-like remove
Portions contributed by: Gordon Ross <gordon.w.ross@gmail.com>
Reviewed by: Yuri Pankov <yuripv@yuripv.net>
Reviewed by: Jason King <jason.king@joyent.com>
Reviewed by: C Fraire <cfraire@me.com>
Approved by: Richard Lowe <richlowe@richlowe.net>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr2.c
          +++ new/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr2.c
↓ open down ↓ 19 lines elided ↑ open up ↑
  20   20   */
  21   21  /*
  22   22   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   *
  25   25   *      Copyright (c) 1983,1984,1985,1986,1987,1988,1989  AT&T.
  26   26   *      All rights reserved.
  27   27   */
  28   28  /*
  29   29   * Copyright (c) 2017 by Delphix. All rights reserved.
       30 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  30   31   */
  31   32  
  32   33  /*
  33   34   * Node hash implementation initially borrowed from NFS (nfs_subr.c)
  34   35   * but then heavily modified. It's no longer an array of hash lists,
  35   36   * but an AVL tree per mount point.  More on this below.
  36   37   */
  37   38  
  38   39  #include <sys/param.h>
  39   40  #include <sys/systm.h>
  40   41  #include <sys/time.h>
  41   42  #include <sys/vnode.h>
       43 +#include <sys/atomic.h>
  42   44  #include <sys/bitmap.h>
       45 +#include <sys/buf.h>
  43   46  #include <sys/dnlc.h>
  44   47  #include <sys/kmem.h>
  45   48  #include <sys/sunddi.h>
  46   49  #include <sys/sysmacros.h>
       50 +#include <sys/fcntl.h>
  47   51  
  48   52  #include <netsmb/smb_osdep.h>
  49   53  
  50   54  #include <netsmb/smb.h>
  51   55  #include <netsmb/smb_conn.h>
  52   56  #include <netsmb/smb_subr.h>
  53   57  #include <netsmb/smb_rq.h>
  54   58  
  55   59  #include <smbfs/smbfs.h>
  56   60  #include <smbfs/smbfs_node.h>
↓ open down ↓ 87 lines elided ↑ open up ↑
 144  148  static smbnode_t *
 145  149  sn_hashfind(smbmntinfo_t *, const char *, int, avl_index_t *);
 146  150  
 147  151  static smbnode_t *
 148  152  make_smbnode(smbmntinfo_t *, const char *, int, int *);
 149  153  
 150  154  /*
 151  155   * Free the resources associated with an smbnode.
 152  156   * Note: This is different from smbfs_inactive
 153  157   *
 154      - * NFS: nfs_subr.c:rinactive
      158 + * From NFS: nfs_subr.c:rinactive
 155  159   */
 156  160  static void
 157  161  sn_inactive(smbnode_t *np)
 158  162  {
 159  163          vsecattr_t      ovsa;
 160  164          cred_t          *oldcr;
 161      -        char            *orpath;
      165 +        char            *orpath;
 162  166          int             orplen;
      167 +        vnode_t         *vp;
 163  168  
 164  169          /*
 165      -         * Flush and invalidate all pages (todo)
      170 +         * Here NFS has:
      171 +         * Flush and invalidate all pages (done by caller)
 166  172           * Free any held credentials and caches...
 167  173           * etc.  (See NFS code)
 168  174           */
 169  175          mutex_enter(&np->r_statelock);
 170  176  
 171  177          ovsa = np->r_secattr;
 172  178          np->r_secattr = smbfs_vsa0;
 173  179          np->r_sectime = 0;
 174  180  
 175  181          oldcr = np->r_cred;
 176  182          np->r_cred = NULL;
 177  183  
 178  184          orpath = np->n_rpath;
 179  185          orplen = np->n_rplen;
 180  186          np->n_rpath = NULL;
 181  187          np->n_rplen = 0;
 182  188  
 183  189          mutex_exit(&np->r_statelock);
 184  190  
      191 +        vp = SMBTOV(np);
      192 +        if (vn_has_cached_data(vp)) {
      193 +                ASSERT3P(vp,==,NULL);
      194 +        }
      195 +
 185  196          if (ovsa.vsa_aclentp != NULL)
 186  197                  kmem_free(ovsa.vsa_aclentp, ovsa.vsa_aclentsz);
 187  198  
 188  199          if (oldcr != NULL)
 189  200                  crfree(oldcr);
 190  201  
 191  202          if (orpath != NULL)
 192  203                  kmem_free(orpath, orplen + 1);
 193  204  }
 194  205  
↓ open down ↓ 2 lines elided ↑ open up ↑
 197  208   * mountinfo, directory, separator, and name.  If the
 198  209   * desired smbnode already exists, return a reference.
 199  210   * If the file attributes pointer is non-null, the node
 200  211   * is created if necessary and linked into the AVL tree.
 201  212   *
 202  213   * Callers that need a node created but don't have the
 203  214   * real attributes pass smbfs_fattr0 to force creation.
 204  215   *
 205  216   * Note: make_smbnode() may upgrade the "hash" lock to exclusive.
 206  217   *
 207      - * NFS: nfs_subr.c:makenfsnode
      218 + * Based on NFS: nfs_subr.c:makenfsnode
 208  219   */
 209  220  smbnode_t *
 210  221  smbfs_node_findcreate(
 211  222          smbmntinfo_t *mi,
 212  223          const char *dirnm,
 213  224          int dirlen,
 214  225          const char *name,
 215  226          int nmlen,
 216  227          char sep,
 217  228          struct smbfattr *fap)
↓ open down ↓ 61 lines elided ↑ open up ↑
 279  290           */
 280  291          ASSERT(np != NULL);
 281  292          if (fap == &smbfs_fattr0)
 282  293                  return (np);
 283  294  
 284  295          /*
 285  296           * Apply the given attributes to this node,
 286  297           * dealing with any cache impact, etc.
 287  298           */
 288  299          vp = SMBTOV(np);
 289      -        if (!newnode) {
 290      -                /*
 291      -                 * Found an existing node.
 292      -                 * Maybe purge caches...
 293      -                 */
 294      -                smbfs_cache_check(vp, fap);
 295      -        }
 296  300          smbfs_attrcache_fa(vp, fap);
 297  301  
 298  302          /*
 299  303           * Note NFS sets vp->v_type here, assuming it
 300  304           * can never change for the life of a node.
 301  305           * We allow v_type to change, and set it in
 302  306           * smbfs_attrcache().  Also: mode, uid, gid
 303  307           */
 304  308          return (np);
 305  309  }
 306  310  
 307  311  /*
 308      - * NFS: nfs_subr.c:rtablehash
      312 + * Here NFS has: nfs_subr.c:rtablehash
 309  313   * We use smbfs_hash().
 310  314   */
 311  315  
 312  316  /*
 313  317   * Find or create an smbnode.
 314      - * NFS: nfs_subr.c:make_rnode
      318 + * From NFS: nfs_subr.c:make_rnode
 315  319   */
 316  320  static smbnode_t *
 317  321  make_smbnode(
 318  322          smbmntinfo_t *mi,
 319  323          const char *rpath,
 320  324          int rplen,
 321  325          int *newnode)
 322  326  {
 323  327          smbnode_t *np;
 324  328          smbnode_t *tnp;
↓ open down ↓ 97 lines elided ↑ open up ↑
 422  426  
 423  427          smbfs_rw_init(&np->r_rwlock, NULL, RW_DEFAULT, NULL);
 424  428          smbfs_rw_init(&np->r_lkserlock, NULL, RW_DEFAULT, NULL);
 425  429          mutex_init(&np->r_statelock, NULL, MUTEX_DEFAULT, NULL);
 426  430          cv_init(&np->r_cv, NULL, CV_DEFAULT, NULL);
 427  431          /* cv_init(&np->r_commit.c_cv, NULL, CV_DEFAULT, NULL); */
 428  432  
 429  433          np->r_vnode = vp;
 430  434          np->n_mount = mi;
 431  435  
 432      -        np->n_fid = SMB_FID_UNUSED;
      436 +        np->n_fid = NULL;
 433  437          np->n_uid = mi->smi_uid;
 434  438          np->n_gid = mi->smi_gid;
 435  439          /* Leave attributes "stale." */
 436  440  
 437      -#if 0 /* XXX dircache */
 438  441          /*
 439      -         * We don't know if it's a directory yet.
 440      -         * Let the caller do this?  XXX
      442 +         * Here NFS has avl_create(&np->r_dir, ...)
      443 +         * for the readdir cache (not used here).
 441  444           */
 442      -        avl_create(&np->r_dir, compar, sizeof (rddir_cache),
 443      -            offsetof(rddir_cache, tree));
 444      -#endif
 445  445  
 446  446          /* Now fill in the vnode. */
 447  447          vn_setops(vp, smbfs_vnodeops);
 448  448          vp->v_data = (caddr_t)np;
 449  449          VFS_HOLD(vfsp);
 450  450          vp->v_vfsp = vfsp;
 451  451          vp->v_type = VNON;
 452  452  
 453  453          /*
 454  454           * We entered with mi->smi_hash_lk held (reader).
↓ open down ↓ 37 lines elided ↑ open up ↑
 492  492  
 493  493  /*
 494  494   * smbfs_addfree
 495  495   * Put an smbnode on the free list, or destroy it immediately
 496  496   * if it offers no value were it to be reclaimed later.  Also
 497  497   * destroy immediately when we have too many smbnodes, etc.
 498  498   *
 499  499   * Normally called by smbfs_inactive, but also
 500  500   * called in here during cleanup operations.
 501  501   *
 502      - * NFS: nfs_subr.c:rp_addfree
      502 + * From NFS: nfs_subr.c:rp_addfree
 503  503   */
 504  504  void
 505  505  smbfs_addfree(smbnode_t *np)
 506  506  {
 507  507          vnode_t *vp;
 508  508          struct vfs *vfsp;
 509  509          smbmntinfo_t *mi;
 510  510  
 511  511          ASSERT(np->r_freef == NULL && np->r_freeb == NULL);
 512  512  
↓ open down ↓ 107 lines elided ↑ open up ↑
 620  620  
 621  621          rw_exit(&mi->smi_hash_lk);
 622  622  }
 623  623  
 624  624  /*
 625  625   * Remove an smbnode from the free list.
 626  626   *
 627  627   * The caller must be holding smbfreelist_lock and the smbnode
 628  628   * must be on the freelist.
 629  629   *
 630      - * NFS: nfs_subr.c:rp_rmfree
      630 + * From NFS: nfs_subr.c:rp_rmfree
 631  631   */
 632  632  static void
 633  633  sn_rmfree(smbnode_t *np)
 634  634  {
 635  635  
 636  636          ASSERT(MUTEX_HELD(&smbfreelist_lock));
 637  637          ASSERT(np->r_freef != NULL && np->r_freeb != NULL);
 638  638  
 639  639          if (np == smbfreelist) {
 640  640                  smbfreelist = np->r_freef;
↓ open down ↓ 5 lines elided ↑ open up ↑
 646  646          np->r_freef->r_freeb = np->r_freeb;
 647  647  
 648  648          np->r_freef = np->r_freeb = NULL;
 649  649  }
 650  650  
 651  651  /*
 652  652   * Put an smbnode in the "hash" AVL tree.
 653  653   *
 654  654   * The caller must be hold the rwlock as writer.
 655  655   *
 656      - * NFS: nfs_subr.c:rp_addhash
      656 + * From NFS: nfs_subr.c:rp_addhash
 657  657   */
 658  658  static void
 659  659  sn_addhash_locked(smbnode_t *np, avl_index_t where)
 660  660  {
 661  661          smbmntinfo_t *mi = np->n_mount;
 662  662  
 663  663          ASSERT(RW_WRITE_HELD(&mi->smi_hash_lk));
 664      -        ASSERT(!(np->r_flags & RHASHED));
 665  664  
 666      -        avl_insert(&mi->smi_hash_avl, np, where);
 667      -
 668  665          mutex_enter(&np->r_statelock);
 669      -        np->r_flags |= RHASHED;
      666 +        if ((np->r_flags & RHASHED) == 0) {
      667 +                avl_insert(&mi->smi_hash_avl, np, where);
      668 +                np->r_flags |= RHASHED;
      669 +        }
 670  670          mutex_exit(&np->r_statelock);
 671  671  }
 672  672  
 673  673  /*
 674  674   * Remove an smbnode from the "hash" AVL tree.
 675  675   *
 676  676   * The caller must hold the rwlock as writer.
 677  677   *
 678      - * NFS: nfs_subr.c:rp_rmhash_locked
      678 + * From NFS: nfs_subr.c:rp_rmhash_locked
 679  679   */
 680  680  static void
 681  681  sn_rmhash_locked(smbnode_t *np)
 682  682  {
 683  683          smbmntinfo_t *mi = np->n_mount;
 684  684  
 685  685          ASSERT(RW_WRITE_HELD(&mi->smi_hash_lk));
 686      -        ASSERT(np->r_flags & RHASHED);
 687  686  
 688      -        avl_remove(&mi->smi_hash_avl, np);
 689      -
 690  687          mutex_enter(&np->r_statelock);
 691      -        np->r_flags &= ~RHASHED;
      688 +        if ((np->r_flags & RHASHED) != 0) {
      689 +                np->r_flags &= ~RHASHED;
      690 +                avl_remove(&mi->smi_hash_avl, np);
      691 +        }
 692  692          mutex_exit(&np->r_statelock);
 693  693  }
 694  694  
 695  695  /*
 696  696   * Remove an smbnode from the "hash" AVL tree.
 697  697   *
 698  698   * The caller must not be holding the rwlock.
 699  699   */
 700  700  void
 701  701  smbfs_rmhash(smbnode_t *np)
↓ open down ↓ 3 lines elided ↑ open up ↑
 705  705          rw_enter(&mi->smi_hash_lk, RW_WRITER);
 706  706          sn_rmhash_locked(np);
 707  707          rw_exit(&mi->smi_hash_lk);
 708  708  }
 709  709  
 710  710  /*
 711  711   * Lookup an smbnode by remote pathname
 712  712   *
 713  713   * The caller must be holding the AVL rwlock, either shared or exclusive.
 714  714   *
 715      - * NFS: nfs_subr.c:rfind
      715 + * From NFS: nfs_subr.c:rfind
 716  716   */
 717  717  static smbnode_t *
 718  718  sn_hashfind(
 719  719          smbmntinfo_t *mi,
 720  720          const char *rpath,
 721  721          int rplen,
 722  722          avl_index_t *pwhere) /* optional */
 723  723  {
 724  724          smbfs_node_hdr_t nhdr;
 725  725          smbnode_t *np;
↓ open down ↓ 134 lines elided ↑ open up ↑
 860  860  
 861  861  /*
 862  862   * Return 1 if there is a active vnode belonging to this vfs in the
 863  863   * smbnode cache.
 864  864   *
 865  865   * Several of these checks are done without holding the usual
 866  866   * locks.  This is safe because destroy_smbtable(), smbfs_addfree(),
 867  867   * etc. will redo the necessary checks before actually destroying
 868  868   * any smbnodes.
 869  869   *
 870      - * NFS: nfs_subr.c:check_rtable
      870 + * From NFS: nfs_subr.c:check_rtable
 871  871   *
 872  872   * Debugging changes here relative to NFS.
 873  873   * Relatively harmless, so left 'em in.
 874  874   */
 875  875  int
 876  876  smbfs_check_table(struct vfs *vfsp, smbnode_t *rtnp)
 877  877  {
 878  878          smbmntinfo_t *mi;
 879  879          smbnode_t *np;
 880  880          vnode_t *vp;
↓ open down ↓ 38 lines elided ↑ open up ↑
 919  919          rw_exit(&mi->smi_hash_lk);
 920  920  
 921  921          return (busycnt);
 922  922  }
 923  923  
 924  924  /*
 925  925   * Destroy inactive vnodes from the AVL tree which belong to this
 926  926   * vfs.  It is essential that we destroy all inactive vnodes during a
 927  927   * forced unmount as well as during a normal unmount.
 928  928   *
 929      - * NFS: nfs_subr.c:destroy_rtable
      929 + * Based on NFS: nfs_subr.c:destroy_rtable
 930  930   *
 931  931   * In here, we're normally destrying all or most of the AVL tree,
 932  932   * so the natural choice is to use avl_destroy_nodes.  However,
 933  933   * there may be a few busy nodes that should remain in the AVL
 934  934   * tree when we're done.  The solution: use a temporary tree to
 935  935   * hold the busy nodes until we're done destroying the old tree,
 936  936   * then copy the temporary tree over the (now emtpy) real tree.
 937  937   */
 938  938  void
 939  939  smbfs_destroy_table(struct vfs *vfsp)
↓ open down ↓ 64 lines elided ↑ open up ↑
1004 1004          while ((np = rlist) != NULL) {
1005 1005                  rlist = (smbnode_t *)np->r_avl_node.avl_child[0];
1006 1006                  smbfs_addfree(np);
1007 1007          }
1008 1008  }
1009 1009  
1010 1010  /*
1011 1011   * This routine destroys all the resources associated with the smbnode
1012 1012   * and then the smbnode itself.  Note: sn_inactive has been called.
1013 1013   *
1014      - * NFS: nfs_subr.c:destroy_rnode
     1014 + * From NFS: nfs_subr.c:destroy_rnode
1015 1015   */
1016 1016  static void
1017 1017  sn_destroy_node(smbnode_t *np)
1018 1018  {
1019 1019          vnode_t *vp;
1020 1020          vfs_t *vfsp;
1021 1021  
1022 1022          vp = SMBTOV(np);
1023 1023          vfsp = vp->v_vfsp;
1024 1024  
↓ open down ↓ 6 lines elided ↑ open up ↑
1031 1031          ASSERT(!(np->r_flags & RHASHED));
1032 1032          ASSERT(np->r_freef == NULL && np->r_freeb == NULL);
1033 1033          atomic_dec_ulong((ulong_t *)&smbnodenew);
1034 1034          vn_invalid(vp);
1035 1035          vn_free(vp);
1036 1036          kmem_cache_free(smbnode_cache, np);
1037 1037          VFS_RELE(vfsp);
1038 1038  }
1039 1039  
1040 1040  /*
     1041 + * From NFS rflush()
1041 1042   * Flush all vnodes in this (or every) vfs.
1042      - * Used by nfs_sync and by nfs_unmount.
     1043 + * Used by smbfs_sync and by smbfs_unmount.
1043 1044   */
1044 1045  /*ARGSUSED*/
1045 1046  void
1046 1047  smbfs_rflush(struct vfs *vfsp, cred_t *cr)
1047 1048  {
1048      -        /* Todo: mmap support. */
     1049 +        smbmntinfo_t *mi;
     1050 +        smbnode_t *np;
     1051 +        vnode_t *vp, **vplist;
     1052 +        long num, cnt;
     1053 +
     1054 +        mi = VFTOSMI(vfsp);
     1055 +
     1056 +        /*
     1057 +         * Check to see whether there is anything to do.
     1058 +         */
     1059 +        num = avl_numnodes(&mi->smi_hash_avl);
     1060 +        if (num == 0)
     1061 +                return;
     1062 +
     1063 +        /*
     1064 +         * Allocate a slot for all currently active rnodes on the
     1065 +         * supposition that they all may need flushing.
     1066 +         */
     1067 +        vplist = kmem_alloc(num * sizeof (*vplist), KM_SLEEP);
     1068 +        cnt = 0;
     1069 +
     1070 +        /*
     1071 +         * Walk the AVL tree looking for rnodes with page
     1072 +         * lists associated with them.  Make a list of these
     1073 +         * files.
     1074 +         */
     1075 +        rw_enter(&mi->smi_hash_lk, RW_READER);
     1076 +        for (np = avl_first(&mi->smi_hash_avl); np != NULL;
     1077 +            np = avl_walk(&mi->smi_hash_avl, np, AVL_AFTER)) {
     1078 +                vp = SMBTOV(np);
     1079 +                /*
     1080 +                 * Don't bother sync'ing a vp if it
     1081 +                 * is part of virtual swap device or
     1082 +                 * if VFS is read-only
     1083 +                 */
     1084 +                if (IS_SWAPVP(vp) || vn_is_readonly(vp))
     1085 +                        continue;
     1086 +                /*
     1087 +                 * If the vnode has pages and is marked as either
     1088 +                 * dirty or mmap'd, hold and add this vnode to the
     1089 +                 * list of vnodes to flush.
     1090 +                 */
     1091 +                if (vn_has_cached_data(vp) &&
     1092 +                    ((np->r_flags & RDIRTY) || np->r_mapcnt > 0)) {
     1093 +                        VN_HOLD(vp);
     1094 +                        vplist[cnt++] = vp;
     1095 +                        if (cnt == num)
     1096 +                                break;
     1097 +                }
     1098 +        }
     1099 +        rw_exit(&mi->smi_hash_lk);
     1100 +
     1101 +        /*
     1102 +         * Flush and release all of the files on the list.
     1103 +         */
     1104 +        while (cnt-- > 0) {
     1105 +                vp = vplist[cnt];
     1106 +                (void) VOP_PUTPAGE(vp, (u_offset_t)0, 0, B_ASYNC, cr, NULL);
     1107 +                VN_RELE(vp);
     1108 +        }
     1109 +
     1110 +        kmem_free(vplist, num * sizeof (vnode_t *));
1049 1111  }
1050 1112  
1051      -/* access cache */
1052      -/* client handles */
     1113 +/* Here NFS has access cache stuff (nfs_subr.c) not used here */
1053 1114  
1054 1115  /*
     1116 + * Set or Clear direct I/O flag
     1117 + * VOP_RWLOCK() is held for write access to prevent a race condition
     1118 + * which would occur if a process is in the middle of a write when
     1119 + * directio flag gets set. It is possible that all pages may not get flushed.
     1120 + * From nfs_common.c
     1121 + */
     1122 +
     1123 +/* ARGSUSED */
     1124 +int
     1125 +smbfs_directio(vnode_t *vp, int cmd, cred_t *cr)
     1126 +{
     1127 +        int     error = 0;
     1128 +        smbnode_t       *np;
     1129 +
     1130 +        np = VTOSMB(vp);
     1131 +
     1132 +        if (cmd == DIRECTIO_ON) {
     1133 +
     1134 +                if (np->r_flags & RDIRECTIO)
     1135 +                        return (0);
     1136 +
     1137 +                /*
     1138 +                 * Flush the page cache.
     1139 +                 */
     1140 +
     1141 +                (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
     1142 +
     1143 +                if (np->r_flags & RDIRECTIO) {
     1144 +                        VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
     1145 +                        return (0);
     1146 +                }
     1147 +
     1148 +                /* Here NFS also checks ->r_awcount */
     1149 +                if (vn_has_cached_data(vp) &&
     1150 +                    (np->r_flags & RDIRTY) != 0) {
     1151 +                        error = VOP_PUTPAGE(vp, (offset_t)0, (uint_t)0,
     1152 +                            B_INVAL, cr, NULL);
     1153 +                        if (error) {
     1154 +                                if (error == ENOSPC || error == EDQUOT) {
     1155 +                                        mutex_enter(&np->r_statelock);
     1156 +                                        if (!np->r_error)
     1157 +                                                np->r_error = error;
     1158 +                                        mutex_exit(&np->r_statelock);
     1159 +                                }
     1160 +                                VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
     1161 +                                return (error);
     1162 +                        }
     1163 +                }
     1164 +
     1165 +                mutex_enter(&np->r_statelock);
     1166 +                np->r_flags |= RDIRECTIO;
     1167 +                mutex_exit(&np->r_statelock);
     1168 +                VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
     1169 +                return (0);
     1170 +        }
     1171 +
     1172 +        if (cmd == DIRECTIO_OFF) {
     1173 +                mutex_enter(&np->r_statelock);
     1174 +                np->r_flags &= ~RDIRECTIO;      /* disable direct mode */
     1175 +                mutex_exit(&np->r_statelock);
     1176 +                return (0);
     1177 +        }
     1178 +
     1179 +        return (EINVAL);
     1180 +}
     1181 +
     1182 +static kmutex_t smbfs_newnum_lock;
     1183 +static uint32_t smbfs_newnum_val = 0;
     1184 +
     1185 +/*
     1186 + * Return a number 0..0xffffffff that's different from the last
     1187 + * 0xffffffff numbers this returned.  Used for unlinked files.
     1188 + * From NFS nfs_subr.c newnum
     1189 + */
     1190 +uint32_t
     1191 +smbfs_newnum(void)
     1192 +{
     1193 +        uint32_t id;
     1194 +
     1195 +        mutex_enter(&smbfs_newnum_lock);
     1196 +        if (smbfs_newnum_val == 0)
     1197 +                smbfs_newnum_val = (uint32_t)gethrestime_sec();
     1198 +        id = smbfs_newnum_val++;
     1199 +        mutex_exit(&smbfs_newnum_lock);
     1200 +        return (id);
     1201 +}
     1202 +
     1203 +/*
     1204 + * Fill in a temporary name at buf
     1205 + */
     1206 +int
     1207 +smbfs_newname(char *buf, size_t buflen)
     1208 +{
     1209 +        uint_t id;
     1210 +        int n;
     1211 +
     1212 +        id = smbfs_newnum();
     1213 +        n = snprintf(buf, buflen, "~$smbfs%08X", id);
     1214 +        return (n);
     1215 +}
     1216 +
     1217 +
     1218 +/*
1055 1219   * initialize resources that are used by smbfs_subr.c
1056 1220   * this is called from the _init() routine (by the way of smbfs_clntinit())
1057 1221   *
1058      - * NFS: nfs_subr.c:nfs_subrinit
     1222 + * From NFS: nfs_subr.c:nfs_subrinit
1059 1223   */
1060 1224  int
1061 1225  smbfs_subrinit(void)
1062 1226  {
1063 1227          ulong_t nsmbnode_max;
1064 1228  
1065 1229          /*
1066 1230           * Allocate and initialize the smbnode cache
1067 1231           */
1068 1232          if (nsmbnode <= 0)
1069 1233                  nsmbnode = ncsize; /* dnlc.h */
1070 1234          nsmbnode_max = (ulong_t)((kmem_maxavail() >> 2) /
1071 1235              sizeof (struct smbnode));
1072 1236          if (nsmbnode > nsmbnode_max || (nsmbnode == 0 && ncsize == 0)) {
1073      -                zcmn_err(GLOBAL_ZONEID, CE_NOTE,
     1237 +                cmn_err(CE_NOTE,
1074 1238                      "setting nsmbnode to max value of %ld", nsmbnode_max);
1075 1239                  nsmbnode = nsmbnode_max;
1076 1240          }
1077 1241  
1078 1242          smbnode_cache = kmem_cache_create("smbnode_cache", sizeof (smbnode_t),
1079 1243              0, NULL, NULL, smbfs_kmem_reclaim, NULL, NULL, 0);
1080 1244  
1081 1245          /*
1082 1246           * Initialize the various mutexes and reader/writer locks
1083 1247           */
1084 1248          mutex_init(&smbfreelist_lock, NULL, MUTEX_DEFAULT, NULL);
1085 1249          mutex_init(&smbfs_minor_lock, NULL, MUTEX_DEFAULT, NULL);
1086 1250  
1087 1251          /*
1088 1252           * Assign unique major number for all smbfs mounts
1089 1253           */
1090 1254          if ((smbfs_major = getudev()) == -1) {
1091      -                zcmn_err(GLOBAL_ZONEID, CE_WARN,
     1255 +                cmn_err(CE_WARN,
1092 1256                      "smbfs: init: can't get unique device number");
1093 1257                  smbfs_major = 0;
1094 1258          }
1095 1259          smbfs_minor = 0;
1096 1260  
1097 1261          return (0);
1098 1262  }
1099 1263  
1100 1264  /*
1101 1265   * free smbfs hash table, etc.
1102      - * NFS: nfs_subr.c:nfs_subrfini
     1266 + * From NFS: nfs_subr.c:nfs_subrfini
1103 1267   */
1104 1268  void
1105 1269  smbfs_subrfini(void)
1106 1270  {
1107 1271  
1108 1272          /*
1109 1273           * Destroy the smbnode cache
1110 1274           */
1111 1275          kmem_cache_destroy(smbnode_cache);
1112 1276  
↓ open down ↓ 54 lines elided ↑ open up ↑
1167 1331   *
1168 1332   * Todo: dump nodes from the free list?
1169 1333   */
1170 1334  /*ARGSUSED*/
1171 1335  void
1172 1336  smbfs_kmem_reclaim(void *cdrarg)
1173 1337  {
1174 1338          smbfs_node_reclaim();
1175 1339  }
1176 1340  
1177      -/* nfs failover stuff */
1178      -/* nfs_rw_xxx - see smbfs_rwlock.c */
     1341 +/*
     1342 + * Here NFS has failover stuff and
     1343 + * nfs_rw_xxx - see smbfs_rwlock.c
     1344 + */
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX