111963SAfshin.Ardakani@Sun.COM /* 211963SAfshin.Ardakani@Sun.COM * CDDL HEADER START 311963SAfshin.Ardakani@Sun.COM * 411963SAfshin.Ardakani@Sun.COM * The contents of this file are subject to the terms of the 511963SAfshin.Ardakani@Sun.COM * Common Development and Distribution License (the "License"). 611963SAfshin.Ardakani@Sun.COM * You may not use this file except in compliance with the License. 711963SAfshin.Ardakani@Sun.COM * 811963SAfshin.Ardakani@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 911963SAfshin.Ardakani@Sun.COM * or http://www.opensolaris.org/os/licensing. 1011963SAfshin.Ardakani@Sun.COM * See the License for the specific language governing permissions 1111963SAfshin.Ardakani@Sun.COM * and limitations under the License. 1211963SAfshin.Ardakani@Sun.COM * 1311963SAfshin.Ardakani@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 1411963SAfshin.Ardakani@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1511963SAfshin.Ardakani@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 1611963SAfshin.Ardakani@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 1711963SAfshin.Ardakani@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 1811963SAfshin.Ardakani@Sun.COM * 1911963SAfshin.Ardakani@Sun.COM * CDDL HEADER END 2011963SAfshin.Ardakani@Sun.COM */ 2111963SAfshin.Ardakani@Sun.COM /* 2212065SKeyur.Desai@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 2311963SAfshin.Ardakani@Sun.COM */ 2411963SAfshin.Ardakani@Sun.COM 2511963SAfshin.Ardakani@Sun.COM #include <sys/param.h> 2611963SAfshin.Ardakani@Sun.COM #include <sys/types.h> 2711963SAfshin.Ardakani@Sun.COM #include <sys/tzfile.h> 2811963SAfshin.Ardakani@Sun.COM #include <sys/atomic.h> 2911963SAfshin.Ardakani@Sun.COM #include <sys/kidmap.h> 3011963SAfshin.Ardakani@Sun.COM #include <sys/time.h> 31*12508Samw@Sun.COM #include <sys/spl.h> 3211963SAfshin.Ardakani@Sun.COM #include <sys/cpuvar.h> 33*12508Samw@Sun.COM #include <sys/random.h> 3411963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_kproto.h> 3511963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_fsops.h> 3611963SAfshin.Ardakani@Sun.COM #include <smbsrv/smbinfo.h> 3711963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_xdr.h> 3811963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_vops.h> 3911963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_idmap.h> 4011963SAfshin.Ardakani@Sun.COM 4111963SAfshin.Ardakani@Sun.COM #include <sys/sid.h> 4211963SAfshin.Ardakani@Sun.COM #include <sys/priv_names.h> 4311963SAfshin.Ardakani@Sun.COM 4411963SAfshin.Ardakani@Sun.COM static kmem_cache_t *smb_dtor_cache; 4511963SAfshin.Ardakani@Sun.COM static boolean_t smb_llist_initialized = B_FALSE; 4611963SAfshin.Ardakani@Sun.COM 4711963SAfshin.Ardakani@Sun.COM static boolean_t smb_thread_continue_timedwait_locked(smb_thread_t *, int); 4811963SAfshin.Ardakani@Sun.COM 49*12508Samw@Sun.COM static boolean_t smb_avl_hold(smb_avl_t *); 50*12508Samw@Sun.COM static void smb_avl_rele(smb_avl_t *); 51*12508Samw@Sun.COM 5211963SAfshin.Ardakani@Sun.COM time_t tzh_leapcnt = 0; 5311963SAfshin.Ardakani@Sun.COM 5411963SAfshin.Ardakani@Sun.COM struct tm 5511963SAfshin.Ardakani@Sun.COM *smb_gmtime_r(time_t *clock, struct tm *result); 5611963SAfshin.Ardakani@Sun.COM 5711963SAfshin.Ardakani@Sun.COM time_t 5811963SAfshin.Ardakani@Sun.COM smb_timegm(struct tm *tm); 5911963SAfshin.Ardakani@Sun.COM 6011963SAfshin.Ardakani@Sun.COM struct tm { 6111963SAfshin.Ardakani@Sun.COM int tm_sec; 6211963SAfshin.Ardakani@Sun.COM int tm_min; 6311963SAfshin.Ardakani@Sun.COM int tm_hour; 6411963SAfshin.Ardakani@Sun.COM int tm_mday; 6511963SAfshin.Ardakani@Sun.COM int tm_mon; 6611963SAfshin.Ardakani@Sun.COM int tm_year; 6711963SAfshin.Ardakani@Sun.COM int tm_wday; 6811963SAfshin.Ardakani@Sun.COM int tm_yday; 6911963SAfshin.Ardakani@Sun.COM int tm_isdst; 7011963SAfshin.Ardakani@Sun.COM }; 7111963SAfshin.Ardakani@Sun.COM 7211963SAfshin.Ardakani@Sun.COM static int days_in_month[] = { 7311963SAfshin.Ardakani@Sun.COM 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 7411963SAfshin.Ardakani@Sun.COM }; 7511963SAfshin.Ardakani@Sun.COM 7611963SAfshin.Ardakani@Sun.COM int 7711963SAfshin.Ardakani@Sun.COM smb_ascii_or_unicode_strlen(struct smb_request *sr, char *str) 7811963SAfshin.Ardakani@Sun.COM { 7911963SAfshin.Ardakani@Sun.COM if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) 8011963SAfshin.Ardakani@Sun.COM return (smb_wcequiv_strlen(str)); 8111963SAfshin.Ardakani@Sun.COM return (strlen(str)); 8211963SAfshin.Ardakani@Sun.COM } 8311963SAfshin.Ardakani@Sun.COM 8411963SAfshin.Ardakani@Sun.COM int 8511963SAfshin.Ardakani@Sun.COM smb_ascii_or_unicode_strlen_null(struct smb_request *sr, char *str) 8611963SAfshin.Ardakani@Sun.COM { 8711963SAfshin.Ardakani@Sun.COM if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) 8811963SAfshin.Ardakani@Sun.COM return (smb_wcequiv_strlen(str) + 2); 8911963SAfshin.Ardakani@Sun.COM return (strlen(str) + 1); 9011963SAfshin.Ardakani@Sun.COM } 9111963SAfshin.Ardakani@Sun.COM 9211963SAfshin.Ardakani@Sun.COM int 9311963SAfshin.Ardakani@Sun.COM smb_ascii_or_unicode_null_len(struct smb_request *sr) 9411963SAfshin.Ardakani@Sun.COM { 9511963SAfshin.Ardakani@Sun.COM if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) 9611963SAfshin.Ardakani@Sun.COM return (2); 9711963SAfshin.Ardakani@Sun.COM return (1); 9811963SAfshin.Ardakani@Sun.COM } 9911963SAfshin.Ardakani@Sun.COM 10011963SAfshin.Ardakani@Sun.COM /* 10111963SAfshin.Ardakani@Sun.COM * Return B_TRUE if pattern contains wildcards 10211963SAfshin.Ardakani@Sun.COM */ 10311963SAfshin.Ardakani@Sun.COM boolean_t 10411963SAfshin.Ardakani@Sun.COM smb_contains_wildcards(const char *pattern) 10511963SAfshin.Ardakani@Sun.COM { 10611963SAfshin.Ardakani@Sun.COM static const char *wildcards = "*?"; 10711963SAfshin.Ardakani@Sun.COM 10811963SAfshin.Ardakani@Sun.COM return (strpbrk(pattern, wildcards) != NULL); 10911963SAfshin.Ardakani@Sun.COM } 11011963SAfshin.Ardakani@Sun.COM 11111963SAfshin.Ardakani@Sun.COM /* 11211963SAfshin.Ardakani@Sun.COM * When converting wildcards a '.' in a name is treated as a base and 11311963SAfshin.Ardakani@Sun.COM * extension separator even if the name is longer than 8.3. 11411963SAfshin.Ardakani@Sun.COM * 11511963SAfshin.Ardakani@Sun.COM * The '*' character matches an entire part of the name. For example, 11611963SAfshin.Ardakani@Sun.COM * "*.abc" matches any name with an extension of "abc". 11711963SAfshin.Ardakani@Sun.COM * 11811963SAfshin.Ardakani@Sun.COM * The '?' character matches a single character. 11911963SAfshin.Ardakani@Sun.COM * If the base contains all ? (8 or more) then it is treated as *. 12011963SAfshin.Ardakani@Sun.COM * If the extension contains all ? (3 or more) then it is treated as *. 12111963SAfshin.Ardakani@Sun.COM * 12211963SAfshin.Ardakani@Sun.COM * Clients convert ASCII wildcards to Unicode wildcards as follows: 12311963SAfshin.Ardakani@Sun.COM * 12411963SAfshin.Ardakani@Sun.COM * ? is converted to > 12511963SAfshin.Ardakani@Sun.COM * . is converted to " if it is followed by ? or * 12611963SAfshin.Ardakani@Sun.COM * * is converted to < if it is followed by . 12711963SAfshin.Ardakani@Sun.COM * 12811963SAfshin.Ardakani@Sun.COM * Note that clients convert "*." to '< and drop the '.' but "*.txt" 12911963SAfshin.Ardakani@Sun.COM * is sent as "<.TXT", i.e. 13011963SAfshin.Ardakani@Sun.COM * 13111963SAfshin.Ardakani@Sun.COM * dir *. -> dir < 13211963SAfshin.Ardakani@Sun.COM * dir *.txt -> dir <.TXT 13311963SAfshin.Ardakani@Sun.COM * 13411963SAfshin.Ardakani@Sun.COM * Since " and < are illegal in Windows file names, we always convert 13511963SAfshin.Ardakani@Sun.COM * these Unicode wildcards without checking the following character. 13611963SAfshin.Ardakani@Sun.COM */ 13711963SAfshin.Ardakani@Sun.COM void 13811963SAfshin.Ardakani@Sun.COM smb_convert_wildcards(char *pattern) 13911963SAfshin.Ardakani@Sun.COM { 14011963SAfshin.Ardakani@Sun.COM static char *match_all[] = { 14111963SAfshin.Ardakani@Sun.COM "*.", 14211963SAfshin.Ardakani@Sun.COM "*.*" 14311963SAfshin.Ardakani@Sun.COM }; 14411963SAfshin.Ardakani@Sun.COM char *extension; 14511963SAfshin.Ardakani@Sun.COM char *p; 14611963SAfshin.Ardakani@Sun.COM int len; 14711963SAfshin.Ardakani@Sun.COM int i; 14811963SAfshin.Ardakani@Sun.COM 14911963SAfshin.Ardakani@Sun.COM /* 15011963SAfshin.Ardakani@Sun.COM * Special case "<" for "dir *.", and fast-track for "*". 15111963SAfshin.Ardakani@Sun.COM */ 15211963SAfshin.Ardakani@Sun.COM if ((*pattern == '<') || (*pattern == '*')) { 15311963SAfshin.Ardakani@Sun.COM if (*(pattern + 1) == '\0') { 15411963SAfshin.Ardakani@Sun.COM *pattern = '*'; 15511963SAfshin.Ardakani@Sun.COM return; 15611963SAfshin.Ardakani@Sun.COM } 15711963SAfshin.Ardakani@Sun.COM } 15811963SAfshin.Ardakani@Sun.COM 15911963SAfshin.Ardakani@Sun.COM for (p = pattern; *p != '\0'; ++p) { 16011963SAfshin.Ardakani@Sun.COM switch (*p) { 16111963SAfshin.Ardakani@Sun.COM case '<': 16211963SAfshin.Ardakani@Sun.COM *p = '*'; 16311963SAfshin.Ardakani@Sun.COM break; 16411963SAfshin.Ardakani@Sun.COM case '>': 16511963SAfshin.Ardakani@Sun.COM *p = '?'; 16611963SAfshin.Ardakani@Sun.COM break; 16711963SAfshin.Ardakani@Sun.COM case '\"': 16811963SAfshin.Ardakani@Sun.COM *p = '.'; 16911963SAfshin.Ardakani@Sun.COM break; 17011963SAfshin.Ardakani@Sun.COM default: 17111963SAfshin.Ardakani@Sun.COM break; 17211963SAfshin.Ardakani@Sun.COM } 17311963SAfshin.Ardakani@Sun.COM } 17411963SAfshin.Ardakani@Sun.COM 17511963SAfshin.Ardakani@Sun.COM /* 17611963SAfshin.Ardakani@Sun.COM * Replace "????????.ext" with "*.ext". 17711963SAfshin.Ardakani@Sun.COM */ 17811963SAfshin.Ardakani@Sun.COM p = pattern; 17911963SAfshin.Ardakani@Sun.COM p += strspn(p, "?"); 18011963SAfshin.Ardakani@Sun.COM if (*p == '.') { 18111963SAfshin.Ardakani@Sun.COM *p = '\0'; 18211963SAfshin.Ardakani@Sun.COM len = strlen(pattern); 18311963SAfshin.Ardakani@Sun.COM *p = '.'; 18411963SAfshin.Ardakani@Sun.COM if (len >= SMB_NAME83_BASELEN) { 18511963SAfshin.Ardakani@Sun.COM *pattern = '*'; 18611963SAfshin.Ardakani@Sun.COM (void) strlcpy(pattern + 1, p, MAXPATHLEN - 1); 18711963SAfshin.Ardakani@Sun.COM } 18811963SAfshin.Ardakani@Sun.COM } 18911963SAfshin.Ardakani@Sun.COM 19011963SAfshin.Ardakani@Sun.COM /* 19111963SAfshin.Ardakani@Sun.COM * Replace "base.???" with 'base.*'. 19211963SAfshin.Ardakani@Sun.COM */ 19311963SAfshin.Ardakani@Sun.COM if ((extension = strrchr(pattern, '.')) != NULL) { 19411963SAfshin.Ardakani@Sun.COM p = ++extension; 19511963SAfshin.Ardakani@Sun.COM p += strspn(p, "?"); 19611963SAfshin.Ardakani@Sun.COM if (*p == '\0') { 19711963SAfshin.Ardakani@Sun.COM len = strlen(extension); 19811963SAfshin.Ardakani@Sun.COM if (len >= SMB_NAME83_EXTLEN) { 19911963SAfshin.Ardakani@Sun.COM *extension = '\0'; 20011963SAfshin.Ardakani@Sun.COM (void) strlcat(pattern, "*", MAXPATHLEN); 20111963SAfshin.Ardakani@Sun.COM } 20211963SAfshin.Ardakani@Sun.COM } 20311963SAfshin.Ardakani@Sun.COM } 20411963SAfshin.Ardakani@Sun.COM 20511963SAfshin.Ardakani@Sun.COM /* 20611963SAfshin.Ardakani@Sun.COM * Replace anything that matches an entry in match_all with "*". 20711963SAfshin.Ardakani@Sun.COM */ 20811963SAfshin.Ardakani@Sun.COM for (i = 0; i < sizeof (match_all) / sizeof (match_all[0]); ++i) { 20911963SAfshin.Ardakani@Sun.COM if (strcmp(pattern, match_all[i]) == 0) { 21011963SAfshin.Ardakani@Sun.COM (void) strlcpy(pattern, "*", MAXPATHLEN); 21111963SAfshin.Ardakani@Sun.COM break; 21211963SAfshin.Ardakani@Sun.COM } 21311963SAfshin.Ardakani@Sun.COM } 21411963SAfshin.Ardakani@Sun.COM } 21511963SAfshin.Ardakani@Sun.COM 21611963SAfshin.Ardakani@Sun.COM /* 21711963SAfshin.Ardakani@Sun.COM * smb_sattr_check 21811963SAfshin.Ardakani@Sun.COM * 21911963SAfshin.Ardakani@Sun.COM * Check file attributes against a search attribute (sattr) mask. 22011963SAfshin.Ardakani@Sun.COM * 22111963SAfshin.Ardakani@Sun.COM * Normal files, which includes READONLY and ARCHIVE, always pass 22211963SAfshin.Ardakani@Sun.COM * this check. If the DIRECTORY, HIDDEN or SYSTEM special attributes 22311963SAfshin.Ardakani@Sun.COM * are set then they must appear in the search mask. The special 22411963SAfshin.Ardakani@Sun.COM * attributes are inclusive, i.e. all special attributes that appear 22511963SAfshin.Ardakani@Sun.COM * in sattr must also appear in the file attributes for the check to 22611963SAfshin.Ardakani@Sun.COM * pass. 22711963SAfshin.Ardakani@Sun.COM * 22811963SAfshin.Ardakani@Sun.COM * The following examples show how this works: 22911963SAfshin.Ardakani@Sun.COM * 23011963SAfshin.Ardakani@Sun.COM * fileA: READONLY 23111963SAfshin.Ardakani@Sun.COM * fileB: 0 (no attributes = normal file) 23211963SAfshin.Ardakani@Sun.COM * fileC: READONLY, ARCHIVE 23311963SAfshin.Ardakani@Sun.COM * fileD: HIDDEN 23411963SAfshin.Ardakani@Sun.COM * fileE: READONLY, HIDDEN, SYSTEM 23511963SAfshin.Ardakani@Sun.COM * dirA: DIRECTORY 23611963SAfshin.Ardakani@Sun.COM * 23711963SAfshin.Ardakani@Sun.COM * search attribute: 0 23811963SAfshin.Ardakani@Sun.COM * Returns: fileA, fileB and fileC. 23911963SAfshin.Ardakani@Sun.COM * search attribute: HIDDEN 24011963SAfshin.Ardakani@Sun.COM * Returns: fileA, fileB, fileC and fileD. 24111963SAfshin.Ardakani@Sun.COM * search attribute: SYSTEM 24211963SAfshin.Ardakani@Sun.COM * Returns: fileA, fileB and fileC. 24311963SAfshin.Ardakani@Sun.COM * search attribute: DIRECTORY 24411963SAfshin.Ardakani@Sun.COM * Returns: fileA, fileB, fileC and dirA. 24511963SAfshin.Ardakani@Sun.COM * search attribute: HIDDEN and SYSTEM 24611963SAfshin.Ardakani@Sun.COM * Returns: fileA, fileB, fileC, fileD and fileE. 24711963SAfshin.Ardakani@Sun.COM * 24811963SAfshin.Ardakani@Sun.COM * Returns true if the file and sattr match; otherwise, returns false. 24911963SAfshin.Ardakani@Sun.COM */ 25011963SAfshin.Ardakani@Sun.COM boolean_t 25111963SAfshin.Ardakani@Sun.COM smb_sattr_check(uint16_t dosattr, uint16_t sattr) 25211963SAfshin.Ardakani@Sun.COM { 25311963SAfshin.Ardakani@Sun.COM if ((dosattr & FILE_ATTRIBUTE_DIRECTORY) && 25411963SAfshin.Ardakani@Sun.COM !(sattr & FILE_ATTRIBUTE_DIRECTORY)) 25511963SAfshin.Ardakani@Sun.COM return (B_FALSE); 25611963SAfshin.Ardakani@Sun.COM 25711963SAfshin.Ardakani@Sun.COM if ((dosattr & FILE_ATTRIBUTE_HIDDEN) && 25811963SAfshin.Ardakani@Sun.COM !(sattr & FILE_ATTRIBUTE_HIDDEN)) 25911963SAfshin.Ardakani@Sun.COM return (B_FALSE); 26011963SAfshin.Ardakani@Sun.COM 26111963SAfshin.Ardakani@Sun.COM if ((dosattr & FILE_ATTRIBUTE_SYSTEM) && 26211963SAfshin.Ardakani@Sun.COM !(sattr & FILE_ATTRIBUTE_SYSTEM)) 26311963SAfshin.Ardakani@Sun.COM return (B_FALSE); 26411963SAfshin.Ardakani@Sun.COM 26511963SAfshin.Ardakani@Sun.COM return (B_TRUE); 26611963SAfshin.Ardakani@Sun.COM } 26711963SAfshin.Ardakani@Sun.COM 26811963SAfshin.Ardakani@Sun.COM int 26911963SAfshin.Ardakani@Sun.COM microtime(timestruc_t *tvp) 27011963SAfshin.Ardakani@Sun.COM { 27111963SAfshin.Ardakani@Sun.COM tvp->tv_sec = gethrestime_sec(); 27211963SAfshin.Ardakani@Sun.COM tvp->tv_nsec = 0; 27311963SAfshin.Ardakani@Sun.COM return (0); 27411963SAfshin.Ardakani@Sun.COM } 27511963SAfshin.Ardakani@Sun.COM 27611963SAfshin.Ardakani@Sun.COM int32_t 27711963SAfshin.Ardakani@Sun.COM clock_get_milli_uptime() 27811963SAfshin.Ardakani@Sun.COM { 27911963SAfshin.Ardakani@Sun.COM return (TICK_TO_MSEC(ddi_get_lbolt())); 28011963SAfshin.Ardakani@Sun.COM } 28111963SAfshin.Ardakani@Sun.COM 28211963SAfshin.Ardakani@Sun.COM int /*ARGSUSED*/ 28311963SAfshin.Ardakani@Sun.COM smb_noop(void *p, size_t size, int foo) 28411963SAfshin.Ardakani@Sun.COM { 28511963SAfshin.Ardakani@Sun.COM return (0); 28611963SAfshin.Ardakani@Sun.COM } 28711963SAfshin.Ardakani@Sun.COM 28811963SAfshin.Ardakani@Sun.COM /* 28911963SAfshin.Ardakani@Sun.COM * smb_idpool_increment 29011963SAfshin.Ardakani@Sun.COM * 29111963SAfshin.Ardakani@Sun.COM * This function increments the ID pool by doubling the current size. This 29211963SAfshin.Ardakani@Sun.COM * function assumes the caller entered the mutex of the pool. 29311963SAfshin.Ardakani@Sun.COM */ 29411963SAfshin.Ardakani@Sun.COM static int 29511963SAfshin.Ardakani@Sun.COM smb_idpool_increment( 29611963SAfshin.Ardakani@Sun.COM smb_idpool_t *pool) 29711963SAfshin.Ardakani@Sun.COM { 29811963SAfshin.Ardakani@Sun.COM uint8_t *new_pool; 29911963SAfshin.Ardakani@Sun.COM uint32_t new_size; 30011963SAfshin.Ardakani@Sun.COM 30111963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC); 30211963SAfshin.Ardakani@Sun.COM 30311963SAfshin.Ardakani@Sun.COM new_size = pool->id_size * 2; 30411963SAfshin.Ardakani@Sun.COM if (new_size <= SMB_IDPOOL_MAX_SIZE) { 30511963SAfshin.Ardakani@Sun.COM new_pool = kmem_alloc(new_size / 8, KM_NOSLEEP); 30611963SAfshin.Ardakani@Sun.COM if (new_pool) { 30711963SAfshin.Ardakani@Sun.COM bzero(new_pool, new_size / 8); 30811963SAfshin.Ardakani@Sun.COM bcopy(pool->id_pool, new_pool, pool->id_size / 8); 30911963SAfshin.Ardakani@Sun.COM kmem_free(pool->id_pool, pool->id_size / 8); 31011963SAfshin.Ardakani@Sun.COM pool->id_pool = new_pool; 31111963SAfshin.Ardakani@Sun.COM pool->id_free_counter += new_size - pool->id_size; 31211963SAfshin.Ardakani@Sun.COM pool->id_max_free_counter += new_size - pool->id_size; 31311963SAfshin.Ardakani@Sun.COM pool->id_size = new_size; 31411963SAfshin.Ardakani@Sun.COM pool->id_idx_msk = (new_size / 8) - 1; 31511963SAfshin.Ardakani@Sun.COM if (new_size >= SMB_IDPOOL_MAX_SIZE) { 31611963SAfshin.Ardakani@Sun.COM /* id -1 made unavailable */ 31711963SAfshin.Ardakani@Sun.COM pool->id_pool[pool->id_idx_msk] = 0x80; 31811963SAfshin.Ardakani@Sun.COM pool->id_free_counter--; 31911963SAfshin.Ardakani@Sun.COM pool->id_max_free_counter--; 32011963SAfshin.Ardakani@Sun.COM } 32111963SAfshin.Ardakani@Sun.COM return (0); 32211963SAfshin.Ardakani@Sun.COM } 32311963SAfshin.Ardakani@Sun.COM } 32411963SAfshin.Ardakani@Sun.COM return (-1); 32511963SAfshin.Ardakani@Sun.COM } 32611963SAfshin.Ardakani@Sun.COM 32711963SAfshin.Ardakani@Sun.COM /* 32811963SAfshin.Ardakani@Sun.COM * smb_idpool_constructor 32911963SAfshin.Ardakani@Sun.COM * 33011963SAfshin.Ardakani@Sun.COM * This function initializes the pool structure provided. 33111963SAfshin.Ardakani@Sun.COM */ 33211963SAfshin.Ardakani@Sun.COM int 33311963SAfshin.Ardakani@Sun.COM smb_idpool_constructor( 33411963SAfshin.Ardakani@Sun.COM smb_idpool_t *pool) 33511963SAfshin.Ardakani@Sun.COM { 33611963SAfshin.Ardakani@Sun.COM 33711963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_magic != SMB_IDPOOL_MAGIC); 33811963SAfshin.Ardakani@Sun.COM 33911963SAfshin.Ardakani@Sun.COM pool->id_size = SMB_IDPOOL_MIN_SIZE; 34011963SAfshin.Ardakani@Sun.COM pool->id_idx_msk = (SMB_IDPOOL_MIN_SIZE / 8) - 1; 34111963SAfshin.Ardakani@Sun.COM pool->id_free_counter = SMB_IDPOOL_MIN_SIZE - 1; 34211963SAfshin.Ardakani@Sun.COM pool->id_max_free_counter = SMB_IDPOOL_MIN_SIZE - 1; 34311963SAfshin.Ardakani@Sun.COM pool->id_bit = 0x02; 34411963SAfshin.Ardakani@Sun.COM pool->id_bit_idx = 1; 34511963SAfshin.Ardakani@Sun.COM pool->id_idx = 0; 34611963SAfshin.Ardakani@Sun.COM pool->id_pool = (uint8_t *)kmem_alloc((SMB_IDPOOL_MIN_SIZE / 8), 34711963SAfshin.Ardakani@Sun.COM KM_SLEEP); 34811963SAfshin.Ardakani@Sun.COM bzero(pool->id_pool, (SMB_IDPOOL_MIN_SIZE / 8)); 34911963SAfshin.Ardakani@Sun.COM /* -1 id made unavailable */ 35011963SAfshin.Ardakani@Sun.COM pool->id_pool[0] = 0x01; /* id 0 made unavailable */ 35111963SAfshin.Ardakani@Sun.COM mutex_init(&pool->id_mutex, NULL, MUTEX_DEFAULT, NULL); 35211963SAfshin.Ardakani@Sun.COM pool->id_magic = SMB_IDPOOL_MAGIC; 35311963SAfshin.Ardakani@Sun.COM return (0); 35411963SAfshin.Ardakani@Sun.COM } 35511963SAfshin.Ardakani@Sun.COM 35611963SAfshin.Ardakani@Sun.COM /* 35711963SAfshin.Ardakani@Sun.COM * smb_idpool_destructor 35811963SAfshin.Ardakani@Sun.COM * 35911963SAfshin.Ardakani@Sun.COM * This function tears down and frees the resources associated with the 36011963SAfshin.Ardakani@Sun.COM * pool provided. 36111963SAfshin.Ardakani@Sun.COM */ 36211963SAfshin.Ardakani@Sun.COM void 36311963SAfshin.Ardakani@Sun.COM smb_idpool_destructor( 36411963SAfshin.Ardakani@Sun.COM smb_idpool_t *pool) 36511963SAfshin.Ardakani@Sun.COM { 36611963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC); 36711963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_free_counter == pool->id_max_free_counter); 36811963SAfshin.Ardakani@Sun.COM pool->id_magic = (uint32_t)~SMB_IDPOOL_MAGIC; 36911963SAfshin.Ardakani@Sun.COM mutex_destroy(&pool->id_mutex); 37011963SAfshin.Ardakani@Sun.COM kmem_free(pool->id_pool, (size_t)(pool->id_size / 8)); 37111963SAfshin.Ardakani@Sun.COM } 37211963SAfshin.Ardakani@Sun.COM 37311963SAfshin.Ardakani@Sun.COM /* 37411963SAfshin.Ardakani@Sun.COM * smb_idpool_alloc 37511963SAfshin.Ardakani@Sun.COM * 37611963SAfshin.Ardakani@Sun.COM * This function allocates an ID from the pool provided. 37711963SAfshin.Ardakani@Sun.COM */ 37811963SAfshin.Ardakani@Sun.COM int 37911963SAfshin.Ardakani@Sun.COM smb_idpool_alloc( 38011963SAfshin.Ardakani@Sun.COM smb_idpool_t *pool, 38111963SAfshin.Ardakani@Sun.COM uint16_t *id) 38211963SAfshin.Ardakani@Sun.COM { 38311963SAfshin.Ardakani@Sun.COM uint32_t i; 38411963SAfshin.Ardakani@Sun.COM uint8_t bit; 38511963SAfshin.Ardakani@Sun.COM uint8_t bit_idx; 38611963SAfshin.Ardakani@Sun.COM uint8_t byte; 38711963SAfshin.Ardakani@Sun.COM 38811963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC); 38911963SAfshin.Ardakani@Sun.COM 39011963SAfshin.Ardakani@Sun.COM mutex_enter(&pool->id_mutex); 39111963SAfshin.Ardakani@Sun.COM if ((pool->id_free_counter == 0) && smb_idpool_increment(pool)) { 39211963SAfshin.Ardakani@Sun.COM mutex_exit(&pool->id_mutex); 39311963SAfshin.Ardakani@Sun.COM return (-1); 39411963SAfshin.Ardakani@Sun.COM } 39511963SAfshin.Ardakani@Sun.COM 39611963SAfshin.Ardakani@Sun.COM i = pool->id_size; 39711963SAfshin.Ardakani@Sun.COM while (i) { 39811963SAfshin.Ardakani@Sun.COM bit = pool->id_bit; 39911963SAfshin.Ardakani@Sun.COM bit_idx = pool->id_bit_idx; 40011963SAfshin.Ardakani@Sun.COM byte = pool->id_pool[pool->id_idx]; 40111963SAfshin.Ardakani@Sun.COM while (bit) { 40211963SAfshin.Ardakani@Sun.COM if (byte & bit) { 40311963SAfshin.Ardakani@Sun.COM bit = bit << 1; 40411963SAfshin.Ardakani@Sun.COM bit_idx++; 40511963SAfshin.Ardakani@Sun.COM continue; 40611963SAfshin.Ardakani@Sun.COM } 40711963SAfshin.Ardakani@Sun.COM pool->id_pool[pool->id_idx] |= bit; 40811963SAfshin.Ardakani@Sun.COM *id = (uint16_t)(pool->id_idx * 8 + (uint32_t)bit_idx); 40911963SAfshin.Ardakani@Sun.COM pool->id_free_counter--; 41011963SAfshin.Ardakani@Sun.COM pool->id_bit = bit; 41111963SAfshin.Ardakani@Sun.COM pool->id_bit_idx = bit_idx; 41211963SAfshin.Ardakani@Sun.COM mutex_exit(&pool->id_mutex); 41311963SAfshin.Ardakani@Sun.COM return (0); 41411963SAfshin.Ardakani@Sun.COM } 41511963SAfshin.Ardakani@Sun.COM pool->id_bit = 1; 41611963SAfshin.Ardakani@Sun.COM pool->id_bit_idx = 0; 41711963SAfshin.Ardakani@Sun.COM pool->id_idx++; 41811963SAfshin.Ardakani@Sun.COM pool->id_idx &= pool->id_idx_msk; 41911963SAfshin.Ardakani@Sun.COM --i; 42011963SAfshin.Ardakani@Sun.COM } 42111963SAfshin.Ardakani@Sun.COM /* 42211963SAfshin.Ardakani@Sun.COM * This section of code shouldn't be reached. If there are IDs 42311963SAfshin.Ardakani@Sun.COM * available and none could be found there's a problem. 42411963SAfshin.Ardakani@Sun.COM */ 42511963SAfshin.Ardakani@Sun.COM ASSERT(0); 42611963SAfshin.Ardakani@Sun.COM mutex_exit(&pool->id_mutex); 42711963SAfshin.Ardakani@Sun.COM return (-1); 42811963SAfshin.Ardakani@Sun.COM } 42911963SAfshin.Ardakani@Sun.COM 43011963SAfshin.Ardakani@Sun.COM /* 43111963SAfshin.Ardakani@Sun.COM * smb_idpool_free 43211963SAfshin.Ardakani@Sun.COM * 43311963SAfshin.Ardakani@Sun.COM * This function frees the ID provided. 43411963SAfshin.Ardakani@Sun.COM */ 43511963SAfshin.Ardakani@Sun.COM void 43611963SAfshin.Ardakani@Sun.COM smb_idpool_free( 43711963SAfshin.Ardakani@Sun.COM smb_idpool_t *pool, 43811963SAfshin.Ardakani@Sun.COM uint16_t id) 43911963SAfshin.Ardakani@Sun.COM { 44011963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC); 44111963SAfshin.Ardakani@Sun.COM ASSERT(id != 0); 44211963SAfshin.Ardakani@Sun.COM ASSERT(id != 0xFFFF); 44311963SAfshin.Ardakani@Sun.COM 44411963SAfshin.Ardakani@Sun.COM mutex_enter(&pool->id_mutex); 44511963SAfshin.Ardakani@Sun.COM if (pool->id_pool[id >> 3] & (1 << (id & 7))) { 44611963SAfshin.Ardakani@Sun.COM pool->id_pool[id >> 3] &= ~(1 << (id & 7)); 44711963SAfshin.Ardakani@Sun.COM pool->id_free_counter++; 44811963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_free_counter <= pool->id_max_free_counter); 44911963SAfshin.Ardakani@Sun.COM mutex_exit(&pool->id_mutex); 45011963SAfshin.Ardakani@Sun.COM return; 45111963SAfshin.Ardakani@Sun.COM } 45211963SAfshin.Ardakani@Sun.COM /* Freeing a free ID. */ 45311963SAfshin.Ardakani@Sun.COM ASSERT(0); 45411963SAfshin.Ardakani@Sun.COM mutex_exit(&pool->id_mutex); 45511963SAfshin.Ardakani@Sun.COM } 45611963SAfshin.Ardakani@Sun.COM 45711963SAfshin.Ardakani@Sun.COM /* 45811963SAfshin.Ardakani@Sun.COM * Initialize the llist delete queue object cache. 45911963SAfshin.Ardakani@Sun.COM */ 46011963SAfshin.Ardakani@Sun.COM void 46111963SAfshin.Ardakani@Sun.COM smb_llist_init(void) 46211963SAfshin.Ardakani@Sun.COM { 46311963SAfshin.Ardakani@Sun.COM if (smb_llist_initialized) 46411963SAfshin.Ardakani@Sun.COM return; 46511963SAfshin.Ardakani@Sun.COM 46611963SAfshin.Ardakani@Sun.COM smb_dtor_cache = kmem_cache_create("smb_dtor_cache", 46711963SAfshin.Ardakani@Sun.COM sizeof (smb_dtor_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 46811963SAfshin.Ardakani@Sun.COM 46911963SAfshin.Ardakani@Sun.COM smb_llist_initialized = B_TRUE; 47011963SAfshin.Ardakani@Sun.COM } 47111963SAfshin.Ardakani@Sun.COM 47211963SAfshin.Ardakani@Sun.COM /* 47311963SAfshin.Ardakani@Sun.COM * Destroy the llist delete queue object cache. 47411963SAfshin.Ardakani@Sun.COM */ 47511963SAfshin.Ardakani@Sun.COM void 47611963SAfshin.Ardakani@Sun.COM smb_llist_fini(void) 47711963SAfshin.Ardakani@Sun.COM { 47811963SAfshin.Ardakani@Sun.COM if (!smb_llist_initialized) 47911963SAfshin.Ardakani@Sun.COM return; 48011963SAfshin.Ardakani@Sun.COM 48111963SAfshin.Ardakani@Sun.COM kmem_cache_destroy(smb_dtor_cache); 48211963SAfshin.Ardakani@Sun.COM smb_llist_initialized = B_FALSE; 48311963SAfshin.Ardakani@Sun.COM } 48411963SAfshin.Ardakani@Sun.COM 48511963SAfshin.Ardakani@Sun.COM /* 48611963SAfshin.Ardakani@Sun.COM * smb_llist_constructor 48711963SAfshin.Ardakani@Sun.COM * 48811963SAfshin.Ardakani@Sun.COM * This function initializes a locked list. 48911963SAfshin.Ardakani@Sun.COM */ 49011963SAfshin.Ardakani@Sun.COM void 49111963SAfshin.Ardakani@Sun.COM smb_llist_constructor( 49211963SAfshin.Ardakani@Sun.COM smb_llist_t *ll, 49311963SAfshin.Ardakani@Sun.COM size_t size, 49411963SAfshin.Ardakani@Sun.COM size_t offset) 49511963SAfshin.Ardakani@Sun.COM { 49611963SAfshin.Ardakani@Sun.COM rw_init(&ll->ll_lock, NULL, RW_DEFAULT, NULL); 49711963SAfshin.Ardakani@Sun.COM mutex_init(&ll->ll_mutex, NULL, MUTEX_DEFAULT, NULL); 49811963SAfshin.Ardakani@Sun.COM list_create(&ll->ll_list, size, offset); 49911963SAfshin.Ardakani@Sun.COM list_create(&ll->ll_deleteq, sizeof (smb_dtor_t), 50011963SAfshin.Ardakani@Sun.COM offsetof(smb_dtor_t, dt_lnd)); 50111963SAfshin.Ardakani@Sun.COM ll->ll_count = 0; 50211963SAfshin.Ardakani@Sun.COM ll->ll_wrop = 0; 50311963SAfshin.Ardakani@Sun.COM ll->ll_deleteq_count = 0; 50411963SAfshin.Ardakani@Sun.COM } 50511963SAfshin.Ardakani@Sun.COM 50611963SAfshin.Ardakani@Sun.COM /* 50711963SAfshin.Ardakani@Sun.COM * Flush the delete queue and destroy a locked list. 50811963SAfshin.Ardakani@Sun.COM */ 50911963SAfshin.Ardakani@Sun.COM void 51011963SAfshin.Ardakani@Sun.COM smb_llist_destructor( 51111963SAfshin.Ardakani@Sun.COM smb_llist_t *ll) 51211963SAfshin.Ardakani@Sun.COM { 51311963SAfshin.Ardakani@Sun.COM smb_llist_flush(ll); 51411963SAfshin.Ardakani@Sun.COM 51511963SAfshin.Ardakani@Sun.COM ASSERT(ll->ll_count == 0); 51611963SAfshin.Ardakani@Sun.COM ASSERT(ll->ll_deleteq_count == 0); 51711963SAfshin.Ardakani@Sun.COM 51811963SAfshin.Ardakani@Sun.COM rw_destroy(&ll->ll_lock); 51911963SAfshin.Ardakani@Sun.COM list_destroy(&ll->ll_list); 52011963SAfshin.Ardakani@Sun.COM list_destroy(&ll->ll_deleteq); 52111963SAfshin.Ardakani@Sun.COM mutex_destroy(&ll->ll_mutex); 52211963SAfshin.Ardakani@Sun.COM } 52311963SAfshin.Ardakani@Sun.COM 52411963SAfshin.Ardakani@Sun.COM /* 52511963SAfshin.Ardakani@Sun.COM * Post an object to the delete queue. The delete queue will be processed 52611963SAfshin.Ardakani@Sun.COM * during list exit or list destruction. Objects are often posted for 52711963SAfshin.Ardakani@Sun.COM * deletion during list iteration (while the list is locked) but that is 52811963SAfshin.Ardakani@Sun.COM * not required, and an object can be posted at any time. 52911963SAfshin.Ardakani@Sun.COM */ 53011963SAfshin.Ardakani@Sun.COM void 53111963SAfshin.Ardakani@Sun.COM smb_llist_post(smb_llist_t *ll, void *object, smb_dtorproc_t dtorproc) 53211963SAfshin.Ardakani@Sun.COM { 53311963SAfshin.Ardakani@Sun.COM smb_dtor_t *dtor; 53411963SAfshin.Ardakani@Sun.COM 53511963SAfshin.Ardakani@Sun.COM ASSERT((object != NULL) && (dtorproc != NULL)); 53611963SAfshin.Ardakani@Sun.COM 53711963SAfshin.Ardakani@Sun.COM dtor = kmem_cache_alloc(smb_dtor_cache, KM_SLEEP); 53811963SAfshin.Ardakani@Sun.COM bzero(dtor, sizeof (smb_dtor_t)); 53911963SAfshin.Ardakani@Sun.COM dtor->dt_magic = SMB_DTOR_MAGIC; 54011963SAfshin.Ardakani@Sun.COM dtor->dt_object = object; 54111963SAfshin.Ardakani@Sun.COM dtor->dt_proc = dtorproc; 54211963SAfshin.Ardakani@Sun.COM 54311963SAfshin.Ardakani@Sun.COM mutex_enter(&ll->ll_mutex); 54411963SAfshin.Ardakani@Sun.COM list_insert_tail(&ll->ll_deleteq, dtor); 54511963SAfshin.Ardakani@Sun.COM ++ll->ll_deleteq_count; 54611963SAfshin.Ardakani@Sun.COM mutex_exit(&ll->ll_mutex); 54711963SAfshin.Ardakani@Sun.COM } 54811963SAfshin.Ardakani@Sun.COM 54911963SAfshin.Ardakani@Sun.COM /* 55011963SAfshin.Ardakani@Sun.COM * Exit the list lock and process the delete queue. 55111963SAfshin.Ardakani@Sun.COM */ 55211963SAfshin.Ardakani@Sun.COM void 55311963SAfshin.Ardakani@Sun.COM smb_llist_exit(smb_llist_t *ll) 55411963SAfshin.Ardakani@Sun.COM { 55511963SAfshin.Ardakani@Sun.COM rw_exit(&ll->ll_lock); 55611963SAfshin.Ardakani@Sun.COM smb_llist_flush(ll); 55711963SAfshin.Ardakani@Sun.COM } 55811963SAfshin.Ardakani@Sun.COM 55911963SAfshin.Ardakani@Sun.COM /* 56011963SAfshin.Ardakani@Sun.COM * Flush the list delete queue. The mutex is dropped across the destructor 56111963SAfshin.Ardakani@Sun.COM * call in case this leads to additional objects being posted to the delete 56211963SAfshin.Ardakani@Sun.COM * queue. 56311963SAfshin.Ardakani@Sun.COM */ 56412065SKeyur.Desai@Sun.COM void 56511963SAfshin.Ardakani@Sun.COM smb_llist_flush(smb_llist_t *ll) 56611963SAfshin.Ardakani@Sun.COM { 56711963SAfshin.Ardakani@Sun.COM smb_dtor_t *dtor; 56811963SAfshin.Ardakani@Sun.COM 56911963SAfshin.Ardakani@Sun.COM mutex_enter(&ll->ll_mutex); 57011963SAfshin.Ardakani@Sun.COM 57111963SAfshin.Ardakani@Sun.COM dtor = list_head(&ll->ll_deleteq); 57211963SAfshin.Ardakani@Sun.COM while (dtor != NULL) { 57311963SAfshin.Ardakani@Sun.COM SMB_DTOR_VALID(dtor); 57411963SAfshin.Ardakani@Sun.COM ASSERT((dtor->dt_object != NULL) && (dtor->dt_proc != NULL)); 57511963SAfshin.Ardakani@Sun.COM list_remove(&ll->ll_deleteq, dtor); 57611963SAfshin.Ardakani@Sun.COM --ll->ll_deleteq_count; 57711963SAfshin.Ardakani@Sun.COM mutex_exit(&ll->ll_mutex); 57811963SAfshin.Ardakani@Sun.COM 57911963SAfshin.Ardakani@Sun.COM dtor->dt_proc(dtor->dt_object); 58011963SAfshin.Ardakani@Sun.COM 58111963SAfshin.Ardakani@Sun.COM dtor->dt_magic = (uint32_t)~SMB_DTOR_MAGIC; 58211963SAfshin.Ardakani@Sun.COM kmem_cache_free(smb_dtor_cache, dtor); 58311963SAfshin.Ardakani@Sun.COM mutex_enter(&ll->ll_mutex); 58411963SAfshin.Ardakani@Sun.COM dtor = list_head(&ll->ll_deleteq); 58511963SAfshin.Ardakani@Sun.COM } 58611963SAfshin.Ardakani@Sun.COM 58711963SAfshin.Ardakani@Sun.COM mutex_exit(&ll->ll_mutex); 58811963SAfshin.Ardakani@Sun.COM } 58911963SAfshin.Ardakani@Sun.COM 59011963SAfshin.Ardakani@Sun.COM /* 59111963SAfshin.Ardakani@Sun.COM * smb_llist_upgrade 59211963SAfshin.Ardakani@Sun.COM * 59311963SAfshin.Ardakani@Sun.COM * This function tries to upgrade the lock of the locked list. It assumes the 59411963SAfshin.Ardakani@Sun.COM * locked has already been entered in RW_READER mode. It first tries using the 59511963SAfshin.Ardakani@Sun.COM * Solaris function rw_tryupgrade(). If that call fails the lock is released 59611963SAfshin.Ardakani@Sun.COM * and reentered in RW_WRITER mode. In that last case a window is opened during 59711963SAfshin.Ardakani@Sun.COM * which the contents of the list may have changed. The return code indicates 59811963SAfshin.Ardakani@Sun.COM * whether or not the list was modified when the lock was exited. 59911963SAfshin.Ardakani@Sun.COM */ 60011963SAfshin.Ardakani@Sun.COM int smb_llist_upgrade( 60111963SAfshin.Ardakani@Sun.COM smb_llist_t *ll) 60211963SAfshin.Ardakani@Sun.COM { 60311963SAfshin.Ardakani@Sun.COM uint64_t wrop; 60411963SAfshin.Ardakani@Sun.COM 60511963SAfshin.Ardakani@Sun.COM if (rw_tryupgrade(&ll->ll_lock) != 0) { 60611963SAfshin.Ardakani@Sun.COM return (0); 60711963SAfshin.Ardakani@Sun.COM } 60811963SAfshin.Ardakani@Sun.COM wrop = ll->ll_wrop; 60911963SAfshin.Ardakani@Sun.COM rw_exit(&ll->ll_lock); 61011963SAfshin.Ardakani@Sun.COM rw_enter(&ll->ll_lock, RW_WRITER); 61111963SAfshin.Ardakani@Sun.COM return (wrop != ll->ll_wrop); 61211963SAfshin.Ardakani@Sun.COM } 61311963SAfshin.Ardakani@Sun.COM 61411963SAfshin.Ardakani@Sun.COM /* 61511963SAfshin.Ardakani@Sun.COM * smb_llist_insert_head 61611963SAfshin.Ardakani@Sun.COM * 61711963SAfshin.Ardakani@Sun.COM * This function inserts the object passed a the beginning of the list. This 61811963SAfshin.Ardakani@Sun.COM * function assumes the lock of the list has already been entered. 61911963SAfshin.Ardakani@Sun.COM */ 62011963SAfshin.Ardakani@Sun.COM void 62111963SAfshin.Ardakani@Sun.COM smb_llist_insert_head( 62211963SAfshin.Ardakani@Sun.COM smb_llist_t *ll, 62311963SAfshin.Ardakani@Sun.COM void *obj) 62411963SAfshin.Ardakani@Sun.COM { 62511963SAfshin.Ardakani@Sun.COM list_insert_head(&ll->ll_list, obj); 62611963SAfshin.Ardakani@Sun.COM ++ll->ll_wrop; 62711963SAfshin.Ardakani@Sun.COM ++ll->ll_count; 62811963SAfshin.Ardakani@Sun.COM } 62911963SAfshin.Ardakani@Sun.COM 63011963SAfshin.Ardakani@Sun.COM /* 63111963SAfshin.Ardakani@Sun.COM * smb_llist_insert_tail 63211963SAfshin.Ardakani@Sun.COM * 63311963SAfshin.Ardakani@Sun.COM * This function appends to the object passed to the list. This function assumes 63411963SAfshin.Ardakani@Sun.COM * the lock of the list has already been entered. 63511963SAfshin.Ardakani@Sun.COM * 63611963SAfshin.Ardakani@Sun.COM */ 63711963SAfshin.Ardakani@Sun.COM void 63811963SAfshin.Ardakani@Sun.COM smb_llist_insert_tail( 63911963SAfshin.Ardakani@Sun.COM smb_llist_t *ll, 64011963SAfshin.Ardakani@Sun.COM void *obj) 64111963SAfshin.Ardakani@Sun.COM { 64211963SAfshin.Ardakani@Sun.COM list_insert_tail(&ll->ll_list, obj); 64311963SAfshin.Ardakani@Sun.COM ++ll->ll_wrop; 64411963SAfshin.Ardakani@Sun.COM ++ll->ll_count; 64511963SAfshin.Ardakani@Sun.COM } 64611963SAfshin.Ardakani@Sun.COM 64711963SAfshin.Ardakani@Sun.COM /* 64811963SAfshin.Ardakani@Sun.COM * smb_llist_remove 64911963SAfshin.Ardakani@Sun.COM * 65011963SAfshin.Ardakani@Sun.COM * This function removes the object passed from the list. This function assumes 65111963SAfshin.Ardakani@Sun.COM * the lock of the list has already been entered. 65211963SAfshin.Ardakani@Sun.COM */ 65311963SAfshin.Ardakani@Sun.COM void 65411963SAfshin.Ardakani@Sun.COM smb_llist_remove( 65511963SAfshin.Ardakani@Sun.COM smb_llist_t *ll, 65611963SAfshin.Ardakani@Sun.COM void *obj) 65711963SAfshin.Ardakani@Sun.COM { 65811963SAfshin.Ardakani@Sun.COM list_remove(&ll->ll_list, obj); 65911963SAfshin.Ardakani@Sun.COM ++ll->ll_wrop; 66011963SAfshin.Ardakani@Sun.COM --ll->ll_count; 66111963SAfshin.Ardakani@Sun.COM } 66211963SAfshin.Ardakani@Sun.COM 66311963SAfshin.Ardakani@Sun.COM /* 66411963SAfshin.Ardakani@Sun.COM * smb_llist_get_count 66511963SAfshin.Ardakani@Sun.COM * 66611963SAfshin.Ardakani@Sun.COM * This function returns the number of elements in the specified list. 66711963SAfshin.Ardakani@Sun.COM */ 66811963SAfshin.Ardakani@Sun.COM uint32_t 66911963SAfshin.Ardakani@Sun.COM smb_llist_get_count( 67011963SAfshin.Ardakani@Sun.COM smb_llist_t *ll) 67111963SAfshin.Ardakani@Sun.COM { 67211963SAfshin.Ardakani@Sun.COM return (ll->ll_count); 67311963SAfshin.Ardakani@Sun.COM } 67411963SAfshin.Ardakani@Sun.COM 67511963SAfshin.Ardakani@Sun.COM /* 67611963SAfshin.Ardakani@Sun.COM * smb_slist_constructor 67711963SAfshin.Ardakani@Sun.COM * 67811963SAfshin.Ardakani@Sun.COM * Synchronized list constructor. 67911963SAfshin.Ardakani@Sun.COM */ 68011963SAfshin.Ardakani@Sun.COM void 68111963SAfshin.Ardakani@Sun.COM smb_slist_constructor( 68211963SAfshin.Ardakani@Sun.COM smb_slist_t *sl, 68311963SAfshin.Ardakani@Sun.COM size_t size, 68411963SAfshin.Ardakani@Sun.COM size_t offset) 68511963SAfshin.Ardakani@Sun.COM { 68611963SAfshin.Ardakani@Sun.COM mutex_init(&sl->sl_mutex, NULL, MUTEX_DEFAULT, NULL); 68711963SAfshin.Ardakani@Sun.COM cv_init(&sl->sl_cv, NULL, CV_DEFAULT, NULL); 68811963SAfshin.Ardakani@Sun.COM list_create(&sl->sl_list, size, offset); 68911963SAfshin.Ardakani@Sun.COM sl->sl_count = 0; 69011963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_FALSE; 69111963SAfshin.Ardakani@Sun.COM } 69211963SAfshin.Ardakani@Sun.COM 69311963SAfshin.Ardakani@Sun.COM /* 69411963SAfshin.Ardakani@Sun.COM * smb_slist_destructor 69511963SAfshin.Ardakani@Sun.COM * 69611963SAfshin.Ardakani@Sun.COM * Synchronized list destructor. 69711963SAfshin.Ardakani@Sun.COM */ 69811963SAfshin.Ardakani@Sun.COM void 69911963SAfshin.Ardakani@Sun.COM smb_slist_destructor( 70011963SAfshin.Ardakani@Sun.COM smb_slist_t *sl) 70111963SAfshin.Ardakani@Sun.COM { 702*12508Samw@Sun.COM VERIFY(sl->sl_count == 0); 70311963SAfshin.Ardakani@Sun.COM 70411963SAfshin.Ardakani@Sun.COM mutex_destroy(&sl->sl_mutex); 70511963SAfshin.Ardakani@Sun.COM cv_destroy(&sl->sl_cv); 70611963SAfshin.Ardakani@Sun.COM list_destroy(&sl->sl_list); 70711963SAfshin.Ardakani@Sun.COM } 70811963SAfshin.Ardakani@Sun.COM 70911963SAfshin.Ardakani@Sun.COM /* 71011963SAfshin.Ardakani@Sun.COM * smb_slist_insert_head 71111963SAfshin.Ardakani@Sun.COM * 71211963SAfshin.Ardakani@Sun.COM * This function inserts the object passed a the beginning of the list. 71311963SAfshin.Ardakani@Sun.COM */ 71411963SAfshin.Ardakani@Sun.COM void 71511963SAfshin.Ardakani@Sun.COM smb_slist_insert_head( 71611963SAfshin.Ardakani@Sun.COM smb_slist_t *sl, 71711963SAfshin.Ardakani@Sun.COM void *obj) 71811963SAfshin.Ardakani@Sun.COM { 71911963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex); 72011963SAfshin.Ardakani@Sun.COM list_insert_head(&sl->sl_list, obj); 72111963SAfshin.Ardakani@Sun.COM ++sl->sl_count; 72211963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 72311963SAfshin.Ardakani@Sun.COM } 72411963SAfshin.Ardakani@Sun.COM 72511963SAfshin.Ardakani@Sun.COM /* 72611963SAfshin.Ardakani@Sun.COM * smb_slist_insert_tail 72711963SAfshin.Ardakani@Sun.COM * 72811963SAfshin.Ardakani@Sun.COM * This function appends the object passed to the list. 72911963SAfshin.Ardakani@Sun.COM */ 73011963SAfshin.Ardakani@Sun.COM void 73111963SAfshin.Ardakani@Sun.COM smb_slist_insert_tail( 73211963SAfshin.Ardakani@Sun.COM smb_slist_t *sl, 73311963SAfshin.Ardakani@Sun.COM void *obj) 73411963SAfshin.Ardakani@Sun.COM { 73511963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex); 73611963SAfshin.Ardakani@Sun.COM list_insert_tail(&sl->sl_list, obj); 73711963SAfshin.Ardakani@Sun.COM ++sl->sl_count; 73811963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 73911963SAfshin.Ardakani@Sun.COM } 74011963SAfshin.Ardakani@Sun.COM 74111963SAfshin.Ardakani@Sun.COM /* 74211963SAfshin.Ardakani@Sun.COM * smb_llist_remove 74311963SAfshin.Ardakani@Sun.COM * 74411963SAfshin.Ardakani@Sun.COM * This function removes the object passed by the caller from the list. 74511963SAfshin.Ardakani@Sun.COM */ 74611963SAfshin.Ardakani@Sun.COM void 74711963SAfshin.Ardakani@Sun.COM smb_slist_remove( 74811963SAfshin.Ardakani@Sun.COM smb_slist_t *sl, 74911963SAfshin.Ardakani@Sun.COM void *obj) 75011963SAfshin.Ardakani@Sun.COM { 75111963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex); 75211963SAfshin.Ardakani@Sun.COM list_remove(&sl->sl_list, obj); 75311963SAfshin.Ardakani@Sun.COM if ((--sl->sl_count == 0) && (sl->sl_waiting)) { 75411963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_FALSE; 75511963SAfshin.Ardakani@Sun.COM cv_broadcast(&sl->sl_cv); 75611963SAfshin.Ardakani@Sun.COM } 75711963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 75811963SAfshin.Ardakani@Sun.COM } 75911963SAfshin.Ardakani@Sun.COM 76011963SAfshin.Ardakani@Sun.COM /* 76111963SAfshin.Ardakani@Sun.COM * smb_slist_move_tail 76211963SAfshin.Ardakani@Sun.COM * 76311963SAfshin.Ardakani@Sun.COM * This function transfers all the contents of the synchronized list to the 76411963SAfshin.Ardakani@Sun.COM * list_t provided. It returns the number of objects transferred. 76511963SAfshin.Ardakani@Sun.COM */ 76611963SAfshin.Ardakani@Sun.COM uint32_t 76711963SAfshin.Ardakani@Sun.COM smb_slist_move_tail( 76811963SAfshin.Ardakani@Sun.COM list_t *lst, 76911963SAfshin.Ardakani@Sun.COM smb_slist_t *sl) 77011963SAfshin.Ardakani@Sun.COM { 77111963SAfshin.Ardakani@Sun.COM uint32_t rv; 77211963SAfshin.Ardakani@Sun.COM 77311963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex); 77411963SAfshin.Ardakani@Sun.COM rv = sl->sl_count; 77511963SAfshin.Ardakani@Sun.COM if (sl->sl_count) { 77611963SAfshin.Ardakani@Sun.COM list_move_tail(lst, &sl->sl_list); 77711963SAfshin.Ardakani@Sun.COM sl->sl_count = 0; 77811963SAfshin.Ardakani@Sun.COM if (sl->sl_waiting) { 77911963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_FALSE; 78011963SAfshin.Ardakani@Sun.COM cv_broadcast(&sl->sl_cv); 78111963SAfshin.Ardakani@Sun.COM } 78211963SAfshin.Ardakani@Sun.COM } 78311963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 78411963SAfshin.Ardakani@Sun.COM return (rv); 78511963SAfshin.Ardakani@Sun.COM } 78611963SAfshin.Ardakani@Sun.COM 78711963SAfshin.Ardakani@Sun.COM /* 78811963SAfshin.Ardakani@Sun.COM * smb_slist_obj_move 78911963SAfshin.Ardakani@Sun.COM * 79011963SAfshin.Ardakani@Sun.COM * This function moves an object from one list to the end of the other list. It 79111963SAfshin.Ardakani@Sun.COM * assumes the mutex of each list has been entered. 79211963SAfshin.Ardakani@Sun.COM */ 79311963SAfshin.Ardakani@Sun.COM void 79411963SAfshin.Ardakani@Sun.COM smb_slist_obj_move( 79511963SAfshin.Ardakani@Sun.COM smb_slist_t *dst, 79611963SAfshin.Ardakani@Sun.COM smb_slist_t *src, 79711963SAfshin.Ardakani@Sun.COM void *obj) 79811963SAfshin.Ardakani@Sun.COM { 79911963SAfshin.Ardakani@Sun.COM ASSERT(dst->sl_list.list_offset == src->sl_list.list_offset); 80011963SAfshin.Ardakani@Sun.COM ASSERT(dst->sl_list.list_size == src->sl_list.list_size); 80111963SAfshin.Ardakani@Sun.COM 80211963SAfshin.Ardakani@Sun.COM list_remove(&src->sl_list, obj); 80311963SAfshin.Ardakani@Sun.COM list_insert_tail(&dst->sl_list, obj); 80411963SAfshin.Ardakani@Sun.COM dst->sl_count++; 80511963SAfshin.Ardakani@Sun.COM src->sl_count--; 80611963SAfshin.Ardakani@Sun.COM if ((src->sl_count == 0) && (src->sl_waiting)) { 80711963SAfshin.Ardakani@Sun.COM src->sl_waiting = B_FALSE; 80811963SAfshin.Ardakani@Sun.COM cv_broadcast(&src->sl_cv); 80911963SAfshin.Ardakani@Sun.COM } 81011963SAfshin.Ardakani@Sun.COM } 81111963SAfshin.Ardakani@Sun.COM 81211963SAfshin.Ardakani@Sun.COM /* 81311963SAfshin.Ardakani@Sun.COM * smb_slist_wait_for_empty 81411963SAfshin.Ardakani@Sun.COM * 81511963SAfshin.Ardakani@Sun.COM * This function waits for a list to be emptied. 81611963SAfshin.Ardakani@Sun.COM */ 81711963SAfshin.Ardakani@Sun.COM void 81811963SAfshin.Ardakani@Sun.COM smb_slist_wait_for_empty( 81911963SAfshin.Ardakani@Sun.COM smb_slist_t *sl) 82011963SAfshin.Ardakani@Sun.COM { 82111963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex); 82211963SAfshin.Ardakani@Sun.COM while (sl->sl_count) { 82311963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_TRUE; 82411963SAfshin.Ardakani@Sun.COM cv_wait(&sl->sl_cv, &sl->sl_mutex); 82511963SAfshin.Ardakani@Sun.COM } 82611963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 82711963SAfshin.Ardakani@Sun.COM } 82811963SAfshin.Ardakani@Sun.COM 82911963SAfshin.Ardakani@Sun.COM /* 83011963SAfshin.Ardakani@Sun.COM * smb_slist_exit 83111963SAfshin.Ardakani@Sun.COM * 83211963SAfshin.Ardakani@Sun.COM * This function exits the muetx of the list and signal the condition variable 83311963SAfshin.Ardakani@Sun.COM * if the list is empty. 83411963SAfshin.Ardakani@Sun.COM */ 83511963SAfshin.Ardakani@Sun.COM void 83611963SAfshin.Ardakani@Sun.COM smb_slist_exit(smb_slist_t *sl) 83711963SAfshin.Ardakani@Sun.COM { 83811963SAfshin.Ardakani@Sun.COM if ((sl->sl_count == 0) && (sl->sl_waiting)) { 83911963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_FALSE; 84011963SAfshin.Ardakani@Sun.COM cv_broadcast(&sl->sl_cv); 84111963SAfshin.Ardakani@Sun.COM } 84211963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 84311963SAfshin.Ardakani@Sun.COM } 84411963SAfshin.Ardakani@Sun.COM 84511963SAfshin.Ardakani@Sun.COM /* 84611963SAfshin.Ardakani@Sun.COM * smb_thread_entry_point 84711963SAfshin.Ardakani@Sun.COM * 84811963SAfshin.Ardakani@Sun.COM * Common entry point for all the threads created through smb_thread_start. 84911963SAfshin.Ardakani@Sun.COM * The state of the thread is set to "running" at the beginning and moved to 85011963SAfshin.Ardakani@Sun.COM * "exiting" just before calling thread_exit(). The condition variable is 85111963SAfshin.Ardakani@Sun.COM * also signaled. 85211963SAfshin.Ardakani@Sun.COM */ 85311963SAfshin.Ardakani@Sun.COM static void 85411963SAfshin.Ardakani@Sun.COM smb_thread_entry_point( 85511963SAfshin.Ardakani@Sun.COM smb_thread_t *thread) 85611963SAfshin.Ardakani@Sun.COM { 85711963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 85811963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 85911963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_state == SMB_THREAD_STATE_STARTING); 86011963SAfshin.Ardakani@Sun.COM thread->sth_th = curthread; 86111963SAfshin.Ardakani@Sun.COM thread->sth_did = thread->sth_th->t_did; 86211963SAfshin.Ardakani@Sun.COM 86311963SAfshin.Ardakani@Sun.COM if (!thread->sth_kill) { 86411963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_RUNNING; 86511963SAfshin.Ardakani@Sun.COM cv_signal(&thread->sth_cv); 86611963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 86711963SAfshin.Ardakani@Sun.COM thread->sth_ep(thread, thread->sth_ep_arg); 86811963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 86911963SAfshin.Ardakani@Sun.COM } 87011963SAfshin.Ardakani@Sun.COM thread->sth_th = NULL; 87111963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_EXITING; 87211963SAfshin.Ardakani@Sun.COM cv_broadcast(&thread->sth_cv); 87311963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 87411963SAfshin.Ardakani@Sun.COM thread_exit(); 87511963SAfshin.Ardakani@Sun.COM } 87611963SAfshin.Ardakani@Sun.COM 87711963SAfshin.Ardakani@Sun.COM /* 87811963SAfshin.Ardakani@Sun.COM * smb_thread_init 87911963SAfshin.Ardakani@Sun.COM */ 88011963SAfshin.Ardakani@Sun.COM void 88111963SAfshin.Ardakani@Sun.COM smb_thread_init( 88211963SAfshin.Ardakani@Sun.COM smb_thread_t *thread, 88311963SAfshin.Ardakani@Sun.COM char *name, 88411963SAfshin.Ardakani@Sun.COM smb_thread_ep_t ep, 88511963SAfshin.Ardakani@Sun.COM void *ep_arg, 88611963SAfshin.Ardakani@Sun.COM smb_thread_aw_t aw, 88711963SAfshin.Ardakani@Sun.COM void *aw_arg) 88811963SAfshin.Ardakani@Sun.COM { 88911963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic != SMB_THREAD_MAGIC); 89011963SAfshin.Ardakani@Sun.COM 89111963SAfshin.Ardakani@Sun.COM bzero(thread, sizeof (*thread)); 89211963SAfshin.Ardakani@Sun.COM 89311963SAfshin.Ardakani@Sun.COM (void) strlcpy(thread->sth_name, name, sizeof (thread->sth_name)); 89411963SAfshin.Ardakani@Sun.COM thread->sth_ep = ep; 89511963SAfshin.Ardakani@Sun.COM thread->sth_ep_arg = ep_arg; 89611963SAfshin.Ardakani@Sun.COM thread->sth_aw = aw; 89711963SAfshin.Ardakani@Sun.COM thread->sth_aw_arg = aw_arg; 89811963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_EXITED; 89911963SAfshin.Ardakani@Sun.COM mutex_init(&thread->sth_mtx, NULL, MUTEX_DEFAULT, NULL); 90011963SAfshin.Ardakani@Sun.COM cv_init(&thread->sth_cv, NULL, CV_DEFAULT, NULL); 90111963SAfshin.Ardakani@Sun.COM thread->sth_magic = SMB_THREAD_MAGIC; 90211963SAfshin.Ardakani@Sun.COM } 90311963SAfshin.Ardakani@Sun.COM 90411963SAfshin.Ardakani@Sun.COM /* 90511963SAfshin.Ardakani@Sun.COM * smb_thread_destroy 90611963SAfshin.Ardakani@Sun.COM */ 90711963SAfshin.Ardakani@Sun.COM void 90811963SAfshin.Ardakani@Sun.COM smb_thread_destroy( 90911963SAfshin.Ardakani@Sun.COM smb_thread_t *thread) 91011963SAfshin.Ardakani@Sun.COM { 91111963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 91211963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_state == SMB_THREAD_STATE_EXITED); 91311963SAfshin.Ardakani@Sun.COM thread->sth_magic = 0; 91411963SAfshin.Ardakani@Sun.COM mutex_destroy(&thread->sth_mtx); 91511963SAfshin.Ardakani@Sun.COM cv_destroy(&thread->sth_cv); 91611963SAfshin.Ardakani@Sun.COM } 91711963SAfshin.Ardakani@Sun.COM 91811963SAfshin.Ardakani@Sun.COM /* 91911963SAfshin.Ardakani@Sun.COM * smb_thread_start 92011963SAfshin.Ardakani@Sun.COM * 92111963SAfshin.Ardakani@Sun.COM * This function starts a thread with the parameters provided. It waits until 92211963SAfshin.Ardakani@Sun.COM * the state of the thread has been moved to running. 92311963SAfshin.Ardakani@Sun.COM */ 92411963SAfshin.Ardakani@Sun.COM /*ARGSUSED*/ 92511963SAfshin.Ardakani@Sun.COM int 92611963SAfshin.Ardakani@Sun.COM smb_thread_start( 92711963SAfshin.Ardakani@Sun.COM smb_thread_t *thread) 92811963SAfshin.Ardakani@Sun.COM { 92911963SAfshin.Ardakani@Sun.COM int rc = 0; 93011963SAfshin.Ardakani@Sun.COM kthread_t *tmpthread; 93111963SAfshin.Ardakani@Sun.COM 93211963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 93311963SAfshin.Ardakani@Sun.COM 93411963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 93511963SAfshin.Ardakani@Sun.COM switch (thread->sth_state) { 93611963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_EXITED: 93711963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_STARTING; 93811963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 93911963SAfshin.Ardakani@Sun.COM tmpthread = thread_create(NULL, 0, smb_thread_entry_point, 94011963SAfshin.Ardakani@Sun.COM thread, 0, &p0, TS_RUN, minclsyspri); 94111963SAfshin.Ardakani@Sun.COM ASSERT(tmpthread != NULL); 94211963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 94311963SAfshin.Ardakani@Sun.COM while (thread->sth_state == SMB_THREAD_STATE_STARTING) 94411963SAfshin.Ardakani@Sun.COM cv_wait(&thread->sth_cv, &thread->sth_mtx); 94511963SAfshin.Ardakani@Sun.COM if (thread->sth_state != SMB_THREAD_STATE_RUNNING) 94611963SAfshin.Ardakani@Sun.COM rc = -1; 94711963SAfshin.Ardakani@Sun.COM break; 94811963SAfshin.Ardakani@Sun.COM default: 94911963SAfshin.Ardakani@Sun.COM ASSERT(0); 95011963SAfshin.Ardakani@Sun.COM rc = -1; 95111963SAfshin.Ardakani@Sun.COM break; 95211963SAfshin.Ardakani@Sun.COM } 95311963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 95411963SAfshin.Ardakani@Sun.COM return (rc); 95511963SAfshin.Ardakani@Sun.COM } 95611963SAfshin.Ardakani@Sun.COM 95711963SAfshin.Ardakani@Sun.COM /* 95811963SAfshin.Ardakani@Sun.COM * smb_thread_stop 95911963SAfshin.Ardakani@Sun.COM * 96011963SAfshin.Ardakani@Sun.COM * This function signals a thread to kill itself and waits until the "exiting" 96111963SAfshin.Ardakani@Sun.COM * state has been reached. 96211963SAfshin.Ardakani@Sun.COM */ 96311963SAfshin.Ardakani@Sun.COM void 96411963SAfshin.Ardakani@Sun.COM smb_thread_stop( 96511963SAfshin.Ardakani@Sun.COM smb_thread_t *thread) 96611963SAfshin.Ardakani@Sun.COM { 96711963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 96811963SAfshin.Ardakani@Sun.COM 96911963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 97011963SAfshin.Ardakani@Sun.COM switch (thread->sth_state) { 97111963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_RUNNING: 97211963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_STARTING: 97311963SAfshin.Ardakani@Sun.COM if (!thread->sth_kill) { 97411963SAfshin.Ardakani@Sun.COM thread->sth_kill = B_TRUE; 97511963SAfshin.Ardakani@Sun.COM if (thread->sth_aw) 97611963SAfshin.Ardakani@Sun.COM thread->sth_aw(thread, thread->sth_aw_arg); 97711963SAfshin.Ardakani@Sun.COM cv_broadcast(&thread->sth_cv); 97811963SAfshin.Ardakani@Sun.COM while (thread->sth_state != SMB_THREAD_STATE_EXITING) 97911963SAfshin.Ardakani@Sun.COM cv_wait(&thread->sth_cv, &thread->sth_mtx); 98011963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 98111963SAfshin.Ardakani@Sun.COM thread_join(thread->sth_did); 98211963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 98311963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_EXITED; 98411963SAfshin.Ardakani@Sun.COM thread->sth_did = 0; 98511963SAfshin.Ardakani@Sun.COM thread->sth_kill = B_FALSE; 98611963SAfshin.Ardakani@Sun.COM cv_broadcast(&thread->sth_cv); 98711963SAfshin.Ardakani@Sun.COM break; 98811963SAfshin.Ardakani@Sun.COM } 98911963SAfshin.Ardakani@Sun.COM /*FALLTHRU*/ 99011963SAfshin.Ardakani@Sun.COM 99111963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_EXITING: 99211963SAfshin.Ardakani@Sun.COM if (thread->sth_kill) { 99311963SAfshin.Ardakani@Sun.COM while (thread->sth_state != SMB_THREAD_STATE_EXITED) 99411963SAfshin.Ardakani@Sun.COM cv_wait(&thread->sth_cv, &thread->sth_mtx); 99511963SAfshin.Ardakani@Sun.COM } else { 99611963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_EXITED; 99711963SAfshin.Ardakani@Sun.COM thread->sth_did = 0; 99811963SAfshin.Ardakani@Sun.COM } 99911963SAfshin.Ardakani@Sun.COM break; 100011963SAfshin.Ardakani@Sun.COM 100111963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_EXITED: 100211963SAfshin.Ardakani@Sun.COM break; 100311963SAfshin.Ardakani@Sun.COM 100411963SAfshin.Ardakani@Sun.COM default: 100511963SAfshin.Ardakani@Sun.COM ASSERT(0); 100611963SAfshin.Ardakani@Sun.COM break; 100711963SAfshin.Ardakani@Sun.COM } 100811963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 100911963SAfshin.Ardakani@Sun.COM } 101011963SAfshin.Ardakani@Sun.COM 101111963SAfshin.Ardakani@Sun.COM /* 101211963SAfshin.Ardakani@Sun.COM * smb_thread_signal 101311963SAfshin.Ardakani@Sun.COM * 101411963SAfshin.Ardakani@Sun.COM * This function signals a thread. 101511963SAfshin.Ardakani@Sun.COM */ 101611963SAfshin.Ardakani@Sun.COM void 101711963SAfshin.Ardakani@Sun.COM smb_thread_signal( 101811963SAfshin.Ardakani@Sun.COM smb_thread_t *thread) 101911963SAfshin.Ardakani@Sun.COM { 102011963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 102111963SAfshin.Ardakani@Sun.COM 102211963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 102311963SAfshin.Ardakani@Sun.COM switch (thread->sth_state) { 102411963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_RUNNING: 102511963SAfshin.Ardakani@Sun.COM if (thread->sth_aw) 102611963SAfshin.Ardakani@Sun.COM thread->sth_aw(thread, thread->sth_aw_arg); 102711963SAfshin.Ardakani@Sun.COM cv_signal(&thread->sth_cv); 102811963SAfshin.Ardakani@Sun.COM break; 102911963SAfshin.Ardakani@Sun.COM 103011963SAfshin.Ardakani@Sun.COM default: 103111963SAfshin.Ardakani@Sun.COM break; 103211963SAfshin.Ardakani@Sun.COM } 103311963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 103411963SAfshin.Ardakani@Sun.COM } 103511963SAfshin.Ardakani@Sun.COM 103611963SAfshin.Ardakani@Sun.COM boolean_t 103711963SAfshin.Ardakani@Sun.COM smb_thread_continue(smb_thread_t *thread) 103811963SAfshin.Ardakani@Sun.COM { 103911963SAfshin.Ardakani@Sun.COM boolean_t result; 104011963SAfshin.Ardakani@Sun.COM 104111963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 104211963SAfshin.Ardakani@Sun.COM 104311963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 104411963SAfshin.Ardakani@Sun.COM result = smb_thread_continue_timedwait_locked(thread, 0); 104511963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 104611963SAfshin.Ardakani@Sun.COM 104711963SAfshin.Ardakani@Sun.COM return (result); 104811963SAfshin.Ardakani@Sun.COM } 104911963SAfshin.Ardakani@Sun.COM 105011963SAfshin.Ardakani@Sun.COM boolean_t 105111963SAfshin.Ardakani@Sun.COM smb_thread_continue_nowait(smb_thread_t *thread) 105211963SAfshin.Ardakani@Sun.COM { 105311963SAfshin.Ardakani@Sun.COM boolean_t result; 105411963SAfshin.Ardakani@Sun.COM 105511963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 105611963SAfshin.Ardakani@Sun.COM 105711963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 105811963SAfshin.Ardakani@Sun.COM /* 105911963SAfshin.Ardakani@Sun.COM * Setting ticks=-1 requests a non-blocking check. We will 106011963SAfshin.Ardakani@Sun.COM * still block if the thread is in "suspend" state. 106111963SAfshin.Ardakani@Sun.COM */ 106211963SAfshin.Ardakani@Sun.COM result = smb_thread_continue_timedwait_locked(thread, -1); 106311963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 106411963SAfshin.Ardakani@Sun.COM 106511963SAfshin.Ardakani@Sun.COM return (result); 106611963SAfshin.Ardakani@Sun.COM } 106711963SAfshin.Ardakani@Sun.COM 106811963SAfshin.Ardakani@Sun.COM boolean_t 106911963SAfshin.Ardakani@Sun.COM smb_thread_continue_timedwait(smb_thread_t *thread, int seconds) 107011963SAfshin.Ardakani@Sun.COM { 107111963SAfshin.Ardakani@Sun.COM boolean_t result; 107211963SAfshin.Ardakani@Sun.COM 107311963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 107411963SAfshin.Ardakani@Sun.COM 107511963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 107611963SAfshin.Ardakani@Sun.COM result = smb_thread_continue_timedwait_locked(thread, 107711963SAfshin.Ardakani@Sun.COM SEC_TO_TICK(seconds)); 107811963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 107911963SAfshin.Ardakani@Sun.COM 108011963SAfshin.Ardakani@Sun.COM return (result); 108111963SAfshin.Ardakani@Sun.COM } 108211963SAfshin.Ardakani@Sun.COM 108311963SAfshin.Ardakani@Sun.COM /* 108411963SAfshin.Ardakani@Sun.COM * smb_thread_continue_timedwait_locked 108511963SAfshin.Ardakani@Sun.COM * 108611963SAfshin.Ardakani@Sun.COM * Internal only. Ticks==-1 means don't block, Ticks == 0 means wait 108711963SAfshin.Ardakani@Sun.COM * indefinitely 108811963SAfshin.Ardakani@Sun.COM */ 108911963SAfshin.Ardakani@Sun.COM static boolean_t 109011963SAfshin.Ardakani@Sun.COM smb_thread_continue_timedwait_locked(smb_thread_t *thread, int ticks) 109111963SAfshin.Ardakani@Sun.COM { 109211963SAfshin.Ardakani@Sun.COM boolean_t result; 109311963SAfshin.Ardakani@Sun.COM 109411963SAfshin.Ardakani@Sun.COM /* -1 means don't block */ 109511963SAfshin.Ardakani@Sun.COM if (ticks != -1 && !thread->sth_kill) { 109611963SAfshin.Ardakani@Sun.COM if (ticks == 0) { 109711963SAfshin.Ardakani@Sun.COM cv_wait(&thread->sth_cv, &thread->sth_mtx); 109811963SAfshin.Ardakani@Sun.COM } else { 109911963SAfshin.Ardakani@Sun.COM (void) cv_reltimedwait(&thread->sth_cv, 110011963SAfshin.Ardakani@Sun.COM &thread->sth_mtx, (clock_t)ticks, TR_CLOCK_TICK); 110111963SAfshin.Ardakani@Sun.COM } 110211963SAfshin.Ardakani@Sun.COM } 110311963SAfshin.Ardakani@Sun.COM result = (thread->sth_kill == 0); 110411963SAfshin.Ardakani@Sun.COM 110511963SAfshin.Ardakani@Sun.COM return (result); 110611963SAfshin.Ardakani@Sun.COM } 110711963SAfshin.Ardakani@Sun.COM 110811963SAfshin.Ardakani@Sun.COM void 110911963SAfshin.Ardakani@Sun.COM smb_thread_set_awaken(smb_thread_t *thread, smb_thread_aw_t new_aw_fn, 111011963SAfshin.Ardakani@Sun.COM void *new_aw_arg) 111111963SAfshin.Ardakani@Sun.COM { 111211963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 111311963SAfshin.Ardakani@Sun.COM 111411963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 111511963SAfshin.Ardakani@Sun.COM thread->sth_aw = new_aw_fn; 111611963SAfshin.Ardakani@Sun.COM thread->sth_aw_arg = new_aw_arg; 111711963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 111811963SAfshin.Ardakani@Sun.COM } 111911963SAfshin.Ardakani@Sun.COM 112011963SAfshin.Ardakani@Sun.COM /* 112111963SAfshin.Ardakani@Sun.COM * smb_rwx_init 112211963SAfshin.Ardakani@Sun.COM */ 112311963SAfshin.Ardakani@Sun.COM void 112411963SAfshin.Ardakani@Sun.COM smb_rwx_init( 112511963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx) 112611963SAfshin.Ardakani@Sun.COM { 112711963SAfshin.Ardakani@Sun.COM bzero(rwx, sizeof (smb_rwx_t)); 112811963SAfshin.Ardakani@Sun.COM cv_init(&rwx->rwx_cv, NULL, CV_DEFAULT, NULL); 112911963SAfshin.Ardakani@Sun.COM mutex_init(&rwx->rwx_mutex, NULL, MUTEX_DEFAULT, NULL); 113011963SAfshin.Ardakani@Sun.COM rw_init(&rwx->rwx_lock, NULL, RW_DEFAULT, NULL); 113111963SAfshin.Ardakani@Sun.COM } 113211963SAfshin.Ardakani@Sun.COM 113311963SAfshin.Ardakani@Sun.COM /* 113411963SAfshin.Ardakani@Sun.COM * smb_rwx_destroy 113511963SAfshin.Ardakani@Sun.COM */ 113611963SAfshin.Ardakani@Sun.COM void 113711963SAfshin.Ardakani@Sun.COM smb_rwx_destroy( 113811963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx) 113911963SAfshin.Ardakani@Sun.COM { 114011963SAfshin.Ardakani@Sun.COM mutex_destroy(&rwx->rwx_mutex); 114111963SAfshin.Ardakani@Sun.COM cv_destroy(&rwx->rwx_cv); 114211963SAfshin.Ardakani@Sun.COM rw_destroy(&rwx->rwx_lock); 114311963SAfshin.Ardakani@Sun.COM } 114411963SAfshin.Ardakani@Sun.COM 114511963SAfshin.Ardakani@Sun.COM /* 114611963SAfshin.Ardakani@Sun.COM * smb_rwx_rwexit 114711963SAfshin.Ardakani@Sun.COM */ 114811963SAfshin.Ardakani@Sun.COM void 114911963SAfshin.Ardakani@Sun.COM smb_rwx_rwexit( 115011963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx) 115111963SAfshin.Ardakani@Sun.COM { 115211963SAfshin.Ardakani@Sun.COM if (rw_write_held(&rwx->rwx_lock)) { 115311963SAfshin.Ardakani@Sun.COM ASSERT(rw_owner(&rwx->rwx_lock) == curthread); 115411963SAfshin.Ardakani@Sun.COM mutex_enter(&rwx->rwx_mutex); 115511963SAfshin.Ardakani@Sun.COM if (rwx->rwx_waiting) { 115611963SAfshin.Ardakani@Sun.COM rwx->rwx_waiting = B_FALSE; 115711963SAfshin.Ardakani@Sun.COM cv_broadcast(&rwx->rwx_cv); 115811963SAfshin.Ardakani@Sun.COM } 115911963SAfshin.Ardakani@Sun.COM mutex_exit(&rwx->rwx_mutex); 116011963SAfshin.Ardakani@Sun.COM } 116111963SAfshin.Ardakani@Sun.COM rw_exit(&rwx->rwx_lock); 116211963SAfshin.Ardakani@Sun.COM } 116311963SAfshin.Ardakani@Sun.COM 116411963SAfshin.Ardakani@Sun.COM /* 116511963SAfshin.Ardakani@Sun.COM * smb_rwx_rwupgrade 116611963SAfshin.Ardakani@Sun.COM */ 116711963SAfshin.Ardakani@Sun.COM krw_t 116811963SAfshin.Ardakani@Sun.COM smb_rwx_rwupgrade( 116911963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx) 117011963SAfshin.Ardakani@Sun.COM { 117111963SAfshin.Ardakani@Sun.COM if (rw_write_held(&rwx->rwx_lock)) { 117211963SAfshin.Ardakani@Sun.COM ASSERT(rw_owner(&rwx->rwx_lock) == curthread); 117311963SAfshin.Ardakani@Sun.COM return (RW_WRITER); 117411963SAfshin.Ardakani@Sun.COM } 117511963SAfshin.Ardakani@Sun.COM if (!rw_tryupgrade(&rwx->rwx_lock)) { 117611963SAfshin.Ardakani@Sun.COM rw_exit(&rwx->rwx_lock); 117711963SAfshin.Ardakani@Sun.COM rw_enter(&rwx->rwx_lock, RW_WRITER); 117811963SAfshin.Ardakani@Sun.COM } 117911963SAfshin.Ardakani@Sun.COM return (RW_READER); 118011963SAfshin.Ardakani@Sun.COM } 118111963SAfshin.Ardakani@Sun.COM 118211963SAfshin.Ardakani@Sun.COM /* 118311963SAfshin.Ardakani@Sun.COM * smb_rwx_rwrestore 118411963SAfshin.Ardakani@Sun.COM */ 118511963SAfshin.Ardakani@Sun.COM void 118611963SAfshin.Ardakani@Sun.COM smb_rwx_rwdowngrade( 118711963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx, 118811963SAfshin.Ardakani@Sun.COM krw_t mode) 118911963SAfshin.Ardakani@Sun.COM { 119011963SAfshin.Ardakani@Sun.COM ASSERT(rw_write_held(&rwx->rwx_lock)); 119111963SAfshin.Ardakani@Sun.COM ASSERT(rw_owner(&rwx->rwx_lock) == curthread); 119211963SAfshin.Ardakani@Sun.COM 119311963SAfshin.Ardakani@Sun.COM if (mode == RW_WRITER) { 119411963SAfshin.Ardakani@Sun.COM return; 119511963SAfshin.Ardakani@Sun.COM } 119611963SAfshin.Ardakani@Sun.COM ASSERT(mode == RW_READER); 119711963SAfshin.Ardakani@Sun.COM mutex_enter(&rwx->rwx_mutex); 119811963SAfshin.Ardakani@Sun.COM if (rwx->rwx_waiting) { 119911963SAfshin.Ardakani@Sun.COM rwx->rwx_waiting = B_FALSE; 120011963SAfshin.Ardakani@Sun.COM cv_broadcast(&rwx->rwx_cv); 120111963SAfshin.Ardakani@Sun.COM } 120211963SAfshin.Ardakani@Sun.COM mutex_exit(&rwx->rwx_mutex); 120311963SAfshin.Ardakani@Sun.COM rw_downgrade(&rwx->rwx_lock); 120411963SAfshin.Ardakani@Sun.COM } 120511963SAfshin.Ardakani@Sun.COM 120611963SAfshin.Ardakani@Sun.COM /* 120711963SAfshin.Ardakani@Sun.COM * smb_rwx_wait 120811963SAfshin.Ardakani@Sun.COM * 120911963SAfshin.Ardakani@Sun.COM * This function assumes the smb_rwx lock was enter in RW_READER or RW_WRITER 121011963SAfshin.Ardakani@Sun.COM * mode. It will: 121111963SAfshin.Ardakani@Sun.COM * 121211963SAfshin.Ardakani@Sun.COM * 1) release the lock and save its current mode. 121311963SAfshin.Ardakani@Sun.COM * 2) wait until the condition variable is signaled. This can happen for 121411963SAfshin.Ardakani@Sun.COM * 2 reasons: When a writer releases the lock or when the time out (if 121511963SAfshin.Ardakani@Sun.COM * provided) expires. 121611963SAfshin.Ardakani@Sun.COM * 3) re-acquire the lock in the mode saved in (1). 121711963SAfshin.Ardakani@Sun.COM */ 121811963SAfshin.Ardakani@Sun.COM int 121911963SAfshin.Ardakani@Sun.COM smb_rwx_rwwait( 122011963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx, 122111963SAfshin.Ardakani@Sun.COM clock_t timeout) 122211963SAfshin.Ardakani@Sun.COM { 122311963SAfshin.Ardakani@Sun.COM int rc; 122411963SAfshin.Ardakani@Sun.COM krw_t mode; 122511963SAfshin.Ardakani@Sun.COM 122611963SAfshin.Ardakani@Sun.COM mutex_enter(&rwx->rwx_mutex); 122711963SAfshin.Ardakani@Sun.COM rwx->rwx_waiting = B_TRUE; 122811963SAfshin.Ardakani@Sun.COM mutex_exit(&rwx->rwx_mutex); 122911963SAfshin.Ardakani@Sun.COM 123011963SAfshin.Ardakani@Sun.COM if (rw_write_held(&rwx->rwx_lock)) { 123111963SAfshin.Ardakani@Sun.COM ASSERT(rw_owner(&rwx->rwx_lock) == curthread); 123211963SAfshin.Ardakani@Sun.COM mode = RW_WRITER; 123311963SAfshin.Ardakani@Sun.COM } else { 123411963SAfshin.Ardakani@Sun.COM ASSERT(rw_read_held(&rwx->rwx_lock)); 123511963SAfshin.Ardakani@Sun.COM mode = RW_READER; 123611963SAfshin.Ardakani@Sun.COM } 123711963SAfshin.Ardakani@Sun.COM rw_exit(&rwx->rwx_lock); 123811963SAfshin.Ardakani@Sun.COM 123911963SAfshin.Ardakani@Sun.COM mutex_enter(&rwx->rwx_mutex); 124011963SAfshin.Ardakani@Sun.COM if (rwx->rwx_waiting) { 124111963SAfshin.Ardakani@Sun.COM if (timeout == -1) { 124211963SAfshin.Ardakani@Sun.COM rc = 1; 124311963SAfshin.Ardakani@Sun.COM cv_wait(&rwx->rwx_cv, &rwx->rwx_mutex); 124411963SAfshin.Ardakani@Sun.COM } else { 124511963SAfshin.Ardakani@Sun.COM rc = cv_reltimedwait(&rwx->rwx_cv, &rwx->rwx_mutex, 124611963SAfshin.Ardakani@Sun.COM timeout, TR_CLOCK_TICK); 124711963SAfshin.Ardakani@Sun.COM } 124811963SAfshin.Ardakani@Sun.COM } 124911963SAfshin.Ardakani@Sun.COM mutex_exit(&rwx->rwx_mutex); 125011963SAfshin.Ardakani@Sun.COM 125111963SAfshin.Ardakani@Sun.COM rw_enter(&rwx->rwx_lock, mode); 125211963SAfshin.Ardakani@Sun.COM return (rc); 125311963SAfshin.Ardakani@Sun.COM } 125411963SAfshin.Ardakani@Sun.COM 125511963SAfshin.Ardakani@Sun.COM /* 125611963SAfshin.Ardakani@Sun.COM * SMB ID mapping 125711963SAfshin.Ardakani@Sun.COM * 125811963SAfshin.Ardakani@Sun.COM * Solaris ID mapping service (aka Winchester) works with domain SIDs 125911963SAfshin.Ardakani@Sun.COM * and RIDs where domain SIDs are in string format. CIFS service works 126011963SAfshin.Ardakani@Sun.COM * with binary SIDs understandable by CIFS clients. A layer of SMB ID 126111963SAfshin.Ardakani@Sun.COM * mapping functions are implemeted to hide the SID conversion details 126211963SAfshin.Ardakani@Sun.COM * and also hide the handling of array of batch mapping requests. 126311963SAfshin.Ardakani@Sun.COM * 126411963SAfshin.Ardakani@Sun.COM * IMPORTANT NOTE The Winchester API requires a zone. Because CIFS server 126511963SAfshin.Ardakani@Sun.COM * currently only runs in the global zone the global zone is specified. 126611963SAfshin.Ardakani@Sun.COM * This needs to be fixed when the CIFS server supports zones. 126711963SAfshin.Ardakani@Sun.COM */ 126811963SAfshin.Ardakani@Sun.COM 126911963SAfshin.Ardakani@Sun.COM static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib); 127011963SAfshin.Ardakani@Sun.COM 127111963SAfshin.Ardakani@Sun.COM /* 127211963SAfshin.Ardakani@Sun.COM * smb_idmap_getid 127311963SAfshin.Ardakani@Sun.COM * 127411963SAfshin.Ardakani@Sun.COM * Maps the given Windows SID to a Solaris ID using the 127511963SAfshin.Ardakani@Sun.COM * simple mapping API. 127611963SAfshin.Ardakani@Sun.COM */ 127711963SAfshin.Ardakani@Sun.COM idmap_stat 127811963SAfshin.Ardakani@Sun.COM smb_idmap_getid(smb_sid_t *sid, uid_t *id, int *idtype) 127911963SAfshin.Ardakani@Sun.COM { 128011963SAfshin.Ardakani@Sun.COM smb_idmap_t sim; 128111963SAfshin.Ardakani@Sun.COM char sidstr[SMB_SID_STRSZ]; 128211963SAfshin.Ardakani@Sun.COM 128311963SAfshin.Ardakani@Sun.COM smb_sid_tostr(sid, sidstr); 128411963SAfshin.Ardakani@Sun.COM if (smb_sid_splitstr(sidstr, &sim.sim_rid) != 0) 128511963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_SID); 128611963SAfshin.Ardakani@Sun.COM sim.sim_domsid = sidstr; 128711963SAfshin.Ardakani@Sun.COM sim.sim_id = id; 128811963SAfshin.Ardakani@Sun.COM 128911963SAfshin.Ardakani@Sun.COM switch (*idtype) { 129011963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_USER: 129111963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getuidbysid(global_zone, sim.sim_domsid, 129211963SAfshin.Ardakani@Sun.COM sim.sim_rid, sim.sim_id); 129311963SAfshin.Ardakani@Sun.COM break; 129411963SAfshin.Ardakani@Sun.COM 129511963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUP: 129611963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getgidbysid(global_zone, sim.sim_domsid, 129711963SAfshin.Ardakani@Sun.COM sim.sim_rid, sim.sim_id); 129811963SAfshin.Ardakani@Sun.COM break; 129911963SAfshin.Ardakani@Sun.COM 130011963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_UNKNOWN: 130111963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getpidbysid(global_zone, sim.sim_domsid, 130211963SAfshin.Ardakani@Sun.COM sim.sim_rid, sim.sim_id, &sim.sim_idtype); 130311963SAfshin.Ardakani@Sun.COM break; 130411963SAfshin.Ardakani@Sun.COM 130511963SAfshin.Ardakani@Sun.COM default: 130611963SAfshin.Ardakani@Sun.COM ASSERT(0); 130711963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_ARG); 130811963SAfshin.Ardakani@Sun.COM } 130911963SAfshin.Ardakani@Sun.COM 131011963SAfshin.Ardakani@Sun.COM *idtype = sim.sim_idtype; 131111963SAfshin.Ardakani@Sun.COM 131211963SAfshin.Ardakani@Sun.COM return (sim.sim_stat); 131311963SAfshin.Ardakani@Sun.COM } 131411963SAfshin.Ardakani@Sun.COM 131511963SAfshin.Ardakani@Sun.COM /* 131611963SAfshin.Ardakani@Sun.COM * smb_idmap_getsid 131711963SAfshin.Ardakani@Sun.COM * 131811963SAfshin.Ardakani@Sun.COM * Maps the given Solaris ID to a Windows SID using the 131911963SAfshin.Ardakani@Sun.COM * simple mapping API. 132011963SAfshin.Ardakani@Sun.COM */ 132111963SAfshin.Ardakani@Sun.COM idmap_stat 132211963SAfshin.Ardakani@Sun.COM smb_idmap_getsid(uid_t id, int idtype, smb_sid_t **sid) 132311963SAfshin.Ardakani@Sun.COM { 132411963SAfshin.Ardakani@Sun.COM smb_idmap_t sim; 132511963SAfshin.Ardakani@Sun.COM 132611963SAfshin.Ardakani@Sun.COM switch (idtype) { 132711963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_USER: 132811963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getsidbyuid(global_zone, id, 132911963SAfshin.Ardakani@Sun.COM (const char **)&sim.sim_domsid, &sim.sim_rid); 133011963SAfshin.Ardakani@Sun.COM break; 133111963SAfshin.Ardakani@Sun.COM 133211963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUP: 133311963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getsidbygid(global_zone, id, 133411963SAfshin.Ardakani@Sun.COM (const char **)&sim.sim_domsid, &sim.sim_rid); 133511963SAfshin.Ardakani@Sun.COM break; 133611963SAfshin.Ardakani@Sun.COM 133711963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_EVERYONE: 133811963SAfshin.Ardakani@Sun.COM /* Everyone S-1-1-0 */ 133911963SAfshin.Ardakani@Sun.COM sim.sim_domsid = "S-1-1"; 134011963SAfshin.Ardakani@Sun.COM sim.sim_rid = 0; 134111963SAfshin.Ardakani@Sun.COM sim.sim_stat = IDMAP_SUCCESS; 134211963SAfshin.Ardakani@Sun.COM break; 134311963SAfshin.Ardakani@Sun.COM 134411963SAfshin.Ardakani@Sun.COM default: 134511963SAfshin.Ardakani@Sun.COM ASSERT(0); 134611963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_ARG); 134711963SAfshin.Ardakani@Sun.COM } 134811963SAfshin.Ardakani@Sun.COM 134911963SAfshin.Ardakani@Sun.COM if (sim.sim_stat != IDMAP_SUCCESS) 135011963SAfshin.Ardakani@Sun.COM return (sim.sim_stat); 135111963SAfshin.Ardakani@Sun.COM 135211963SAfshin.Ardakani@Sun.COM if (sim.sim_domsid == NULL) 135311963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_NOMAPPING); 135411963SAfshin.Ardakani@Sun.COM 135511963SAfshin.Ardakani@Sun.COM sim.sim_sid = smb_sid_fromstr(sim.sim_domsid); 135611963SAfshin.Ardakani@Sun.COM if (sim.sim_sid == NULL) 135711963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_INTERNAL); 135811963SAfshin.Ardakani@Sun.COM 135911963SAfshin.Ardakani@Sun.COM *sid = smb_sid_splice(sim.sim_sid, sim.sim_rid); 136011963SAfshin.Ardakani@Sun.COM smb_sid_free(sim.sim_sid); 136111963SAfshin.Ardakani@Sun.COM if (*sid == NULL) 136211963SAfshin.Ardakani@Sun.COM sim.sim_stat = IDMAP_ERR_INTERNAL; 136311963SAfshin.Ardakani@Sun.COM 136411963SAfshin.Ardakani@Sun.COM return (sim.sim_stat); 136511963SAfshin.Ardakani@Sun.COM } 136611963SAfshin.Ardakani@Sun.COM 136711963SAfshin.Ardakani@Sun.COM /* 136811963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_create 136911963SAfshin.Ardakani@Sun.COM * 137011963SAfshin.Ardakani@Sun.COM * Creates and initializes the context for batch ID mapping. 137111963SAfshin.Ardakani@Sun.COM */ 137211963SAfshin.Ardakani@Sun.COM idmap_stat 137311963SAfshin.Ardakani@Sun.COM smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags) 137411963SAfshin.Ardakani@Sun.COM { 137511963SAfshin.Ardakani@Sun.COM ASSERT(sib); 137611963SAfshin.Ardakani@Sun.COM 137711963SAfshin.Ardakani@Sun.COM bzero(sib, sizeof (smb_idmap_batch_t)); 137811963SAfshin.Ardakani@Sun.COM 137911963SAfshin.Ardakani@Sun.COM sib->sib_idmaph = kidmap_get_create(global_zone); 138011963SAfshin.Ardakani@Sun.COM 138111963SAfshin.Ardakani@Sun.COM sib->sib_flags = flags; 138211963SAfshin.Ardakani@Sun.COM sib->sib_nmap = nmap; 138311963SAfshin.Ardakani@Sun.COM sib->sib_size = nmap * sizeof (smb_idmap_t); 138411963SAfshin.Ardakani@Sun.COM sib->sib_maps = kmem_zalloc(sib->sib_size, KM_SLEEP); 138511963SAfshin.Ardakani@Sun.COM 138611963SAfshin.Ardakani@Sun.COM return (IDMAP_SUCCESS); 138711963SAfshin.Ardakani@Sun.COM } 138811963SAfshin.Ardakani@Sun.COM 138911963SAfshin.Ardakani@Sun.COM /* 139011963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_destroy 139111963SAfshin.Ardakani@Sun.COM * 139211963SAfshin.Ardakani@Sun.COM * Frees the batch ID mapping context. 139311963SAfshin.Ardakani@Sun.COM * If ID mapping is Solaris -> Windows it frees memories 139411963SAfshin.Ardakani@Sun.COM * allocated for binary SIDs. 139511963SAfshin.Ardakani@Sun.COM */ 139611963SAfshin.Ardakani@Sun.COM void 139711963SAfshin.Ardakani@Sun.COM smb_idmap_batch_destroy(smb_idmap_batch_t *sib) 139811963SAfshin.Ardakani@Sun.COM { 139911963SAfshin.Ardakani@Sun.COM char *domsid; 140011963SAfshin.Ardakani@Sun.COM int i; 140111963SAfshin.Ardakani@Sun.COM 140211963SAfshin.Ardakani@Sun.COM ASSERT(sib); 140311963SAfshin.Ardakani@Sun.COM ASSERT(sib->sib_maps); 140411963SAfshin.Ardakani@Sun.COM 140511963SAfshin.Ardakani@Sun.COM if (sib->sib_idmaph) 140611963SAfshin.Ardakani@Sun.COM kidmap_get_destroy(sib->sib_idmaph); 140711963SAfshin.Ardakani@Sun.COM 140811963SAfshin.Ardakani@Sun.COM if (sib->sib_flags & SMB_IDMAP_ID2SID) { 140911963SAfshin.Ardakani@Sun.COM /* 141011963SAfshin.Ardakani@Sun.COM * SIDs are allocated only when mapping 141111963SAfshin.Ardakani@Sun.COM * UID/GID to SIDs 141211963SAfshin.Ardakani@Sun.COM */ 141311963SAfshin.Ardakani@Sun.COM for (i = 0; i < sib->sib_nmap; i++) 141411963SAfshin.Ardakani@Sun.COM smb_sid_free(sib->sib_maps[i].sim_sid); 141511963SAfshin.Ardakani@Sun.COM } else if (sib->sib_flags & SMB_IDMAP_SID2ID) { 141611963SAfshin.Ardakani@Sun.COM /* 141711963SAfshin.Ardakani@Sun.COM * SID prefixes are allocated only when mapping 141811963SAfshin.Ardakani@Sun.COM * SIDs to UID/GID 141911963SAfshin.Ardakani@Sun.COM */ 142011963SAfshin.Ardakani@Sun.COM for (i = 0; i < sib->sib_nmap; i++) { 142111963SAfshin.Ardakani@Sun.COM domsid = sib->sib_maps[i].sim_domsid; 142211963SAfshin.Ardakani@Sun.COM if (domsid) 142311963SAfshin.Ardakani@Sun.COM smb_mem_free(domsid); 142411963SAfshin.Ardakani@Sun.COM } 142511963SAfshin.Ardakani@Sun.COM } 142611963SAfshin.Ardakani@Sun.COM 142711963SAfshin.Ardakani@Sun.COM if (sib->sib_size && sib->sib_maps) 142811963SAfshin.Ardakani@Sun.COM kmem_free(sib->sib_maps, sib->sib_size); 142911963SAfshin.Ardakani@Sun.COM } 143011963SAfshin.Ardakani@Sun.COM 143111963SAfshin.Ardakani@Sun.COM /* 143211963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_getid 143311963SAfshin.Ardakani@Sun.COM * 143411963SAfshin.Ardakani@Sun.COM * Queue a request to map the given SID to a UID or GID. 143511963SAfshin.Ardakani@Sun.COM * 143611963SAfshin.Ardakani@Sun.COM * sim->sim_id should point to variable that's supposed to 143711963SAfshin.Ardakani@Sun.COM * hold the returned UID/GID. This needs to be setup by caller 143811963SAfshin.Ardakani@Sun.COM * of this function. 143911963SAfshin.Ardakani@Sun.COM * 144011963SAfshin.Ardakani@Sun.COM * If requested ID type is known, it's passed as 'idtype', 144111963SAfshin.Ardakani@Sun.COM * if it's unknown it'll be returned in sim->sim_idtype. 144211963SAfshin.Ardakani@Sun.COM */ 144311963SAfshin.Ardakani@Sun.COM idmap_stat 144411963SAfshin.Ardakani@Sun.COM smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, 144511963SAfshin.Ardakani@Sun.COM smb_sid_t *sid, int idtype) 144611963SAfshin.Ardakani@Sun.COM { 144711963SAfshin.Ardakani@Sun.COM char strsid[SMB_SID_STRSZ]; 144811963SAfshin.Ardakani@Sun.COM idmap_stat idm_stat; 144911963SAfshin.Ardakani@Sun.COM 145011963SAfshin.Ardakani@Sun.COM ASSERT(idmaph); 145111963SAfshin.Ardakani@Sun.COM ASSERT(sim); 145211963SAfshin.Ardakani@Sun.COM ASSERT(sid); 145311963SAfshin.Ardakani@Sun.COM 145411963SAfshin.Ardakani@Sun.COM smb_sid_tostr(sid, strsid); 145511963SAfshin.Ardakani@Sun.COM if (smb_sid_splitstr(strsid, &sim->sim_rid) != 0) 145611963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_SID); 145711963SAfshin.Ardakani@Sun.COM sim->sim_domsid = smb_mem_strdup(strsid); 145811963SAfshin.Ardakani@Sun.COM 145911963SAfshin.Ardakani@Sun.COM switch (idtype) { 146011963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_USER: 146111963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getuidbysid(idmaph, sim->sim_domsid, 146211963SAfshin.Ardakani@Sun.COM sim->sim_rid, sim->sim_id, &sim->sim_stat); 146311963SAfshin.Ardakani@Sun.COM break; 146411963SAfshin.Ardakani@Sun.COM 146511963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUP: 146611963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getgidbysid(idmaph, sim->sim_domsid, 146711963SAfshin.Ardakani@Sun.COM sim->sim_rid, sim->sim_id, &sim->sim_stat); 146811963SAfshin.Ardakani@Sun.COM break; 146911963SAfshin.Ardakani@Sun.COM 147011963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_UNKNOWN: 147111963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getpidbysid(idmaph, sim->sim_domsid, 147211963SAfshin.Ardakani@Sun.COM sim->sim_rid, sim->sim_id, &sim->sim_idtype, 147311963SAfshin.Ardakani@Sun.COM &sim->sim_stat); 147411963SAfshin.Ardakani@Sun.COM break; 147511963SAfshin.Ardakani@Sun.COM 147611963SAfshin.Ardakani@Sun.COM default: 147711963SAfshin.Ardakani@Sun.COM ASSERT(0); 147811963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_ARG); 147911963SAfshin.Ardakani@Sun.COM } 148011963SAfshin.Ardakani@Sun.COM 148111963SAfshin.Ardakani@Sun.COM return (idm_stat); 148211963SAfshin.Ardakani@Sun.COM } 148311963SAfshin.Ardakani@Sun.COM 148411963SAfshin.Ardakani@Sun.COM /* 148511963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_getsid 148611963SAfshin.Ardakani@Sun.COM * 148711963SAfshin.Ardakani@Sun.COM * Queue a request to map the given UID/GID to a SID. 148811963SAfshin.Ardakani@Sun.COM * 148911963SAfshin.Ardakani@Sun.COM * sim->sim_domsid and sim->sim_rid will contain the mapping 149011963SAfshin.Ardakani@Sun.COM * result upon successful process of the batched request. 149111963SAfshin.Ardakani@Sun.COM */ 149211963SAfshin.Ardakani@Sun.COM idmap_stat 149311963SAfshin.Ardakani@Sun.COM smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, 149411963SAfshin.Ardakani@Sun.COM uid_t id, int idtype) 149511963SAfshin.Ardakani@Sun.COM { 149611963SAfshin.Ardakani@Sun.COM idmap_stat idm_stat; 149711963SAfshin.Ardakani@Sun.COM 149811963SAfshin.Ardakani@Sun.COM switch (idtype) { 149911963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_USER: 150011963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getsidbyuid(idmaph, id, 150111963SAfshin.Ardakani@Sun.COM (const char **)&sim->sim_domsid, &sim->sim_rid, 150211963SAfshin.Ardakani@Sun.COM &sim->sim_stat); 150311963SAfshin.Ardakani@Sun.COM break; 150411963SAfshin.Ardakani@Sun.COM 150511963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUP: 150611963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getsidbygid(idmaph, id, 150711963SAfshin.Ardakani@Sun.COM (const char **)&sim->sim_domsid, &sim->sim_rid, 150811963SAfshin.Ardakani@Sun.COM &sim->sim_stat); 150911963SAfshin.Ardakani@Sun.COM break; 151011963SAfshin.Ardakani@Sun.COM 151111963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_OWNERAT: 151211963SAfshin.Ardakani@Sun.COM /* Current Owner S-1-5-32-766 */ 151311963SAfshin.Ardakani@Sun.COM sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR; 151411963SAfshin.Ardakani@Sun.COM sim->sim_rid = SECURITY_CURRENT_OWNER_RID; 151511963SAfshin.Ardakani@Sun.COM sim->sim_stat = IDMAP_SUCCESS; 151611963SAfshin.Ardakani@Sun.COM idm_stat = IDMAP_SUCCESS; 151711963SAfshin.Ardakani@Sun.COM break; 151811963SAfshin.Ardakani@Sun.COM 151911963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUPAT: 152011963SAfshin.Ardakani@Sun.COM /* Current Group S-1-5-32-767 */ 152111963SAfshin.Ardakani@Sun.COM sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR; 152211963SAfshin.Ardakani@Sun.COM sim->sim_rid = SECURITY_CURRENT_GROUP_RID; 152311963SAfshin.Ardakani@Sun.COM sim->sim_stat = IDMAP_SUCCESS; 152411963SAfshin.Ardakani@Sun.COM idm_stat = IDMAP_SUCCESS; 152511963SAfshin.Ardakani@Sun.COM break; 152611963SAfshin.Ardakani@Sun.COM 152711963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_EVERYONE: 152811963SAfshin.Ardakani@Sun.COM /* Everyone S-1-1-0 */ 152911963SAfshin.Ardakani@Sun.COM sim->sim_domsid = NT_WORLD_AUTH_SIDSTR; 153011963SAfshin.Ardakani@Sun.COM sim->sim_rid = 0; 153111963SAfshin.Ardakani@Sun.COM sim->sim_stat = IDMAP_SUCCESS; 153211963SAfshin.Ardakani@Sun.COM idm_stat = IDMAP_SUCCESS; 153311963SAfshin.Ardakani@Sun.COM break; 153411963SAfshin.Ardakani@Sun.COM 153511963SAfshin.Ardakani@Sun.COM default: 153611963SAfshin.Ardakani@Sun.COM ASSERT(0); 153711963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_ARG); 153811963SAfshin.Ardakani@Sun.COM } 153911963SAfshin.Ardakani@Sun.COM 154011963SAfshin.Ardakani@Sun.COM return (idm_stat); 154111963SAfshin.Ardakani@Sun.COM } 154211963SAfshin.Ardakani@Sun.COM 154311963SAfshin.Ardakani@Sun.COM /* 154411963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_binsid 154511963SAfshin.Ardakani@Sun.COM * 154611963SAfshin.Ardakani@Sun.COM * Convert sidrids to binary sids 154711963SAfshin.Ardakani@Sun.COM * 154811963SAfshin.Ardakani@Sun.COM * Returns 0 if successful and non-zero upon failure. 154911963SAfshin.Ardakani@Sun.COM */ 155011963SAfshin.Ardakani@Sun.COM static int 155111963SAfshin.Ardakani@Sun.COM smb_idmap_batch_binsid(smb_idmap_batch_t *sib) 155211963SAfshin.Ardakani@Sun.COM { 155311963SAfshin.Ardakani@Sun.COM smb_sid_t *sid; 155411963SAfshin.Ardakani@Sun.COM smb_idmap_t *sim; 155511963SAfshin.Ardakani@Sun.COM int i; 155611963SAfshin.Ardakani@Sun.COM 155711963SAfshin.Ardakani@Sun.COM if (sib->sib_flags & SMB_IDMAP_SID2ID) 155811963SAfshin.Ardakani@Sun.COM /* This operation is not required */ 155911963SAfshin.Ardakani@Sun.COM return (0); 156011963SAfshin.Ardakani@Sun.COM 156111963SAfshin.Ardakani@Sun.COM sim = sib->sib_maps; 156211963SAfshin.Ardakani@Sun.COM for (i = 0; i < sib->sib_nmap; sim++, i++) { 156311963SAfshin.Ardakani@Sun.COM ASSERT(sim->sim_domsid); 156411963SAfshin.Ardakani@Sun.COM if (sim->sim_domsid == NULL) 156511963SAfshin.Ardakani@Sun.COM return (1); 156611963SAfshin.Ardakani@Sun.COM 156711963SAfshin.Ardakani@Sun.COM if ((sid = smb_sid_fromstr(sim->sim_domsid)) == NULL) 156811963SAfshin.Ardakani@Sun.COM return (1); 156911963SAfshin.Ardakani@Sun.COM 157011963SAfshin.Ardakani@Sun.COM sim->sim_sid = smb_sid_splice(sid, sim->sim_rid); 157111963SAfshin.Ardakani@Sun.COM smb_sid_free(sid); 157211963SAfshin.Ardakani@Sun.COM } 157311963SAfshin.Ardakani@Sun.COM 157411963SAfshin.Ardakani@Sun.COM return (0); 157511963SAfshin.Ardakani@Sun.COM } 157611963SAfshin.Ardakani@Sun.COM 157711963SAfshin.Ardakani@Sun.COM /* 157811963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_getmappings 157911963SAfshin.Ardakani@Sun.COM * 158011963SAfshin.Ardakani@Sun.COM * trigger ID mapping service to get the mappings for queued 158111963SAfshin.Ardakani@Sun.COM * requests. 158211963SAfshin.Ardakani@Sun.COM * 158311963SAfshin.Ardakani@Sun.COM * Checks the result of all the queued requests. 158411963SAfshin.Ardakani@Sun.COM * If this is a Solaris -> Windows mapping it generates 158511963SAfshin.Ardakani@Sun.COM * binary SIDs from returned (domsid, rid) pairs. 158611963SAfshin.Ardakani@Sun.COM */ 158711963SAfshin.Ardakani@Sun.COM idmap_stat 158811963SAfshin.Ardakani@Sun.COM smb_idmap_batch_getmappings(smb_idmap_batch_t *sib) 158911963SAfshin.Ardakani@Sun.COM { 159011963SAfshin.Ardakani@Sun.COM idmap_stat idm_stat = IDMAP_SUCCESS; 159111963SAfshin.Ardakani@Sun.COM int i; 159211963SAfshin.Ardakani@Sun.COM 159311963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_get_mappings(sib->sib_idmaph); 159411963SAfshin.Ardakani@Sun.COM if (idm_stat != IDMAP_SUCCESS) 159511963SAfshin.Ardakani@Sun.COM return (idm_stat); 159611963SAfshin.Ardakani@Sun.COM 159711963SAfshin.Ardakani@Sun.COM /* 159811963SAfshin.Ardakani@Sun.COM * Check the status for all the queued requests 159911963SAfshin.Ardakani@Sun.COM */ 160011963SAfshin.Ardakani@Sun.COM for (i = 0; i < sib->sib_nmap; i++) { 160111963SAfshin.Ardakani@Sun.COM if (sib->sib_maps[i].sim_stat != IDMAP_SUCCESS) 160211963SAfshin.Ardakani@Sun.COM return (sib->sib_maps[i].sim_stat); 160311963SAfshin.Ardakani@Sun.COM } 160411963SAfshin.Ardakani@Sun.COM 160511963SAfshin.Ardakani@Sun.COM if (smb_idmap_batch_binsid(sib) != 0) 160611963SAfshin.Ardakani@Sun.COM idm_stat = IDMAP_ERR_OTHER; 160711963SAfshin.Ardakani@Sun.COM 160811963SAfshin.Ardakani@Sun.COM return (idm_stat); 160911963SAfshin.Ardakani@Sun.COM } 161011963SAfshin.Ardakani@Sun.COM 161111963SAfshin.Ardakani@Sun.COM uint64_t 161211963SAfshin.Ardakani@Sun.COM smb_time_unix_to_nt(timestruc_t *unix_time) 161311963SAfshin.Ardakani@Sun.COM { 161411963SAfshin.Ardakani@Sun.COM uint64_t nt_time; 161511963SAfshin.Ardakani@Sun.COM 161611963SAfshin.Ardakani@Sun.COM if ((unix_time->tv_sec == 0) && (unix_time->tv_nsec == 0)) 161711963SAfshin.Ardakani@Sun.COM return (0); 161811963SAfshin.Ardakani@Sun.COM 161911963SAfshin.Ardakani@Sun.COM nt_time = unix_time->tv_sec; 162011963SAfshin.Ardakani@Sun.COM nt_time *= 10000000; /* seconds to 100ns */ 162111963SAfshin.Ardakani@Sun.COM nt_time += unix_time->tv_nsec / 100; 162211963SAfshin.Ardakani@Sun.COM return (nt_time + NT_TIME_BIAS); 162311963SAfshin.Ardakani@Sun.COM } 162411963SAfshin.Ardakani@Sun.COM 162511963SAfshin.Ardakani@Sun.COM void 162611963SAfshin.Ardakani@Sun.COM smb_time_nt_to_unix(uint64_t nt_time, timestruc_t *unix_time) 162711963SAfshin.Ardakani@Sun.COM { 162811963SAfshin.Ardakani@Sun.COM uint32_t seconds; 162911963SAfshin.Ardakani@Sun.COM 163011963SAfshin.Ardakani@Sun.COM ASSERT(unix_time); 163111963SAfshin.Ardakani@Sun.COM 163211963SAfshin.Ardakani@Sun.COM if ((nt_time == 0) || (nt_time == -1)) { 163311963SAfshin.Ardakani@Sun.COM unix_time->tv_sec = 0; 163411963SAfshin.Ardakani@Sun.COM unix_time->tv_nsec = 0; 163511963SAfshin.Ardakani@Sun.COM return; 163611963SAfshin.Ardakani@Sun.COM } 163711963SAfshin.Ardakani@Sun.COM 163811963SAfshin.Ardakani@Sun.COM nt_time -= NT_TIME_BIAS; 163911963SAfshin.Ardakani@Sun.COM seconds = nt_time / 10000000; 164011963SAfshin.Ardakani@Sun.COM unix_time->tv_sec = seconds; 164111963SAfshin.Ardakani@Sun.COM unix_time->tv_nsec = (nt_time % 10000000) * 100; 164211963SAfshin.Ardakani@Sun.COM } 164311963SAfshin.Ardakani@Sun.COM 164411963SAfshin.Ardakani@Sun.COM /* 164511963SAfshin.Ardakani@Sun.COM * smb_time_gmt_to_local, smb_time_local_to_gmt 164611963SAfshin.Ardakani@Sun.COM * 164711963SAfshin.Ardakani@Sun.COM * Apply the gmt offset to convert between local time and gmt 164811963SAfshin.Ardakani@Sun.COM */ 164911963SAfshin.Ardakani@Sun.COM int32_t 165011963SAfshin.Ardakani@Sun.COM smb_time_gmt_to_local(smb_request_t *sr, int32_t gmt) 165111963SAfshin.Ardakani@Sun.COM { 165211963SAfshin.Ardakani@Sun.COM if ((gmt == 0) || (gmt == -1)) 165311963SAfshin.Ardakani@Sun.COM return (0); 165411963SAfshin.Ardakani@Sun.COM 165511963SAfshin.Ardakani@Sun.COM return (gmt - sr->sr_gmtoff); 165611963SAfshin.Ardakani@Sun.COM } 165711963SAfshin.Ardakani@Sun.COM 165811963SAfshin.Ardakani@Sun.COM int32_t 165911963SAfshin.Ardakani@Sun.COM smb_time_local_to_gmt(smb_request_t *sr, int32_t local) 166011963SAfshin.Ardakani@Sun.COM { 166111963SAfshin.Ardakani@Sun.COM if ((local == 0) || (local == -1)) 166211963SAfshin.Ardakani@Sun.COM return (0); 166311963SAfshin.Ardakani@Sun.COM 166411963SAfshin.Ardakani@Sun.COM return (local + sr->sr_gmtoff); 166511963SAfshin.Ardakani@Sun.COM } 166611963SAfshin.Ardakani@Sun.COM 166711963SAfshin.Ardakani@Sun.COM 166811963SAfshin.Ardakani@Sun.COM /* 166911963SAfshin.Ardakani@Sun.COM * smb_time_dos_to_unix 167011963SAfshin.Ardakani@Sun.COM * 167111963SAfshin.Ardakani@Sun.COM * Convert SMB_DATE & SMB_TIME values to a unix timestamp. 167211963SAfshin.Ardakani@Sun.COM * 167311963SAfshin.Ardakani@Sun.COM * A date/time field of 0 means that that server file system 167411963SAfshin.Ardakani@Sun.COM * assigned value need not be changed. The behaviour when the 167511963SAfshin.Ardakani@Sun.COM * date/time field is set to -1 is not documented but is 167611963SAfshin.Ardakani@Sun.COM * generally treated like 0. 167711963SAfshin.Ardakani@Sun.COM * If date or time is 0 or -1 the unix time is returned as 0 167811963SAfshin.Ardakani@Sun.COM * so that the caller can identify and handle this special case. 167911963SAfshin.Ardakani@Sun.COM */ 168011963SAfshin.Ardakani@Sun.COM int32_t 168111963SAfshin.Ardakani@Sun.COM smb_time_dos_to_unix(int16_t date, int16_t time) 168211963SAfshin.Ardakani@Sun.COM { 168311963SAfshin.Ardakani@Sun.COM struct tm atm; 168411963SAfshin.Ardakani@Sun.COM 168511963SAfshin.Ardakani@Sun.COM if (((date == 0) || (time == 0)) || 168611963SAfshin.Ardakani@Sun.COM ((date == -1) || (time == -1))) { 168711963SAfshin.Ardakani@Sun.COM return (0); 168811963SAfshin.Ardakani@Sun.COM } 168911963SAfshin.Ardakani@Sun.COM 169011963SAfshin.Ardakani@Sun.COM atm.tm_year = ((date >> 9) & 0x3F) + 80; 169111963SAfshin.Ardakani@Sun.COM atm.tm_mon = ((date >> 5) & 0x0F) - 1; 169211963SAfshin.Ardakani@Sun.COM atm.tm_mday = ((date >> 0) & 0x1F); 169311963SAfshin.Ardakani@Sun.COM atm.tm_hour = ((time >> 11) & 0x1F); 169411963SAfshin.Ardakani@Sun.COM atm.tm_min = ((time >> 5) & 0x3F); 169511963SAfshin.Ardakani@Sun.COM atm.tm_sec = ((time >> 0) & 0x1F) << 1; 169611963SAfshin.Ardakani@Sun.COM 169711963SAfshin.Ardakani@Sun.COM return (smb_timegm(&atm)); 169811963SAfshin.Ardakani@Sun.COM } 169911963SAfshin.Ardakani@Sun.COM 170011963SAfshin.Ardakani@Sun.COM void 170111963SAfshin.Ardakani@Sun.COM smb_time_unix_to_dos(int32_t ux_time, int16_t *date_p, int16_t *time_p) 170211963SAfshin.Ardakani@Sun.COM { 170311963SAfshin.Ardakani@Sun.COM struct tm atm; 170411963SAfshin.Ardakani@Sun.COM int i; 170511963SAfshin.Ardakani@Sun.COM time_t tmp_time; 170611963SAfshin.Ardakani@Sun.COM 170711963SAfshin.Ardakani@Sun.COM if (ux_time == 0) { 170811963SAfshin.Ardakani@Sun.COM *date_p = 0; 170911963SAfshin.Ardakani@Sun.COM *time_p = 0; 171011963SAfshin.Ardakani@Sun.COM return; 171111963SAfshin.Ardakani@Sun.COM } 171211963SAfshin.Ardakani@Sun.COM 171311963SAfshin.Ardakani@Sun.COM tmp_time = (time_t)ux_time; 171411963SAfshin.Ardakani@Sun.COM (void) smb_gmtime_r(&tmp_time, &atm); 171511963SAfshin.Ardakani@Sun.COM 171611963SAfshin.Ardakani@Sun.COM if (date_p) { 171711963SAfshin.Ardakani@Sun.COM i = 0; 171811963SAfshin.Ardakani@Sun.COM i += atm.tm_year - 80; 171911963SAfshin.Ardakani@Sun.COM i <<= 4; 172011963SAfshin.Ardakani@Sun.COM i += atm.tm_mon + 1; 172111963SAfshin.Ardakani@Sun.COM i <<= 5; 172211963SAfshin.Ardakani@Sun.COM i += atm.tm_mday; 172311963SAfshin.Ardakani@Sun.COM 172411963SAfshin.Ardakani@Sun.COM *date_p = (short)i; 172511963SAfshin.Ardakani@Sun.COM } 172611963SAfshin.Ardakani@Sun.COM if (time_p) { 172711963SAfshin.Ardakani@Sun.COM i = 0; 172811963SAfshin.Ardakani@Sun.COM i += atm.tm_hour; 172911963SAfshin.Ardakani@Sun.COM i <<= 6; 173011963SAfshin.Ardakani@Sun.COM i += atm.tm_min; 173111963SAfshin.Ardakani@Sun.COM i <<= 5; 173211963SAfshin.Ardakani@Sun.COM i += atm.tm_sec >> 1; 173311963SAfshin.Ardakani@Sun.COM 173411963SAfshin.Ardakani@Sun.COM *time_p = (short)i; 173511963SAfshin.Ardakani@Sun.COM } 173611963SAfshin.Ardakani@Sun.COM } 173711963SAfshin.Ardakani@Sun.COM 173811963SAfshin.Ardakani@Sun.COM 173911963SAfshin.Ardakani@Sun.COM /* 174011963SAfshin.Ardakani@Sun.COM * smb_gmtime_r 174111963SAfshin.Ardakani@Sun.COM * 174211963SAfshin.Ardakani@Sun.COM * Thread-safe version of smb_gmtime. Returns a null pointer if either 174311963SAfshin.Ardakani@Sun.COM * input parameter is a null pointer. Otherwise returns a pointer 174411963SAfshin.Ardakani@Sun.COM * to result. 174511963SAfshin.Ardakani@Sun.COM * 174611963SAfshin.Ardakani@Sun.COM * Day of the week calculation: the Epoch was a thursday. 174711963SAfshin.Ardakani@Sun.COM * 174811963SAfshin.Ardakani@Sun.COM * There are no timezone corrections so tm_isdst and tm_gmtoff are 174911963SAfshin.Ardakani@Sun.COM * always zero, and the zone is always WET. 175011963SAfshin.Ardakani@Sun.COM */ 175111963SAfshin.Ardakani@Sun.COM struct tm * 175211963SAfshin.Ardakani@Sun.COM smb_gmtime_r(time_t *clock, struct tm *result) 175311963SAfshin.Ardakani@Sun.COM { 175411963SAfshin.Ardakani@Sun.COM time_t tsec; 175511963SAfshin.Ardakani@Sun.COM int year; 175611963SAfshin.Ardakani@Sun.COM int month; 175711963SAfshin.Ardakani@Sun.COM int sec_per_month; 175811963SAfshin.Ardakani@Sun.COM 175911963SAfshin.Ardakani@Sun.COM if (clock == 0 || result == 0) 176011963SAfshin.Ardakani@Sun.COM return (0); 176111963SAfshin.Ardakani@Sun.COM 176211963SAfshin.Ardakani@Sun.COM bzero(result, sizeof (struct tm)); 176311963SAfshin.Ardakani@Sun.COM tsec = *clock; 176411963SAfshin.Ardakani@Sun.COM tsec -= tzh_leapcnt; 176511963SAfshin.Ardakani@Sun.COM 176611963SAfshin.Ardakani@Sun.COM result->tm_wday = tsec / SECSPERDAY; 176711963SAfshin.Ardakani@Sun.COM result->tm_wday = (result->tm_wday + TM_THURSDAY) % DAYSPERWEEK; 176811963SAfshin.Ardakani@Sun.COM 176911963SAfshin.Ardakani@Sun.COM year = EPOCH_YEAR; 177011963SAfshin.Ardakani@Sun.COM while (tsec >= (isleap(year) ? (SECSPERDAY * DAYSPERLYEAR) : 177111963SAfshin.Ardakani@Sun.COM (SECSPERDAY * DAYSPERNYEAR))) { 177211963SAfshin.Ardakani@Sun.COM if (isleap(year)) 177311963SAfshin.Ardakani@Sun.COM tsec -= SECSPERDAY * DAYSPERLYEAR; 177411963SAfshin.Ardakani@Sun.COM else 177511963SAfshin.Ardakani@Sun.COM tsec -= SECSPERDAY * DAYSPERNYEAR; 177611963SAfshin.Ardakani@Sun.COM 177711963SAfshin.Ardakani@Sun.COM ++year; 177811963SAfshin.Ardakani@Sun.COM } 177911963SAfshin.Ardakani@Sun.COM 178011963SAfshin.Ardakani@Sun.COM result->tm_year = year - TM_YEAR_BASE; 178111963SAfshin.Ardakani@Sun.COM result->tm_yday = tsec / SECSPERDAY; 178211963SAfshin.Ardakani@Sun.COM 178311963SAfshin.Ardakani@Sun.COM for (month = TM_JANUARY; month <= TM_DECEMBER; ++month) { 178411963SAfshin.Ardakani@Sun.COM sec_per_month = days_in_month[month] * SECSPERDAY; 178511963SAfshin.Ardakani@Sun.COM 178611963SAfshin.Ardakani@Sun.COM if (month == TM_FEBRUARY && isleap(year)) 178711963SAfshin.Ardakani@Sun.COM sec_per_month += SECSPERDAY; 178811963SAfshin.Ardakani@Sun.COM 178911963SAfshin.Ardakani@Sun.COM if (tsec < sec_per_month) 179011963SAfshin.Ardakani@Sun.COM break; 179111963SAfshin.Ardakani@Sun.COM 179211963SAfshin.Ardakani@Sun.COM tsec -= sec_per_month; 179311963SAfshin.Ardakani@Sun.COM } 179411963SAfshin.Ardakani@Sun.COM 179511963SAfshin.Ardakani@Sun.COM result->tm_mon = month; 179611963SAfshin.Ardakani@Sun.COM result->tm_mday = (tsec / SECSPERDAY) + 1; 179711963SAfshin.Ardakani@Sun.COM tsec %= SECSPERDAY; 179811963SAfshin.Ardakani@Sun.COM result->tm_sec = tsec % 60; 179911963SAfshin.Ardakani@Sun.COM tsec /= 60; 180011963SAfshin.Ardakani@Sun.COM result->tm_min = tsec % 60; 180111963SAfshin.Ardakani@Sun.COM tsec /= 60; 180211963SAfshin.Ardakani@Sun.COM result->tm_hour = (int)tsec; 180311963SAfshin.Ardakani@Sun.COM 180411963SAfshin.Ardakani@Sun.COM return (result); 180511963SAfshin.Ardakani@Sun.COM } 180611963SAfshin.Ardakani@Sun.COM 180711963SAfshin.Ardakani@Sun.COM 180811963SAfshin.Ardakani@Sun.COM /* 180911963SAfshin.Ardakani@Sun.COM * smb_timegm 181011963SAfshin.Ardakani@Sun.COM * 181111963SAfshin.Ardakani@Sun.COM * Converts the broken-down time in tm to a time value, i.e. the number 181211963SAfshin.Ardakani@Sun.COM * of seconds since the Epoch (00:00:00 UTC, January 1, 1970). This is 181311963SAfshin.Ardakani@Sun.COM * not a POSIX or ANSI function. Per the man page, the input values of 181411963SAfshin.Ardakani@Sun.COM * tm_wday and tm_yday are ignored and, as the input data is assumed to 181511963SAfshin.Ardakani@Sun.COM * represent GMT, we force tm_isdst and tm_gmtoff to 0. 181611963SAfshin.Ardakani@Sun.COM * 181711963SAfshin.Ardakani@Sun.COM * Before returning the clock time, we use smb_gmtime_r to set up tm_wday 181811963SAfshin.Ardakani@Sun.COM * and tm_yday, and bring the other fields within normal range. I don't 181911963SAfshin.Ardakani@Sun.COM * think this is really how it should be done but it's convenient for 182011963SAfshin.Ardakani@Sun.COM * now. 182111963SAfshin.Ardakani@Sun.COM */ 182211963SAfshin.Ardakani@Sun.COM time_t 182311963SAfshin.Ardakani@Sun.COM smb_timegm(struct tm *tm) 182411963SAfshin.Ardakani@Sun.COM { 182511963SAfshin.Ardakani@Sun.COM time_t tsec; 182611963SAfshin.Ardakani@Sun.COM int dd; 182711963SAfshin.Ardakani@Sun.COM int mm; 182811963SAfshin.Ardakani@Sun.COM int yy; 182911963SAfshin.Ardakani@Sun.COM int year; 183011963SAfshin.Ardakani@Sun.COM 183111963SAfshin.Ardakani@Sun.COM if (tm == 0) 183211963SAfshin.Ardakani@Sun.COM return (-1); 183311963SAfshin.Ardakani@Sun.COM 183411963SAfshin.Ardakani@Sun.COM year = tm->tm_year + TM_YEAR_BASE; 183511963SAfshin.Ardakani@Sun.COM tsec = tzh_leapcnt; 183611963SAfshin.Ardakani@Sun.COM 183711963SAfshin.Ardakani@Sun.COM for (yy = EPOCH_YEAR; yy < year; ++yy) { 183811963SAfshin.Ardakani@Sun.COM if (isleap(yy)) 183911963SAfshin.Ardakani@Sun.COM tsec += SECSPERDAY * DAYSPERLYEAR; 184011963SAfshin.Ardakani@Sun.COM else 184111963SAfshin.Ardakani@Sun.COM tsec += SECSPERDAY * DAYSPERNYEAR; 184211963SAfshin.Ardakani@Sun.COM } 184311963SAfshin.Ardakani@Sun.COM 184411963SAfshin.Ardakani@Sun.COM for (mm = TM_JANUARY; mm < tm->tm_mon; ++mm) { 184511963SAfshin.Ardakani@Sun.COM dd = days_in_month[mm] * SECSPERDAY; 184611963SAfshin.Ardakani@Sun.COM 184711963SAfshin.Ardakani@Sun.COM if (mm == TM_FEBRUARY && isleap(year)) 184811963SAfshin.Ardakani@Sun.COM dd += SECSPERDAY; 184911963SAfshin.Ardakani@Sun.COM 185011963SAfshin.Ardakani@Sun.COM tsec += dd; 185111963SAfshin.Ardakani@Sun.COM } 185211963SAfshin.Ardakani@Sun.COM 185311963SAfshin.Ardakani@Sun.COM tsec += (tm->tm_mday - 1) * SECSPERDAY; 185411963SAfshin.Ardakani@Sun.COM tsec += tm->tm_sec; 185511963SAfshin.Ardakani@Sun.COM tsec += tm->tm_min * SECSPERMIN; 185611963SAfshin.Ardakani@Sun.COM tsec += tm->tm_hour * SECSPERHOUR; 185711963SAfshin.Ardakani@Sun.COM 185811963SAfshin.Ardakani@Sun.COM tm->tm_isdst = 0; 185911963SAfshin.Ardakani@Sun.COM (void) smb_gmtime_r(&tsec, tm); 186011963SAfshin.Ardakani@Sun.COM return (tsec); 186111963SAfshin.Ardakani@Sun.COM } 186211963SAfshin.Ardakani@Sun.COM 186311963SAfshin.Ardakani@Sun.COM /* 186411963SAfshin.Ardakani@Sun.COM * smb_pad_align 186511963SAfshin.Ardakani@Sun.COM * 186611963SAfshin.Ardakani@Sun.COM * Returns the number of bytes required to pad an offset to the 186711963SAfshin.Ardakani@Sun.COM * specified alignment. 186811963SAfshin.Ardakani@Sun.COM */ 186911963SAfshin.Ardakani@Sun.COM uint32_t 187011963SAfshin.Ardakani@Sun.COM smb_pad_align(uint32_t offset, uint32_t align) 187111963SAfshin.Ardakani@Sun.COM { 187211963SAfshin.Ardakani@Sun.COM uint32_t pad = offset % align; 187311963SAfshin.Ardakani@Sun.COM 187411963SAfshin.Ardakani@Sun.COM if (pad != 0) 187511963SAfshin.Ardakani@Sun.COM pad = align - pad; 187611963SAfshin.Ardakani@Sun.COM 187711963SAfshin.Ardakani@Sun.COM return (pad); 187811963SAfshin.Ardakani@Sun.COM } 187911963SAfshin.Ardakani@Sun.COM 188011963SAfshin.Ardakani@Sun.COM /* 188111963SAfshin.Ardakani@Sun.COM * smb_panic 188211963SAfshin.Ardakani@Sun.COM * 188311963SAfshin.Ardakani@Sun.COM * Logs the file name, function name and line number passed in and panics the 188411963SAfshin.Ardakani@Sun.COM * system. 188511963SAfshin.Ardakani@Sun.COM */ 188611963SAfshin.Ardakani@Sun.COM void 188711963SAfshin.Ardakani@Sun.COM smb_panic(char *file, const char *func, int line) 188811963SAfshin.Ardakani@Sun.COM { 188911963SAfshin.Ardakani@Sun.COM cmn_err(CE_PANIC, "%s:%s:%d\n", file, func, line); 189011963SAfshin.Ardakani@Sun.COM } 1891*12508Samw@Sun.COM 1892*12508Samw@Sun.COM /* 1893*12508Samw@Sun.COM * Creates an AVL tree and initializes the given smb_avl_t 1894*12508Samw@Sun.COM * structure using the passed args 1895*12508Samw@Sun.COM */ 1896*12508Samw@Sun.COM void 1897*12508Samw@Sun.COM smb_avl_create(smb_avl_t *avl, size_t size, size_t offset, smb_avl_nops_t *ops) 1898*12508Samw@Sun.COM { 1899*12508Samw@Sun.COM ASSERT(avl); 1900*12508Samw@Sun.COM ASSERT(ops); 1901*12508Samw@Sun.COM 1902*12508Samw@Sun.COM rw_init(&avl->avl_lock, NULL, RW_DEFAULT, NULL); 1903*12508Samw@Sun.COM mutex_init(&avl->avl_mutex, NULL, MUTEX_DEFAULT, NULL); 1904*12508Samw@Sun.COM 1905*12508Samw@Sun.COM avl->avl_nops = ops; 1906*12508Samw@Sun.COM avl->avl_state = SMB_AVL_STATE_READY; 1907*12508Samw@Sun.COM avl->avl_refcnt = 0; 1908*12508Samw@Sun.COM (void) random_get_pseudo_bytes((uint8_t *)&avl->avl_sequence, 1909*12508Samw@Sun.COM sizeof (uint32_t)); 1910*12508Samw@Sun.COM 1911*12508Samw@Sun.COM avl_create(&avl->avl_tree, ops->avln_cmp, size, offset); 1912*12508Samw@Sun.COM } 1913*12508Samw@Sun.COM 1914*12508Samw@Sun.COM /* 1915*12508Samw@Sun.COM * Destroys the specified AVL tree. 1916*12508Samw@Sun.COM * It waits for all the in-flight operations to finish 1917*12508Samw@Sun.COM * before destroying the AVL. 1918*12508Samw@Sun.COM */ 1919*12508Samw@Sun.COM void 1920*12508Samw@Sun.COM smb_avl_destroy(smb_avl_t *avl) 1921*12508Samw@Sun.COM { 1922*12508Samw@Sun.COM void *cookie = NULL; 1923*12508Samw@Sun.COM void *node; 1924*12508Samw@Sun.COM 1925*12508Samw@Sun.COM ASSERT(avl); 1926*12508Samw@Sun.COM 1927*12508Samw@Sun.COM mutex_enter(&avl->avl_mutex); 1928*12508Samw@Sun.COM if (avl->avl_state != SMB_AVL_STATE_READY) { 1929*12508Samw@Sun.COM mutex_exit(&avl->avl_mutex); 1930*12508Samw@Sun.COM return; 1931*12508Samw@Sun.COM } 1932*12508Samw@Sun.COM 1933*12508Samw@Sun.COM avl->avl_state = SMB_AVL_STATE_DESTROYING; 1934*12508Samw@Sun.COM 1935*12508Samw@Sun.COM while (avl->avl_refcnt > 0) 1936*12508Samw@Sun.COM (void) cv_wait(&avl->avl_cv, &avl->avl_mutex); 1937*12508Samw@Sun.COM mutex_exit(&avl->avl_mutex); 1938*12508Samw@Sun.COM 1939*12508Samw@Sun.COM rw_enter(&avl->avl_lock, RW_WRITER); 1940*12508Samw@Sun.COM while ((node = avl_destroy_nodes(&avl->avl_tree, &cookie)) != NULL) 1941*12508Samw@Sun.COM avl->avl_nops->avln_destroy(node); 1942*12508Samw@Sun.COM 1943*12508Samw@Sun.COM avl_destroy(&avl->avl_tree); 1944*12508Samw@Sun.COM rw_exit(&avl->avl_lock); 1945*12508Samw@Sun.COM 1946*12508Samw@Sun.COM rw_destroy(&avl->avl_lock); 1947*12508Samw@Sun.COM 1948*12508Samw@Sun.COM mutex_destroy(&avl->avl_mutex); 1949*12508Samw@Sun.COM bzero(avl, sizeof (smb_avl_t)); 1950*12508Samw@Sun.COM } 1951*12508Samw@Sun.COM 1952*12508Samw@Sun.COM /* 1953*12508Samw@Sun.COM * Adds the given item to the AVL if it's 1954*12508Samw@Sun.COM * not already there. 1955*12508Samw@Sun.COM * 1956*12508Samw@Sun.COM * Returns: 1957*12508Samw@Sun.COM * 1958*12508Samw@Sun.COM * ENOTACTIVE AVL is not in READY state 1959*12508Samw@Sun.COM * EEXIST The item is already in AVL 1960*12508Samw@Sun.COM */ 1961*12508Samw@Sun.COM int 1962*12508Samw@Sun.COM smb_avl_add(smb_avl_t *avl, void *item) 1963*12508Samw@Sun.COM { 1964*12508Samw@Sun.COM avl_index_t where; 1965*12508Samw@Sun.COM 1966*12508Samw@Sun.COM ASSERT(avl); 1967*12508Samw@Sun.COM ASSERT(item); 1968*12508Samw@Sun.COM 1969*12508Samw@Sun.COM if (!smb_avl_hold(avl)) 1970*12508Samw@Sun.COM return (ENOTACTIVE); 1971*12508Samw@Sun.COM 1972*12508Samw@Sun.COM rw_enter(&avl->avl_lock, RW_WRITER); 1973*12508Samw@Sun.COM if (avl_find(&avl->avl_tree, item, &where) != NULL) { 1974*12508Samw@Sun.COM rw_exit(&avl->avl_lock); 1975*12508Samw@Sun.COM smb_avl_rele(avl); 1976*12508Samw@Sun.COM return (EEXIST); 1977*12508Samw@Sun.COM } 1978*12508Samw@Sun.COM 1979*12508Samw@Sun.COM avl_insert(&avl->avl_tree, item, where); 1980*12508Samw@Sun.COM avl->avl_sequence++; 1981*12508Samw@Sun.COM rw_exit(&avl->avl_lock); 1982*12508Samw@Sun.COM 1983*12508Samw@Sun.COM smb_avl_rele(avl); 1984*12508Samw@Sun.COM return (0); 1985*12508Samw@Sun.COM } 1986*12508Samw@Sun.COM 1987*12508Samw@Sun.COM /* 1988*12508Samw@Sun.COM * Removes the given item from the AVL. 1989*12508Samw@Sun.COM * If no reference is left on the item 1990*12508Samw@Sun.COM * it will also be destroyed by calling the 1991*12508Samw@Sun.COM * registered destroy operation. 1992*12508Samw@Sun.COM */ 1993*12508Samw@Sun.COM void 1994*12508Samw@Sun.COM smb_avl_remove(smb_avl_t *avl, void *item) 1995*12508Samw@Sun.COM { 1996*12508Samw@Sun.COM avl_index_t where; 1997*12508Samw@Sun.COM void *rm_item; 1998*12508Samw@Sun.COM 1999*12508Samw@Sun.COM ASSERT(avl); 2000*12508Samw@Sun.COM ASSERT(item); 2001*12508Samw@Sun.COM 2002*12508Samw@Sun.COM if (!smb_avl_hold(avl)) 2003*12508Samw@Sun.COM return; 2004*12508Samw@Sun.COM 2005*12508Samw@Sun.COM rw_enter(&avl->avl_lock, RW_WRITER); 2006*12508Samw@Sun.COM if ((rm_item = avl_find(&avl->avl_tree, item, &where)) == NULL) { 2007*12508Samw@Sun.COM rw_exit(&avl->avl_lock); 2008*12508Samw@Sun.COM smb_avl_rele(avl); 2009*12508Samw@Sun.COM return; 2010*12508Samw@Sun.COM } 2011*12508Samw@Sun.COM 2012*12508Samw@Sun.COM avl_remove(&avl->avl_tree, rm_item); 2013*12508Samw@Sun.COM if (avl->avl_nops->avln_rele(rm_item)) 2014*12508Samw@Sun.COM avl->avl_nops->avln_destroy(rm_item); 2015*12508Samw@Sun.COM avl->avl_sequence++; 2016*12508Samw@Sun.COM rw_exit(&avl->avl_lock); 2017*12508Samw@Sun.COM 2018*12508Samw@Sun.COM smb_avl_rele(avl); 2019*12508Samw@Sun.COM } 2020*12508Samw@Sun.COM 2021*12508Samw@Sun.COM /* 2022*12508Samw@Sun.COM * Looks up the AVL for the given item. 2023*12508Samw@Sun.COM * If the item is found a hold on the object 2024*12508Samw@Sun.COM * is taken before the pointer to it is 2025*12508Samw@Sun.COM * returned to the caller. The caller MUST 2026*12508Samw@Sun.COM * always call smb_avl_release() after it's done 2027*12508Samw@Sun.COM * using the returned object to release the hold 2028*12508Samw@Sun.COM * taken on the object. 2029*12508Samw@Sun.COM */ 2030*12508Samw@Sun.COM void * 2031*12508Samw@Sun.COM smb_avl_lookup(smb_avl_t *avl, void *item) 2032*12508Samw@Sun.COM { 2033*12508Samw@Sun.COM void *node = NULL; 2034*12508Samw@Sun.COM 2035*12508Samw@Sun.COM ASSERT(avl); 2036*12508Samw@Sun.COM ASSERT(item); 2037*12508Samw@Sun.COM 2038*12508Samw@Sun.COM if (!smb_avl_hold(avl)) 2039*12508Samw@Sun.COM return (NULL); 2040*12508Samw@Sun.COM 2041*12508Samw@Sun.COM rw_enter(&avl->avl_lock, RW_READER); 2042*12508Samw@Sun.COM node = avl_find(&avl->avl_tree, item, NULL); 2043*12508Samw@Sun.COM if (node != NULL) 2044*12508Samw@Sun.COM avl->avl_nops->avln_hold(node); 2045*12508Samw@Sun.COM rw_exit(&avl->avl_lock); 2046*12508Samw@Sun.COM 2047*12508Samw@Sun.COM if (node == NULL) 2048*12508Samw@Sun.COM smb_avl_rele(avl); 2049*12508Samw@Sun.COM 2050*12508Samw@Sun.COM return (node); 2051*12508Samw@Sun.COM } 2052*12508Samw@Sun.COM 2053*12508Samw@Sun.COM /* 2054*12508Samw@Sun.COM * The hold on the given object is released. 2055*12508Samw@Sun.COM * This function MUST always be called after 2056*12508Samw@Sun.COM * smb_avl_lookup() and smb_avl_iterate() for 2057*12508Samw@Sun.COM * the returned object. 2058*12508Samw@Sun.COM * 2059*12508Samw@Sun.COM * If AVL is in DESTROYING state, the destroying 2060*12508Samw@Sun.COM * thread will be notified. 2061*12508Samw@Sun.COM */ 2062*12508Samw@Sun.COM void 2063*12508Samw@Sun.COM smb_avl_release(smb_avl_t *avl, void *item) 2064*12508Samw@Sun.COM { 2065*12508Samw@Sun.COM ASSERT(avl); 2066*12508Samw@Sun.COM ASSERT(item); 2067*12508Samw@Sun.COM 2068*12508Samw@Sun.COM if (avl->avl_nops->avln_rele(item)) 2069*12508Samw@Sun.COM avl->avl_nops->avln_destroy(item); 2070*12508Samw@Sun.COM 2071*12508Samw@Sun.COM smb_avl_rele(avl); 2072*12508Samw@Sun.COM } 2073*12508Samw@Sun.COM 2074*12508Samw@Sun.COM /* 2075*12508Samw@Sun.COM * Initializes the given cursor for the AVL. 2076*12508Samw@Sun.COM * The cursor will be used to iterate through the AVL 2077*12508Samw@Sun.COM */ 2078*12508Samw@Sun.COM void 2079*12508Samw@Sun.COM smb_avl_iterinit(smb_avl_t *avl, smb_avl_cursor_t *cursor) 2080*12508Samw@Sun.COM { 2081*12508Samw@Sun.COM ASSERT(avl); 2082*12508Samw@Sun.COM ASSERT(cursor); 2083*12508Samw@Sun.COM 2084*12508Samw@Sun.COM cursor->avlc_next = NULL; 2085*12508Samw@Sun.COM cursor->avlc_sequence = avl->avl_sequence; 2086*12508Samw@Sun.COM } 2087*12508Samw@Sun.COM 2088*12508Samw@Sun.COM /* 2089*12508Samw@Sun.COM * Iterates through the AVL using the given cursor. 2090*12508Samw@Sun.COM * It always starts at the beginning and then returns 2091*12508Samw@Sun.COM * a pointer to the next object on each subsequent call. 2092*12508Samw@Sun.COM * 2093*12508Samw@Sun.COM * If a new object is added to or removed from the AVL 2094*12508Samw@Sun.COM * between two calls to this function, the iteration 2095*12508Samw@Sun.COM * will terminate prematurely. 2096*12508Samw@Sun.COM * 2097*12508Samw@Sun.COM * The caller MUST always call smb_avl_release() after it's 2098*12508Samw@Sun.COM * done using the returned object to release the hold taken 2099*12508Samw@Sun.COM * on the object. 2100*12508Samw@Sun.COM */ 2101*12508Samw@Sun.COM void * 2102*12508Samw@Sun.COM smb_avl_iterate(smb_avl_t *avl, smb_avl_cursor_t *cursor) 2103*12508Samw@Sun.COM { 2104*12508Samw@Sun.COM void *node; 2105*12508Samw@Sun.COM 2106*12508Samw@Sun.COM ASSERT(avl); 2107*12508Samw@Sun.COM ASSERT(cursor); 2108*12508Samw@Sun.COM 2109*12508Samw@Sun.COM if (!smb_avl_hold(avl)) 2110*12508Samw@Sun.COM return (NULL); 2111*12508Samw@Sun.COM 2112*12508Samw@Sun.COM rw_enter(&avl->avl_lock, RW_READER); 2113*12508Samw@Sun.COM if (cursor->avlc_sequence != avl->avl_sequence) { 2114*12508Samw@Sun.COM rw_exit(&avl->avl_lock); 2115*12508Samw@Sun.COM smb_avl_rele(avl); 2116*12508Samw@Sun.COM return (NULL); 2117*12508Samw@Sun.COM } 2118*12508Samw@Sun.COM 2119*12508Samw@Sun.COM if (cursor->avlc_next == NULL) 2120*12508Samw@Sun.COM node = avl_first(&avl->avl_tree); 2121*12508Samw@Sun.COM else 2122*12508Samw@Sun.COM node = AVL_NEXT(&avl->avl_tree, cursor->avlc_next); 2123*12508Samw@Sun.COM 2124*12508Samw@Sun.COM if (node != NULL) 2125*12508Samw@Sun.COM avl->avl_nops->avln_hold(node); 2126*12508Samw@Sun.COM 2127*12508Samw@Sun.COM cursor->avlc_next = node; 2128*12508Samw@Sun.COM rw_exit(&avl->avl_lock); 2129*12508Samw@Sun.COM 2130*12508Samw@Sun.COM if (node == NULL) 2131*12508Samw@Sun.COM smb_avl_rele(avl); 2132*12508Samw@Sun.COM 2133*12508Samw@Sun.COM return (node); 2134*12508Samw@Sun.COM } 2135*12508Samw@Sun.COM 2136*12508Samw@Sun.COM /* 2137*12508Samw@Sun.COM * Increments the AVL reference count in order to 2138*12508Samw@Sun.COM * prevent the avl from being destroyed while it's 2139*12508Samw@Sun.COM * being accessed. 2140*12508Samw@Sun.COM */ 2141*12508Samw@Sun.COM static boolean_t 2142*12508Samw@Sun.COM smb_avl_hold(smb_avl_t *avl) 2143*12508Samw@Sun.COM { 2144*12508Samw@Sun.COM mutex_enter(&avl->avl_mutex); 2145*12508Samw@Sun.COM if (avl->avl_state != SMB_AVL_STATE_READY) { 2146*12508Samw@Sun.COM mutex_exit(&avl->avl_mutex); 2147*12508Samw@Sun.COM return (B_FALSE); 2148*12508Samw@Sun.COM } 2149*12508Samw@Sun.COM avl->avl_refcnt++; 2150*12508Samw@Sun.COM mutex_exit(&avl->avl_mutex); 2151*12508Samw@Sun.COM 2152*12508Samw@Sun.COM return (B_TRUE); 2153*12508Samw@Sun.COM } 2154*12508Samw@Sun.COM 2155*12508Samw@Sun.COM /* 2156*12508Samw@Sun.COM * Decrements the AVL reference count to release the 2157*12508Samw@Sun.COM * hold. If another thread is trying to destroy the 2158*12508Samw@Sun.COM * AVL and is waiting for the reference count to become 2159*12508Samw@Sun.COM * 0, it is signaled to wake up. 2160*12508Samw@Sun.COM */ 2161*12508Samw@Sun.COM static void 2162*12508Samw@Sun.COM smb_avl_rele(smb_avl_t *avl) 2163*12508Samw@Sun.COM { 2164*12508Samw@Sun.COM mutex_enter(&avl->avl_mutex); 2165*12508Samw@Sun.COM ASSERT(avl->avl_refcnt > 0); 2166*12508Samw@Sun.COM avl->avl_refcnt--; 2167*12508Samw@Sun.COM if (avl->avl_state == SMB_AVL_STATE_DESTROYING) 2168*12508Samw@Sun.COM cv_broadcast(&avl->avl_cv); 2169*12508Samw@Sun.COM mutex_exit(&avl->avl_mutex); 2170*12508Samw@Sun.COM } 2171*12508Samw@Sun.COM 2172*12508Samw@Sun.COM /* 2173*12508Samw@Sun.COM * smb_latency_init 2174*12508Samw@Sun.COM */ 2175*12508Samw@Sun.COM void 2176*12508Samw@Sun.COM smb_latency_init(smb_latency_t *lat) 2177*12508Samw@Sun.COM { 2178*12508Samw@Sun.COM bzero(lat, sizeof (*lat)); 2179*12508Samw@Sun.COM mutex_init(&lat->ly_mutex, NULL, MUTEX_SPIN, (void *)ipltospl(SPL7)); 2180*12508Samw@Sun.COM } 2181*12508Samw@Sun.COM 2182*12508Samw@Sun.COM /* 2183*12508Samw@Sun.COM * smb_latency_destroy 2184*12508Samw@Sun.COM */ 2185*12508Samw@Sun.COM void 2186*12508Samw@Sun.COM smb_latency_destroy(smb_latency_t *lat) 2187*12508Samw@Sun.COM { 2188*12508Samw@Sun.COM mutex_destroy(&lat->ly_mutex); 2189*12508Samw@Sun.COM } 2190*12508Samw@Sun.COM 2191*12508Samw@Sun.COM /* 2192*12508Samw@Sun.COM * smb_latency_add_sample 2193*12508Samw@Sun.COM * 2194*12508Samw@Sun.COM * Uses the new sample to calculate the new mean and standard deviation. The 2195*12508Samw@Sun.COM * sample must be a scaled value. 2196*12508Samw@Sun.COM */ 2197*12508Samw@Sun.COM void 2198*12508Samw@Sun.COM smb_latency_add_sample(smb_latency_t *lat, hrtime_t sample) 2199*12508Samw@Sun.COM { 2200*12508Samw@Sun.COM hrtime_t a_mean; 2201*12508Samw@Sun.COM hrtime_t d_mean; 2202*12508Samw@Sun.COM 2203*12508Samw@Sun.COM mutex_enter(&lat->ly_mutex); 2204*12508Samw@Sun.COM lat->ly_a_nreq++; 2205*12508Samw@Sun.COM lat->ly_a_sum += sample; 2206*12508Samw@Sun.COM if (lat->ly_a_nreq != 0) { 2207*12508Samw@Sun.COM a_mean = lat->ly_a_sum / lat->ly_a_nreq; 2208*12508Samw@Sun.COM lat->ly_a_stddev = 2209*12508Samw@Sun.COM (sample - a_mean) * (sample - lat->ly_a_mean); 2210*12508Samw@Sun.COM lat->ly_a_mean = a_mean; 2211*12508Samw@Sun.COM } 2212*12508Samw@Sun.COM lat->ly_d_nreq++; 2213*12508Samw@Sun.COM lat->ly_d_sum += sample; 2214*12508Samw@Sun.COM if (lat->ly_d_nreq != 0) { 2215*12508Samw@Sun.COM d_mean = lat->ly_d_sum / lat->ly_d_nreq; 2216*12508Samw@Sun.COM lat->ly_d_stddev = 2217*12508Samw@Sun.COM (sample - d_mean) * (sample - lat->ly_d_mean); 2218*12508Samw@Sun.COM lat->ly_d_mean = d_mean; 2219*12508Samw@Sun.COM } 2220*12508Samw@Sun.COM mutex_exit(&lat->ly_mutex); 2221*12508Samw@Sun.COM } 2222*12508Samw@Sun.COM 2223*12508Samw@Sun.COM /* 2224*12508Samw@Sun.COM * smb_srqueue_init 2225*12508Samw@Sun.COM */ 2226*12508Samw@Sun.COM void 2227*12508Samw@Sun.COM smb_srqueue_init(smb_srqueue_t *srq) 2228*12508Samw@Sun.COM { 2229*12508Samw@Sun.COM bzero(srq, sizeof (*srq)); 2230*12508Samw@Sun.COM mutex_init(&srq->srq_mutex, NULL, MUTEX_SPIN, (void *)ipltospl(SPL7)); 2231*12508Samw@Sun.COM srq->srq_wlastupdate = srq->srq_rlastupdate = gethrtime_unscaled(); 2232*12508Samw@Sun.COM } 2233*12508Samw@Sun.COM 2234*12508Samw@Sun.COM /* 2235*12508Samw@Sun.COM * smb_srqueue_destroy 2236*12508Samw@Sun.COM */ 2237*12508Samw@Sun.COM void 2238*12508Samw@Sun.COM smb_srqueue_destroy(smb_srqueue_t *srq) 2239*12508Samw@Sun.COM { 2240*12508Samw@Sun.COM mutex_destroy(&srq->srq_mutex); 2241*12508Samw@Sun.COM } 2242*12508Samw@Sun.COM 2243*12508Samw@Sun.COM /* 2244*12508Samw@Sun.COM * smb_srqueue_waitq_enter 2245*12508Samw@Sun.COM */ 2246*12508Samw@Sun.COM void 2247*12508Samw@Sun.COM smb_srqueue_waitq_enter(smb_srqueue_t *srq) 2248*12508Samw@Sun.COM { 2249*12508Samw@Sun.COM hrtime_t new; 2250*12508Samw@Sun.COM hrtime_t delta; 2251*12508Samw@Sun.COM uint32_t wcnt; 2252*12508Samw@Sun.COM 2253*12508Samw@Sun.COM mutex_enter(&srq->srq_mutex); 2254*12508Samw@Sun.COM new = gethrtime_unscaled(); 2255*12508Samw@Sun.COM delta = new - srq->srq_wlastupdate; 2256*12508Samw@Sun.COM srq->srq_wlastupdate = new; 2257*12508Samw@Sun.COM wcnt = srq->srq_wcnt++; 2258*12508Samw@Sun.COM if (wcnt != 0) { 2259*12508Samw@Sun.COM srq->srq_wlentime += delta * wcnt; 2260*12508Samw@Sun.COM srq->srq_wtime += delta; 2261*12508Samw@Sun.COM } 2262*12508Samw@Sun.COM mutex_exit(&srq->srq_mutex); 2263*12508Samw@Sun.COM } 2264*12508Samw@Sun.COM 2265*12508Samw@Sun.COM /* 2266*12508Samw@Sun.COM * smb_srqueue_runq_exit 2267*12508Samw@Sun.COM */ 2268*12508Samw@Sun.COM void 2269*12508Samw@Sun.COM smb_srqueue_runq_exit(smb_srqueue_t *srq) 2270*12508Samw@Sun.COM { 2271*12508Samw@Sun.COM hrtime_t new; 2272*12508Samw@Sun.COM hrtime_t delta; 2273*12508Samw@Sun.COM uint32_t rcnt; 2274*12508Samw@Sun.COM 2275*12508Samw@Sun.COM mutex_enter(&srq->srq_mutex); 2276*12508Samw@Sun.COM new = gethrtime_unscaled(); 2277*12508Samw@Sun.COM delta = new - srq->srq_rlastupdate; 2278*12508Samw@Sun.COM srq->srq_rlastupdate = new; 2279*12508Samw@Sun.COM rcnt = srq->srq_rcnt--; 2280*12508Samw@Sun.COM ASSERT(rcnt > 0); 2281*12508Samw@Sun.COM srq->srq_rlentime += delta * rcnt; 2282*12508Samw@Sun.COM srq->srq_rtime += delta; 2283*12508Samw@Sun.COM mutex_exit(&srq->srq_mutex); 2284*12508Samw@Sun.COM } 2285*12508Samw@Sun.COM 2286*12508Samw@Sun.COM /* 2287*12508Samw@Sun.COM * smb_srqueue_waitq_to_runq 2288*12508Samw@Sun.COM */ 2289*12508Samw@Sun.COM void 2290*12508Samw@Sun.COM smb_srqueue_waitq_to_runq(smb_srqueue_t *srq) 2291*12508Samw@Sun.COM { 2292*12508Samw@Sun.COM hrtime_t new; 2293*12508Samw@Sun.COM hrtime_t delta; 2294*12508Samw@Sun.COM uint32_t wcnt; 2295*12508Samw@Sun.COM uint32_t rcnt; 2296*12508Samw@Sun.COM 2297*12508Samw@Sun.COM mutex_enter(&srq->srq_mutex); 2298*12508Samw@Sun.COM new = gethrtime_unscaled(); 2299*12508Samw@Sun.COM delta = new - srq->srq_wlastupdate; 2300*12508Samw@Sun.COM srq->srq_wlastupdate = new; 2301*12508Samw@Sun.COM wcnt = srq->srq_wcnt--; 2302*12508Samw@Sun.COM ASSERT(wcnt > 0); 2303*12508Samw@Sun.COM srq->srq_wlentime += delta * wcnt; 2304*12508Samw@Sun.COM srq->srq_wtime += delta; 2305*12508Samw@Sun.COM delta = new - srq->srq_rlastupdate; 2306*12508Samw@Sun.COM srq->srq_rlastupdate = new; 2307*12508Samw@Sun.COM rcnt = srq->srq_rcnt++; 2308*12508Samw@Sun.COM if (rcnt != 0) { 2309*12508Samw@Sun.COM srq->srq_rlentime += delta * rcnt; 2310*12508Samw@Sun.COM srq->srq_rtime += delta; 2311*12508Samw@Sun.COM } 2312*12508Samw@Sun.COM mutex_exit(&srq->srq_mutex); 2313*12508Samw@Sun.COM } 2314*12508Samw@Sun.COM 2315*12508Samw@Sun.COM /* 2316*12508Samw@Sun.COM * smb_srqueue_update 2317*12508Samw@Sun.COM * 2318*12508Samw@Sun.COM * Takes a snapshot of the smb_sr_stat_t structure passed in. 2319*12508Samw@Sun.COM */ 2320*12508Samw@Sun.COM void 2321*12508Samw@Sun.COM smb_srqueue_update(smb_srqueue_t *srq, smb_kstat_utilization_t *kd) 2322*12508Samw@Sun.COM { 2323*12508Samw@Sun.COM hrtime_t delta; 2324*12508Samw@Sun.COM hrtime_t snaptime; 2325*12508Samw@Sun.COM 2326*12508Samw@Sun.COM mutex_enter(&srq->srq_mutex); 2327*12508Samw@Sun.COM snaptime = gethrtime_unscaled(); 2328*12508Samw@Sun.COM delta = snaptime - srq->srq_wlastupdate; 2329*12508Samw@Sun.COM srq->srq_wlastupdate = snaptime; 2330*12508Samw@Sun.COM if (srq->srq_wcnt != 0) { 2331*12508Samw@Sun.COM srq->srq_wlentime += delta * srq->srq_wcnt; 2332*12508Samw@Sun.COM srq->srq_wtime += delta; 2333*12508Samw@Sun.COM } 2334*12508Samw@Sun.COM delta = snaptime - srq->srq_rlastupdate; 2335*12508Samw@Sun.COM srq->srq_rlastupdate = snaptime; 2336*12508Samw@Sun.COM if (srq->srq_rcnt != 0) { 2337*12508Samw@Sun.COM srq->srq_rlentime += delta * srq->srq_rcnt; 2338*12508Samw@Sun.COM srq->srq_rtime += delta; 2339*12508Samw@Sun.COM } 2340*12508Samw@Sun.COM kd->ku_rlentime = srq->srq_rlentime; 2341*12508Samw@Sun.COM kd->ku_rtime = srq->srq_rtime; 2342*12508Samw@Sun.COM kd->ku_wlentime = srq->srq_wlentime; 2343*12508Samw@Sun.COM kd->ku_wtime = srq->srq_wtime; 2344*12508Samw@Sun.COM mutex_exit(&srq->srq_mutex); 2345*12508Samw@Sun.COM scalehrtime(&kd->ku_rlentime); 2346*12508Samw@Sun.COM scalehrtime(&kd->ku_rtime); 2347*12508Samw@Sun.COM scalehrtime(&kd->ku_wlentime); 2348*12508Samw@Sun.COM scalehrtime(&kd->ku_wtime); 2349*12508Samw@Sun.COM } 2350