xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_kutil.c (revision d17be682a2c70b4505d43c830bbd2603da11918d)
1 /*
2  * CDDL HEADER START
3  *
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  * Copyright 2022 RackTop Systems, Inc.
26  */
27 
28 #include <sys/param.h>
29 #include <sys/types.h>
30 #include <sys/tzfile.h>
31 #include <sys/atomic.h>
32 #include <sys/time.h>
33 #include <sys/spl.h>
34 #include <sys/random.h>
35 #include <smbsrv/smb_kproto.h>
36 #include <smbsrv/smb_fsops.h>
37 #include <smbsrv/smbinfo.h>
38 #include <smbsrv/smb_xdr.h>
39 #include <smbsrv/smb_vops.h>
40 #include <smbsrv/smb_idmap.h>
41 
42 #include <sys/sid.h>
43 #include <sys/priv_names.h>
44 #include <sys/bitmap.h>
45 
46 static kmem_cache_t	*smb_dtor_cache = NULL;
47 
48 static boolean_t smb_avl_hold(smb_avl_t *);
49 static void smb_avl_rele(smb_avl_t *);
50 
51 time_t tzh_leapcnt = 0;
52 
53 struct tm
54 *smb_gmtime_r(time_t *clock, struct tm *result);
55 
56 time_t
57 smb_timegm(struct tm *tm);
58 
59 struct	tm {
60 	int	tm_sec;
61 	int	tm_min;
62 	int	tm_hour;
63 	int	tm_mday;
64 	int	tm_mon;
65 	int	tm_year;
66 	int	tm_wday;
67 	int	tm_yday;
68 	int	tm_isdst;
69 };
70 
71 static const int days_in_month[] = {
72 	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
73 };
74 
75 /*
76  * Given a UTF-8 string (our internal form everywhere)
77  * return either the Unicode (UTF-16) length in bytes,
78  * or the OEM length in bytes.  Which we return is
79  * determined by whether the client supports Unicode.
80  * This length does NOT include the null.
81  */
82 int
83 smb_ascii_or_unicode_strlen(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));
88 	return (smb_sbequiv_strlen(str));
89 }
90 
91 /*
92  * Given a UTF-8 string (our internal form everywhere)
93  * return either the Unicode (UTF-16) length in bytes,
94  * or the OEM length in bytes.  Which we return is
95  * determined by whether the client supports Unicode.
96  * This length DOES include the null.
97  */
98 int
99 smb_ascii_or_unicode_strlen_null(struct smb_request *sr, char *str)
100 {
101 	if (sr->session->dialect >= SMB_VERS_2_BASE ||
102 	    (sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0)
103 		return (smb_wcequiv_strlen(str) + 2);
104 	return (smb_sbequiv_strlen(str) + 1);
105 }
106 
107 int
108 smb_ascii_or_unicode_null_len(struct smb_request *sr)
109 {
110 	if (sr->session->dialect >= SMB_VERS_2_BASE ||
111 	    (sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0)
112 		return (2);
113 	return (1);
114 }
115 
116 /*
117  *
118  * Convert old-style (DOS, LanMan) wildcard strings to NT style.
119  * This should ONLY happen to patterns that come from old clients,
120  * meaning dialect LANMAN2_1 etc. (dialect < NT_LM_0_12).
121  *
122  *	? is converted to >
123  *	* is converted to < if it is followed by .
124  *	. is converted to " if it is followed by ? or * or end of pattern
125  *
126  * Note: modifies pattern in place.
127  */
128 void
129 smb_convert_wildcards(char *pattern)
130 {
131 	char	*p;
132 
133 	for (p = pattern; *p != '\0'; p++) {
134 		switch (*p) {
135 		case '?':
136 			*p = '>';
137 			break;
138 		case '*':
139 			if (p[1] == '.')
140 				*p = '<';
141 			break;
142 		case '.':
143 			if (p[1] == '?' || p[1] == '*' || p[1] == '\0')
144 				*p = '\"';
145 			break;
146 		}
147 	}
148 }
149 
150 /*
151  * smb_sattr_check
152  *
153  * Check file attributes against a search attribute (sattr) mask.
154  *
155  * Normal files, which includes READONLY and ARCHIVE, always pass
156  * this check.  If the DIRECTORY, HIDDEN or SYSTEM special attributes
157  * are set then they must appear in the search mask.  The special
158  * attributes are inclusive, i.e. all special attributes that appear
159  * in sattr must also appear in the file attributes for the check to
160  * pass.
161  *
162  * The following examples show how this works:
163  *
164  *		fileA:	READONLY
165  *		fileB:	0 (no attributes = normal file)
166  *		fileC:	READONLY, ARCHIVE
167  *		fileD:	HIDDEN
168  *		fileE:	READONLY, HIDDEN, SYSTEM
169  *		dirA:	DIRECTORY
170  *
171  * search attribute: 0
172  *		Returns: fileA, fileB and fileC.
173  * search attribute: HIDDEN
174  *		Returns: fileA, fileB, fileC and fileD.
175  * search attribute: SYSTEM
176  *		Returns: fileA, fileB and fileC.
177  * search attribute: DIRECTORY
178  *		Returns: fileA, fileB, fileC and dirA.
179  * search attribute: HIDDEN and SYSTEM
180  *		Returns: fileA, fileB, fileC, fileD and fileE.
181  *
182  * Returns true if the file and sattr match; otherwise, returns false.
183  */
184 boolean_t
185 smb_sattr_check(uint16_t dosattr, uint16_t sattr)
186 {
187 	if ((dosattr & FILE_ATTRIBUTE_DIRECTORY) &&
188 	    !(sattr & FILE_ATTRIBUTE_DIRECTORY))
189 		return (B_FALSE);
190 
191 	if ((dosattr & FILE_ATTRIBUTE_HIDDEN) &&
192 	    !(sattr & FILE_ATTRIBUTE_HIDDEN))
193 		return (B_FALSE);
194 
195 	if ((dosattr & FILE_ATTRIBUTE_SYSTEM) &&
196 	    !(sattr & FILE_ATTRIBUTE_SYSTEM))
197 		return (B_FALSE);
198 
199 	return (B_TRUE);
200 }
201 
202 time_t
203 smb_get_boottime(void)
204 {
205 	extern time_t	boot_time;
206 	zone_t *z = curzone;
207 
208 	/* Unfortunately, the GZ doesn't set zone_boot_time. */
209 	if (z->zone_id == GLOBAL_ZONEID)
210 		return (boot_time);
211 
212 	return (z->zone_boot_time);
213 }
214 
215 /*
216  * smb_idpool_increment
217  *
218  * This function increments the ID pool by doubling the current size. This
219  * function assumes the caller entered the mutex of the pool.
220  */
221 static int
222 smb_idpool_increment(
223     smb_idpool_t	*pool)
224 {
225 	uint8_t		*new_pool;
226 	uint32_t	new_size;
227 
228 	ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC);
229 
230 	new_size = pool->id_size * 2;
231 	if (new_size <= SMB_IDPOOL_MAX_SIZE) {
232 		new_pool = kmem_alloc(new_size / 8, KM_NOSLEEP);
233 		if (new_pool) {
234 			bzero(new_pool, new_size / 8);
235 			bcopy(pool->id_pool, new_pool, pool->id_size / 8);
236 			kmem_free(pool->id_pool, pool->id_size / 8);
237 			pool->id_pool = new_pool;
238 			pool->id_free_counter += new_size - pool->id_size;
239 			pool->id_max_free_counter += new_size - pool->id_size;
240 			pool->id_size = new_size;
241 			pool->id_idx_msk = (new_size / 8) - 1;
242 			if (new_size >= SMB_IDPOOL_MAX_SIZE) {
243 				/* id -1 made unavailable */
244 				pool->id_pool[pool->id_idx_msk] = 0x80;
245 				pool->id_free_counter--;
246 				pool->id_max_free_counter--;
247 			}
248 			return (0);
249 		}
250 	}
251 	return (-1);
252 }
253 
254 /*
255  * smb_idpool_constructor
256  *
257  * This function initializes the pool structure provided.
258  */
259 int
260 smb_idpool_constructor(
261     smb_idpool_t	*pool)
262 {
263 
264 	ASSERT(pool->id_magic != SMB_IDPOOL_MAGIC);
265 
266 	pool->id_size = SMB_IDPOOL_MIN_SIZE;
267 	pool->id_idx_msk = (SMB_IDPOOL_MIN_SIZE / 8) - 1;
268 	pool->id_free_counter = SMB_IDPOOL_MIN_SIZE - 1;
269 	pool->id_max_free_counter = SMB_IDPOOL_MIN_SIZE - 1;
270 	pool->id_bit = 0x02;
271 	pool->id_bit_idx = 1;
272 	pool->id_idx = 0;
273 	pool->id_pool = (uint8_t *)kmem_alloc((SMB_IDPOOL_MIN_SIZE / 8),
274 	    KM_SLEEP);
275 	bzero(pool->id_pool, (SMB_IDPOOL_MIN_SIZE / 8));
276 	/* -1 id made unavailable */
277 	pool->id_pool[0] = 0x01;		/* id 0 made unavailable */
278 	mutex_init(&pool->id_mutex, NULL, MUTEX_DEFAULT, NULL);
279 	pool->id_magic = SMB_IDPOOL_MAGIC;
280 	return (0);
281 }
282 
283 /*
284  * smb_idpool_destructor
285  *
286  * This function tears down and frees the resources associated with the
287  * pool provided.
288  */
289 void
290 smb_idpool_destructor(
291     smb_idpool_t	*pool)
292 {
293 	ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC);
294 	ASSERT(pool->id_free_counter == pool->id_max_free_counter);
295 	pool->id_magic = (uint32_t)~SMB_IDPOOL_MAGIC;
296 	mutex_destroy(&pool->id_mutex);
297 	kmem_free(pool->id_pool, (size_t)(pool->id_size / 8));
298 }
299 
300 /*
301  * smb_idpool_alloc
302  *
303  * This function allocates an ID from the pool provided.
304  */
305 int
306 smb_idpool_alloc(
307     smb_idpool_t	*pool,
308     uint16_t		*id)
309 {
310 	uint32_t	i;
311 	uint8_t		bit;
312 	uint8_t		bit_idx;
313 	uint8_t		byte;
314 
315 	ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC);
316 
317 	mutex_enter(&pool->id_mutex);
318 	if ((pool->id_free_counter == 0) && smb_idpool_increment(pool)) {
319 		mutex_exit(&pool->id_mutex);
320 		return (-1);
321 	}
322 
323 	i = pool->id_size;
324 	while (i) {
325 		bit = pool->id_bit;
326 		bit_idx = pool->id_bit_idx;
327 		byte = pool->id_pool[pool->id_idx];
328 		while (bit) {
329 			if (byte & bit) {
330 				bit = bit << 1;
331 				bit_idx++;
332 				continue;
333 			}
334 			pool->id_pool[pool->id_idx] |= bit;
335 			*id = (uint16_t)(pool->id_idx * 8 + (uint32_t)bit_idx);
336 			pool->id_free_counter--;
337 			/*
338 			 * Leave position at next bit to allocate,
339 			 * so we don't keep re-using the last in an
340 			 * alloc/free/alloc/free sequence.  Doing
341 			 * that can confuse some SMB clients.
342 			 */
343 			if (bit & 0x80) {
344 				pool->id_bit = 1;
345 				pool->id_bit_idx = 0;
346 				pool->id_idx++;
347 				pool->id_idx &= pool->id_idx_msk;
348 			} else {
349 				pool->id_bit = (bit << 1);
350 				pool->id_bit_idx = bit_idx + 1;
351 				/* keep id_idx */
352 			}
353 			mutex_exit(&pool->id_mutex);
354 			return (0);
355 		}
356 		pool->id_bit = 1;
357 		pool->id_bit_idx = 0;
358 		pool->id_idx++;
359 		pool->id_idx &= pool->id_idx_msk;
360 		--i;
361 	}
362 	/*
363 	 * This section of code shouldn't be reached. If there are IDs
364 	 * available and none could be found there's a problem.
365 	 */
366 	ASSERT(0);
367 	mutex_exit(&pool->id_mutex);
368 	return (-1);
369 }
370 
371 /*
372  * smb_idpool_free
373  *
374  * This function frees the ID provided.
375  */
376 void
377 smb_idpool_free(
378     smb_idpool_t	*pool,
379     uint16_t		id)
380 {
381 	ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC);
382 	ASSERT(id != 0);
383 	ASSERT(id != 0xFFFF);
384 
385 	mutex_enter(&pool->id_mutex);
386 	if (pool->id_pool[id >> 3] & (1 << (id & 7))) {
387 		pool->id_pool[id >> 3] &= ~(1 << (id & 7));
388 		pool->id_free_counter++;
389 		ASSERT(pool->id_free_counter <= pool->id_max_free_counter);
390 		mutex_exit(&pool->id_mutex);
391 		return;
392 	}
393 	/* Freeing a free ID. */
394 	ASSERT(0);
395 	mutex_exit(&pool->id_mutex);
396 }
397 
398 /*
399  * smb_lavl_constructor
400  *
401  * This function initializes a locked avl.
402  */
403 void
404 smb_lavl_constructor(
405     smb_lavl_t	*la,
406     int (*compar) (const void *, const void *),
407     size_t	size,
408     size_t	offset)
409 {
410 	rw_init(&la->la_lock, NULL, RW_DEFAULT, NULL);
411 	mutex_init(&la->la_mutex, NULL, MUTEX_DEFAULT, NULL);
412 	avl_create(&la->la_tree, compar, size, offset);
413 	list_create(&la->la_deleteq, sizeof (smb_dtor_t),
414 	    offsetof(smb_dtor_t, dt_lnd));
415 	la->la_wrop = 0;
416 	la->la_deleteq_count = 0;
417 	la->la_flushing = B_FALSE;
418 }
419 
420 /*
421  * Flush the delete queue and destroy a locked avl.
422  */
423 void
424 smb_lavl_destructor(
425     smb_lavl_t	*la)
426 {
427 	smb_lavl_flush(la);
428 
429 	ASSERT(la->la_deleteq_count == 0);
430 	ASSERT0(avl_numnodes(&la->la_tree));
431 
432 	rw_destroy(&la->la_lock);
433 	avl_destroy(&la->la_tree);
434 	list_destroy(&la->la_deleteq);
435 	mutex_destroy(&la->la_mutex);
436 }
437 
438 /*
439  * smb_lavl_enter
440  * Not a macro so dtrace smbsrv:* can see it.
441  */
442 void
443 smb_lavl_enter(smb_lavl_t *la, krw_t mode)
444 {
445 	rw_enter(&la->la_lock, mode);
446 }
447 
448 /*
449  * Post an object to the delete queue.  The delete queue will be processed
450  * during smb_lavl_exit or lavl destruction.  Objects are often posted for
451  * deletion during avl iteration (while the lavl is locked) but that is
452  * not required, and an object can be posted at any time.
453  */
454 void
455 smb_lavl_post(smb_lavl_t *la, void *object, smb_dtorproc_t dtorproc)
456 {
457 	smb_dtor_t	*dtor;
458 
459 	ASSERT((object != NULL) && (dtorproc != NULL));
460 
461 	dtor = kmem_cache_alloc(smb_dtor_cache, KM_SLEEP);
462 	bzero(dtor, sizeof (smb_dtor_t));
463 	dtor->dt_magic = SMB_DTOR_MAGIC;
464 	dtor->dt_object = object;
465 	dtor->dt_proc = dtorproc;
466 
467 	mutex_enter(&la->la_mutex);
468 	list_insert_tail(&la->la_deleteq, dtor);
469 	++la->la_deleteq_count;
470 	mutex_exit(&la->la_mutex);
471 }
472 
473 /*
474  * Exit the lavl lock and process the delete queue.
475  */
476 void
477 smb_lavl_exit(smb_lavl_t *la)
478 {
479 	rw_exit(&la->la_lock);
480 	smb_lavl_flush(la);
481 }
482 
483 /*
484  * Flush the lavl delete queue.  The mutex is dropped across the destructor
485  * call in case this leads to additional objects being posted to the delete
486  * queue.
487  */
488 void
489 smb_lavl_flush(smb_lavl_t *la)
490 {
491 	smb_dtor_t    *dtor;
492 
493 	mutex_enter(&la->la_mutex);
494 	if (la->la_flushing) {
495 		mutex_exit(&la->la_mutex);
496 		return;
497 	}
498 	la->la_flushing = B_TRUE;
499 
500 	dtor = list_head(&la->la_deleteq);
501 	while (dtor != NULL) {
502 		SMB_DTOR_VALID(dtor);
503 		ASSERT((dtor->dt_object != NULL) && (dtor->dt_proc != NULL));
504 		list_remove(&la->la_deleteq, dtor);
505 		--la->la_deleteq_count;
506 		mutex_exit(&la->la_mutex);
507 
508 		dtor->dt_proc(dtor->dt_object);
509 
510 		dtor->dt_magic = (uint32_t)~SMB_DTOR_MAGIC;
511 		kmem_cache_free(smb_dtor_cache, dtor);
512 		mutex_enter(&la->la_mutex);
513 		dtor = list_head(&la->la_deleteq);
514 	}
515 	la->la_flushing = B_FALSE;
516 
517 	mutex_exit(&la->la_mutex);
518 }
519 
520 /*
521  * smb_lavl_upgrade
522  *
523  * This function tries to upgrade the lock of the locked avl. It assumes the
524  * locked has already been entered in RW_READER mode. It first tries using the
525  * Solaris function rw_tryupgrade(). If that call fails the lock is released
526  * and reentered in RW_WRITER mode. In that last case a window is opened during
527  * which the contents of the avl may have changed. The return code indicates
528  * whether or not the avl was modified when the lock was exited.
529  */
530 int smb_lavl_upgrade(
531     smb_lavl_t *la)
532 {
533 	uint64_t	wrop;
534 
535 	if (rw_tryupgrade(&la->la_lock) != 0) {
536 		return (0);
537 	}
538 	wrop = la->la_wrop;
539 	rw_exit(&la->la_lock);
540 	rw_enter(&la->la_lock, RW_WRITER);
541 	return (wrop != la->la_wrop);
542 }
543 
544 /*
545  * smb_lavl_insert
546  *
547  * This function inserts the object passed into the tree
548  * at the position determined by the AVL comparator.
549  */
550 void
551 smb_lavl_insert(
552     smb_lavl_t	*la,
553     void	*obj)
554 {
555 	avl_add(&la->la_tree, obj);
556 	++la->la_wrop;
557 }
558 
559 /*
560  * smb_lavl_remove
561  *
562  * This function removes the object passed from the lavl. This function
563  * assumes the lock of the lavl has already been entered.
564  */
565 void
566 smb_lavl_remove(
567     smb_lavl_t	*la,
568     void	*obj)
569 {
570 	avl_remove(&la->la_tree, obj);
571 	++la->la_wrop;
572 }
573 
574 /*
575  * smb_lavl_get_count
576  *
577  * This function returns the number of elements in the specified avl.
578  */
579 uint32_t
580 smb_lavl_get_count(
581     smb_lavl_t *la)
582 {
583 	return ((uint32_t)avl_numnodes(&la->la_tree));
584 }
585 
586 /*
587  * Initialize the llist delete queue object cache.
588  */
589 void
590 smb_llist_init(void)
591 {
592 	if (smb_dtor_cache != NULL)
593 		return;
594 
595 	smb_dtor_cache = kmem_cache_create("smb_dtor_cache",
596 	    sizeof (smb_dtor_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
597 }
598 
599 /*
600  * Destroy the llist delete queue object cache.
601  */
602 void
603 smb_llist_fini(void)
604 {
605 	if (smb_dtor_cache != NULL) {
606 		kmem_cache_destroy(smb_dtor_cache);
607 		smb_dtor_cache = NULL;
608 	}
609 }
610 
611 /*
612  * smb_llist_constructor
613  *
614  * This function initializes a locked list.
615  */
616 void
617 smb_llist_constructor(
618     smb_llist_t	*ll,
619     size_t	size,
620     size_t	offset)
621 {
622 	rw_init(&ll->ll_lock, NULL, RW_DEFAULT, NULL);
623 	mutex_init(&ll->ll_mutex, NULL, MUTEX_DEFAULT, NULL);
624 	list_create(&ll->ll_list, size, offset);
625 	list_create(&ll->ll_deleteq, sizeof (smb_dtor_t),
626 	    offsetof(smb_dtor_t, dt_lnd));
627 	ll->ll_count = 0;
628 	ll->ll_wrop = 0;
629 	ll->ll_deleteq_count = 0;
630 	ll->ll_flushing = B_FALSE;
631 }
632 
633 /*
634  * Flush the delete queue and destroy a locked list.
635  */
636 void
637 smb_llist_destructor(
638     smb_llist_t	*ll)
639 {
640 	smb_llist_flush(ll);
641 
642 	ASSERT(ll->ll_count == 0);
643 	ASSERT(ll->ll_deleteq_count == 0);
644 
645 	rw_destroy(&ll->ll_lock);
646 	list_destroy(&ll->ll_list);
647 	list_destroy(&ll->ll_deleteq);
648 	mutex_destroy(&ll->ll_mutex);
649 }
650 
651 /*
652  * smb_llist_enter
653  * Not a macro so dtrace smbsrv:* can see it.
654  */
655 void
656 smb_llist_enter(smb_llist_t *ll, krw_t mode)
657 {
658 	rw_enter(&ll->ll_lock, mode);
659 }
660 
661 /*
662  * Post an object to the delete queue.  The delete queue will be processed
663  * during list exit or list destruction.  Objects are often posted for
664  * deletion during list iteration (while the list is locked) but that is
665  * not required, and an object can be posted at any time.
666  */
667 void
668 smb_llist_post(smb_llist_t *ll, void *object, smb_dtorproc_t dtorproc)
669 {
670 	smb_dtor_t	*dtor;
671 
672 	ASSERT((object != NULL) && (dtorproc != NULL));
673 
674 	dtor = kmem_cache_alloc(smb_dtor_cache, KM_SLEEP);
675 	bzero(dtor, sizeof (smb_dtor_t));
676 	dtor->dt_magic = SMB_DTOR_MAGIC;
677 	dtor->dt_object = object;
678 	dtor->dt_proc = dtorproc;
679 
680 	mutex_enter(&ll->ll_mutex);
681 	list_insert_tail(&ll->ll_deleteq, dtor);
682 	++ll->ll_deleteq_count;
683 	mutex_exit(&ll->ll_mutex);
684 }
685 
686 /*
687  * Exit the list lock and process the delete queue.
688  */
689 void
690 smb_llist_exit(smb_llist_t *ll)
691 {
692 	rw_exit(&ll->ll_lock);
693 	smb_llist_flush(ll);
694 }
695 
696 /*
697  * Flush the list delete queue.  The mutex is dropped across the destructor
698  * call in case this leads to additional objects being posted to the delete
699  * queue.
700  */
701 void
702 smb_llist_flush(smb_llist_t *ll)
703 {
704 	smb_dtor_t    *dtor;
705 
706 	mutex_enter(&ll->ll_mutex);
707 	if (ll->ll_flushing) {
708 		mutex_exit(&ll->ll_mutex);
709 		return;
710 	}
711 	ll->ll_flushing = B_TRUE;
712 
713 	dtor = list_head(&ll->ll_deleteq);
714 	while (dtor != NULL) {
715 		SMB_DTOR_VALID(dtor);
716 		ASSERT((dtor->dt_object != NULL) && (dtor->dt_proc != NULL));
717 		list_remove(&ll->ll_deleteq, dtor);
718 		--ll->ll_deleteq_count;
719 		mutex_exit(&ll->ll_mutex);
720 
721 		dtor->dt_proc(dtor->dt_object);
722 
723 		dtor->dt_magic = (uint32_t)~SMB_DTOR_MAGIC;
724 		kmem_cache_free(smb_dtor_cache, dtor);
725 		mutex_enter(&ll->ll_mutex);
726 		dtor = list_head(&ll->ll_deleteq);
727 	}
728 	ll->ll_flushing = B_FALSE;
729 
730 	mutex_exit(&ll->ll_mutex);
731 }
732 
733 /*
734  * smb_llist_upgrade
735  *
736  * This function tries to upgrade the lock of the locked list. It assumes the
737  * locked has already been entered in RW_READER mode. It first tries using the
738  * Solaris function rw_tryupgrade(). If that call fails the lock is released
739  * and reentered in RW_WRITER mode. In that last case a window is opened during
740  * which the contents of the list may have changed. The return code indicates
741  * whether or not the list was modified when the lock was exited.
742  */
743 int smb_llist_upgrade(
744     smb_llist_t *ll)
745 {
746 	uint64_t	wrop;
747 
748 	if (rw_tryupgrade(&ll->ll_lock) != 0) {
749 		return (0);
750 	}
751 	wrop = ll->ll_wrop;
752 	rw_exit(&ll->ll_lock);
753 	rw_enter(&ll->ll_lock, RW_WRITER);
754 	return (wrop != ll->ll_wrop);
755 }
756 
757 /*
758  * smb_llist_insert_head
759  *
760  * This function inserts the object passed a the beginning of the list. This
761  * function assumes the lock of the list has already been entered.
762  */
763 void
764 smb_llist_insert_head(
765     smb_llist_t	*ll,
766     void	*obj)
767 {
768 	list_insert_head(&ll->ll_list, obj);
769 	++ll->ll_wrop;
770 	++ll->ll_count;
771 }
772 
773 /*
774  * smb_llist_insert_tail
775  *
776  * This function appends to the object passed to the list. This function assumes
777  * the lock of the list has already been entered.
778  *
779  */
780 void
781 smb_llist_insert_tail(
782     smb_llist_t	*ll,
783     void	*obj)
784 {
785 	list_insert_tail(&ll->ll_list, obj);
786 	++ll->ll_wrop;
787 	++ll->ll_count;
788 }
789 
790 /*
791  * smb_llist_remove
792  *
793  * This function removes the object passed from the list. This function assumes
794  * the lock of the list has already been entered.
795  */
796 void
797 smb_llist_remove(
798     smb_llist_t	*ll,
799     void	*obj)
800 {
801 	list_remove(&ll->ll_list, obj);
802 	++ll->ll_wrop;
803 	--ll->ll_count;
804 }
805 
806 /*
807  * smb_llist_get_count
808  *
809  * This function returns the number of elements in the specified list.
810  */
811 uint32_t
812 smb_llist_get_count(
813     smb_llist_t *ll)
814 {
815 	return (ll->ll_count);
816 }
817 
818 /*
819  * smb_slist_constructor
820  *
821  * Synchronized list constructor.
822  */
823 void
824 smb_slist_constructor(
825     smb_slist_t	*sl,
826     size_t	size,
827     size_t	offset)
828 {
829 	mutex_init(&sl->sl_mutex, NULL, MUTEX_DEFAULT, NULL);
830 	cv_init(&sl->sl_cv, NULL, CV_DEFAULT, NULL);
831 	list_create(&sl->sl_list, size, offset);
832 	sl->sl_count = 0;
833 	sl->sl_waiting = B_FALSE;
834 }
835 
836 /*
837  * smb_slist_destructor
838  *
839  * Synchronized list destructor.
840  */
841 void
842 smb_slist_destructor(
843     smb_slist_t	*sl)
844 {
845 	VERIFY(sl->sl_count == 0);
846 
847 	mutex_destroy(&sl->sl_mutex);
848 	cv_destroy(&sl->sl_cv);
849 	list_destroy(&sl->sl_list);
850 }
851 
852 /*
853  * smb_slist_enter
854  * Not a macro so dtrace smbsrv:* can see it.
855  */
856 void
857 smb_slist_enter(smb_slist_t *sl)
858 {
859 	mutex_enter(&(sl)->sl_mutex);
860 }
861 
862 /*
863  * smb_slist_insert_head
864  *
865  * This function inserts the object passed a the beginning of the list.
866  */
867 void
868 smb_slist_insert_head(
869     smb_slist_t	*sl,
870     void	*obj)
871 {
872 	mutex_enter(&sl->sl_mutex);
873 	list_insert_head(&sl->sl_list, obj);
874 	++sl->sl_count;
875 	mutex_exit(&sl->sl_mutex);
876 }
877 
878 /*
879  * smb_slist_insert_tail
880  *
881  * This function appends the object passed to the list.
882  */
883 void
884 smb_slist_insert_tail(
885     smb_slist_t	*sl,
886     void	*obj)
887 {
888 	mutex_enter(&sl->sl_mutex);
889 	list_insert_tail(&sl->sl_list, obj);
890 	++sl->sl_count;
891 	mutex_exit(&sl->sl_mutex);
892 }
893 
894 /*
895  * smb_llist_remove
896  *
897  * This function removes the object passed by the caller from the list.
898  */
899 void
900 smb_slist_remove(
901     smb_slist_t	*sl,
902     void	*obj)
903 {
904 	mutex_enter(&sl->sl_mutex);
905 	list_remove(&sl->sl_list, obj);
906 	if ((--sl->sl_count == 0) && (sl->sl_waiting)) {
907 		sl->sl_waiting = B_FALSE;
908 		cv_broadcast(&sl->sl_cv);
909 	}
910 	mutex_exit(&sl->sl_mutex);
911 }
912 
913 /*
914  * smb_slist_move_tail
915  *
916  * This function transfers all the contents of the synchronized list to the
917  * list_t provided. It returns the number of objects transferred.
918  */
919 uint32_t
920 smb_slist_move_tail(
921     list_t	*lst,
922     smb_slist_t	*sl)
923 {
924 	uint32_t	rv;
925 
926 	mutex_enter(&sl->sl_mutex);
927 	rv = sl->sl_count;
928 	if (sl->sl_count) {
929 		list_move_tail(lst, &sl->sl_list);
930 		sl->sl_count = 0;
931 		if (sl->sl_waiting) {
932 			sl->sl_waiting = B_FALSE;
933 			cv_broadcast(&sl->sl_cv);
934 		}
935 	}
936 	mutex_exit(&sl->sl_mutex);
937 	return (rv);
938 }
939 
940 /*
941  * smb_slist_obj_move
942  *
943  * This function moves an object from one list to the end of the other list. It
944  * assumes the mutex of each list has been entered.
945  */
946 void
947 smb_slist_obj_move(
948     smb_slist_t	*dst,
949     smb_slist_t	*src,
950     void	*obj)
951 {
952 	ASSERT(dst->sl_list.list_offset == src->sl_list.list_offset);
953 	ASSERT(dst->sl_list.list_size == src->sl_list.list_size);
954 
955 	list_remove(&src->sl_list, obj);
956 	list_insert_tail(&dst->sl_list, obj);
957 	dst->sl_count++;
958 	src->sl_count--;
959 	if ((src->sl_count == 0) && (src->sl_waiting)) {
960 		src->sl_waiting = B_FALSE;
961 		cv_broadcast(&src->sl_cv);
962 	}
963 }
964 
965 /*
966  * smb_slist_wait_for_empty
967  *
968  * This function waits for a list to be emptied.
969  */
970 void
971 smb_slist_wait_for_empty(
972     smb_slist_t	*sl)
973 {
974 	mutex_enter(&sl->sl_mutex);
975 	while (sl->sl_count) {
976 		sl->sl_waiting = B_TRUE;
977 		cv_wait(&sl->sl_cv, &sl->sl_mutex);
978 	}
979 	mutex_exit(&sl->sl_mutex);
980 }
981 
982 /*
983  * smb_slist_exit
984  *
985  * This function exits the muetx of the list and signal the condition variable
986  * if the list is empty.
987  */
988 void
989 smb_slist_exit(smb_slist_t *sl)
990 {
991 	if ((sl->sl_count == 0) && (sl->sl_waiting)) {
992 		sl->sl_waiting = B_FALSE;
993 		cv_broadcast(&sl->sl_cv);
994 	}
995 	mutex_exit(&sl->sl_mutex);
996 }
997 
998 /* smb_thread_... moved to smb_thread.c */
999 
1000 /*
1001  * smb_rwx_init
1002  */
1003 void
1004 smb_rwx_init(
1005     smb_rwx_t	*rwx)
1006 {
1007 	bzero(rwx, sizeof (smb_rwx_t));
1008 	cv_init(&rwx->rwx_cv, NULL, CV_DEFAULT, NULL);
1009 	mutex_init(&rwx->rwx_mutex, NULL, MUTEX_DEFAULT, NULL);
1010 	rw_init(&rwx->rwx_lock, NULL, RW_DEFAULT, NULL);
1011 }
1012 
1013 /*
1014  * smb_rwx_destroy
1015  */
1016 void
1017 smb_rwx_destroy(
1018     smb_rwx_t	*rwx)
1019 {
1020 	mutex_destroy(&rwx->rwx_mutex);
1021 	cv_destroy(&rwx->rwx_cv);
1022 	rw_destroy(&rwx->rwx_lock);
1023 }
1024 
1025 /*
1026  * smb_rwx_rwenter
1027  */
1028 void
1029 smb_rwx_rwenter(smb_rwx_t *rwx, krw_t mode)
1030 {
1031 	rw_enter(&rwx->rwx_lock, mode);
1032 }
1033 
1034 /*
1035  * smb_rwx_rwexit
1036  */
1037 void
1038 smb_rwx_rwexit(
1039     smb_rwx_t	*rwx)
1040 {
1041 	rw_exit(&rwx->rwx_lock);
1042 }
1043 
1044 
1045 /*
1046  * smb_rwx_cvwait
1047  *
1048  * Wait on rwx->rw_cv, dropping the rw lock and retake after wakeup.
1049  * Assumes the smb_rwx lock was entered in RW_READER or RW_WRITER
1050  * mode. It will:
1051  *
1052  *	1) release the lock and save its current mode.
1053  *	2) wait until the condition variable is signaled.
1054  *	3) re-acquire the lock in the mode saved in (1).
1055  *
1056  * Lock order: rwlock, mutex
1057  */
1058 int
1059 smb_rwx_cvwait(
1060     smb_rwx_t	*rwx,
1061     clock_t	timeout)
1062 {
1063 	krw_t	mode;
1064 	int	rc = 1;
1065 
1066 	if (rw_write_held(&rwx->rwx_lock)) {
1067 		ASSERT(rw_owner(&rwx->rwx_lock) == curthread);
1068 		mode = RW_WRITER;
1069 	} else {
1070 		ASSERT(rw_read_held(&rwx->rwx_lock));
1071 		mode = RW_READER;
1072 	}
1073 
1074 	mutex_enter(&rwx->rwx_mutex);
1075 	rw_exit(&rwx->rwx_lock);
1076 
1077 	rwx->rwx_waiting = B_TRUE;
1078 	if (timeout == -1) {
1079 		cv_wait(&rwx->rwx_cv, &rwx->rwx_mutex);
1080 	} else {
1081 		rc = cv_reltimedwait(&rwx->rwx_cv, &rwx->rwx_mutex,
1082 		    timeout, TR_CLOCK_TICK);
1083 	}
1084 	mutex_exit(&rwx->rwx_mutex);
1085 
1086 	rw_enter(&rwx->rwx_lock, mode);
1087 	return (rc);
1088 }
1089 
1090 /*
1091  * smb_rwx_cvbcast
1092  *
1093  * Wake up threads waiting on rx_cv
1094  * The rw lock may or may not be held.
1095  * The mutex MUST NOT be held.
1096  */
1097 void
1098 smb_rwx_cvbcast(smb_rwx_t *rwx)
1099 {
1100 	mutex_enter(&rwx->rwx_mutex);
1101 	if (rwx->rwx_waiting) {
1102 		rwx->rwx_waiting = B_FALSE;
1103 		cv_broadcast(&rwx->rwx_cv);
1104 	}
1105 	mutex_exit(&rwx->rwx_mutex);
1106 }
1107 
1108 /* smb_idmap_... moved to smb_idmap.c */
1109 
1110 uint64_t
1111 smb_time_unix_to_nt(timestruc_t *unix_time)
1112 {
1113 	uint64_t nt_time;
1114 
1115 	if ((unix_time->tv_sec == 0) && (unix_time->tv_nsec == 0))
1116 		return (0);
1117 
1118 	nt_time = unix_time->tv_sec;
1119 	nt_time *= 10000000;  /* seconds to 100ns */
1120 	nt_time += unix_time->tv_nsec / 100;
1121 	return (nt_time + NT_TIME_BIAS);
1122 }
1123 
1124 void
1125 smb_time_nt_to_unix(uint64_t nt_time, timestruc_t *unix_time)
1126 {
1127 	uint32_t seconds;
1128 
1129 	ASSERT(unix_time);
1130 
1131 	if ((nt_time == 0) || (nt_time == -1)) {
1132 		unix_time->tv_sec = 0;
1133 		unix_time->tv_nsec = 0;
1134 		return;
1135 	}
1136 
1137 	/*
1138 	 * Can't represent times less than or equal NT_TIME_BIAS,
1139 	 * so convert them to the oldest date we can store.
1140 	 * Note that time zero is "special" being converted
1141 	 * both directions as 0:0 (unix-to-nt, nt-to-unix).
1142 	 */
1143 	if (nt_time <= NT_TIME_BIAS) {
1144 		unix_time->tv_sec = 0;
1145 		unix_time->tv_nsec = 100;
1146 		return;
1147 	}
1148 
1149 	nt_time -= NT_TIME_BIAS;
1150 	seconds = nt_time / 10000000;
1151 	unix_time->tv_sec = seconds;
1152 	unix_time->tv_nsec = (nt_time  % 10000000) * 100;
1153 }
1154 
1155 /*
1156  * smb_time_gmt_to_local, smb_time_local_to_gmt
1157  *
1158  * Apply the gmt offset to convert between local time and gmt
1159  */
1160 int32_t
1161 smb_time_gmt_to_local(smb_request_t *sr, int32_t gmt)
1162 {
1163 	if ((gmt == 0) || (gmt == -1))
1164 		return (0);
1165 
1166 	return (gmt - sr->sr_gmtoff);
1167 }
1168 
1169 int32_t
1170 smb_time_local_to_gmt(smb_request_t *sr, int32_t local)
1171 {
1172 	if ((local == 0) || (local == -1))
1173 		return (0);
1174 
1175 	return (local + sr->sr_gmtoff);
1176 }
1177 
1178 
1179 /*
1180  * smb_time_dos_to_unix
1181  *
1182  * Convert SMB_DATE & SMB_TIME values to a unix timestamp.
1183  *
1184  * A date/time field of 0 means that that server file system
1185  * assigned value need not be changed. The behaviour when the
1186  * date/time field is set to -1 is not documented but is
1187  * generally treated like 0.
1188  * If date or time is 0 or -1 the unix time is returned as 0
1189  * so that the caller can identify and handle this special case.
1190  */
1191 int32_t
1192 smb_time_dos_to_unix(int16_t date, int16_t time)
1193 {
1194 	struct tm	atm;
1195 
1196 	if (((date == 0) || (time == 0)) ||
1197 	    ((date == -1) || (time == -1))) {
1198 		return (0);
1199 	}
1200 
1201 	atm.tm_year = ((date >>  9) & 0x3F) + 80;
1202 	atm.tm_mon  = ((date >>  5) & 0x0F) - 1;
1203 	atm.tm_mday = ((date >>  0) & 0x1F);
1204 	atm.tm_hour = ((time >> 11) & 0x1F);
1205 	atm.tm_min  = ((time >>  5) & 0x3F);
1206 	atm.tm_sec  = ((time >>  0) & 0x1F) << 1;
1207 
1208 	return (smb_timegm(&atm));
1209 }
1210 
1211 void
1212 smb_time_unix_to_dos(int32_t ux_time, int16_t *date_p, int16_t *time_p)
1213 {
1214 	struct tm	atm;
1215 	int		i;
1216 	time_t		tmp_time;
1217 
1218 	if (ux_time == 0) {
1219 		*date_p = 0;
1220 		*time_p = 0;
1221 		return;
1222 	}
1223 
1224 	tmp_time = (time_t)ux_time;
1225 	(void) smb_gmtime_r(&tmp_time, &atm);
1226 
1227 	if (date_p) {
1228 		i = 0;
1229 		i += atm.tm_year - 80;
1230 		i <<= 4;
1231 		i += atm.tm_mon + 1;
1232 		i <<= 5;
1233 		i += atm.tm_mday;
1234 
1235 		*date_p = (short)i;
1236 	}
1237 	if (time_p) {
1238 		i = 0;
1239 		i += atm.tm_hour;
1240 		i <<= 6;
1241 		i += atm.tm_min;
1242 		i <<= 5;
1243 		i += atm.tm_sec >> 1;
1244 
1245 		*time_p = (short)i;
1246 	}
1247 }
1248 
1249 
1250 /*
1251  * smb_gmtime_r
1252  *
1253  * Thread-safe version of smb_gmtime. Returns a null pointer if either
1254  * input parameter is a null pointer. Otherwise returns a pointer
1255  * to result.
1256  *
1257  * Day of the week calculation: the Epoch was a thursday.
1258  *
1259  * There are no timezone corrections so tm_isdst and tm_gmtoff are
1260  * always zero, and the zone is always WET.
1261  */
1262 struct tm *
1263 smb_gmtime_r(time_t *clock, struct tm *result)
1264 {
1265 	time_t tsec;
1266 	int year;
1267 	int month;
1268 	int sec_per_month;
1269 
1270 	if (clock == 0 || result == 0)
1271 		return (0);
1272 
1273 	bzero(result, sizeof (struct tm));
1274 	tsec = *clock;
1275 	tsec -= tzh_leapcnt;
1276 
1277 	result->tm_wday = tsec / SECSPERDAY;
1278 	result->tm_wday = (result->tm_wday + TM_THURSDAY) % DAYSPERWEEK;
1279 
1280 	year = EPOCH_YEAR;
1281 	while (tsec >= (isleap(year) ? (SECSPERDAY * DAYSPERLYEAR) :
1282 	    (SECSPERDAY * DAYSPERNYEAR))) {
1283 		if (isleap(year))
1284 			tsec -= SECSPERDAY * DAYSPERLYEAR;
1285 		else
1286 			tsec -= SECSPERDAY * DAYSPERNYEAR;
1287 
1288 		++year;
1289 	}
1290 
1291 	result->tm_year = year - TM_YEAR_BASE;
1292 	result->tm_yday = tsec / SECSPERDAY;
1293 
1294 	for (month = TM_JANUARY; month <= TM_DECEMBER; ++month) {
1295 		sec_per_month = days_in_month[month] * SECSPERDAY;
1296 
1297 		if (month == TM_FEBRUARY && isleap(year))
1298 			sec_per_month += SECSPERDAY;
1299 
1300 		if (tsec < sec_per_month)
1301 			break;
1302 
1303 		tsec -= sec_per_month;
1304 	}
1305 
1306 	result->tm_mon = month;
1307 	result->tm_mday = (tsec / SECSPERDAY) + 1;
1308 	tsec %= SECSPERDAY;
1309 	result->tm_sec = tsec % 60;
1310 	tsec /= 60;
1311 	result->tm_min = tsec % 60;
1312 	tsec /= 60;
1313 	result->tm_hour = (int)tsec;
1314 
1315 	return (result);
1316 }
1317 
1318 
1319 /*
1320  * smb_timegm
1321  *
1322  * Converts the broken-down time in tm to a time value, i.e. the number
1323  * of seconds since the Epoch (00:00:00 UTC, January 1, 1970). This is
1324  * not a POSIX or ANSI function. Per the man page, the input values of
1325  * tm_wday and tm_yday are ignored and, as the input data is assumed to
1326  * represent GMT, we force tm_isdst and tm_gmtoff to 0.
1327  *
1328  * Before returning the clock time, we use smb_gmtime_r to set up tm_wday
1329  * and tm_yday, and bring the other fields within normal range. I don't
1330  * think this is really how it should be done but it's convenient for
1331  * now.
1332  */
1333 time_t
1334 smb_timegm(struct tm *tm)
1335 {
1336 	time_t tsec;
1337 	int dd;
1338 	int mm;
1339 	int yy;
1340 	int year;
1341 
1342 	if (tm == 0)
1343 		return (-1);
1344 
1345 	year = tm->tm_year + TM_YEAR_BASE;
1346 	tsec = tzh_leapcnt;
1347 
1348 	for (yy = EPOCH_YEAR; yy < year; ++yy) {
1349 		if (isleap(yy))
1350 			tsec += SECSPERDAY * DAYSPERLYEAR;
1351 		else
1352 			tsec += SECSPERDAY * DAYSPERNYEAR;
1353 	}
1354 
1355 	for (mm = TM_JANUARY; mm < tm->tm_mon; ++mm) {
1356 		dd = days_in_month[mm] * SECSPERDAY;
1357 
1358 		if (mm == TM_FEBRUARY && isleap(year))
1359 			dd += SECSPERDAY;
1360 
1361 		tsec += dd;
1362 	}
1363 
1364 	tsec += (tm->tm_mday - 1) * SECSPERDAY;
1365 	tsec += tm->tm_sec;
1366 	tsec += tm->tm_min * SECSPERMIN;
1367 	tsec += tm->tm_hour * SECSPERHOUR;
1368 
1369 	tm->tm_isdst = 0;
1370 	(void) smb_gmtime_r(&tsec, tm);
1371 	return (tsec);
1372 }
1373 
1374 /*
1375  * smb_pad_align
1376  *
1377  * Returns the number of bytes required to pad an offset to the
1378  * specified alignment.
1379  */
1380 uint32_t
1381 smb_pad_align(uint32_t offset, uint32_t align)
1382 {
1383 	uint32_t pad = offset % align;
1384 
1385 	if (pad != 0)
1386 		pad = align - pad;
1387 
1388 	return (pad);
1389 }
1390 
1391 /*
1392  * smb_panic
1393  *
1394  * Logs the file name, function name and line number passed in and panics the
1395  * system.
1396  */
1397 void
1398 smb_panic(char *file, const char *func, int line)
1399 {
1400 	cmn_err(CE_PANIC, "%s:%s:%d\n", file, func, line);
1401 }
1402 
1403 /*
1404  * Creates an AVL tree and initializes the given smb_avl_t
1405  * structure using the passed args
1406  */
1407 void
1408 smb_avl_create(smb_avl_t *avl, size_t size, size_t offset,
1409     const smb_avl_nops_t *ops)
1410 {
1411 	ASSERT(avl);
1412 	ASSERT(ops);
1413 
1414 	rw_init(&avl->avl_lock, NULL, RW_DEFAULT, NULL);
1415 	mutex_init(&avl->avl_mutex, NULL, MUTEX_DEFAULT, NULL);
1416 
1417 	avl->avl_nops = ops;
1418 	avl->avl_state = SMB_AVL_STATE_READY;
1419 	avl->avl_refcnt = 0;
1420 	(void) random_get_pseudo_bytes((uint8_t *)&avl->avl_sequence,
1421 	    sizeof (uint32_t));
1422 
1423 	avl_create(&avl->avl_tree, ops->avln_cmp, size, offset);
1424 }
1425 
1426 /*
1427  * Destroys the specified AVL tree.
1428  * It waits for all the in-flight operations to finish
1429  * before destroying the AVL.
1430  */
1431 void
1432 smb_avl_destroy(smb_avl_t *avl)
1433 {
1434 	void *cookie = NULL;
1435 	void *node;
1436 
1437 	ASSERT(avl);
1438 
1439 	mutex_enter(&avl->avl_mutex);
1440 	if (avl->avl_state != SMB_AVL_STATE_READY) {
1441 		mutex_exit(&avl->avl_mutex);
1442 		return;
1443 	}
1444 
1445 	avl->avl_state = SMB_AVL_STATE_DESTROYING;
1446 
1447 	while (avl->avl_refcnt > 0)
1448 		(void) cv_wait(&avl->avl_cv, &avl->avl_mutex);
1449 	mutex_exit(&avl->avl_mutex);
1450 
1451 	rw_enter(&avl->avl_lock, RW_WRITER);
1452 	while ((node = avl_destroy_nodes(&avl->avl_tree, &cookie)) != NULL)
1453 		avl->avl_nops->avln_destroy(node);
1454 
1455 	avl_destroy(&avl->avl_tree);
1456 	rw_exit(&avl->avl_lock);
1457 
1458 	rw_destroy(&avl->avl_lock);
1459 
1460 	mutex_destroy(&avl->avl_mutex);
1461 	bzero(avl, sizeof (smb_avl_t));
1462 }
1463 
1464 /*
1465  * Adds the given item to the AVL if it's
1466  * not already there.
1467  *
1468  * Returns:
1469  *
1470  *	ENOTACTIVE	AVL is not in READY state
1471  *	EEXIST		The item is already in AVL
1472  */
1473 int
1474 smb_avl_add(smb_avl_t *avl, void *item)
1475 {
1476 	avl_index_t where;
1477 
1478 	ASSERT(avl);
1479 	ASSERT(item);
1480 
1481 	if (!smb_avl_hold(avl))
1482 		return (ENOTACTIVE);
1483 
1484 	rw_enter(&avl->avl_lock, RW_WRITER);
1485 	if (avl_find(&avl->avl_tree, item, &where) != NULL) {
1486 		rw_exit(&avl->avl_lock);
1487 		smb_avl_rele(avl);
1488 		return (EEXIST);
1489 	}
1490 
1491 	avl_insert(&avl->avl_tree, item, where);
1492 	avl->avl_sequence++;
1493 	rw_exit(&avl->avl_lock);
1494 
1495 	smb_avl_rele(avl);
1496 	return (0);
1497 }
1498 
1499 /*
1500  * Removes the given item from the AVL.
1501  * If no reference is left on the item
1502  * it will also be destroyed by calling the
1503  * registered destroy operation.
1504  */
1505 void
1506 smb_avl_remove(smb_avl_t *avl, void *item)
1507 {
1508 	avl_index_t where;
1509 	void *rm_item;
1510 
1511 	ASSERT(avl);
1512 	ASSERT(item);
1513 
1514 	if (!smb_avl_hold(avl))
1515 		return;
1516 
1517 	rw_enter(&avl->avl_lock, RW_WRITER);
1518 	if ((rm_item = avl_find(&avl->avl_tree, item, &where)) == NULL) {
1519 		rw_exit(&avl->avl_lock);
1520 		smb_avl_rele(avl);
1521 		return;
1522 	}
1523 
1524 	avl_remove(&avl->avl_tree, rm_item);
1525 	if (avl->avl_nops->avln_rele(rm_item))
1526 		avl->avl_nops->avln_destroy(rm_item);
1527 	avl->avl_sequence++;
1528 	rw_exit(&avl->avl_lock);
1529 
1530 	smb_avl_rele(avl);
1531 }
1532 
1533 /*
1534  * Looks up the AVL for the given item.
1535  * If the item is found a hold on the object
1536  * is taken before the pointer to it is
1537  * returned to the caller. The caller MUST
1538  * always call smb_avl_release() after it's done
1539  * using the returned object to release the hold
1540  * taken on the object.
1541  */
1542 void *
1543 smb_avl_lookup(smb_avl_t *avl, void *item)
1544 {
1545 	void *node = NULL;
1546 
1547 	ASSERT(avl);
1548 	ASSERT(item);
1549 
1550 	if (!smb_avl_hold(avl))
1551 		return (NULL);
1552 
1553 	rw_enter(&avl->avl_lock, RW_READER);
1554 	node = avl_find(&avl->avl_tree, item, NULL);
1555 	if (node != NULL)
1556 		avl->avl_nops->avln_hold(node);
1557 	rw_exit(&avl->avl_lock);
1558 
1559 	if (node == NULL)
1560 		smb_avl_rele(avl);
1561 
1562 	return (node);
1563 }
1564 
1565 /*
1566  * The hold on the given object is released.
1567  * This function MUST always be called after
1568  * smb_avl_lookup() and smb_avl_iterate() for
1569  * the returned object.
1570  *
1571  * If AVL is in DESTROYING state, the destroying
1572  * thread will be notified.
1573  */
1574 void
1575 smb_avl_release(smb_avl_t *avl, void *item)
1576 {
1577 	ASSERT(avl);
1578 	ASSERT(item);
1579 
1580 	if (avl->avl_nops->avln_rele(item))
1581 		avl->avl_nops->avln_destroy(item);
1582 
1583 	smb_avl_rele(avl);
1584 }
1585 
1586 /*
1587  * Initializes the given cursor for the AVL.
1588  * The cursor will be used to iterate through the AVL
1589  */
1590 void
1591 smb_avl_iterinit(smb_avl_t *avl, smb_avl_cursor_t *cursor)
1592 {
1593 	ASSERT(avl);
1594 	ASSERT(cursor);
1595 
1596 	cursor->avlc_next = NULL;
1597 	cursor->avlc_sequence = avl->avl_sequence;
1598 }
1599 
1600 /*
1601  * Iterates through the AVL using the given cursor.
1602  * It always starts at the beginning and then returns
1603  * a pointer to the next object on each subsequent call.
1604  *
1605  * If a new object is added to or removed from the AVL
1606  * between two calls to this function, the iteration
1607  * will terminate prematurely.
1608  *
1609  * The caller MUST always call smb_avl_release() after it's
1610  * done using the returned object to release the hold taken
1611  * on the object.
1612  */
1613 void *
1614 smb_avl_iterate(smb_avl_t *avl, smb_avl_cursor_t *cursor)
1615 {
1616 	void *node;
1617 
1618 	ASSERT(avl);
1619 	ASSERT(cursor);
1620 
1621 	if (!smb_avl_hold(avl))
1622 		return (NULL);
1623 
1624 	rw_enter(&avl->avl_lock, RW_READER);
1625 	if (cursor->avlc_sequence != avl->avl_sequence) {
1626 		rw_exit(&avl->avl_lock);
1627 		smb_avl_rele(avl);
1628 		return (NULL);
1629 	}
1630 
1631 	if (cursor->avlc_next == NULL)
1632 		node = avl_first(&avl->avl_tree);
1633 	else
1634 		node = AVL_NEXT(&avl->avl_tree, cursor->avlc_next);
1635 
1636 	if (node != NULL)
1637 		avl->avl_nops->avln_hold(node);
1638 
1639 	cursor->avlc_next = node;
1640 	rw_exit(&avl->avl_lock);
1641 
1642 	if (node == NULL)
1643 		smb_avl_rele(avl);
1644 
1645 	return (node);
1646 }
1647 
1648 /*
1649  * Increments the AVL reference count in order to
1650  * prevent the avl from being destroyed while it's
1651  * being accessed.
1652  */
1653 static boolean_t
1654 smb_avl_hold(smb_avl_t *avl)
1655 {
1656 	mutex_enter(&avl->avl_mutex);
1657 	if (avl->avl_state != SMB_AVL_STATE_READY) {
1658 		mutex_exit(&avl->avl_mutex);
1659 		return (B_FALSE);
1660 	}
1661 	avl->avl_refcnt++;
1662 	mutex_exit(&avl->avl_mutex);
1663 
1664 	return (B_TRUE);
1665 }
1666 
1667 /*
1668  * Decrements the AVL reference count to release the
1669  * hold. If another thread is trying to destroy the
1670  * AVL and is waiting for the reference count to become
1671  * 0, it is signaled to wake up.
1672  */
1673 static void
1674 smb_avl_rele(smb_avl_t *avl)
1675 {
1676 	mutex_enter(&avl->avl_mutex);
1677 	ASSERT(avl->avl_refcnt > 0);
1678 	avl->avl_refcnt--;
1679 	if (avl->avl_state == SMB_AVL_STATE_DESTROYING)
1680 		cv_broadcast(&avl->avl_cv);
1681 	mutex_exit(&avl->avl_mutex);
1682 }
1683 
1684 /*
1685  * smb_latency_init
1686  */
1687 void
1688 smb_latency_init(smb_latency_t *lat)
1689 {
1690 	bzero(lat, sizeof (*lat));
1691 	mutex_init(&lat->ly_mutex, NULL, MUTEX_SPIN, (void *)ipltospl(SPL7));
1692 }
1693 
1694 /*
1695  * smb_latency_destroy
1696  */
1697 void
1698 smb_latency_destroy(smb_latency_t *lat)
1699 {
1700 	mutex_destroy(&lat->ly_mutex);
1701 }
1702 
1703 /*
1704  * smb_latency_add_sample
1705  *
1706  * Uses the new sample to calculate the new mean and standard deviation. The
1707  * sample must be a scaled value.
1708  */
1709 void
1710 smb_latency_add_sample(smb_latency_t *lat, hrtime_t sample)
1711 {
1712 	hrtime_t	a_mean;
1713 	hrtime_t	d_mean;
1714 
1715 	mutex_enter(&lat->ly_mutex);
1716 	lat->ly_a_nreq++;
1717 	lat->ly_a_sum += sample;
1718 	if (lat->ly_a_nreq != 0) {
1719 		a_mean = lat->ly_a_sum / lat->ly_a_nreq;
1720 		lat->ly_a_stddev =
1721 		    (sample - a_mean) * (sample - lat->ly_a_mean);
1722 		lat->ly_a_mean = a_mean;
1723 	}
1724 	lat->ly_d_nreq++;
1725 	lat->ly_d_sum += sample;
1726 	if (lat->ly_d_nreq != 0) {
1727 		d_mean = lat->ly_d_sum / lat->ly_d_nreq;
1728 		lat->ly_d_stddev =
1729 		    (sample - d_mean) * (sample - lat->ly_d_mean);
1730 		lat->ly_d_mean = d_mean;
1731 	}
1732 	mutex_exit(&lat->ly_mutex);
1733 }
1734 
1735 /*
1736  * smb_srqueue_init
1737  */
1738 void
1739 smb_srqueue_init(smb_srqueue_t *srq)
1740 {
1741 	bzero(srq, sizeof (*srq));
1742 	mutex_init(&srq->srq_mutex, NULL, MUTEX_SPIN, (void *)ipltospl(SPL7));
1743 	srq->srq_wlastupdate = srq->srq_rlastupdate = gethrtime_unscaled();
1744 }
1745 
1746 /*
1747  * smb_srqueue_destroy
1748  */
1749 void
1750 smb_srqueue_destroy(smb_srqueue_t *srq)
1751 {
1752 	mutex_destroy(&srq->srq_mutex);
1753 }
1754 
1755 /*
1756  * smb_srqueue_waitq_enter
1757  */
1758 void
1759 smb_srqueue_waitq_enter(smb_srqueue_t *srq)
1760 {
1761 	hrtime_t	new;
1762 	hrtime_t	delta;
1763 	uint32_t	wcnt;
1764 
1765 	mutex_enter(&srq->srq_mutex);
1766 	new = gethrtime_unscaled();
1767 	delta = new - srq->srq_wlastupdate;
1768 	srq->srq_wlastupdate = new;
1769 	wcnt = srq->srq_wcnt++;
1770 	if (wcnt != 0) {
1771 		srq->srq_wlentime += delta * wcnt;
1772 		srq->srq_wtime += delta;
1773 	}
1774 	mutex_exit(&srq->srq_mutex);
1775 }
1776 
1777 /*
1778  * smb_srqueue_runq_exit
1779  */
1780 void
1781 smb_srqueue_runq_exit(smb_srqueue_t *srq)
1782 {
1783 	hrtime_t	new;
1784 	hrtime_t	delta;
1785 	uint32_t	rcnt;
1786 
1787 	mutex_enter(&srq->srq_mutex);
1788 	new = gethrtime_unscaled();
1789 	delta = new - srq->srq_rlastupdate;
1790 	srq->srq_rlastupdate = new;
1791 	rcnt = srq->srq_rcnt--;
1792 	ASSERT(rcnt > 0);
1793 	srq->srq_rlentime += delta * rcnt;
1794 	srq->srq_rtime += delta;
1795 	mutex_exit(&srq->srq_mutex);
1796 }
1797 
1798 /*
1799  * smb_srqueue_waitq_to_runq
1800  */
1801 void
1802 smb_srqueue_waitq_to_runq(smb_srqueue_t *srq)
1803 {
1804 	hrtime_t	new;
1805 	hrtime_t	delta;
1806 	uint32_t	wcnt;
1807 	uint32_t	rcnt;
1808 
1809 	mutex_enter(&srq->srq_mutex);
1810 	new = gethrtime_unscaled();
1811 	delta = new - srq->srq_wlastupdate;
1812 	srq->srq_wlastupdate = new;
1813 	wcnt = srq->srq_wcnt--;
1814 	ASSERT(wcnt > 0);
1815 	srq->srq_wlentime += delta * wcnt;
1816 	srq->srq_wtime += delta;
1817 	delta = new - srq->srq_rlastupdate;
1818 	srq->srq_rlastupdate = new;
1819 	rcnt = srq->srq_rcnt++;
1820 	if (rcnt != 0) {
1821 		srq->srq_rlentime += delta * rcnt;
1822 		srq->srq_rtime += delta;
1823 	}
1824 	mutex_exit(&srq->srq_mutex);
1825 }
1826 
1827 /*
1828  * smb_srqueue_update
1829  *
1830  * Takes a snapshot of the smb_sr_stat_t structure passed in.
1831  */
1832 void
1833 smb_srqueue_update(smb_srqueue_t *srq, smb_kstat_utilization_t *kd)
1834 {
1835 	hrtime_t	delta;
1836 	hrtime_t	snaptime;
1837 
1838 	mutex_enter(&srq->srq_mutex);
1839 	snaptime = gethrtime_unscaled();
1840 	delta = snaptime - srq->srq_wlastupdate;
1841 	srq->srq_wlastupdate = snaptime;
1842 	if (srq->srq_wcnt != 0) {
1843 		srq->srq_wlentime += delta * srq->srq_wcnt;
1844 		srq->srq_wtime += delta;
1845 	}
1846 	delta = snaptime - srq->srq_rlastupdate;
1847 	srq->srq_rlastupdate = snaptime;
1848 	if (srq->srq_rcnt != 0) {
1849 		srq->srq_rlentime += delta * srq->srq_rcnt;
1850 		srq->srq_rtime += delta;
1851 	}
1852 	kd->ku_rlentime = srq->srq_rlentime;
1853 	kd->ku_rtime = srq->srq_rtime;
1854 	kd->ku_wlentime = srq->srq_wlentime;
1855 	kd->ku_wtime = srq->srq_wtime;
1856 	mutex_exit(&srq->srq_mutex);
1857 	scalehrtime(&kd->ku_rlentime);
1858 	scalehrtime(&kd->ku_rtime);
1859 	scalehrtime(&kd->ku_wlentime);
1860 	scalehrtime(&kd->ku_wtime);
1861 }
1862 
1863 void
1864 smb_threshold_init(smb_cmd_threshold_t *ct, char *cmd,
1865     uint_t threshold, uint_t timeout)
1866 {
1867 	bzero(ct, sizeof (smb_cmd_threshold_t));
1868 	mutex_init(&ct->ct_mutex, NULL, MUTEX_DEFAULT, NULL);
1869 	cv_init(&ct->ct_cond, NULL, CV_DEFAULT, NULL);
1870 
1871 	ct->ct_cmd = cmd;
1872 	ct->ct_threshold = threshold;
1873 	ct->ct_timeout = timeout;
1874 }
1875 
1876 void
1877 smb_threshold_fini(smb_cmd_threshold_t *ct)
1878 {
1879 	cv_destroy(&ct->ct_cond);
1880 	mutex_destroy(&ct->ct_mutex);
1881 }
1882 
1883 /*
1884  * This threshold mechanism is used to limit the number of simultaneous
1885  * named pipe connections, concurrent authentication conversations, etc.
1886  * Requests that would take us over the threshold wait until either the
1887  * resources are available (return zero) or timeout (return error).
1888  */
1889 int
1890 smb_threshold_enter(smb_cmd_threshold_t *ct)
1891 {
1892 	clock_t	time, rem;
1893 
1894 	time = MSEC_TO_TICK(ct->ct_timeout) + ddi_get_lbolt();
1895 	mutex_enter(&ct->ct_mutex);
1896 
1897 	while (ct->ct_threshold != 0 &&
1898 	    ct->ct_threshold <= ct->ct_active_cnt) {
1899 		ct->ct_blocked_cnt++;
1900 		rem = cv_timedwait(&ct->ct_cond, &ct->ct_mutex, time);
1901 		ct->ct_blocked_cnt--;
1902 		if (rem < 0) {
1903 			mutex_exit(&ct->ct_mutex);
1904 			return (ETIME);
1905 		}
1906 	}
1907 	if (ct->ct_threshold == 0) {
1908 		mutex_exit(&ct->ct_mutex);
1909 		return (ECANCELED);
1910 	}
1911 
1912 	ASSERT3U(ct->ct_active_cnt, <, ct->ct_threshold);
1913 	ct->ct_active_cnt++;
1914 
1915 	mutex_exit(&ct->ct_mutex);
1916 	return (0);
1917 }
1918 
1919 void
1920 smb_threshold_exit(smb_cmd_threshold_t *ct)
1921 {
1922 	mutex_enter(&ct->ct_mutex);
1923 	ASSERT3U(ct->ct_active_cnt, >, 0);
1924 	ct->ct_active_cnt--;
1925 	if (ct->ct_blocked_cnt)
1926 		cv_signal(&ct->ct_cond);
1927 	mutex_exit(&ct->ct_mutex);
1928 }
1929 
1930 void
1931 smb_threshold_wake_all(smb_cmd_threshold_t *ct)
1932 {
1933 	mutex_enter(&ct->ct_mutex);
1934 	ct->ct_threshold = 0;
1935 	cv_broadcast(&ct->ct_cond);
1936 	mutex_exit(&ct->ct_mutex);
1937 }
1938 
1939 /* taken from mod_hash_byptr */
1940 uint_t
1941 smb_hash_uint64(smb_hash_t *hash, uint64_t val)
1942 {
1943 	uint64_t k = val >> hash->rshift;
1944 	uint_t idx = ((uint_t)k) & (hash->num_buckets - 1);
1945 
1946 	return (idx);
1947 }
1948 
1949 boolean_t
1950 smb_is_pow2(size_t n)
1951 {
1952 	return ((n & (n - 1)) == 0);
1953 }
1954 
1955 smb_hash_t *
1956 smb_hash_create(size_t elemsz, size_t link_offset,
1957     uint32_t num_buckets)
1958 {
1959 	smb_hash_t *hash = kmem_alloc(sizeof (*hash), KM_SLEEP);
1960 	int i;
1961 
1962 	if (!smb_is_pow2(num_buckets))
1963 		num_buckets = 1 << highbit(num_buckets);
1964 
1965 	hash->rshift = highbit(elemsz);
1966 	hash->num_buckets = num_buckets;
1967 	hash->buckets = kmem_zalloc(num_buckets * sizeof (smb_bucket_t),
1968 	    KM_SLEEP);
1969 	for (i = 0; i < num_buckets; i++)
1970 		smb_llist_constructor(&hash->buckets[i].b_list, elemsz,
1971 		    link_offset);
1972 	return (hash);
1973 }
1974 
1975 void
1976 smb_hash_destroy(smb_hash_t *hash)
1977 {
1978 	int i;
1979 
1980 	for (i = 0; i < hash->num_buckets; i++)
1981 		smb_llist_destructor(&hash->buckets[i].b_list);
1982 
1983 	kmem_free(hash->buckets, hash->num_buckets * sizeof (smb_bucket_t));
1984 	kmem_free(hash, sizeof (*hash));
1985 }
1986