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


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
  25  */
  26 
  27 #include <sys/param.h>
  28 #include <sys/types.h>
  29 #include <sys/tzfile.h>
  30 #include <sys/atomic.h>
  31 #include <sys/time.h>
  32 #include <sys/spl.h>
  33 #include <sys/random.h>
  34 #include <smbsrv/smb_kproto.h>
  35 #include <smbsrv/smb_fsops.h>
  36 #include <smbsrv/smbinfo.h>
  37 #include <smbsrv/smb_xdr.h>
  38 #include <smbsrv/smb_vops.h>
  39 #include <smbsrv/smb_idmap.h>
  40 
  41 #include <sys/sid.h>
  42 #include <sys/priv_names.h>

  43 
  44 static kmem_cache_t     *smb_dtor_cache = NULL;
  45 
  46 static boolean_t smb_avl_hold(smb_avl_t *);
  47 static void smb_avl_rele(smb_avl_t *);
  48 
  49 time_t tzh_leapcnt = 0;
  50 
  51 struct tm
  52 *smb_gmtime_r(time_t *clock, struct tm *result);
  53 
  54 time_t
  55 smb_timegm(struct tm *tm);
  56 
  57 struct  tm {
  58         int     tm_sec;
  59         int     tm_min;
  60         int     tm_hour;
  61         int     tm_mday;
  62         int     tm_mon;
  63         int     tm_year;
  64         int     tm_wday;
  65         int     tm_yday;
  66         int     tm_isdst;
  67 };
  68 
  69 static const int days_in_month[] = {
  70         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  71 };
  72 







  73 int
  74 smb_ascii_or_unicode_strlen(struct smb_request *sr, char *str)
  75 {
  76         if (sr->session->dialect >= SMB_VERS_2_BASE ||
  77             (sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0)
  78                 return (smb_wcequiv_strlen(str));
  79         return (strlen(str));
  80 }
  81 







  82 int
  83 smb_ascii_or_unicode_strlen_null(struct smb_request *sr, char *str)
  84 {
  85         if (sr->session->dialect >= SMB_VERS_2_BASE ||
  86             (sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0)
  87                 return (smb_wcequiv_strlen(str) + 2);
  88         return (strlen(str) + 1);
  89 }
  90 
  91 int
  92 smb_ascii_or_unicode_null_len(struct smb_request *sr)
  93 {
  94         if (sr->session->dialect >= SMB_VERS_2_BASE ||
  95             (sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0)
  96                 return (2);
  97         return (1);
  98 }
  99 
 100 /*
 101  *
 102  * Convert old-style (DOS, LanMan) wildcard strings to NT style.
 103  * This should ONLY happen to patterns that come from old clients,
 104  * meaning dialect LANMAN2_1 etc. (dialect < NT_LM_0_12).
 105  *
 106  *      ? is converted to >
 107  *      * is converted to < if it is followed by .
 108  *      . is converted to " if it is followed by ? or * or end of pattern


 301         mutex_enter(&pool->id_mutex);
 302         if ((pool->id_free_counter == 0) && smb_idpool_increment(pool)) {
 303                 mutex_exit(&pool->id_mutex);
 304                 return (-1);
 305         }
 306 
 307         i = pool->id_size;
 308         while (i) {
 309                 bit = pool->id_bit;
 310                 bit_idx = pool->id_bit_idx;
 311                 byte = pool->id_pool[pool->id_idx];
 312                 while (bit) {
 313                         if (byte & bit) {
 314                                 bit = bit << 1;
 315                                 bit_idx++;
 316                                 continue;
 317                         }
 318                         pool->id_pool[pool->id_idx] |= bit;
 319                         *id = (uint16_t)(pool->id_idx * 8 + (uint32_t)bit_idx);
 320                         pool->id_free_counter--;
 321                         pool->id_bit = bit;
 322                         pool->id_bit_idx = bit_idx;














 323                         mutex_exit(&pool->id_mutex);
 324                         return (0);
 325                 }
 326                 pool->id_bit = 1;
 327                 pool->id_bit_idx = 0;
 328                 pool->id_idx++;
 329                 pool->id_idx &= pool->id_idx_msk;
 330                 --i;
 331         }
 332         /*
 333          * This section of code shouldn't be reached. If there are IDs
 334          * available and none could be found there's a problem.
 335          */
 336         ASSERT(0);
 337         mutex_exit(&pool->id_mutex);
 338         return (-1);
 339 }
 340 
 341 /*
 342  * smb_idpool_free


 438  */
 439 void
 440 smb_llist_post(smb_llist_t *ll, void *object, smb_dtorproc_t dtorproc)
 441 {
 442         smb_dtor_t      *dtor;
 443 
 444         ASSERT((object != NULL) && (dtorproc != NULL));
 445 
 446         dtor = kmem_cache_alloc(smb_dtor_cache, KM_SLEEP);
 447         bzero(dtor, sizeof (smb_dtor_t));
 448         dtor->dt_magic = SMB_DTOR_MAGIC;
 449         dtor->dt_object = object;
 450         dtor->dt_proc = dtorproc;
 451 
 452         mutex_enter(&ll->ll_mutex);
 453         list_insert_tail(&ll->ll_deleteq, dtor);
 454         ++ll->ll_deleteq_count;
 455         mutex_exit(&ll->ll_mutex);
 456 }
 457 






 458 /*
 459  * Exit the list lock and process the delete queue.
 460  */
 461 void
 462 smb_llist_exit(smb_llist_t *ll)
 463 {
 464         rw_exit(&ll->ll_lock);
 465         smb_llist_flush(ll);
 466 }
 467 
 468 /*
 469  * Flush the list delete queue.  The mutex is dropped across the destructor
 470  * call in case this leads to additional objects being posted to the delete
 471  * queue.
 472  */
 473 void
 474 smb_llist_flush(smb_llist_t *ll)
 475 {
 476         smb_dtor_t    *dtor;
 477 


 771         mutex_init(&rwx->rwx_mutex, NULL, MUTEX_DEFAULT, NULL);
 772         rw_init(&rwx->rwx_lock, NULL, RW_DEFAULT, NULL);
 773 }
 774 
 775 /*
 776  * smb_rwx_destroy
 777  */
 778 void
 779 smb_rwx_destroy(
 780     smb_rwx_t   *rwx)
 781 {
 782         mutex_destroy(&rwx->rwx_mutex);
 783         cv_destroy(&rwx->rwx_cv);
 784         rw_destroy(&rwx->rwx_lock);
 785 }
 786 
 787 /*
 788  * smb_rwx_rwexit
 789  */
 790 void
 791 smb_rwx_rwexit(
 792     smb_rwx_t   *rwx)
 793 {
 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);
 804 }
 805 
 806 /*
 807  * smb_rwx_rwupgrade
 808  */
 809 krw_t
 810 smb_rwx_rwupgrade(
 811     smb_rwx_t   *rwx)
 812 {
 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);
 822 }
 823 
 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 
 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 /*
 849  * smb_rwx_wait
 850  *
 851  * This function assumes the smb_rwx lock was enter in RW_READER or RW_WRITER

 852  * mode. It will:
 853  *
 854  *      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.
 858  *      3) re-acquire the lock in the mode saved in (1).


 859  */
 860 int
 861 smb_rwx_rwwait(
 862     smb_rwx_t   *rwx,
 863     clock_t     timeout)
 864 {
 865         krw_t   mode;
 866         int     rc = 1;
 867 
 868         mutex_enter(&rwx->rwx_mutex);
 869         rwx->rwx_waiting = B_TRUE;
 870         mutex_exit(&rwx->rwx_mutex);
 871 
 872         if (rw_write_held(&rwx->rwx_lock)) {
 873                 ASSERT(rw_owner(&rwx->rwx_lock) == curthread);
 874                 mode = RW_WRITER;
 875         } else {
 876                 ASSERT(rw_read_held(&rwx->rwx_lock));
 877                 mode = RW_READER;
 878         }
 879         rw_exit(&rwx->rwx_lock);
 880 
 881         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                 }
 889         }
 890         mutex_exit(&rwx->rwx_mutex);
 891 
 892         rw_enter(&rwx->rwx_lock, mode);
 893         return (rc);
 894 }
 895 


















 896 /* smb_idmap_... moved to smb_idmap.c */
 897 
 898 uint64_t
 899 smb_time_unix_to_nt(timestruc_t *unix_time)
 900 {
 901         uint64_t nt_time;
 902 
 903         if ((unix_time->tv_sec == 0) && (unix_time->tv_nsec == 0))
 904                 return (0);
 905 
 906         nt_time = unix_time->tv_sec;
 907         nt_time *= 10000000;  /* seconds to 100ns */
 908         nt_time += unix_time->tv_nsec / 100;
 909         return (nt_time + NT_TIME_BIAS);
 910 }
 911 
 912 void
 913 smb_time_nt_to_unix(uint64_t nt_time, timestruc_t *unix_time)
 914 {
 915         uint32_t seconds;


1705 }
1706 
1707 void
1708 smb_threshold_exit(smb_cmd_threshold_t *ct)
1709 {
1710         mutex_enter(&ct->ct_mutex);
1711         ASSERT3U(ct->ct_active_cnt, >, 0);
1712         ct->ct_active_cnt--;
1713         if (ct->ct_blocked_cnt)
1714                 cv_signal(&ct->ct_cond);
1715         mutex_exit(&ct->ct_mutex);
1716 }
1717 
1718 void
1719 smb_threshold_wake_all(smb_cmd_threshold_t *ct)
1720 {
1721         mutex_enter(&ct->ct_mutex);
1722         ct->ct_threshold = 0;
1723         cv_broadcast(&ct->ct_cond);
1724         mutex_exit(&ct->ct_mutex);
















































1725 }


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
  25  */
  26 
  27 #include <sys/param.h>
  28 #include <sys/types.h>
  29 #include <sys/tzfile.h>
  30 #include <sys/atomic.h>
  31 #include <sys/time.h>
  32 #include <sys/spl.h>
  33 #include <sys/random.h>
  34 #include <smbsrv/smb_kproto.h>
  35 #include <smbsrv/smb_fsops.h>
  36 #include <smbsrv/smbinfo.h>
  37 #include <smbsrv/smb_xdr.h>
  38 #include <smbsrv/smb_vops.h>
  39 #include <smbsrv/smb_idmap.h>
  40 
  41 #include <sys/sid.h>
  42 #include <sys/priv_names.h>
  43 #include <sys/bitmap.h>
  44 
  45 static kmem_cache_t     *smb_dtor_cache = NULL;
  46 
  47 static boolean_t smb_avl_hold(smb_avl_t *);
  48 static void smb_avl_rele(smb_avl_t *);
  49 
  50 time_t tzh_leapcnt = 0;
  51 
  52 struct tm
  53 *smb_gmtime_r(time_t *clock, struct tm *result);
  54 
  55 time_t
  56 smb_timegm(struct tm *tm);
  57 
  58 struct  tm {
  59         int     tm_sec;
  60         int     tm_min;
  61         int     tm_hour;
  62         int     tm_mday;
  63         int     tm_mon;
  64         int     tm_year;
  65         int     tm_wday;
  66         int     tm_yday;
  67         int     tm_isdst;
  68 };
  69 
  70 static const int days_in_month[] = {
  71         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  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  */
  81 int
  82 smb_ascii_or_unicode_strlen(struct smb_request *sr, char *str)
  83 {
  84         if (sr->session->dialect >= SMB_VERS_2_BASE ||
  85             (sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0)
  86                 return (smb_wcequiv_strlen(str));
  87         return (smb_sbequiv_strlen(str));
  88 }
  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  */
  97 int
  98 smb_ascii_or_unicode_strlen_null(struct smb_request *sr, char *str)
  99 {
 100         if (sr->session->dialect >= SMB_VERS_2_BASE ||
 101             (sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0)
 102                 return (smb_wcequiv_strlen(str) + 2);
 103         return (smb_sbequiv_strlen(str) + 1);
 104 }
 105 
 106 int
 107 smb_ascii_or_unicode_null_len(struct smb_request *sr)
 108 {
 109         if (sr->session->dialect >= SMB_VERS_2_BASE ||
 110             (sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0)
 111                 return (2);
 112         return (1);
 113 }
 114 
 115 /*
 116  *
 117  * Convert old-style (DOS, LanMan) wildcard strings to NT style.
 118  * This should ONLY happen to patterns that come from old clients,
 119  * meaning dialect LANMAN2_1 etc. (dialect < NT_LM_0_12).
 120  *
 121  *      ? is converted to >
 122  *      * is converted to < if it is followed by .
 123  *      . is converted to " if it is followed by ? or * or end of pattern


 316         mutex_enter(&pool->id_mutex);
 317         if ((pool->id_free_counter == 0) && smb_idpool_increment(pool)) {
 318                 mutex_exit(&pool->id_mutex);
 319                 return (-1);
 320         }
 321 
 322         i = pool->id_size;
 323         while (i) {
 324                 bit = pool->id_bit;
 325                 bit_idx = pool->id_bit_idx;
 326                 byte = pool->id_pool[pool->id_idx];
 327                 while (bit) {
 328                         if (byte & bit) {
 329                                 bit = bit << 1;
 330                                 bit_idx++;
 331                                 continue;
 332                         }
 333                         pool->id_pool[pool->id_idx] |= bit;
 334                         *id = (uint16_t)(pool->id_idx * 8 + (uint32_t)bit_idx);
 335                         pool->id_free_counter--;
 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                         }
 352                         mutex_exit(&pool->id_mutex);
 353                         return (0);
 354                 }
 355                 pool->id_bit = 1;
 356                 pool->id_bit_idx = 0;
 357                 pool->id_idx++;
 358                 pool->id_idx &= pool->id_idx_msk;
 359                 --i;
 360         }
 361         /*
 362          * This section of code shouldn't be reached. If there are IDs
 363          * available and none could be found there's a problem.
 364          */
 365         ASSERT(0);
 366         mutex_exit(&pool->id_mutex);
 367         return (-1);
 368 }
 369 
 370 /*
 371  * smb_idpool_free


 467  */
 468 void
 469 smb_llist_post(smb_llist_t *ll, void *object, smb_dtorproc_t dtorproc)
 470 {
 471         smb_dtor_t      *dtor;
 472 
 473         ASSERT((object != NULL) && (dtorproc != NULL));
 474 
 475         dtor = kmem_cache_alloc(smb_dtor_cache, KM_SLEEP);
 476         bzero(dtor, sizeof (smb_dtor_t));
 477         dtor->dt_magic = SMB_DTOR_MAGIC;
 478         dtor->dt_object = object;
 479         dtor->dt_proc = dtorproc;
 480 
 481         mutex_enter(&ll->ll_mutex);
 482         list_insert_tail(&ll->ll_deleteq, dtor);
 483         ++ll->ll_deleteq_count;
 484         mutex_exit(&ll->ll_mutex);
 485 }
 486 
 487 void
 488 smb_llist_enter(smb_llist_t *ll, krw_t mode)
 489 {
 490         rw_enter(&ll->ll_lock, mode);
 491 }
 492 
 493 /*
 494  * Exit the list lock and process the delete queue.
 495  */
 496 void
 497 smb_llist_exit(smb_llist_t *ll)
 498 {
 499         rw_exit(&ll->ll_lock);
 500         smb_llist_flush(ll);
 501 }
 502 
 503 /*
 504  * Flush the list delete queue.  The mutex is dropped across the destructor
 505  * call in case this leads to additional objects being posted to the delete
 506  * queue.
 507  */
 508 void
 509 smb_llist_flush(smb_llist_t *ll)
 510 {
 511         smb_dtor_t    *dtor;
 512 


 806         mutex_init(&rwx->rwx_mutex, NULL, MUTEX_DEFAULT, NULL);
 807         rw_init(&rwx->rwx_lock, NULL, RW_DEFAULT, NULL);
 808 }
 809 
 810 /*
 811  * smb_rwx_destroy
 812  */
 813 void
 814 smb_rwx_destroy(
 815     smb_rwx_t   *rwx)
 816 {
 817         mutex_destroy(&rwx->rwx_mutex);
 818         cv_destroy(&rwx->rwx_cv);
 819         rw_destroy(&rwx->rwx_lock);
 820 }
 821 
 822 /*
 823  * smb_rwx_rwexit
 824  */
 825 void
 826 smb_rwx_rwenter(smb_rwx_t *rwx, krw_t mode)

 827 {
 828         rw_enter(&rwx->rwx_lock, mode);









 829 }
 830 
 831 /*
 832  * smb_rwx_rwexit
 833  */
 834 void
 835 smb_rwx_rwexit(
 836     smb_rwx_t   *rwx)
 837 {





 838         rw_exit(&rwx->rwx_lock);



 839 }
 840 










 841 













 842 /*
 843  * smb_rwx_cvwait
 844  *
 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
 847  * mode. It will:
 848  *
 849  *      1) release the lock and save its current mode.
 850  *      2) wait until the condition variable is signaled.


 851  *      3) re-acquire the lock in the mode saved in (1).
 852  *
 853  * Lock order: rwlock, mutex
 854  */
 855 int
 856 smb_rwx_cvwait(
 857     smb_rwx_t   *rwx,
 858     clock_t     timeout)
 859 {
 860         krw_t   mode;
 861         int     rc = 1;
 862 




 863         if (rw_write_held(&rwx->rwx_lock)) {
 864                 ASSERT(rw_owner(&rwx->rwx_lock) == curthread);
 865                 mode = RW_WRITER;
 866         } else {
 867                 ASSERT(rw_read_held(&rwx->rwx_lock));
 868                 mode = RW_READER;
 869         }

 870 
 871         mutex_enter(&rwx->rwx_mutex);
 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);
 880         }

 881         mutex_exit(&rwx->rwx_mutex);
 882 
 883         rw_enter(&rwx->rwx_lock, mode);
 884         return (rc);
 885 }
 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 
 905 /* smb_idmap_... moved to smb_idmap.c */
 906 
 907 uint64_t
 908 smb_time_unix_to_nt(timestruc_t *unix_time)
 909 {
 910         uint64_t nt_time;
 911 
 912         if ((unix_time->tv_sec == 0) && (unix_time->tv_nsec == 0))
 913                 return (0);
 914 
 915         nt_time = unix_time->tv_sec;
 916         nt_time *= 10000000;  /* seconds to 100ns */
 917         nt_time += unix_time->tv_nsec / 100;
 918         return (nt_time + NT_TIME_BIAS);
 919 }
 920 
 921 void
 922 smb_time_nt_to_unix(uint64_t nt_time, timestruc_t *unix_time)
 923 {
 924         uint32_t seconds;


1714 }
1715 
1716 void
1717 smb_threshold_exit(smb_cmd_threshold_t *ct)
1718 {
1719         mutex_enter(&ct->ct_mutex);
1720         ASSERT3U(ct->ct_active_cnt, >, 0);
1721         ct->ct_active_cnt--;
1722         if (ct->ct_blocked_cnt)
1723                 cv_signal(&ct->ct_cond);
1724         mutex_exit(&ct->ct_mutex);
1725 }
1726 
1727 void
1728 smb_threshold_wake_all(smb_cmd_threshold_t *ct)
1729 {
1730         mutex_enter(&ct->ct_mutex);
1731         ct->ct_threshold = 0;
1732         cv_broadcast(&ct->ct_cond);
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));
1782 }