Print this page
NEX-19373 SMB2 file ID re-use can confuse clients
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-16519 Panic while running IOmeter to a pool through an SMB share
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-5599 SMB needs a pointer-based hash table for durable handles
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-4458 Incorrect directory listing response for non-UNICODE clients
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-3787 Sync. up SMB server with: Merge with illumos-gate 12380e1e
NEX-3611 CLONE NEX-3550 Replace smb2_enable with max_protocol
Reviewed by: Yuri Pankov <Yuri.Pankov@nexenta.com>
NEX-2894 Using a date that is outside of the UNIX epoch fails on CIFS
NEX-2781 SMB2 credit handling needs work
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
SMB-50 User-mode SMB server
 Includes work by these authors:
 Thomas Keiser <thomas.keiser@nexenta.com>
 Albert Lee <trisk@nexenta.com>
SUP-694 panic on bad mutex in smb_event_wait() - nits
SUP-694 panic on bad mutex in smb_event_wait()
SMB-65 SMB server in non-global zones (data structure changes)
Many things move to the smb_server_t object, and
many functions gain an sv arg (which server).
SMB-65 SMB server in non-global zones (kmem_caches)
common kmem_cache instances across zones
separate GZ-only init from NGZ init
SMB-64 smbsrv workers run at excessively high priority
SMB-48 Panic with smbtorture raw.scan-eamax
re #6854 FindFirstFile,FindFirstFileEx,... are not working correctly on Nexenta CIFS-shares

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/smbsrv/smb_kutil.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_kutil.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24      - * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
       24 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
  25   25   */
  26   26  
  27   27  #include <sys/param.h>
  28   28  #include <sys/types.h>
  29   29  #include <sys/tzfile.h>
  30   30  #include <sys/atomic.h>
  31   31  #include <sys/time.h>
  32   32  #include <sys/spl.h>
  33   33  #include <sys/random.h>
  34   34  #include <smbsrv/smb_kproto.h>
  35   35  #include <smbsrv/smb_fsops.h>
  36   36  #include <smbsrv/smbinfo.h>
  37   37  #include <smbsrv/smb_xdr.h>
  38   38  #include <smbsrv/smb_vops.h>
  39   39  #include <smbsrv/smb_idmap.h>
  40   40  
  41   41  #include <sys/sid.h>
  42   42  #include <sys/priv_names.h>
       43 +#include <sys/bitmap.h>
  43   44  
  44   45  static kmem_cache_t     *smb_dtor_cache = NULL;
  45   46  
  46   47  static boolean_t smb_avl_hold(smb_avl_t *);
  47   48  static void smb_avl_rele(smb_avl_t *);
  48   49  
  49   50  time_t tzh_leapcnt = 0;
  50   51  
  51   52  struct tm
  52   53  *smb_gmtime_r(time_t *clock, struct tm *result);
↓ open down ↓ 10 lines elided ↑ open up ↑
  63   64          int     tm_year;
  64   65          int     tm_wday;
  65   66          int     tm_yday;
  66   67          int     tm_isdst;
  67   68  };
  68   69  
  69   70  static const int days_in_month[] = {
  70   71          31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  71   72  };
  72   73  
       74 +/*
       75 + * Given a UTF-8 string (our internal form everywhere)
       76 + * return either the Unicode (UTF-16) length in bytes,
       77 + * or the OEM length in bytes.  Which we return is
       78 + * determined by whether the client supports Unicode.
       79 + * This length does NOT include the null.
       80 + */
  73   81  int
  74   82  smb_ascii_or_unicode_strlen(struct smb_request *sr, char *str)
  75   83  {
  76   84          if (sr->session->dialect >= SMB_VERS_2_BASE ||
  77   85              (sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0)
  78   86                  return (smb_wcequiv_strlen(str));
  79      -        return (strlen(str));
       87 +        return (smb_sbequiv_strlen(str));
  80   88  }
  81   89  
       90 +/*
       91 + * Given a UTF-8 string (our internal form everywhere)
       92 + * return either the Unicode (UTF-16) length in bytes,
       93 + * or the OEM length in bytes.  Which we return is
       94 + * determined by whether the client supports Unicode.
       95 + * This length DOES include the null.
       96 + */
  82   97  int
  83   98  smb_ascii_or_unicode_strlen_null(struct smb_request *sr, char *str)
  84   99  {
  85  100          if (sr->session->dialect >= SMB_VERS_2_BASE ||
  86  101              (sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0)
  87  102                  return (smb_wcequiv_strlen(str) + 2);
  88      -        return (strlen(str) + 1);
      103 +        return (smb_sbequiv_strlen(str) + 1);
  89  104  }
  90  105  
  91  106  int
  92  107  smb_ascii_or_unicode_null_len(struct smb_request *sr)
  93  108  {
  94  109          if (sr->session->dialect >= SMB_VERS_2_BASE ||
  95  110              (sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0)
  96  111                  return (2);
  97  112          return (1);
  98  113  }
↓ open down ↓ 212 lines elided ↑ open up ↑
 311  326                  byte = pool->id_pool[pool->id_idx];
 312  327                  while (bit) {
 313  328                          if (byte & bit) {
 314  329                                  bit = bit << 1;
 315  330                                  bit_idx++;
 316  331                                  continue;
 317  332                          }
 318  333                          pool->id_pool[pool->id_idx] |= bit;
 319  334                          *id = (uint16_t)(pool->id_idx * 8 + (uint32_t)bit_idx);
 320  335                          pool->id_free_counter--;
 321      -                        pool->id_bit = bit;
 322      -                        pool->id_bit_idx = bit_idx;
      336 +                        /*
      337 +                         * Leave position at next bit to allocate,
      338 +                         * so we don't keep re-using the last in an
      339 +                         * alloc/free/alloc/free sequence.  Doing
      340 +                         * that can confuse some SMB clients.
      341 +                         */
      342 +                        if (bit & 0x80) {
      343 +                                pool->id_bit = 1;
      344 +                                pool->id_bit_idx = 0;
      345 +                                pool->id_idx++;
      346 +                                pool->id_idx &= pool->id_idx_msk;
      347 +                        } else {
      348 +                                pool->id_bit = (bit << 1);
      349 +                                pool->id_bit_idx = bit_idx + 1;
      350 +                                /* keep id_idx */
      351 +                        }
 323  352                          mutex_exit(&pool->id_mutex);
 324  353                          return (0);
 325  354                  }
 326  355                  pool->id_bit = 1;
 327  356                  pool->id_bit_idx = 0;
 328  357                  pool->id_idx++;
 329  358                  pool->id_idx &= pool->id_idx_msk;
 330  359                  --i;
 331  360          }
 332  361          /*
↓ open down ↓ 115 lines elided ↑ open up ↑
 448  477          dtor->dt_magic = SMB_DTOR_MAGIC;
 449  478          dtor->dt_object = object;
 450  479          dtor->dt_proc = dtorproc;
 451  480  
 452  481          mutex_enter(&ll->ll_mutex);
 453  482          list_insert_tail(&ll->ll_deleteq, dtor);
 454  483          ++ll->ll_deleteq_count;
 455  484          mutex_exit(&ll->ll_mutex);
 456  485  }
 457  486  
      487 +void
      488 +smb_llist_enter(smb_llist_t *ll, krw_t mode)
      489 +{
      490 +        rw_enter(&ll->ll_lock, mode);
      491 +}
      492 +
 458  493  /*
 459  494   * Exit the list lock and process the delete queue.
 460  495   */
 461  496  void
 462  497  smb_llist_exit(smb_llist_t *ll)
 463  498  {
 464  499          rw_exit(&ll->ll_lock);
 465  500          smb_llist_flush(ll);
 466  501  }
 467  502  
↓ open down ↓ 313 lines elided ↑ open up ↑
 781  816  {
 782  817          mutex_destroy(&rwx->rwx_mutex);
 783  818          cv_destroy(&rwx->rwx_cv);
 784  819          rw_destroy(&rwx->rwx_lock);
 785  820  }
 786  821  
 787  822  /*
 788  823   * smb_rwx_rwexit
 789  824   */
 790  825  void
 791      -smb_rwx_rwexit(
 792      -    smb_rwx_t   *rwx)
      826 +smb_rwx_rwenter(smb_rwx_t *rwx, krw_t mode)
 793  827  {
 794      -        if (rw_write_held(&rwx->rwx_lock)) {
 795      -                ASSERT(rw_owner(&rwx->rwx_lock) == curthread);
 796      -                mutex_enter(&rwx->rwx_mutex);
 797      -                if (rwx->rwx_waiting) {
 798      -                        rwx->rwx_waiting = B_FALSE;
 799      -                        cv_broadcast(&rwx->rwx_cv);
 800      -                }
 801      -                mutex_exit(&rwx->rwx_mutex);
 802      -        }
 803      -        rw_exit(&rwx->rwx_lock);
      828 +        rw_enter(&rwx->rwx_lock, mode);
 804  829  }
 805  830  
 806  831  /*
 807      - * smb_rwx_rwupgrade
      832 + * smb_rwx_rwexit
 808  833   */
 809      -krw_t
 810      -smb_rwx_rwupgrade(
      834 +void
      835 +smb_rwx_rwexit(
 811  836      smb_rwx_t   *rwx)
 812  837  {
 813      -        if (rw_write_held(&rwx->rwx_lock)) {
 814      -                ASSERT(rw_owner(&rwx->rwx_lock) == curthread);
 815      -                return (RW_WRITER);
 816      -        }
 817      -        if (!rw_tryupgrade(&rwx->rwx_lock)) {
 818      -                rw_exit(&rwx->rwx_lock);
 819      -                rw_enter(&rwx->rwx_lock, RW_WRITER);
 820      -        }
 821      -        return (RW_READER);
      838 +        rw_exit(&rwx->rwx_lock);
 822  839  }
 823  840  
 824      -/*
 825      - * smb_rwx_rwrestore
 826      - */
 827      -void
 828      -smb_rwx_rwdowngrade(
 829      -    smb_rwx_t   *rwx,
 830      -    krw_t       mode)
 831      -{
 832      -        ASSERT(rw_write_held(&rwx->rwx_lock));
 833      -        ASSERT(rw_owner(&rwx->rwx_lock) == curthread);
 834  841  
 835      -        if (mode == RW_WRITER) {
 836      -                return;
 837      -        }
 838      -        ASSERT(mode == RW_READER);
 839      -        mutex_enter(&rwx->rwx_mutex);
 840      -        if (rwx->rwx_waiting) {
 841      -                rwx->rwx_waiting = B_FALSE;
 842      -                cv_broadcast(&rwx->rwx_cv);
 843      -        }
 844      -        mutex_exit(&rwx->rwx_mutex);
 845      -        rw_downgrade(&rwx->rwx_lock);
 846      -}
 847      -
 848  842  /*
 849      - * smb_rwx_wait
      843 + * smb_rwx_cvwait
 850  844   *
 851      - * This function assumes the smb_rwx lock was enter in RW_READER or RW_WRITER
      845 + * Wait on rwx->rw_cv, dropping the rw lock and retake after wakeup.
      846 + * Assumes the smb_rwx lock was entered in RW_READER or RW_WRITER
 852  847   * mode. It will:
 853  848   *
 854  849   *      1) release the lock and save its current mode.
 855      - *      2) wait until the condition variable is signaled. This can happen for
 856      - *         2 reasons: When a writer releases the lock or when the time out (if
 857      - *         provided) expires.
      850 + *      2) wait until the condition variable is signaled.
 858  851   *      3) re-acquire the lock in the mode saved in (1).
      852 + *
      853 + * Lock order: rwlock, mutex
 859  854   */
 860  855  int
 861      -smb_rwx_rwwait(
      856 +smb_rwx_cvwait(
 862  857      smb_rwx_t   *rwx,
 863  858      clock_t     timeout)
 864  859  {
 865  860          krw_t   mode;
 866  861          int     rc = 1;
 867  862  
 868      -        mutex_enter(&rwx->rwx_mutex);
 869      -        rwx->rwx_waiting = B_TRUE;
 870      -        mutex_exit(&rwx->rwx_mutex);
 871      -
 872  863          if (rw_write_held(&rwx->rwx_lock)) {
 873  864                  ASSERT(rw_owner(&rwx->rwx_lock) == curthread);
 874  865                  mode = RW_WRITER;
 875  866          } else {
 876  867                  ASSERT(rw_read_held(&rwx->rwx_lock));
 877  868                  mode = RW_READER;
 878  869          }
 879      -        rw_exit(&rwx->rwx_lock);
 880  870  
 881  871          mutex_enter(&rwx->rwx_mutex);
 882      -        if (rwx->rwx_waiting) {
 883      -                if (timeout == -1) {
 884      -                        cv_wait(&rwx->rwx_cv, &rwx->rwx_mutex);
 885      -                } else {
 886      -                        rc = cv_reltimedwait(&rwx->rwx_cv, &rwx->rwx_mutex,
 887      -                            timeout, TR_CLOCK_TICK);
 888      -                }
      872 +        rw_exit(&rwx->rwx_lock);
      873 +
      874 +        rwx->rwx_waiting = B_TRUE;
      875 +        if (timeout == -1) {
      876 +                cv_wait(&rwx->rwx_cv, &rwx->rwx_mutex);
      877 +        } else {
      878 +                rc = cv_reltimedwait(&rwx->rwx_cv, &rwx->rwx_mutex,
      879 +                    timeout, TR_CLOCK_TICK);
 889  880          }
 890  881          mutex_exit(&rwx->rwx_mutex);
 891  882  
 892  883          rw_enter(&rwx->rwx_lock, mode);
 893  884          return (rc);
 894  885  }
 895  886  
      887 +/*
      888 + * smb_rwx_cvbcast
      889 + *
      890 + * Wake up threads waiting on rx_cv
      891 + * The rw lock may or may not be held.
      892 + * The mutex MUST NOT be held.
      893 + */
      894 +void
      895 +smb_rwx_cvbcast(smb_rwx_t *rwx)
      896 +{
      897 +        mutex_enter(&rwx->rwx_mutex);
      898 +        if (rwx->rwx_waiting) {
      899 +                rwx->rwx_waiting = B_FALSE;
      900 +                cv_broadcast(&rwx->rwx_cv);
      901 +        }
      902 +        mutex_exit(&rwx->rwx_mutex);
      903 +}
      904 +
 896  905  /* smb_idmap_... moved to smb_idmap.c */
 897  906  
 898  907  uint64_t
 899  908  smb_time_unix_to_nt(timestruc_t *unix_time)
 900  909  {
 901  910          uint64_t nt_time;
 902  911  
 903  912          if ((unix_time->tv_sec == 0) && (unix_time->tv_nsec == 0))
 904  913                  return (0);
 905  914  
↓ open down ↓ 342 lines elided ↑ open up ↑
1248 1257          mutex_destroy(&avl->avl_mutex);
1249 1258          bzero(avl, sizeof (smb_avl_t));
1250 1259  }
1251 1260  
1252 1261  /*
1253 1262   * Adds the given item to the AVL if it's
1254 1263   * not already there.
1255 1264   *
1256 1265   * Returns:
1257 1266   *
1258      - *      ENOTACTIVE      AVL is not in READY state
1259      - *      EEXIST          The item is already in AVL
     1267 + *      ENOTACTIVE      AVL is not in READY state
     1268 + *      EEXIST          The item is already in AVL
1260 1269   */
1261 1270  int
1262 1271  smb_avl_add(smb_avl_t *avl, void *item)
1263 1272  {
1264 1273          avl_index_t where;
1265 1274  
1266 1275          ASSERT(avl);
1267 1276          ASSERT(item);
1268 1277  
1269 1278          if (!smb_avl_hold(avl))
↓ open down ↓ 445 lines elided ↑ open up ↑
1715 1724          mutex_exit(&ct->ct_mutex);
1716 1725  }
1717 1726  
1718 1727  void
1719 1728  smb_threshold_wake_all(smb_cmd_threshold_t *ct)
1720 1729  {
1721 1730          mutex_enter(&ct->ct_mutex);
1722 1731          ct->ct_threshold = 0;
1723 1732          cv_broadcast(&ct->ct_cond);
1724 1733          mutex_exit(&ct->ct_mutex);
     1734 +}
     1735 +
     1736 +/* taken from mod_hash_byptr */
     1737 +uint_t
     1738 +smb_hash_uint64(smb_hash_t *hash, uint64_t val)
     1739 +{
     1740 +        uint64_t k = val >> hash->rshift;
     1741 +        uint_t idx = ((uint_t)k) & (hash->num_buckets - 1);
     1742 +
     1743 +        return (idx);
     1744 +}
     1745 +
     1746 +boolean_t
     1747 +smb_is_pow2(size_t n)
     1748 +{
     1749 +        return ((n & (n - 1)) == 0);
     1750 +}
     1751 +
     1752 +smb_hash_t *
     1753 +smb_hash_create(size_t elemsz, size_t link_offset,
     1754 +    uint32_t num_buckets)
     1755 +{
     1756 +        smb_hash_t *hash = kmem_alloc(sizeof (*hash), KM_SLEEP);
     1757 +        int i;
     1758 +
     1759 +        if (!smb_is_pow2(num_buckets))
     1760 +                num_buckets = 1 << highbit(num_buckets);
     1761 +
     1762 +        hash->rshift = highbit(elemsz);
     1763 +        hash->num_buckets = num_buckets;
     1764 +        hash->buckets = kmem_zalloc(num_buckets * sizeof (smb_bucket_t),
     1765 +            KM_SLEEP);
     1766 +        for (i = 0; i < num_buckets; i++)
     1767 +                smb_llist_constructor(&hash->buckets[i].b_list, elemsz,
     1768 +                    link_offset);
     1769 +        return (hash);
     1770 +}
     1771 +
     1772 +void
     1773 +smb_hash_destroy(smb_hash_t *hash)
     1774 +{
     1775 +        int i;
     1776 +
     1777 +        for (i = 0; i < hash->num_buckets; i++)
     1778 +                smb_llist_destructor(&hash->buckets[i].b_list);
     1779 +
     1780 +        kmem_free(hash->buckets, hash->num_buckets * sizeof (smb_bucket_t));
     1781 +        kmem_free(hash, sizeof (*hash));
1725 1782  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX