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>
3112508Samw@Sun.COM #include <sys/spl.h>
3211963SAfshin.Ardakani@Sun.COM #include <sys/cpuvar.h>
3312508Samw@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
4912508Samw@Sun.COM static boolean_t smb_avl_hold(smb_avl_t *);
5012508Samw@Sun.COM static void smb_avl_rele(smb_avl_t *);
5112508Samw@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
smb_ascii_or_unicode_strlen(struct smb_request * sr,char * str)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
smb_ascii_or_unicode_strlen_null(struct smb_request * sr,char * str)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
smb_ascii_or_unicode_null_len(struct smb_request * sr)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
smb_contains_wildcards(const char * pattern)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
smb_convert_wildcards(char * pattern)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
smb_sattr_check(uint16_t dosattr,uint16_t sattr)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
microtime(timestruc_t * tvp)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
clock_get_milli_uptime()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*/
smb_noop(void * p,size_t size,int foo)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
smb_idpool_increment(smb_idpool_t * pool)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
smb_idpool_constructor(smb_idpool_t * pool)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
smb_idpool_destructor(smb_idpool_t * pool)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
smb_idpool_alloc(smb_idpool_t * pool,uint16_t * id)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
smb_idpool_free(smb_idpool_t * pool,uint16_t id)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
smb_llist_init(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
smb_llist_fini(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
smb_llist_constructor(smb_llist_t * ll,size_t size,size_t offset)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;
50412890SJoyce.McIntosh@Sun.COM ll->ll_flushing = B_FALSE;
50511963SAfshin.Ardakani@Sun.COM }
50611963SAfshin.Ardakani@Sun.COM
50711963SAfshin.Ardakani@Sun.COM /*
50811963SAfshin.Ardakani@Sun.COM * Flush the delete queue and destroy a locked list.
50911963SAfshin.Ardakani@Sun.COM */
51011963SAfshin.Ardakani@Sun.COM void
smb_llist_destructor(smb_llist_t * ll)51111963SAfshin.Ardakani@Sun.COM smb_llist_destructor(
51211963SAfshin.Ardakani@Sun.COM smb_llist_t *ll)
51311963SAfshin.Ardakani@Sun.COM {
51411963SAfshin.Ardakani@Sun.COM smb_llist_flush(ll);
51511963SAfshin.Ardakani@Sun.COM
51611963SAfshin.Ardakani@Sun.COM ASSERT(ll->ll_count == 0);
51711963SAfshin.Ardakani@Sun.COM ASSERT(ll->ll_deleteq_count == 0);
51811963SAfshin.Ardakani@Sun.COM
51911963SAfshin.Ardakani@Sun.COM rw_destroy(&ll->ll_lock);
52011963SAfshin.Ardakani@Sun.COM list_destroy(&ll->ll_list);
52111963SAfshin.Ardakani@Sun.COM list_destroy(&ll->ll_deleteq);
52211963SAfshin.Ardakani@Sun.COM mutex_destroy(&ll->ll_mutex);
52311963SAfshin.Ardakani@Sun.COM }
52411963SAfshin.Ardakani@Sun.COM
52511963SAfshin.Ardakani@Sun.COM /*
52611963SAfshin.Ardakani@Sun.COM * Post an object to the delete queue. The delete queue will be processed
52711963SAfshin.Ardakani@Sun.COM * during list exit or list destruction. Objects are often posted for
52811963SAfshin.Ardakani@Sun.COM * deletion during list iteration (while the list is locked) but that is
52911963SAfshin.Ardakani@Sun.COM * not required, and an object can be posted at any time.
53011963SAfshin.Ardakani@Sun.COM */
53111963SAfshin.Ardakani@Sun.COM void
smb_llist_post(smb_llist_t * ll,void * object,smb_dtorproc_t dtorproc)53211963SAfshin.Ardakani@Sun.COM smb_llist_post(smb_llist_t *ll, void *object, smb_dtorproc_t dtorproc)
53311963SAfshin.Ardakani@Sun.COM {
53411963SAfshin.Ardakani@Sun.COM smb_dtor_t *dtor;
53511963SAfshin.Ardakani@Sun.COM
53611963SAfshin.Ardakani@Sun.COM ASSERT((object != NULL) && (dtorproc != NULL));
53711963SAfshin.Ardakani@Sun.COM
53811963SAfshin.Ardakani@Sun.COM dtor = kmem_cache_alloc(smb_dtor_cache, KM_SLEEP);
53911963SAfshin.Ardakani@Sun.COM bzero(dtor, sizeof (smb_dtor_t));
54011963SAfshin.Ardakani@Sun.COM dtor->dt_magic = SMB_DTOR_MAGIC;
54111963SAfshin.Ardakani@Sun.COM dtor->dt_object = object;
54211963SAfshin.Ardakani@Sun.COM dtor->dt_proc = dtorproc;
54311963SAfshin.Ardakani@Sun.COM
54411963SAfshin.Ardakani@Sun.COM mutex_enter(&ll->ll_mutex);
54511963SAfshin.Ardakani@Sun.COM list_insert_tail(&ll->ll_deleteq, dtor);
54611963SAfshin.Ardakani@Sun.COM ++ll->ll_deleteq_count;
54711963SAfshin.Ardakani@Sun.COM mutex_exit(&ll->ll_mutex);
54811963SAfshin.Ardakani@Sun.COM }
54911963SAfshin.Ardakani@Sun.COM
55011963SAfshin.Ardakani@Sun.COM /*
55111963SAfshin.Ardakani@Sun.COM * Exit the list lock and process the delete queue.
55211963SAfshin.Ardakani@Sun.COM */
55311963SAfshin.Ardakani@Sun.COM void
smb_llist_exit(smb_llist_t * ll)55411963SAfshin.Ardakani@Sun.COM smb_llist_exit(smb_llist_t *ll)
55511963SAfshin.Ardakani@Sun.COM {
55611963SAfshin.Ardakani@Sun.COM rw_exit(&ll->ll_lock);
55711963SAfshin.Ardakani@Sun.COM smb_llist_flush(ll);
55811963SAfshin.Ardakani@Sun.COM }
55911963SAfshin.Ardakani@Sun.COM
56011963SAfshin.Ardakani@Sun.COM /*
56111963SAfshin.Ardakani@Sun.COM * Flush the list delete queue. The mutex is dropped across the destructor
56211963SAfshin.Ardakani@Sun.COM * call in case this leads to additional objects being posted to the delete
56311963SAfshin.Ardakani@Sun.COM * queue.
56411963SAfshin.Ardakani@Sun.COM */
56512065SKeyur.Desai@Sun.COM void
smb_llist_flush(smb_llist_t * ll)56611963SAfshin.Ardakani@Sun.COM smb_llist_flush(smb_llist_t *ll)
56711963SAfshin.Ardakani@Sun.COM {
56811963SAfshin.Ardakani@Sun.COM smb_dtor_t *dtor;
56911963SAfshin.Ardakani@Sun.COM
57011963SAfshin.Ardakani@Sun.COM mutex_enter(&ll->ll_mutex);
57112890SJoyce.McIntosh@Sun.COM if (ll->ll_flushing) {
57212890SJoyce.McIntosh@Sun.COM mutex_exit(&ll->ll_mutex);
57312890SJoyce.McIntosh@Sun.COM return;
57412890SJoyce.McIntosh@Sun.COM }
57512890SJoyce.McIntosh@Sun.COM ll->ll_flushing = B_TRUE;
57611963SAfshin.Ardakani@Sun.COM
57711963SAfshin.Ardakani@Sun.COM dtor = list_head(&ll->ll_deleteq);
57811963SAfshin.Ardakani@Sun.COM while (dtor != NULL) {
57911963SAfshin.Ardakani@Sun.COM SMB_DTOR_VALID(dtor);
58011963SAfshin.Ardakani@Sun.COM ASSERT((dtor->dt_object != NULL) && (dtor->dt_proc != NULL));
58111963SAfshin.Ardakani@Sun.COM list_remove(&ll->ll_deleteq, dtor);
58211963SAfshin.Ardakani@Sun.COM --ll->ll_deleteq_count;
58311963SAfshin.Ardakani@Sun.COM mutex_exit(&ll->ll_mutex);
58411963SAfshin.Ardakani@Sun.COM
58511963SAfshin.Ardakani@Sun.COM dtor->dt_proc(dtor->dt_object);
58611963SAfshin.Ardakani@Sun.COM
58711963SAfshin.Ardakani@Sun.COM dtor->dt_magic = (uint32_t)~SMB_DTOR_MAGIC;
58811963SAfshin.Ardakani@Sun.COM kmem_cache_free(smb_dtor_cache, dtor);
58911963SAfshin.Ardakani@Sun.COM mutex_enter(&ll->ll_mutex);
59011963SAfshin.Ardakani@Sun.COM dtor = list_head(&ll->ll_deleteq);
59111963SAfshin.Ardakani@Sun.COM }
59212890SJoyce.McIntosh@Sun.COM ll->ll_flushing = B_FALSE;
59311963SAfshin.Ardakani@Sun.COM
59411963SAfshin.Ardakani@Sun.COM mutex_exit(&ll->ll_mutex);
59511963SAfshin.Ardakani@Sun.COM }
59611963SAfshin.Ardakani@Sun.COM
59711963SAfshin.Ardakani@Sun.COM /*
59811963SAfshin.Ardakani@Sun.COM * smb_llist_upgrade
59911963SAfshin.Ardakani@Sun.COM *
60011963SAfshin.Ardakani@Sun.COM * This function tries to upgrade the lock of the locked list. It assumes the
60111963SAfshin.Ardakani@Sun.COM * locked has already been entered in RW_READER mode. It first tries using the
60211963SAfshin.Ardakani@Sun.COM * Solaris function rw_tryupgrade(). If that call fails the lock is released
60311963SAfshin.Ardakani@Sun.COM * and reentered in RW_WRITER mode. In that last case a window is opened during
60411963SAfshin.Ardakani@Sun.COM * which the contents of the list may have changed. The return code indicates
60511963SAfshin.Ardakani@Sun.COM * whether or not the list was modified when the lock was exited.
60611963SAfshin.Ardakani@Sun.COM */
smb_llist_upgrade(smb_llist_t * ll)60711963SAfshin.Ardakani@Sun.COM int smb_llist_upgrade(
60811963SAfshin.Ardakani@Sun.COM smb_llist_t *ll)
60911963SAfshin.Ardakani@Sun.COM {
61011963SAfshin.Ardakani@Sun.COM uint64_t wrop;
61111963SAfshin.Ardakani@Sun.COM
61211963SAfshin.Ardakani@Sun.COM if (rw_tryupgrade(&ll->ll_lock) != 0) {
61311963SAfshin.Ardakani@Sun.COM return (0);
61411963SAfshin.Ardakani@Sun.COM }
61511963SAfshin.Ardakani@Sun.COM wrop = ll->ll_wrop;
61611963SAfshin.Ardakani@Sun.COM rw_exit(&ll->ll_lock);
61711963SAfshin.Ardakani@Sun.COM rw_enter(&ll->ll_lock, RW_WRITER);
61811963SAfshin.Ardakani@Sun.COM return (wrop != ll->ll_wrop);
61911963SAfshin.Ardakani@Sun.COM }
62011963SAfshin.Ardakani@Sun.COM
62111963SAfshin.Ardakani@Sun.COM /*
62211963SAfshin.Ardakani@Sun.COM * smb_llist_insert_head
62311963SAfshin.Ardakani@Sun.COM *
62411963SAfshin.Ardakani@Sun.COM * This function inserts the object passed a the beginning of the list. This
62511963SAfshin.Ardakani@Sun.COM * function assumes the lock of the list has already been entered.
62611963SAfshin.Ardakani@Sun.COM */
62711963SAfshin.Ardakani@Sun.COM void
smb_llist_insert_head(smb_llist_t * ll,void * obj)62811963SAfshin.Ardakani@Sun.COM smb_llist_insert_head(
62911963SAfshin.Ardakani@Sun.COM smb_llist_t *ll,
63011963SAfshin.Ardakani@Sun.COM void *obj)
63111963SAfshin.Ardakani@Sun.COM {
63211963SAfshin.Ardakani@Sun.COM list_insert_head(&ll->ll_list, obj);
63311963SAfshin.Ardakani@Sun.COM ++ll->ll_wrop;
63411963SAfshin.Ardakani@Sun.COM ++ll->ll_count;
63511963SAfshin.Ardakani@Sun.COM }
63611963SAfshin.Ardakani@Sun.COM
63711963SAfshin.Ardakani@Sun.COM /*
63811963SAfshin.Ardakani@Sun.COM * smb_llist_insert_tail
63911963SAfshin.Ardakani@Sun.COM *
64011963SAfshin.Ardakani@Sun.COM * This function appends to the object passed to the list. This function assumes
64111963SAfshin.Ardakani@Sun.COM * the lock of the list has already been entered.
64211963SAfshin.Ardakani@Sun.COM *
64311963SAfshin.Ardakani@Sun.COM */
64411963SAfshin.Ardakani@Sun.COM void
smb_llist_insert_tail(smb_llist_t * ll,void * obj)64511963SAfshin.Ardakani@Sun.COM smb_llist_insert_tail(
64611963SAfshin.Ardakani@Sun.COM smb_llist_t *ll,
64711963SAfshin.Ardakani@Sun.COM void *obj)
64811963SAfshin.Ardakani@Sun.COM {
64911963SAfshin.Ardakani@Sun.COM list_insert_tail(&ll->ll_list, obj);
65011963SAfshin.Ardakani@Sun.COM ++ll->ll_wrop;
65111963SAfshin.Ardakani@Sun.COM ++ll->ll_count;
65211963SAfshin.Ardakani@Sun.COM }
65311963SAfshin.Ardakani@Sun.COM
65411963SAfshin.Ardakani@Sun.COM /*
65511963SAfshin.Ardakani@Sun.COM * smb_llist_remove
65611963SAfshin.Ardakani@Sun.COM *
65711963SAfshin.Ardakani@Sun.COM * This function removes the object passed from the list. This function assumes
65811963SAfshin.Ardakani@Sun.COM * the lock of the list has already been entered.
65911963SAfshin.Ardakani@Sun.COM */
66011963SAfshin.Ardakani@Sun.COM void
smb_llist_remove(smb_llist_t * ll,void * obj)66111963SAfshin.Ardakani@Sun.COM smb_llist_remove(
66211963SAfshin.Ardakani@Sun.COM smb_llist_t *ll,
66311963SAfshin.Ardakani@Sun.COM void *obj)
66411963SAfshin.Ardakani@Sun.COM {
66511963SAfshin.Ardakani@Sun.COM list_remove(&ll->ll_list, obj);
66611963SAfshin.Ardakani@Sun.COM ++ll->ll_wrop;
66711963SAfshin.Ardakani@Sun.COM --ll->ll_count;
66811963SAfshin.Ardakani@Sun.COM }
66911963SAfshin.Ardakani@Sun.COM
67011963SAfshin.Ardakani@Sun.COM /*
67111963SAfshin.Ardakani@Sun.COM * smb_llist_get_count
67211963SAfshin.Ardakani@Sun.COM *
67311963SAfshin.Ardakani@Sun.COM * This function returns the number of elements in the specified list.
67411963SAfshin.Ardakani@Sun.COM */
67511963SAfshin.Ardakani@Sun.COM uint32_t
smb_llist_get_count(smb_llist_t * ll)67611963SAfshin.Ardakani@Sun.COM smb_llist_get_count(
67711963SAfshin.Ardakani@Sun.COM smb_llist_t *ll)
67811963SAfshin.Ardakani@Sun.COM {
67911963SAfshin.Ardakani@Sun.COM return (ll->ll_count);
68011963SAfshin.Ardakani@Sun.COM }
68111963SAfshin.Ardakani@Sun.COM
68211963SAfshin.Ardakani@Sun.COM /*
68311963SAfshin.Ardakani@Sun.COM * smb_slist_constructor
68411963SAfshin.Ardakani@Sun.COM *
68511963SAfshin.Ardakani@Sun.COM * Synchronized list constructor.
68611963SAfshin.Ardakani@Sun.COM */
68711963SAfshin.Ardakani@Sun.COM void
smb_slist_constructor(smb_slist_t * sl,size_t size,size_t offset)68811963SAfshin.Ardakani@Sun.COM smb_slist_constructor(
68911963SAfshin.Ardakani@Sun.COM smb_slist_t *sl,
69011963SAfshin.Ardakani@Sun.COM size_t size,
69111963SAfshin.Ardakani@Sun.COM size_t offset)
69211963SAfshin.Ardakani@Sun.COM {
69311963SAfshin.Ardakani@Sun.COM mutex_init(&sl->sl_mutex, NULL, MUTEX_DEFAULT, NULL);
69411963SAfshin.Ardakani@Sun.COM cv_init(&sl->sl_cv, NULL, CV_DEFAULT, NULL);
69511963SAfshin.Ardakani@Sun.COM list_create(&sl->sl_list, size, offset);
69611963SAfshin.Ardakani@Sun.COM sl->sl_count = 0;
69711963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_FALSE;
69811963SAfshin.Ardakani@Sun.COM }
69911963SAfshin.Ardakani@Sun.COM
70011963SAfshin.Ardakani@Sun.COM /*
70111963SAfshin.Ardakani@Sun.COM * smb_slist_destructor
70211963SAfshin.Ardakani@Sun.COM *
70311963SAfshin.Ardakani@Sun.COM * Synchronized list destructor.
70411963SAfshin.Ardakani@Sun.COM */
70511963SAfshin.Ardakani@Sun.COM void
smb_slist_destructor(smb_slist_t * sl)70611963SAfshin.Ardakani@Sun.COM smb_slist_destructor(
70711963SAfshin.Ardakani@Sun.COM smb_slist_t *sl)
70811963SAfshin.Ardakani@Sun.COM {
70912508Samw@Sun.COM VERIFY(sl->sl_count == 0);
71011963SAfshin.Ardakani@Sun.COM
71111963SAfshin.Ardakani@Sun.COM mutex_destroy(&sl->sl_mutex);
71211963SAfshin.Ardakani@Sun.COM cv_destroy(&sl->sl_cv);
71311963SAfshin.Ardakani@Sun.COM list_destroy(&sl->sl_list);
71411963SAfshin.Ardakani@Sun.COM }
71511963SAfshin.Ardakani@Sun.COM
71611963SAfshin.Ardakani@Sun.COM /*
71711963SAfshin.Ardakani@Sun.COM * smb_slist_insert_head
71811963SAfshin.Ardakani@Sun.COM *
71911963SAfshin.Ardakani@Sun.COM * This function inserts the object passed a the beginning of the list.
72011963SAfshin.Ardakani@Sun.COM */
72111963SAfshin.Ardakani@Sun.COM void
smb_slist_insert_head(smb_slist_t * sl,void * obj)72211963SAfshin.Ardakani@Sun.COM smb_slist_insert_head(
72311963SAfshin.Ardakani@Sun.COM smb_slist_t *sl,
72411963SAfshin.Ardakani@Sun.COM void *obj)
72511963SAfshin.Ardakani@Sun.COM {
72611963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex);
72711963SAfshin.Ardakani@Sun.COM list_insert_head(&sl->sl_list, obj);
72811963SAfshin.Ardakani@Sun.COM ++sl->sl_count;
72911963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex);
73011963SAfshin.Ardakani@Sun.COM }
73111963SAfshin.Ardakani@Sun.COM
73211963SAfshin.Ardakani@Sun.COM /*
73311963SAfshin.Ardakani@Sun.COM * smb_slist_insert_tail
73411963SAfshin.Ardakani@Sun.COM *
73511963SAfshin.Ardakani@Sun.COM * This function appends the object passed to the list.
73611963SAfshin.Ardakani@Sun.COM */
73711963SAfshin.Ardakani@Sun.COM void
smb_slist_insert_tail(smb_slist_t * sl,void * obj)73811963SAfshin.Ardakani@Sun.COM smb_slist_insert_tail(
73911963SAfshin.Ardakani@Sun.COM smb_slist_t *sl,
74011963SAfshin.Ardakani@Sun.COM void *obj)
74111963SAfshin.Ardakani@Sun.COM {
74211963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex);
74311963SAfshin.Ardakani@Sun.COM list_insert_tail(&sl->sl_list, obj);
74411963SAfshin.Ardakani@Sun.COM ++sl->sl_count;
74511963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex);
74611963SAfshin.Ardakani@Sun.COM }
74711963SAfshin.Ardakani@Sun.COM
74811963SAfshin.Ardakani@Sun.COM /*
74911963SAfshin.Ardakani@Sun.COM * smb_llist_remove
75011963SAfshin.Ardakani@Sun.COM *
75111963SAfshin.Ardakani@Sun.COM * This function removes the object passed by the caller from the list.
75211963SAfshin.Ardakani@Sun.COM */
75311963SAfshin.Ardakani@Sun.COM void
smb_slist_remove(smb_slist_t * sl,void * obj)75411963SAfshin.Ardakani@Sun.COM smb_slist_remove(
75511963SAfshin.Ardakani@Sun.COM smb_slist_t *sl,
75611963SAfshin.Ardakani@Sun.COM void *obj)
75711963SAfshin.Ardakani@Sun.COM {
75811963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex);
75911963SAfshin.Ardakani@Sun.COM list_remove(&sl->sl_list, obj);
76011963SAfshin.Ardakani@Sun.COM if ((--sl->sl_count == 0) && (sl->sl_waiting)) {
76111963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_FALSE;
76211963SAfshin.Ardakani@Sun.COM cv_broadcast(&sl->sl_cv);
76311963SAfshin.Ardakani@Sun.COM }
76411963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex);
76511963SAfshin.Ardakani@Sun.COM }
76611963SAfshin.Ardakani@Sun.COM
76711963SAfshin.Ardakani@Sun.COM /*
76811963SAfshin.Ardakani@Sun.COM * smb_slist_move_tail
76911963SAfshin.Ardakani@Sun.COM *
77011963SAfshin.Ardakani@Sun.COM * This function transfers all the contents of the synchronized list to the
77111963SAfshin.Ardakani@Sun.COM * list_t provided. It returns the number of objects transferred.
77211963SAfshin.Ardakani@Sun.COM */
77311963SAfshin.Ardakani@Sun.COM uint32_t
smb_slist_move_tail(list_t * lst,smb_slist_t * sl)77411963SAfshin.Ardakani@Sun.COM smb_slist_move_tail(
77511963SAfshin.Ardakani@Sun.COM list_t *lst,
77611963SAfshin.Ardakani@Sun.COM smb_slist_t *sl)
77711963SAfshin.Ardakani@Sun.COM {
77811963SAfshin.Ardakani@Sun.COM uint32_t rv;
77911963SAfshin.Ardakani@Sun.COM
78011963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex);
78111963SAfshin.Ardakani@Sun.COM rv = sl->sl_count;
78211963SAfshin.Ardakani@Sun.COM if (sl->sl_count) {
78311963SAfshin.Ardakani@Sun.COM list_move_tail(lst, &sl->sl_list);
78411963SAfshin.Ardakani@Sun.COM sl->sl_count = 0;
78511963SAfshin.Ardakani@Sun.COM if (sl->sl_waiting) {
78611963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_FALSE;
78711963SAfshin.Ardakani@Sun.COM cv_broadcast(&sl->sl_cv);
78811963SAfshin.Ardakani@Sun.COM }
78911963SAfshin.Ardakani@Sun.COM }
79011963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex);
79111963SAfshin.Ardakani@Sun.COM return (rv);
79211963SAfshin.Ardakani@Sun.COM }
79311963SAfshin.Ardakani@Sun.COM
79411963SAfshin.Ardakani@Sun.COM /*
79511963SAfshin.Ardakani@Sun.COM * smb_slist_obj_move
79611963SAfshin.Ardakani@Sun.COM *
79711963SAfshin.Ardakani@Sun.COM * This function moves an object from one list to the end of the other list. It
79811963SAfshin.Ardakani@Sun.COM * assumes the mutex of each list has been entered.
79911963SAfshin.Ardakani@Sun.COM */
80011963SAfshin.Ardakani@Sun.COM void
smb_slist_obj_move(smb_slist_t * dst,smb_slist_t * src,void * obj)80111963SAfshin.Ardakani@Sun.COM smb_slist_obj_move(
80211963SAfshin.Ardakani@Sun.COM smb_slist_t *dst,
80311963SAfshin.Ardakani@Sun.COM smb_slist_t *src,
80411963SAfshin.Ardakani@Sun.COM void *obj)
80511963SAfshin.Ardakani@Sun.COM {
80611963SAfshin.Ardakani@Sun.COM ASSERT(dst->sl_list.list_offset == src->sl_list.list_offset);
80711963SAfshin.Ardakani@Sun.COM ASSERT(dst->sl_list.list_size == src->sl_list.list_size);
80811963SAfshin.Ardakani@Sun.COM
80911963SAfshin.Ardakani@Sun.COM list_remove(&src->sl_list, obj);
81011963SAfshin.Ardakani@Sun.COM list_insert_tail(&dst->sl_list, obj);
81111963SAfshin.Ardakani@Sun.COM dst->sl_count++;
81211963SAfshin.Ardakani@Sun.COM src->sl_count--;
81311963SAfshin.Ardakani@Sun.COM if ((src->sl_count == 0) && (src->sl_waiting)) {
81411963SAfshin.Ardakani@Sun.COM src->sl_waiting = B_FALSE;
81511963SAfshin.Ardakani@Sun.COM cv_broadcast(&src->sl_cv);
81611963SAfshin.Ardakani@Sun.COM }
81711963SAfshin.Ardakani@Sun.COM }
81811963SAfshin.Ardakani@Sun.COM
81911963SAfshin.Ardakani@Sun.COM /*
82011963SAfshin.Ardakani@Sun.COM * smb_slist_wait_for_empty
82111963SAfshin.Ardakani@Sun.COM *
82211963SAfshin.Ardakani@Sun.COM * This function waits for a list to be emptied.
82311963SAfshin.Ardakani@Sun.COM */
82411963SAfshin.Ardakani@Sun.COM void
smb_slist_wait_for_empty(smb_slist_t * sl)82511963SAfshin.Ardakani@Sun.COM smb_slist_wait_for_empty(
82611963SAfshin.Ardakani@Sun.COM smb_slist_t *sl)
82711963SAfshin.Ardakani@Sun.COM {
82811963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex);
82911963SAfshin.Ardakani@Sun.COM while (sl->sl_count) {
83011963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_TRUE;
83111963SAfshin.Ardakani@Sun.COM cv_wait(&sl->sl_cv, &sl->sl_mutex);
83211963SAfshin.Ardakani@Sun.COM }
83311963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex);
83411963SAfshin.Ardakani@Sun.COM }
83511963SAfshin.Ardakani@Sun.COM
83611963SAfshin.Ardakani@Sun.COM /*
83711963SAfshin.Ardakani@Sun.COM * smb_slist_exit
83811963SAfshin.Ardakani@Sun.COM *
83911963SAfshin.Ardakani@Sun.COM * This function exits the muetx of the list and signal the condition variable
84011963SAfshin.Ardakani@Sun.COM * if the list is empty.
84111963SAfshin.Ardakani@Sun.COM */
84211963SAfshin.Ardakani@Sun.COM void
smb_slist_exit(smb_slist_t * sl)84311963SAfshin.Ardakani@Sun.COM smb_slist_exit(smb_slist_t *sl)
84411963SAfshin.Ardakani@Sun.COM {
84511963SAfshin.Ardakani@Sun.COM if ((sl->sl_count == 0) && (sl->sl_waiting)) {
84611963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_FALSE;
84711963SAfshin.Ardakani@Sun.COM cv_broadcast(&sl->sl_cv);
84811963SAfshin.Ardakani@Sun.COM }
84911963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex);
85011963SAfshin.Ardakani@Sun.COM }
85111963SAfshin.Ardakani@Sun.COM
85211963SAfshin.Ardakani@Sun.COM /*
85311963SAfshin.Ardakani@Sun.COM * smb_thread_entry_point
85411963SAfshin.Ardakani@Sun.COM *
85511963SAfshin.Ardakani@Sun.COM * Common entry point for all the threads created through smb_thread_start.
85611963SAfshin.Ardakani@Sun.COM * The state of the thread is set to "running" at the beginning and moved to
85711963SAfshin.Ardakani@Sun.COM * "exiting" just before calling thread_exit(). The condition variable is
85811963SAfshin.Ardakani@Sun.COM * also signaled.
85911963SAfshin.Ardakani@Sun.COM */
86011963SAfshin.Ardakani@Sun.COM static void
smb_thread_entry_point(smb_thread_t * thread)86111963SAfshin.Ardakani@Sun.COM smb_thread_entry_point(
86211963SAfshin.Ardakani@Sun.COM smb_thread_t *thread)
86311963SAfshin.Ardakani@Sun.COM {
86411963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
86511963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx);
86611963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_state == SMB_THREAD_STATE_STARTING);
86711963SAfshin.Ardakani@Sun.COM thread->sth_th = curthread;
86811963SAfshin.Ardakani@Sun.COM thread->sth_did = thread->sth_th->t_did;
86911963SAfshin.Ardakani@Sun.COM
87011963SAfshin.Ardakani@Sun.COM if (!thread->sth_kill) {
87111963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_RUNNING;
87211963SAfshin.Ardakani@Sun.COM cv_signal(&thread->sth_cv);
87311963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx);
87411963SAfshin.Ardakani@Sun.COM thread->sth_ep(thread, thread->sth_ep_arg);
87511963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx);
87611963SAfshin.Ardakani@Sun.COM }
87711963SAfshin.Ardakani@Sun.COM thread->sth_th = NULL;
87811963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_EXITING;
87911963SAfshin.Ardakani@Sun.COM cv_broadcast(&thread->sth_cv);
88011963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx);
88111963SAfshin.Ardakani@Sun.COM thread_exit();
88211963SAfshin.Ardakani@Sun.COM }
88311963SAfshin.Ardakani@Sun.COM
88411963SAfshin.Ardakani@Sun.COM /*
88511963SAfshin.Ardakani@Sun.COM * smb_thread_init
88611963SAfshin.Ardakani@Sun.COM */
88711963SAfshin.Ardakani@Sun.COM void
smb_thread_init(smb_thread_t * thread,char * name,smb_thread_ep_t ep,void * ep_arg)88811963SAfshin.Ardakani@Sun.COM smb_thread_init(
88911963SAfshin.Ardakani@Sun.COM smb_thread_t *thread,
89011963SAfshin.Ardakani@Sun.COM char *name,
89111963SAfshin.Ardakani@Sun.COM smb_thread_ep_t ep,
892*13138SJose.Borrego@Sun.COM void *ep_arg)
89311963SAfshin.Ardakani@Sun.COM {
89411963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic != SMB_THREAD_MAGIC);
89511963SAfshin.Ardakani@Sun.COM
89611963SAfshin.Ardakani@Sun.COM bzero(thread, sizeof (*thread));
89711963SAfshin.Ardakani@Sun.COM
89811963SAfshin.Ardakani@Sun.COM (void) strlcpy(thread->sth_name, name, sizeof (thread->sth_name));
89911963SAfshin.Ardakani@Sun.COM thread->sth_ep = ep;
90011963SAfshin.Ardakani@Sun.COM thread->sth_ep_arg = ep_arg;
90111963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_EXITED;
90211963SAfshin.Ardakani@Sun.COM mutex_init(&thread->sth_mtx, NULL, MUTEX_DEFAULT, NULL);
90311963SAfshin.Ardakani@Sun.COM cv_init(&thread->sth_cv, NULL, CV_DEFAULT, NULL);
90411963SAfshin.Ardakani@Sun.COM thread->sth_magic = SMB_THREAD_MAGIC;
90511963SAfshin.Ardakani@Sun.COM }
90611963SAfshin.Ardakani@Sun.COM
90711963SAfshin.Ardakani@Sun.COM /*
90811963SAfshin.Ardakani@Sun.COM * smb_thread_destroy
90911963SAfshin.Ardakani@Sun.COM */
91011963SAfshin.Ardakani@Sun.COM void
smb_thread_destroy(smb_thread_t * thread)91111963SAfshin.Ardakani@Sun.COM smb_thread_destroy(
91211963SAfshin.Ardakani@Sun.COM smb_thread_t *thread)
91311963SAfshin.Ardakani@Sun.COM {
91411963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
91511963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_state == SMB_THREAD_STATE_EXITED);
91611963SAfshin.Ardakani@Sun.COM thread->sth_magic = 0;
91711963SAfshin.Ardakani@Sun.COM mutex_destroy(&thread->sth_mtx);
91811963SAfshin.Ardakani@Sun.COM cv_destroy(&thread->sth_cv);
91911963SAfshin.Ardakani@Sun.COM }
92011963SAfshin.Ardakani@Sun.COM
92111963SAfshin.Ardakani@Sun.COM /*
92211963SAfshin.Ardakani@Sun.COM * smb_thread_start
92311963SAfshin.Ardakani@Sun.COM *
92411963SAfshin.Ardakani@Sun.COM * This function starts a thread with the parameters provided. It waits until
92511963SAfshin.Ardakani@Sun.COM * the state of the thread has been moved to running.
92611963SAfshin.Ardakani@Sun.COM */
92711963SAfshin.Ardakani@Sun.COM /*ARGSUSED*/
92811963SAfshin.Ardakani@Sun.COM int
smb_thread_start(smb_thread_t * thread)92911963SAfshin.Ardakani@Sun.COM smb_thread_start(
93011963SAfshin.Ardakani@Sun.COM smb_thread_t *thread)
93111963SAfshin.Ardakani@Sun.COM {
93211963SAfshin.Ardakani@Sun.COM int rc = 0;
93311963SAfshin.Ardakani@Sun.COM kthread_t *tmpthread;
93411963SAfshin.Ardakani@Sun.COM
93511963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
93611963SAfshin.Ardakani@Sun.COM
93711963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx);
93811963SAfshin.Ardakani@Sun.COM switch (thread->sth_state) {
93911963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_EXITED:
94011963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_STARTING;
94111963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx);
94211963SAfshin.Ardakani@Sun.COM tmpthread = thread_create(NULL, 0, smb_thread_entry_point,
94311963SAfshin.Ardakani@Sun.COM thread, 0, &p0, TS_RUN, minclsyspri);
94411963SAfshin.Ardakani@Sun.COM ASSERT(tmpthread != NULL);
94511963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx);
94611963SAfshin.Ardakani@Sun.COM while (thread->sth_state == SMB_THREAD_STATE_STARTING)
94711963SAfshin.Ardakani@Sun.COM cv_wait(&thread->sth_cv, &thread->sth_mtx);
94811963SAfshin.Ardakani@Sun.COM if (thread->sth_state != SMB_THREAD_STATE_RUNNING)
94911963SAfshin.Ardakani@Sun.COM rc = -1;
95011963SAfshin.Ardakani@Sun.COM break;
95111963SAfshin.Ardakani@Sun.COM default:
95211963SAfshin.Ardakani@Sun.COM ASSERT(0);
95311963SAfshin.Ardakani@Sun.COM rc = -1;
95411963SAfshin.Ardakani@Sun.COM break;
95511963SAfshin.Ardakani@Sun.COM }
95611963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx);
95711963SAfshin.Ardakani@Sun.COM return (rc);
95811963SAfshin.Ardakani@Sun.COM }
95911963SAfshin.Ardakani@Sun.COM
96011963SAfshin.Ardakani@Sun.COM /*
96111963SAfshin.Ardakani@Sun.COM * smb_thread_stop
96211963SAfshin.Ardakani@Sun.COM *
96311963SAfshin.Ardakani@Sun.COM * This function signals a thread to kill itself and waits until the "exiting"
96411963SAfshin.Ardakani@Sun.COM * state has been reached.
96511963SAfshin.Ardakani@Sun.COM */
96611963SAfshin.Ardakani@Sun.COM void
smb_thread_stop(smb_thread_t * thread)967*13138SJose.Borrego@Sun.COM smb_thread_stop(smb_thread_t *thread)
96811963SAfshin.Ardakani@Sun.COM {
96911963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
97011963SAfshin.Ardakani@Sun.COM
97111963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx);
97211963SAfshin.Ardakani@Sun.COM switch (thread->sth_state) {
97311963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_RUNNING:
97411963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_STARTING:
97511963SAfshin.Ardakani@Sun.COM if (!thread->sth_kill) {
97611963SAfshin.Ardakani@Sun.COM thread->sth_kill = B_TRUE;
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
smb_thread_signal(smb_thread_t * thread)1017*13138SJose.Borrego@Sun.COM smb_thread_signal(smb_thread_t *thread)
101811963SAfshin.Ardakani@Sun.COM {
101911963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
102011963SAfshin.Ardakani@Sun.COM
102111963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx);
102211963SAfshin.Ardakani@Sun.COM switch (thread->sth_state) {
102311963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_RUNNING:
102411963SAfshin.Ardakani@Sun.COM cv_signal(&thread->sth_cv);
102511963SAfshin.Ardakani@Sun.COM break;
102611963SAfshin.Ardakani@Sun.COM
102711963SAfshin.Ardakani@Sun.COM default:
102811963SAfshin.Ardakani@Sun.COM break;
102911963SAfshin.Ardakani@Sun.COM }
103011963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx);
103111963SAfshin.Ardakani@Sun.COM }
103211963SAfshin.Ardakani@Sun.COM
103311963SAfshin.Ardakani@Sun.COM boolean_t
smb_thread_continue(smb_thread_t * thread)103411963SAfshin.Ardakani@Sun.COM smb_thread_continue(smb_thread_t *thread)
103511963SAfshin.Ardakani@Sun.COM {
103611963SAfshin.Ardakani@Sun.COM boolean_t result;
103711963SAfshin.Ardakani@Sun.COM
103811963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
103911963SAfshin.Ardakani@Sun.COM
104011963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx);
104111963SAfshin.Ardakani@Sun.COM result = smb_thread_continue_timedwait_locked(thread, 0);
104211963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx);
104311963SAfshin.Ardakani@Sun.COM
104411963SAfshin.Ardakani@Sun.COM return (result);
104511963SAfshin.Ardakani@Sun.COM }
104611963SAfshin.Ardakani@Sun.COM
104711963SAfshin.Ardakani@Sun.COM boolean_t
smb_thread_continue_nowait(smb_thread_t * thread)104811963SAfshin.Ardakani@Sun.COM smb_thread_continue_nowait(smb_thread_t *thread)
104911963SAfshin.Ardakani@Sun.COM {
105011963SAfshin.Ardakani@Sun.COM boolean_t result;
105111963SAfshin.Ardakani@Sun.COM
105211963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
105311963SAfshin.Ardakani@Sun.COM
105411963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx);
105511963SAfshin.Ardakani@Sun.COM /*
105611963SAfshin.Ardakani@Sun.COM * Setting ticks=-1 requests a non-blocking check. We will
105711963SAfshin.Ardakani@Sun.COM * still block if the thread is in "suspend" state.
105811963SAfshin.Ardakani@Sun.COM */
105911963SAfshin.Ardakani@Sun.COM result = smb_thread_continue_timedwait_locked(thread, -1);
106011963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx);
106111963SAfshin.Ardakani@Sun.COM
106211963SAfshin.Ardakani@Sun.COM return (result);
106311963SAfshin.Ardakani@Sun.COM }
106411963SAfshin.Ardakani@Sun.COM
106511963SAfshin.Ardakani@Sun.COM boolean_t
smb_thread_continue_timedwait(smb_thread_t * thread,int seconds)106611963SAfshin.Ardakani@Sun.COM smb_thread_continue_timedwait(smb_thread_t *thread, int seconds)
106711963SAfshin.Ardakani@Sun.COM {
106811963SAfshin.Ardakani@Sun.COM boolean_t result;
106911963SAfshin.Ardakani@Sun.COM
107011963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
107111963SAfshin.Ardakani@Sun.COM
107211963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx);
107311963SAfshin.Ardakani@Sun.COM result = smb_thread_continue_timedwait_locked(thread,
107411963SAfshin.Ardakani@Sun.COM SEC_TO_TICK(seconds));
107511963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx);
107611963SAfshin.Ardakani@Sun.COM
107711963SAfshin.Ardakani@Sun.COM return (result);
107811963SAfshin.Ardakani@Sun.COM }
107911963SAfshin.Ardakani@Sun.COM
108011963SAfshin.Ardakani@Sun.COM /*
108111963SAfshin.Ardakani@Sun.COM * smb_thread_continue_timedwait_locked
108211963SAfshin.Ardakani@Sun.COM *
108311963SAfshin.Ardakani@Sun.COM * Internal only. Ticks==-1 means don't block, Ticks == 0 means wait
108411963SAfshin.Ardakani@Sun.COM * indefinitely
108511963SAfshin.Ardakani@Sun.COM */
108611963SAfshin.Ardakani@Sun.COM static boolean_t
smb_thread_continue_timedwait_locked(smb_thread_t * thread,int ticks)108711963SAfshin.Ardakani@Sun.COM smb_thread_continue_timedwait_locked(smb_thread_t *thread, int ticks)
108811963SAfshin.Ardakani@Sun.COM {
108911963SAfshin.Ardakani@Sun.COM boolean_t result;
109011963SAfshin.Ardakani@Sun.COM
109111963SAfshin.Ardakani@Sun.COM /* -1 means don't block */
109211963SAfshin.Ardakani@Sun.COM if (ticks != -1 && !thread->sth_kill) {
109311963SAfshin.Ardakani@Sun.COM if (ticks == 0) {
109411963SAfshin.Ardakani@Sun.COM cv_wait(&thread->sth_cv, &thread->sth_mtx);
109511963SAfshin.Ardakani@Sun.COM } else {
109611963SAfshin.Ardakani@Sun.COM (void) cv_reltimedwait(&thread->sth_cv,
109711963SAfshin.Ardakani@Sun.COM &thread->sth_mtx, (clock_t)ticks, TR_CLOCK_TICK);
109811963SAfshin.Ardakani@Sun.COM }
109911963SAfshin.Ardakani@Sun.COM }
110011963SAfshin.Ardakani@Sun.COM result = (thread->sth_kill == 0);
110111963SAfshin.Ardakani@Sun.COM
110211963SAfshin.Ardakani@Sun.COM return (result);
110311963SAfshin.Ardakani@Sun.COM }
110411963SAfshin.Ardakani@Sun.COM
110511963SAfshin.Ardakani@Sun.COM /*
110611963SAfshin.Ardakani@Sun.COM * smb_rwx_init
110711963SAfshin.Ardakani@Sun.COM */
110811963SAfshin.Ardakani@Sun.COM void
smb_rwx_init(smb_rwx_t * rwx)110911963SAfshin.Ardakani@Sun.COM smb_rwx_init(
111011963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx)
111111963SAfshin.Ardakani@Sun.COM {
111211963SAfshin.Ardakani@Sun.COM bzero(rwx, sizeof (smb_rwx_t));
111311963SAfshin.Ardakani@Sun.COM cv_init(&rwx->rwx_cv, NULL, CV_DEFAULT, NULL);
111411963SAfshin.Ardakani@Sun.COM mutex_init(&rwx->rwx_mutex, NULL, MUTEX_DEFAULT, NULL);
111511963SAfshin.Ardakani@Sun.COM rw_init(&rwx->rwx_lock, NULL, RW_DEFAULT, NULL);
111611963SAfshin.Ardakani@Sun.COM }
111711963SAfshin.Ardakani@Sun.COM
111811963SAfshin.Ardakani@Sun.COM /*
111911963SAfshin.Ardakani@Sun.COM * smb_rwx_destroy
112011963SAfshin.Ardakani@Sun.COM */
112111963SAfshin.Ardakani@Sun.COM void
smb_rwx_destroy(smb_rwx_t * rwx)112211963SAfshin.Ardakani@Sun.COM smb_rwx_destroy(
112311963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx)
112411963SAfshin.Ardakani@Sun.COM {
112511963SAfshin.Ardakani@Sun.COM mutex_destroy(&rwx->rwx_mutex);
112611963SAfshin.Ardakani@Sun.COM cv_destroy(&rwx->rwx_cv);
112711963SAfshin.Ardakani@Sun.COM rw_destroy(&rwx->rwx_lock);
112811963SAfshin.Ardakani@Sun.COM }
112911963SAfshin.Ardakani@Sun.COM
113011963SAfshin.Ardakani@Sun.COM /*
113111963SAfshin.Ardakani@Sun.COM * smb_rwx_rwexit
113211963SAfshin.Ardakani@Sun.COM */
113311963SAfshin.Ardakani@Sun.COM void
smb_rwx_rwexit(smb_rwx_t * rwx)113411963SAfshin.Ardakani@Sun.COM smb_rwx_rwexit(
113511963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx)
113611963SAfshin.Ardakani@Sun.COM {
113711963SAfshin.Ardakani@Sun.COM if (rw_write_held(&rwx->rwx_lock)) {
113811963SAfshin.Ardakani@Sun.COM ASSERT(rw_owner(&rwx->rwx_lock) == curthread);
113911963SAfshin.Ardakani@Sun.COM mutex_enter(&rwx->rwx_mutex);
114011963SAfshin.Ardakani@Sun.COM if (rwx->rwx_waiting) {
114111963SAfshin.Ardakani@Sun.COM rwx->rwx_waiting = B_FALSE;
114211963SAfshin.Ardakani@Sun.COM cv_broadcast(&rwx->rwx_cv);
114311963SAfshin.Ardakani@Sun.COM }
114411963SAfshin.Ardakani@Sun.COM mutex_exit(&rwx->rwx_mutex);
114511963SAfshin.Ardakani@Sun.COM }
114611963SAfshin.Ardakani@Sun.COM rw_exit(&rwx->rwx_lock);
114711963SAfshin.Ardakani@Sun.COM }
114811963SAfshin.Ardakani@Sun.COM
114911963SAfshin.Ardakani@Sun.COM /*
115011963SAfshin.Ardakani@Sun.COM * smb_rwx_rwupgrade
115111963SAfshin.Ardakani@Sun.COM */
115211963SAfshin.Ardakani@Sun.COM krw_t
smb_rwx_rwupgrade(smb_rwx_t * rwx)115311963SAfshin.Ardakani@Sun.COM smb_rwx_rwupgrade(
115411963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx)
115511963SAfshin.Ardakani@Sun.COM {
115611963SAfshin.Ardakani@Sun.COM if (rw_write_held(&rwx->rwx_lock)) {
115711963SAfshin.Ardakani@Sun.COM ASSERT(rw_owner(&rwx->rwx_lock) == curthread);
115811963SAfshin.Ardakani@Sun.COM return (RW_WRITER);
115911963SAfshin.Ardakani@Sun.COM }
116011963SAfshin.Ardakani@Sun.COM if (!rw_tryupgrade(&rwx->rwx_lock)) {
116111963SAfshin.Ardakani@Sun.COM rw_exit(&rwx->rwx_lock);
116211963SAfshin.Ardakani@Sun.COM rw_enter(&rwx->rwx_lock, RW_WRITER);
116311963SAfshin.Ardakani@Sun.COM }
116411963SAfshin.Ardakani@Sun.COM return (RW_READER);
116511963SAfshin.Ardakani@Sun.COM }
116611963SAfshin.Ardakani@Sun.COM
116711963SAfshin.Ardakani@Sun.COM /*
116811963SAfshin.Ardakani@Sun.COM * smb_rwx_rwrestore
116911963SAfshin.Ardakani@Sun.COM */
117011963SAfshin.Ardakani@Sun.COM void
smb_rwx_rwdowngrade(smb_rwx_t * rwx,krw_t mode)117111963SAfshin.Ardakani@Sun.COM smb_rwx_rwdowngrade(
117211963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx,
117311963SAfshin.Ardakani@Sun.COM krw_t mode)
117411963SAfshin.Ardakani@Sun.COM {
117511963SAfshin.Ardakani@Sun.COM ASSERT(rw_write_held(&rwx->rwx_lock));
117611963SAfshin.Ardakani@Sun.COM ASSERT(rw_owner(&rwx->rwx_lock) == curthread);
117711963SAfshin.Ardakani@Sun.COM
117811963SAfshin.Ardakani@Sun.COM if (mode == RW_WRITER) {
117911963SAfshin.Ardakani@Sun.COM return;
118011963SAfshin.Ardakani@Sun.COM }
118111963SAfshin.Ardakani@Sun.COM ASSERT(mode == RW_READER);
118211963SAfshin.Ardakani@Sun.COM mutex_enter(&rwx->rwx_mutex);
118311963SAfshin.Ardakani@Sun.COM if (rwx->rwx_waiting) {
118411963SAfshin.Ardakani@Sun.COM rwx->rwx_waiting = B_FALSE;
118511963SAfshin.Ardakani@Sun.COM cv_broadcast(&rwx->rwx_cv);
118611963SAfshin.Ardakani@Sun.COM }
118711963SAfshin.Ardakani@Sun.COM mutex_exit(&rwx->rwx_mutex);
118811963SAfshin.Ardakani@Sun.COM rw_downgrade(&rwx->rwx_lock);
118911963SAfshin.Ardakani@Sun.COM }
119011963SAfshin.Ardakani@Sun.COM
119111963SAfshin.Ardakani@Sun.COM /*
119211963SAfshin.Ardakani@Sun.COM * smb_rwx_wait
119311963SAfshin.Ardakani@Sun.COM *
119411963SAfshin.Ardakani@Sun.COM * This function assumes the smb_rwx lock was enter in RW_READER or RW_WRITER
119511963SAfshin.Ardakani@Sun.COM * mode. It will:
119611963SAfshin.Ardakani@Sun.COM *
119711963SAfshin.Ardakani@Sun.COM * 1) release the lock and save its current mode.
119811963SAfshin.Ardakani@Sun.COM * 2) wait until the condition variable is signaled. This can happen for
119911963SAfshin.Ardakani@Sun.COM * 2 reasons: When a writer releases the lock or when the time out (if
120011963SAfshin.Ardakani@Sun.COM * provided) expires.
120111963SAfshin.Ardakani@Sun.COM * 3) re-acquire the lock in the mode saved in (1).
120211963SAfshin.Ardakani@Sun.COM */
120311963SAfshin.Ardakani@Sun.COM int
smb_rwx_rwwait(smb_rwx_t * rwx,clock_t timeout)120411963SAfshin.Ardakani@Sun.COM smb_rwx_rwwait(
120511963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx,
120611963SAfshin.Ardakani@Sun.COM clock_t timeout)
120711963SAfshin.Ardakani@Sun.COM {
120811963SAfshin.Ardakani@Sun.COM int rc;
120911963SAfshin.Ardakani@Sun.COM krw_t mode;
121011963SAfshin.Ardakani@Sun.COM
121111963SAfshin.Ardakani@Sun.COM mutex_enter(&rwx->rwx_mutex);
121211963SAfshin.Ardakani@Sun.COM rwx->rwx_waiting = B_TRUE;
121311963SAfshin.Ardakani@Sun.COM mutex_exit(&rwx->rwx_mutex);
121411963SAfshin.Ardakani@Sun.COM
121511963SAfshin.Ardakani@Sun.COM if (rw_write_held(&rwx->rwx_lock)) {
121611963SAfshin.Ardakani@Sun.COM ASSERT(rw_owner(&rwx->rwx_lock) == curthread);
121711963SAfshin.Ardakani@Sun.COM mode = RW_WRITER;
121811963SAfshin.Ardakani@Sun.COM } else {
121911963SAfshin.Ardakani@Sun.COM ASSERT(rw_read_held(&rwx->rwx_lock));
122011963SAfshin.Ardakani@Sun.COM mode = RW_READER;
122111963SAfshin.Ardakani@Sun.COM }
122211963SAfshin.Ardakani@Sun.COM rw_exit(&rwx->rwx_lock);
122311963SAfshin.Ardakani@Sun.COM
122411963SAfshin.Ardakani@Sun.COM mutex_enter(&rwx->rwx_mutex);
122511963SAfshin.Ardakani@Sun.COM if (rwx->rwx_waiting) {
122611963SAfshin.Ardakani@Sun.COM if (timeout == -1) {
122711963SAfshin.Ardakani@Sun.COM rc = 1;
122811963SAfshin.Ardakani@Sun.COM cv_wait(&rwx->rwx_cv, &rwx->rwx_mutex);
122911963SAfshin.Ardakani@Sun.COM } else {
123011963SAfshin.Ardakani@Sun.COM rc = cv_reltimedwait(&rwx->rwx_cv, &rwx->rwx_mutex,
123111963SAfshin.Ardakani@Sun.COM timeout, TR_CLOCK_TICK);
123211963SAfshin.Ardakani@Sun.COM }
123311963SAfshin.Ardakani@Sun.COM }
123411963SAfshin.Ardakani@Sun.COM mutex_exit(&rwx->rwx_mutex);
123511963SAfshin.Ardakani@Sun.COM
123611963SAfshin.Ardakani@Sun.COM rw_enter(&rwx->rwx_lock, mode);
123711963SAfshin.Ardakani@Sun.COM return (rc);
123811963SAfshin.Ardakani@Sun.COM }
123911963SAfshin.Ardakani@Sun.COM
124011963SAfshin.Ardakani@Sun.COM /*
124111963SAfshin.Ardakani@Sun.COM * SMB ID mapping
124211963SAfshin.Ardakani@Sun.COM *
124311963SAfshin.Ardakani@Sun.COM * Solaris ID mapping service (aka Winchester) works with domain SIDs
124411963SAfshin.Ardakani@Sun.COM * and RIDs where domain SIDs are in string format. CIFS service works
124511963SAfshin.Ardakani@Sun.COM * with binary SIDs understandable by CIFS clients. A layer of SMB ID
124611963SAfshin.Ardakani@Sun.COM * mapping functions are implemeted to hide the SID conversion details
124711963SAfshin.Ardakani@Sun.COM * and also hide the handling of array of batch mapping requests.
124811963SAfshin.Ardakani@Sun.COM *
124911963SAfshin.Ardakani@Sun.COM * IMPORTANT NOTE The Winchester API requires a zone. Because CIFS server
125011963SAfshin.Ardakani@Sun.COM * currently only runs in the global zone the global zone is specified.
125111963SAfshin.Ardakani@Sun.COM * This needs to be fixed when the CIFS server supports zones.
125211963SAfshin.Ardakani@Sun.COM */
125311963SAfshin.Ardakani@Sun.COM
125411963SAfshin.Ardakani@Sun.COM static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib);
125511963SAfshin.Ardakani@Sun.COM
125611963SAfshin.Ardakani@Sun.COM /*
125711963SAfshin.Ardakani@Sun.COM * smb_idmap_getid
125811963SAfshin.Ardakani@Sun.COM *
125911963SAfshin.Ardakani@Sun.COM * Maps the given Windows SID to a Solaris ID using the
126011963SAfshin.Ardakani@Sun.COM * simple mapping API.
126111963SAfshin.Ardakani@Sun.COM */
126211963SAfshin.Ardakani@Sun.COM idmap_stat
smb_idmap_getid(smb_sid_t * sid,uid_t * id,int * idtype)126311963SAfshin.Ardakani@Sun.COM smb_idmap_getid(smb_sid_t *sid, uid_t *id, int *idtype)
126411963SAfshin.Ardakani@Sun.COM {
126511963SAfshin.Ardakani@Sun.COM smb_idmap_t sim;
126611963SAfshin.Ardakani@Sun.COM char sidstr[SMB_SID_STRSZ];
126711963SAfshin.Ardakani@Sun.COM
126811963SAfshin.Ardakani@Sun.COM smb_sid_tostr(sid, sidstr);
126911963SAfshin.Ardakani@Sun.COM if (smb_sid_splitstr(sidstr, &sim.sim_rid) != 0)
127011963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_SID);
127111963SAfshin.Ardakani@Sun.COM sim.sim_domsid = sidstr;
127211963SAfshin.Ardakani@Sun.COM sim.sim_id = id;
127311963SAfshin.Ardakani@Sun.COM
127411963SAfshin.Ardakani@Sun.COM switch (*idtype) {
127511963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_USER:
127611963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getuidbysid(global_zone, sim.sim_domsid,
127711963SAfshin.Ardakani@Sun.COM sim.sim_rid, sim.sim_id);
127811963SAfshin.Ardakani@Sun.COM break;
127911963SAfshin.Ardakani@Sun.COM
128011963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUP:
128111963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getgidbysid(global_zone, sim.sim_domsid,
128211963SAfshin.Ardakani@Sun.COM sim.sim_rid, sim.sim_id);
128311963SAfshin.Ardakani@Sun.COM break;
128411963SAfshin.Ardakani@Sun.COM
128511963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_UNKNOWN:
128611963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getpidbysid(global_zone, sim.sim_domsid,
128711963SAfshin.Ardakani@Sun.COM sim.sim_rid, sim.sim_id, &sim.sim_idtype);
128811963SAfshin.Ardakani@Sun.COM break;
128911963SAfshin.Ardakani@Sun.COM
129011963SAfshin.Ardakani@Sun.COM default:
129111963SAfshin.Ardakani@Sun.COM ASSERT(0);
129211963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_ARG);
129311963SAfshin.Ardakani@Sun.COM }
129411963SAfshin.Ardakani@Sun.COM
129511963SAfshin.Ardakani@Sun.COM *idtype = sim.sim_idtype;
129611963SAfshin.Ardakani@Sun.COM
129711963SAfshin.Ardakani@Sun.COM return (sim.sim_stat);
129811963SAfshin.Ardakani@Sun.COM }
129911963SAfshin.Ardakani@Sun.COM
130011963SAfshin.Ardakani@Sun.COM /*
130111963SAfshin.Ardakani@Sun.COM * smb_idmap_getsid
130211963SAfshin.Ardakani@Sun.COM *
130311963SAfshin.Ardakani@Sun.COM * Maps the given Solaris ID to a Windows SID using the
130411963SAfshin.Ardakani@Sun.COM * simple mapping API.
130511963SAfshin.Ardakani@Sun.COM */
130611963SAfshin.Ardakani@Sun.COM idmap_stat
smb_idmap_getsid(uid_t id,int idtype,smb_sid_t ** sid)130711963SAfshin.Ardakani@Sun.COM smb_idmap_getsid(uid_t id, int idtype, smb_sid_t **sid)
130811963SAfshin.Ardakani@Sun.COM {
130911963SAfshin.Ardakani@Sun.COM smb_idmap_t sim;
131011963SAfshin.Ardakani@Sun.COM
131111963SAfshin.Ardakani@Sun.COM switch (idtype) {
131211963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_USER:
131311963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getsidbyuid(global_zone, id,
131411963SAfshin.Ardakani@Sun.COM (const char **)&sim.sim_domsid, &sim.sim_rid);
131511963SAfshin.Ardakani@Sun.COM break;
131611963SAfshin.Ardakani@Sun.COM
131711963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUP:
131811963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getsidbygid(global_zone, id,
131911963SAfshin.Ardakani@Sun.COM (const char **)&sim.sim_domsid, &sim.sim_rid);
132011963SAfshin.Ardakani@Sun.COM break;
132111963SAfshin.Ardakani@Sun.COM
132211963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_EVERYONE:
132311963SAfshin.Ardakani@Sun.COM /* Everyone S-1-1-0 */
132411963SAfshin.Ardakani@Sun.COM sim.sim_domsid = "S-1-1";
132511963SAfshin.Ardakani@Sun.COM sim.sim_rid = 0;
132611963SAfshin.Ardakani@Sun.COM sim.sim_stat = IDMAP_SUCCESS;
132711963SAfshin.Ardakani@Sun.COM break;
132811963SAfshin.Ardakani@Sun.COM
132911963SAfshin.Ardakani@Sun.COM default:
133011963SAfshin.Ardakani@Sun.COM ASSERT(0);
133111963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_ARG);
133211963SAfshin.Ardakani@Sun.COM }
133311963SAfshin.Ardakani@Sun.COM
133411963SAfshin.Ardakani@Sun.COM if (sim.sim_stat != IDMAP_SUCCESS)
133511963SAfshin.Ardakani@Sun.COM return (sim.sim_stat);
133611963SAfshin.Ardakani@Sun.COM
133711963SAfshin.Ardakani@Sun.COM if (sim.sim_domsid == NULL)
133811963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_NOMAPPING);
133911963SAfshin.Ardakani@Sun.COM
134011963SAfshin.Ardakani@Sun.COM sim.sim_sid = smb_sid_fromstr(sim.sim_domsid);
134111963SAfshin.Ardakani@Sun.COM if (sim.sim_sid == NULL)
134211963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_INTERNAL);
134311963SAfshin.Ardakani@Sun.COM
134411963SAfshin.Ardakani@Sun.COM *sid = smb_sid_splice(sim.sim_sid, sim.sim_rid);
134511963SAfshin.Ardakani@Sun.COM smb_sid_free(sim.sim_sid);
134611963SAfshin.Ardakani@Sun.COM if (*sid == NULL)
134711963SAfshin.Ardakani@Sun.COM sim.sim_stat = IDMAP_ERR_INTERNAL;
134811963SAfshin.Ardakani@Sun.COM
134911963SAfshin.Ardakani@Sun.COM return (sim.sim_stat);
135011963SAfshin.Ardakani@Sun.COM }
135111963SAfshin.Ardakani@Sun.COM
135211963SAfshin.Ardakani@Sun.COM /*
135311963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_create
135411963SAfshin.Ardakani@Sun.COM *
135511963SAfshin.Ardakani@Sun.COM * Creates and initializes the context for batch ID mapping.
135611963SAfshin.Ardakani@Sun.COM */
135711963SAfshin.Ardakani@Sun.COM idmap_stat
smb_idmap_batch_create(smb_idmap_batch_t * sib,uint16_t nmap,int flags)135811963SAfshin.Ardakani@Sun.COM smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags)
135911963SAfshin.Ardakani@Sun.COM {
136011963SAfshin.Ardakani@Sun.COM ASSERT(sib);
136111963SAfshin.Ardakani@Sun.COM
136211963SAfshin.Ardakani@Sun.COM bzero(sib, sizeof (smb_idmap_batch_t));
136311963SAfshin.Ardakani@Sun.COM
136411963SAfshin.Ardakani@Sun.COM sib->sib_idmaph = kidmap_get_create(global_zone);
136511963SAfshin.Ardakani@Sun.COM
136611963SAfshin.Ardakani@Sun.COM sib->sib_flags = flags;
136711963SAfshin.Ardakani@Sun.COM sib->sib_nmap = nmap;
136811963SAfshin.Ardakani@Sun.COM sib->sib_size = nmap * sizeof (smb_idmap_t);
136911963SAfshin.Ardakani@Sun.COM sib->sib_maps = kmem_zalloc(sib->sib_size, KM_SLEEP);
137011963SAfshin.Ardakani@Sun.COM
137111963SAfshin.Ardakani@Sun.COM return (IDMAP_SUCCESS);
137211963SAfshin.Ardakani@Sun.COM }
137311963SAfshin.Ardakani@Sun.COM
137411963SAfshin.Ardakani@Sun.COM /*
137511963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_destroy
137611963SAfshin.Ardakani@Sun.COM *
137711963SAfshin.Ardakani@Sun.COM * Frees the batch ID mapping context.
137811963SAfshin.Ardakani@Sun.COM * If ID mapping is Solaris -> Windows it frees memories
137911963SAfshin.Ardakani@Sun.COM * allocated for binary SIDs.
138011963SAfshin.Ardakani@Sun.COM */
138111963SAfshin.Ardakani@Sun.COM void
smb_idmap_batch_destroy(smb_idmap_batch_t * sib)138211963SAfshin.Ardakani@Sun.COM smb_idmap_batch_destroy(smb_idmap_batch_t *sib)
138311963SAfshin.Ardakani@Sun.COM {
138411963SAfshin.Ardakani@Sun.COM char *domsid;
138511963SAfshin.Ardakani@Sun.COM int i;
138611963SAfshin.Ardakani@Sun.COM
138711963SAfshin.Ardakani@Sun.COM ASSERT(sib);
138811963SAfshin.Ardakani@Sun.COM ASSERT(sib->sib_maps);
138911963SAfshin.Ardakani@Sun.COM
139011963SAfshin.Ardakani@Sun.COM if (sib->sib_idmaph)
139111963SAfshin.Ardakani@Sun.COM kidmap_get_destroy(sib->sib_idmaph);
139211963SAfshin.Ardakani@Sun.COM
139311963SAfshin.Ardakani@Sun.COM if (sib->sib_flags & SMB_IDMAP_ID2SID) {
139411963SAfshin.Ardakani@Sun.COM /*
139511963SAfshin.Ardakani@Sun.COM * SIDs are allocated only when mapping
139611963SAfshin.Ardakani@Sun.COM * UID/GID to SIDs
139711963SAfshin.Ardakani@Sun.COM */
139811963SAfshin.Ardakani@Sun.COM for (i = 0; i < sib->sib_nmap; i++)
139911963SAfshin.Ardakani@Sun.COM smb_sid_free(sib->sib_maps[i].sim_sid);
140011963SAfshin.Ardakani@Sun.COM } else if (sib->sib_flags & SMB_IDMAP_SID2ID) {
140111963SAfshin.Ardakani@Sun.COM /*
140211963SAfshin.Ardakani@Sun.COM * SID prefixes are allocated only when mapping
140311963SAfshin.Ardakani@Sun.COM * SIDs to UID/GID
140411963SAfshin.Ardakani@Sun.COM */
140511963SAfshin.Ardakani@Sun.COM for (i = 0; i < sib->sib_nmap; i++) {
140611963SAfshin.Ardakani@Sun.COM domsid = sib->sib_maps[i].sim_domsid;
140711963SAfshin.Ardakani@Sun.COM if (domsid)
140811963SAfshin.Ardakani@Sun.COM smb_mem_free(domsid);
140911963SAfshin.Ardakani@Sun.COM }
141011963SAfshin.Ardakani@Sun.COM }
141111963SAfshin.Ardakani@Sun.COM
141211963SAfshin.Ardakani@Sun.COM if (sib->sib_size && sib->sib_maps)
141311963SAfshin.Ardakani@Sun.COM kmem_free(sib->sib_maps, sib->sib_size);
141411963SAfshin.Ardakani@Sun.COM }
141511963SAfshin.Ardakani@Sun.COM
141611963SAfshin.Ardakani@Sun.COM /*
141711963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_getid
141811963SAfshin.Ardakani@Sun.COM *
141911963SAfshin.Ardakani@Sun.COM * Queue a request to map the given SID to a UID or GID.
142011963SAfshin.Ardakani@Sun.COM *
142111963SAfshin.Ardakani@Sun.COM * sim->sim_id should point to variable that's supposed to
142211963SAfshin.Ardakani@Sun.COM * hold the returned UID/GID. This needs to be setup by caller
142311963SAfshin.Ardakani@Sun.COM * of this function.
142411963SAfshin.Ardakani@Sun.COM *
142511963SAfshin.Ardakani@Sun.COM * If requested ID type is known, it's passed as 'idtype',
142611963SAfshin.Ardakani@Sun.COM * if it's unknown it'll be returned in sim->sim_idtype.
142711963SAfshin.Ardakani@Sun.COM */
142811963SAfshin.Ardakani@Sun.COM idmap_stat
smb_idmap_batch_getid(idmap_get_handle_t * idmaph,smb_idmap_t * sim,smb_sid_t * sid,int idtype)142911963SAfshin.Ardakani@Sun.COM smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
143011963SAfshin.Ardakani@Sun.COM smb_sid_t *sid, int idtype)
143111963SAfshin.Ardakani@Sun.COM {
143211963SAfshin.Ardakani@Sun.COM char strsid[SMB_SID_STRSZ];
143311963SAfshin.Ardakani@Sun.COM idmap_stat idm_stat;
143411963SAfshin.Ardakani@Sun.COM
143511963SAfshin.Ardakani@Sun.COM ASSERT(idmaph);
143611963SAfshin.Ardakani@Sun.COM ASSERT(sim);
143711963SAfshin.Ardakani@Sun.COM ASSERT(sid);
143811963SAfshin.Ardakani@Sun.COM
143911963SAfshin.Ardakani@Sun.COM smb_sid_tostr(sid, strsid);
144011963SAfshin.Ardakani@Sun.COM if (smb_sid_splitstr(strsid, &sim->sim_rid) != 0)
144111963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_SID);
144211963SAfshin.Ardakani@Sun.COM sim->sim_domsid = smb_mem_strdup(strsid);
144311963SAfshin.Ardakani@Sun.COM
144411963SAfshin.Ardakani@Sun.COM switch (idtype) {
144511963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_USER:
144611963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getuidbysid(idmaph, sim->sim_domsid,
144711963SAfshin.Ardakani@Sun.COM sim->sim_rid, sim->sim_id, &sim->sim_stat);
144811963SAfshin.Ardakani@Sun.COM break;
144911963SAfshin.Ardakani@Sun.COM
145011963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUP:
145111963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getgidbysid(idmaph, sim->sim_domsid,
145211963SAfshin.Ardakani@Sun.COM sim->sim_rid, sim->sim_id, &sim->sim_stat);
145311963SAfshin.Ardakani@Sun.COM break;
145411963SAfshin.Ardakani@Sun.COM
145511963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_UNKNOWN:
145611963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getpidbysid(idmaph, sim->sim_domsid,
145711963SAfshin.Ardakani@Sun.COM sim->sim_rid, sim->sim_id, &sim->sim_idtype,
145811963SAfshin.Ardakani@Sun.COM &sim->sim_stat);
145911963SAfshin.Ardakani@Sun.COM break;
146011963SAfshin.Ardakani@Sun.COM
146111963SAfshin.Ardakani@Sun.COM default:
146211963SAfshin.Ardakani@Sun.COM ASSERT(0);
146311963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_ARG);
146411963SAfshin.Ardakani@Sun.COM }
146511963SAfshin.Ardakani@Sun.COM
146611963SAfshin.Ardakani@Sun.COM return (idm_stat);
146711963SAfshin.Ardakani@Sun.COM }
146811963SAfshin.Ardakani@Sun.COM
146911963SAfshin.Ardakani@Sun.COM /*
147011963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_getsid
147111963SAfshin.Ardakani@Sun.COM *
147211963SAfshin.Ardakani@Sun.COM * Queue a request to map the given UID/GID to a SID.
147311963SAfshin.Ardakani@Sun.COM *
147411963SAfshin.Ardakani@Sun.COM * sim->sim_domsid and sim->sim_rid will contain the mapping
147511963SAfshin.Ardakani@Sun.COM * result upon successful process of the batched request.
147611963SAfshin.Ardakani@Sun.COM */
147711963SAfshin.Ardakani@Sun.COM idmap_stat
smb_idmap_batch_getsid(idmap_get_handle_t * idmaph,smb_idmap_t * sim,uid_t id,int idtype)147811963SAfshin.Ardakani@Sun.COM smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
147911963SAfshin.Ardakani@Sun.COM uid_t id, int idtype)
148011963SAfshin.Ardakani@Sun.COM {
148111963SAfshin.Ardakani@Sun.COM idmap_stat idm_stat;
148211963SAfshin.Ardakani@Sun.COM
148311963SAfshin.Ardakani@Sun.COM switch (idtype) {
148411963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_USER:
148511963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getsidbyuid(idmaph, id,
148611963SAfshin.Ardakani@Sun.COM (const char **)&sim->sim_domsid, &sim->sim_rid,
148711963SAfshin.Ardakani@Sun.COM &sim->sim_stat);
148811963SAfshin.Ardakani@Sun.COM break;
148911963SAfshin.Ardakani@Sun.COM
149011963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUP:
149111963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getsidbygid(idmaph, id,
149211963SAfshin.Ardakani@Sun.COM (const char **)&sim->sim_domsid, &sim->sim_rid,
149311963SAfshin.Ardakani@Sun.COM &sim->sim_stat);
149411963SAfshin.Ardakani@Sun.COM break;
149511963SAfshin.Ardakani@Sun.COM
149611963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_OWNERAT:
149711963SAfshin.Ardakani@Sun.COM /* Current Owner S-1-5-32-766 */
149811963SAfshin.Ardakani@Sun.COM sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR;
149911963SAfshin.Ardakani@Sun.COM sim->sim_rid = SECURITY_CURRENT_OWNER_RID;
150011963SAfshin.Ardakani@Sun.COM sim->sim_stat = IDMAP_SUCCESS;
150111963SAfshin.Ardakani@Sun.COM idm_stat = IDMAP_SUCCESS;
150211963SAfshin.Ardakani@Sun.COM break;
150311963SAfshin.Ardakani@Sun.COM
150411963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUPAT:
150511963SAfshin.Ardakani@Sun.COM /* Current Group S-1-5-32-767 */
150611963SAfshin.Ardakani@Sun.COM sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR;
150711963SAfshin.Ardakani@Sun.COM sim->sim_rid = SECURITY_CURRENT_GROUP_RID;
150811963SAfshin.Ardakani@Sun.COM sim->sim_stat = IDMAP_SUCCESS;
150911963SAfshin.Ardakani@Sun.COM idm_stat = IDMAP_SUCCESS;
151011963SAfshin.Ardakani@Sun.COM break;
151111963SAfshin.Ardakani@Sun.COM
151211963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_EVERYONE:
151311963SAfshin.Ardakani@Sun.COM /* Everyone S-1-1-0 */
151411963SAfshin.Ardakani@Sun.COM sim->sim_domsid = NT_WORLD_AUTH_SIDSTR;
151511963SAfshin.Ardakani@Sun.COM sim->sim_rid = 0;
151611963SAfshin.Ardakani@Sun.COM sim->sim_stat = IDMAP_SUCCESS;
151711963SAfshin.Ardakani@Sun.COM idm_stat = IDMAP_SUCCESS;
151811963SAfshin.Ardakani@Sun.COM break;
151911963SAfshin.Ardakani@Sun.COM
152011963SAfshin.Ardakani@Sun.COM default:
152111963SAfshin.Ardakani@Sun.COM ASSERT(0);
152211963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_ARG);
152311963SAfshin.Ardakani@Sun.COM }
152411963SAfshin.Ardakani@Sun.COM
152511963SAfshin.Ardakani@Sun.COM return (idm_stat);
152611963SAfshin.Ardakani@Sun.COM }
152711963SAfshin.Ardakani@Sun.COM
152811963SAfshin.Ardakani@Sun.COM /*
152911963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_binsid
153011963SAfshin.Ardakani@Sun.COM *
153111963SAfshin.Ardakani@Sun.COM * Convert sidrids to binary sids
153211963SAfshin.Ardakani@Sun.COM *
153311963SAfshin.Ardakani@Sun.COM * Returns 0 if successful and non-zero upon failure.
153411963SAfshin.Ardakani@Sun.COM */
153511963SAfshin.Ardakani@Sun.COM static int
smb_idmap_batch_binsid(smb_idmap_batch_t * sib)153611963SAfshin.Ardakani@Sun.COM smb_idmap_batch_binsid(smb_idmap_batch_t *sib)
153711963SAfshin.Ardakani@Sun.COM {
153811963SAfshin.Ardakani@Sun.COM smb_sid_t *sid;
153911963SAfshin.Ardakani@Sun.COM smb_idmap_t *sim;
154011963SAfshin.Ardakani@Sun.COM int i;
154111963SAfshin.Ardakani@Sun.COM
154211963SAfshin.Ardakani@Sun.COM if (sib->sib_flags & SMB_IDMAP_SID2ID)
154311963SAfshin.Ardakani@Sun.COM /* This operation is not required */
154411963SAfshin.Ardakani@Sun.COM return (0);
154511963SAfshin.Ardakani@Sun.COM
154611963SAfshin.Ardakani@Sun.COM sim = sib->sib_maps;
154711963SAfshin.Ardakani@Sun.COM for (i = 0; i < sib->sib_nmap; sim++, i++) {
154811963SAfshin.Ardakani@Sun.COM ASSERT(sim->sim_domsid);
154911963SAfshin.Ardakani@Sun.COM if (sim->sim_domsid == NULL)
155011963SAfshin.Ardakani@Sun.COM return (1);
155111963SAfshin.Ardakani@Sun.COM
155211963SAfshin.Ardakani@Sun.COM if ((sid = smb_sid_fromstr(sim->sim_domsid)) == NULL)
155311963SAfshin.Ardakani@Sun.COM return (1);
155411963SAfshin.Ardakani@Sun.COM
155511963SAfshin.Ardakani@Sun.COM sim->sim_sid = smb_sid_splice(sid, sim->sim_rid);
155611963SAfshin.Ardakani@Sun.COM smb_sid_free(sid);
155711963SAfshin.Ardakani@Sun.COM }
155811963SAfshin.Ardakani@Sun.COM
155911963SAfshin.Ardakani@Sun.COM return (0);
156011963SAfshin.Ardakani@Sun.COM }
156111963SAfshin.Ardakani@Sun.COM
156211963SAfshin.Ardakani@Sun.COM /*
156311963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_getmappings
156411963SAfshin.Ardakani@Sun.COM *
156511963SAfshin.Ardakani@Sun.COM * trigger ID mapping service to get the mappings for queued
156611963SAfshin.Ardakani@Sun.COM * requests.
156711963SAfshin.Ardakani@Sun.COM *
156811963SAfshin.Ardakani@Sun.COM * Checks the result of all the queued requests.
156911963SAfshin.Ardakani@Sun.COM * If this is a Solaris -> Windows mapping it generates
157011963SAfshin.Ardakani@Sun.COM * binary SIDs from returned (domsid, rid) pairs.
157111963SAfshin.Ardakani@Sun.COM */
157211963SAfshin.Ardakani@Sun.COM idmap_stat
smb_idmap_batch_getmappings(smb_idmap_batch_t * sib)157311963SAfshin.Ardakani@Sun.COM smb_idmap_batch_getmappings(smb_idmap_batch_t *sib)
157411963SAfshin.Ardakani@Sun.COM {
157511963SAfshin.Ardakani@Sun.COM idmap_stat idm_stat = IDMAP_SUCCESS;
157611963SAfshin.Ardakani@Sun.COM int i;
157711963SAfshin.Ardakani@Sun.COM
157811963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_get_mappings(sib->sib_idmaph);
157911963SAfshin.Ardakani@Sun.COM if (idm_stat != IDMAP_SUCCESS)
158011963SAfshin.Ardakani@Sun.COM return (idm_stat);
158111963SAfshin.Ardakani@Sun.COM
158211963SAfshin.Ardakani@Sun.COM /*
158311963SAfshin.Ardakani@Sun.COM * Check the status for all the queued requests
158411963SAfshin.Ardakani@Sun.COM */
158511963SAfshin.Ardakani@Sun.COM for (i = 0; i < sib->sib_nmap; i++) {
158611963SAfshin.Ardakani@Sun.COM if (sib->sib_maps[i].sim_stat != IDMAP_SUCCESS)
158711963SAfshin.Ardakani@Sun.COM return (sib->sib_maps[i].sim_stat);
158811963SAfshin.Ardakani@Sun.COM }
158911963SAfshin.Ardakani@Sun.COM
159011963SAfshin.Ardakani@Sun.COM if (smb_idmap_batch_binsid(sib) != 0)
159111963SAfshin.Ardakani@Sun.COM idm_stat = IDMAP_ERR_OTHER;
159211963SAfshin.Ardakani@Sun.COM
159311963SAfshin.Ardakani@Sun.COM return (idm_stat);
159411963SAfshin.Ardakani@Sun.COM }
159511963SAfshin.Ardakani@Sun.COM
159611963SAfshin.Ardakani@Sun.COM uint64_t
smb_time_unix_to_nt(timestruc_t * unix_time)159711963SAfshin.Ardakani@Sun.COM smb_time_unix_to_nt(timestruc_t *unix_time)
159811963SAfshin.Ardakani@Sun.COM {
159911963SAfshin.Ardakani@Sun.COM uint64_t nt_time;
160011963SAfshin.Ardakani@Sun.COM
160111963SAfshin.Ardakani@Sun.COM if ((unix_time->tv_sec == 0) && (unix_time->tv_nsec == 0))
160211963SAfshin.Ardakani@Sun.COM return (0);
160311963SAfshin.Ardakani@Sun.COM
160411963SAfshin.Ardakani@Sun.COM nt_time = unix_time->tv_sec;
160511963SAfshin.Ardakani@Sun.COM nt_time *= 10000000; /* seconds to 100ns */
160611963SAfshin.Ardakani@Sun.COM nt_time += unix_time->tv_nsec / 100;
160711963SAfshin.Ardakani@Sun.COM return (nt_time + NT_TIME_BIAS);
160811963SAfshin.Ardakani@Sun.COM }
160911963SAfshin.Ardakani@Sun.COM
161011963SAfshin.Ardakani@Sun.COM void
smb_time_nt_to_unix(uint64_t nt_time,timestruc_t * unix_time)161111963SAfshin.Ardakani@Sun.COM smb_time_nt_to_unix(uint64_t nt_time, timestruc_t *unix_time)
161211963SAfshin.Ardakani@Sun.COM {
161311963SAfshin.Ardakani@Sun.COM uint32_t seconds;
161411963SAfshin.Ardakani@Sun.COM
161511963SAfshin.Ardakani@Sun.COM ASSERT(unix_time);
161611963SAfshin.Ardakani@Sun.COM
161711963SAfshin.Ardakani@Sun.COM if ((nt_time == 0) || (nt_time == -1)) {
161811963SAfshin.Ardakani@Sun.COM unix_time->tv_sec = 0;
161911963SAfshin.Ardakani@Sun.COM unix_time->tv_nsec = 0;
162011963SAfshin.Ardakani@Sun.COM return;
162111963SAfshin.Ardakani@Sun.COM }
162211963SAfshin.Ardakani@Sun.COM
162311963SAfshin.Ardakani@Sun.COM nt_time -= NT_TIME_BIAS;
162411963SAfshin.Ardakani@Sun.COM seconds = nt_time / 10000000;
162511963SAfshin.Ardakani@Sun.COM unix_time->tv_sec = seconds;
162611963SAfshin.Ardakani@Sun.COM unix_time->tv_nsec = (nt_time % 10000000) * 100;
162711963SAfshin.Ardakani@Sun.COM }
162811963SAfshin.Ardakani@Sun.COM
162911963SAfshin.Ardakani@Sun.COM /*
163011963SAfshin.Ardakani@Sun.COM * smb_time_gmt_to_local, smb_time_local_to_gmt
163111963SAfshin.Ardakani@Sun.COM *
163211963SAfshin.Ardakani@Sun.COM * Apply the gmt offset to convert between local time and gmt
163311963SAfshin.Ardakani@Sun.COM */
163411963SAfshin.Ardakani@Sun.COM int32_t
smb_time_gmt_to_local(smb_request_t * sr,int32_t gmt)163511963SAfshin.Ardakani@Sun.COM smb_time_gmt_to_local(smb_request_t *sr, int32_t gmt)
163611963SAfshin.Ardakani@Sun.COM {
163711963SAfshin.Ardakani@Sun.COM if ((gmt == 0) || (gmt == -1))
163811963SAfshin.Ardakani@Sun.COM return (0);
163911963SAfshin.Ardakani@Sun.COM
164011963SAfshin.Ardakani@Sun.COM return (gmt - sr->sr_gmtoff);
164111963SAfshin.Ardakani@Sun.COM }
164211963SAfshin.Ardakani@Sun.COM
164311963SAfshin.Ardakani@Sun.COM int32_t
smb_time_local_to_gmt(smb_request_t * sr,int32_t local)164411963SAfshin.Ardakani@Sun.COM smb_time_local_to_gmt(smb_request_t *sr, int32_t local)
164511963SAfshin.Ardakani@Sun.COM {
164611963SAfshin.Ardakani@Sun.COM if ((local == 0) || (local == -1))
164711963SAfshin.Ardakani@Sun.COM return (0);
164811963SAfshin.Ardakani@Sun.COM
164911963SAfshin.Ardakani@Sun.COM return (local + sr->sr_gmtoff);
165011963SAfshin.Ardakani@Sun.COM }
165111963SAfshin.Ardakani@Sun.COM
165211963SAfshin.Ardakani@Sun.COM
165311963SAfshin.Ardakani@Sun.COM /*
165411963SAfshin.Ardakani@Sun.COM * smb_time_dos_to_unix
165511963SAfshin.Ardakani@Sun.COM *
165611963SAfshin.Ardakani@Sun.COM * Convert SMB_DATE & SMB_TIME values to a unix timestamp.
165711963SAfshin.Ardakani@Sun.COM *
165811963SAfshin.Ardakani@Sun.COM * A date/time field of 0 means that that server file system
165911963SAfshin.Ardakani@Sun.COM * assigned value need not be changed. The behaviour when the
166011963SAfshin.Ardakani@Sun.COM * date/time field is set to -1 is not documented but is
166111963SAfshin.Ardakani@Sun.COM * generally treated like 0.
166211963SAfshin.Ardakani@Sun.COM * If date or time is 0 or -1 the unix time is returned as 0
166311963SAfshin.Ardakani@Sun.COM * so that the caller can identify and handle this special case.
166411963SAfshin.Ardakani@Sun.COM */
166511963SAfshin.Ardakani@Sun.COM int32_t
smb_time_dos_to_unix(int16_t date,int16_t time)166611963SAfshin.Ardakani@Sun.COM smb_time_dos_to_unix(int16_t date, int16_t time)
166711963SAfshin.Ardakani@Sun.COM {
166811963SAfshin.Ardakani@Sun.COM struct tm atm;
166911963SAfshin.Ardakani@Sun.COM
167011963SAfshin.Ardakani@Sun.COM if (((date == 0) || (time == 0)) ||
167111963SAfshin.Ardakani@Sun.COM ((date == -1) || (time == -1))) {
167211963SAfshin.Ardakani@Sun.COM return (0);
167311963SAfshin.Ardakani@Sun.COM }
167411963SAfshin.Ardakani@Sun.COM
167511963SAfshin.Ardakani@Sun.COM atm.tm_year = ((date >> 9) & 0x3F) + 80;
167611963SAfshin.Ardakani@Sun.COM atm.tm_mon = ((date >> 5) & 0x0F) - 1;
167711963SAfshin.Ardakani@Sun.COM atm.tm_mday = ((date >> 0) & 0x1F);
167811963SAfshin.Ardakani@Sun.COM atm.tm_hour = ((time >> 11) & 0x1F);
167911963SAfshin.Ardakani@Sun.COM atm.tm_min = ((time >> 5) & 0x3F);
168011963SAfshin.Ardakani@Sun.COM atm.tm_sec = ((time >> 0) & 0x1F) << 1;
168111963SAfshin.Ardakani@Sun.COM
168211963SAfshin.Ardakani@Sun.COM return (smb_timegm(&atm));
168311963SAfshin.Ardakani@Sun.COM }
168411963SAfshin.Ardakani@Sun.COM
168511963SAfshin.Ardakani@Sun.COM void
smb_time_unix_to_dos(int32_t ux_time,int16_t * date_p,int16_t * time_p)168611963SAfshin.Ardakani@Sun.COM smb_time_unix_to_dos(int32_t ux_time, int16_t *date_p, int16_t *time_p)
168711963SAfshin.Ardakani@Sun.COM {
168811963SAfshin.Ardakani@Sun.COM struct tm atm;
168911963SAfshin.Ardakani@Sun.COM int i;
169011963SAfshin.Ardakani@Sun.COM time_t tmp_time;
169111963SAfshin.Ardakani@Sun.COM
169211963SAfshin.Ardakani@Sun.COM if (ux_time == 0) {
169311963SAfshin.Ardakani@Sun.COM *date_p = 0;
169411963SAfshin.Ardakani@Sun.COM *time_p = 0;
169511963SAfshin.Ardakani@Sun.COM return;
169611963SAfshin.Ardakani@Sun.COM }
169711963SAfshin.Ardakani@Sun.COM
169811963SAfshin.Ardakani@Sun.COM tmp_time = (time_t)ux_time;
169911963SAfshin.Ardakani@Sun.COM (void) smb_gmtime_r(&tmp_time, &atm);
170011963SAfshin.Ardakani@Sun.COM
170111963SAfshin.Ardakani@Sun.COM if (date_p) {
170211963SAfshin.Ardakani@Sun.COM i = 0;
170311963SAfshin.Ardakani@Sun.COM i += atm.tm_year - 80;
170411963SAfshin.Ardakani@Sun.COM i <<= 4;
170511963SAfshin.Ardakani@Sun.COM i += atm.tm_mon + 1;
170611963SAfshin.Ardakani@Sun.COM i <<= 5;
170711963SAfshin.Ardakani@Sun.COM i += atm.tm_mday;
170811963SAfshin.Ardakani@Sun.COM
170911963SAfshin.Ardakani@Sun.COM *date_p = (short)i;
171011963SAfshin.Ardakani@Sun.COM }
171111963SAfshin.Ardakani@Sun.COM if (time_p) {
171211963SAfshin.Ardakani@Sun.COM i = 0;
171311963SAfshin.Ardakani@Sun.COM i += atm.tm_hour;
171411963SAfshin.Ardakani@Sun.COM i <<= 6;
171511963SAfshin.Ardakani@Sun.COM i += atm.tm_min;
171611963SAfshin.Ardakani@Sun.COM i <<= 5;
171711963SAfshin.Ardakani@Sun.COM i += atm.tm_sec >> 1;
171811963SAfshin.Ardakani@Sun.COM
171911963SAfshin.Ardakani@Sun.COM *time_p = (short)i;
172011963SAfshin.Ardakani@Sun.COM }
172111963SAfshin.Ardakani@Sun.COM }
172211963SAfshin.Ardakani@Sun.COM
172311963SAfshin.Ardakani@Sun.COM
172411963SAfshin.Ardakani@Sun.COM /*
172511963SAfshin.Ardakani@Sun.COM * smb_gmtime_r
172611963SAfshin.Ardakani@Sun.COM *
172711963SAfshin.Ardakani@Sun.COM * Thread-safe version of smb_gmtime. Returns a null pointer if either
172811963SAfshin.Ardakani@Sun.COM * input parameter is a null pointer. Otherwise returns a pointer
172911963SAfshin.Ardakani@Sun.COM * to result.
173011963SAfshin.Ardakani@Sun.COM *
173111963SAfshin.Ardakani@Sun.COM * Day of the week calculation: the Epoch was a thursday.
173211963SAfshin.Ardakani@Sun.COM *
173311963SAfshin.Ardakani@Sun.COM * There are no timezone corrections so tm_isdst and tm_gmtoff are
173411963SAfshin.Ardakani@Sun.COM * always zero, and the zone is always WET.
173511963SAfshin.Ardakani@Sun.COM */
173611963SAfshin.Ardakani@Sun.COM struct tm *
smb_gmtime_r(time_t * clock,struct tm * result)173711963SAfshin.Ardakani@Sun.COM smb_gmtime_r(time_t *clock, struct tm *result)
173811963SAfshin.Ardakani@Sun.COM {
173911963SAfshin.Ardakani@Sun.COM time_t tsec;
174011963SAfshin.Ardakani@Sun.COM int year;
174111963SAfshin.Ardakani@Sun.COM int month;
174211963SAfshin.Ardakani@Sun.COM int sec_per_month;
174311963SAfshin.Ardakani@Sun.COM
174411963SAfshin.Ardakani@Sun.COM if (clock == 0 || result == 0)
174511963SAfshin.Ardakani@Sun.COM return (0);
174611963SAfshin.Ardakani@Sun.COM
174711963SAfshin.Ardakani@Sun.COM bzero(result, sizeof (struct tm));
174811963SAfshin.Ardakani@Sun.COM tsec = *clock;
174911963SAfshin.Ardakani@Sun.COM tsec -= tzh_leapcnt;
175011963SAfshin.Ardakani@Sun.COM
175111963SAfshin.Ardakani@Sun.COM result->tm_wday = tsec / SECSPERDAY;
175211963SAfshin.Ardakani@Sun.COM result->tm_wday = (result->tm_wday + TM_THURSDAY) % DAYSPERWEEK;
175311963SAfshin.Ardakani@Sun.COM
175411963SAfshin.Ardakani@Sun.COM year = EPOCH_YEAR;
175511963SAfshin.Ardakani@Sun.COM while (tsec >= (isleap(year) ? (SECSPERDAY * DAYSPERLYEAR) :
175611963SAfshin.Ardakani@Sun.COM (SECSPERDAY * DAYSPERNYEAR))) {
175711963SAfshin.Ardakani@Sun.COM if (isleap(year))
175811963SAfshin.Ardakani@Sun.COM tsec -= SECSPERDAY * DAYSPERLYEAR;
175911963SAfshin.Ardakani@Sun.COM else
176011963SAfshin.Ardakani@Sun.COM tsec -= SECSPERDAY * DAYSPERNYEAR;
176111963SAfshin.Ardakani@Sun.COM
176211963SAfshin.Ardakani@Sun.COM ++year;
176311963SAfshin.Ardakani@Sun.COM }
176411963SAfshin.Ardakani@Sun.COM
176511963SAfshin.Ardakani@Sun.COM result->tm_year = year - TM_YEAR_BASE;
176611963SAfshin.Ardakani@Sun.COM result->tm_yday = tsec / SECSPERDAY;
176711963SAfshin.Ardakani@Sun.COM
176811963SAfshin.Ardakani@Sun.COM for (month = TM_JANUARY; month <= TM_DECEMBER; ++month) {
176911963SAfshin.Ardakani@Sun.COM sec_per_month = days_in_month[month] * SECSPERDAY;
177011963SAfshin.Ardakani@Sun.COM
177111963SAfshin.Ardakani@Sun.COM if (month == TM_FEBRUARY && isleap(year))
177211963SAfshin.Ardakani@Sun.COM sec_per_month += SECSPERDAY;
177311963SAfshin.Ardakani@Sun.COM
177411963SAfshin.Ardakani@Sun.COM if (tsec < sec_per_month)
177511963SAfshin.Ardakani@Sun.COM break;
177611963SAfshin.Ardakani@Sun.COM
177711963SAfshin.Ardakani@Sun.COM tsec -= sec_per_month;
177811963SAfshin.Ardakani@Sun.COM }
177911963SAfshin.Ardakani@Sun.COM
178011963SAfshin.Ardakani@Sun.COM result->tm_mon = month;
178111963SAfshin.Ardakani@Sun.COM result->tm_mday = (tsec / SECSPERDAY) + 1;
178211963SAfshin.Ardakani@Sun.COM tsec %= SECSPERDAY;
178311963SAfshin.Ardakani@Sun.COM result->tm_sec = tsec % 60;
178411963SAfshin.Ardakani@Sun.COM tsec /= 60;
178511963SAfshin.Ardakani@Sun.COM result->tm_min = tsec % 60;
178611963SAfshin.Ardakani@Sun.COM tsec /= 60;
178711963SAfshin.Ardakani@Sun.COM result->tm_hour = (int)tsec;
178811963SAfshin.Ardakani@Sun.COM
178911963SAfshin.Ardakani@Sun.COM return (result);
179011963SAfshin.Ardakani@Sun.COM }
179111963SAfshin.Ardakani@Sun.COM
179211963SAfshin.Ardakani@Sun.COM
179311963SAfshin.Ardakani@Sun.COM /*
179411963SAfshin.Ardakani@Sun.COM * smb_timegm
179511963SAfshin.Ardakani@Sun.COM *
179611963SAfshin.Ardakani@Sun.COM * Converts the broken-down time in tm to a time value, i.e. the number
179711963SAfshin.Ardakani@Sun.COM * of seconds since the Epoch (00:00:00 UTC, January 1, 1970). This is
179811963SAfshin.Ardakani@Sun.COM * not a POSIX or ANSI function. Per the man page, the input values of
179911963SAfshin.Ardakani@Sun.COM * tm_wday and tm_yday are ignored and, as the input data is assumed to
180011963SAfshin.Ardakani@Sun.COM * represent GMT, we force tm_isdst and tm_gmtoff to 0.
180111963SAfshin.Ardakani@Sun.COM *
180211963SAfshin.Ardakani@Sun.COM * Before returning the clock time, we use smb_gmtime_r to set up tm_wday
180311963SAfshin.Ardakani@Sun.COM * and tm_yday, and bring the other fields within normal range. I don't
180411963SAfshin.Ardakani@Sun.COM * think this is really how it should be done but it's convenient for
180511963SAfshin.Ardakani@Sun.COM * now.
180611963SAfshin.Ardakani@Sun.COM */
180711963SAfshin.Ardakani@Sun.COM time_t
smb_timegm(struct tm * tm)180811963SAfshin.Ardakani@Sun.COM smb_timegm(struct tm *tm)
180911963SAfshin.Ardakani@Sun.COM {
181011963SAfshin.Ardakani@Sun.COM time_t tsec;
181111963SAfshin.Ardakani@Sun.COM int dd;
181211963SAfshin.Ardakani@Sun.COM int mm;
181311963SAfshin.Ardakani@Sun.COM int yy;
181411963SAfshin.Ardakani@Sun.COM int year;
181511963SAfshin.Ardakani@Sun.COM
181611963SAfshin.Ardakani@Sun.COM if (tm == 0)
181711963SAfshin.Ardakani@Sun.COM return (-1);
181811963SAfshin.Ardakani@Sun.COM
181911963SAfshin.Ardakani@Sun.COM year = tm->tm_year + TM_YEAR_BASE;
182011963SAfshin.Ardakani@Sun.COM tsec = tzh_leapcnt;
182111963SAfshin.Ardakani@Sun.COM
182211963SAfshin.Ardakani@Sun.COM for (yy = EPOCH_YEAR; yy < year; ++yy) {
182311963SAfshin.Ardakani@Sun.COM if (isleap(yy))
182411963SAfshin.Ardakani@Sun.COM tsec += SECSPERDAY * DAYSPERLYEAR;
182511963SAfshin.Ardakani@Sun.COM else
182611963SAfshin.Ardakani@Sun.COM tsec += SECSPERDAY * DAYSPERNYEAR;
182711963SAfshin.Ardakani@Sun.COM }
182811963SAfshin.Ardakani@Sun.COM
182911963SAfshin.Ardakani@Sun.COM for (mm = TM_JANUARY; mm < tm->tm_mon; ++mm) {
183011963SAfshin.Ardakani@Sun.COM dd = days_in_month[mm] * SECSPERDAY;
183111963SAfshin.Ardakani@Sun.COM
183211963SAfshin.Ardakani@Sun.COM if (mm == TM_FEBRUARY && isleap(year))
183311963SAfshin.Ardakani@Sun.COM dd += SECSPERDAY;
183411963SAfshin.Ardakani@Sun.COM
183511963SAfshin.Ardakani@Sun.COM tsec += dd;
183611963SAfshin.Ardakani@Sun.COM }
183711963SAfshin.Ardakani@Sun.COM
183811963SAfshin.Ardakani@Sun.COM tsec += (tm->tm_mday - 1) * SECSPERDAY;
183911963SAfshin.Ardakani@Sun.COM tsec += tm->tm_sec;
184011963SAfshin.Ardakani@Sun.COM tsec += tm->tm_min * SECSPERMIN;
184111963SAfshin.Ardakani@Sun.COM tsec += tm->tm_hour * SECSPERHOUR;
184211963SAfshin.Ardakani@Sun.COM
184311963SAfshin.Ardakani@Sun.COM tm->tm_isdst = 0;
184411963SAfshin.Ardakani@Sun.COM (void) smb_gmtime_r(&tsec, tm);
184511963SAfshin.Ardakani@Sun.COM return (tsec);
184611963SAfshin.Ardakani@Sun.COM }
184711963SAfshin.Ardakani@Sun.COM
184811963SAfshin.Ardakani@Sun.COM /*
184911963SAfshin.Ardakani@Sun.COM * smb_pad_align
185011963SAfshin.Ardakani@Sun.COM *
185111963SAfshin.Ardakani@Sun.COM * Returns the number of bytes required to pad an offset to the
185211963SAfshin.Ardakani@Sun.COM * specified alignment.
185311963SAfshin.Ardakani@Sun.COM */
185411963SAfshin.Ardakani@Sun.COM uint32_t
smb_pad_align(uint32_t offset,uint32_t align)185511963SAfshin.Ardakani@Sun.COM smb_pad_align(uint32_t offset, uint32_t align)
185611963SAfshin.Ardakani@Sun.COM {
185711963SAfshin.Ardakani@Sun.COM uint32_t pad = offset % align;
185811963SAfshin.Ardakani@Sun.COM
185911963SAfshin.Ardakani@Sun.COM if (pad != 0)
186011963SAfshin.Ardakani@Sun.COM pad = align - pad;
186111963SAfshin.Ardakani@Sun.COM
186211963SAfshin.Ardakani@Sun.COM return (pad);
186311963SAfshin.Ardakani@Sun.COM }
186411963SAfshin.Ardakani@Sun.COM
186511963SAfshin.Ardakani@Sun.COM /*
186611963SAfshin.Ardakani@Sun.COM * smb_panic
186711963SAfshin.Ardakani@Sun.COM *
186811963SAfshin.Ardakani@Sun.COM * Logs the file name, function name and line number passed in and panics the
186911963SAfshin.Ardakani@Sun.COM * system.
187011963SAfshin.Ardakani@Sun.COM */
187111963SAfshin.Ardakani@Sun.COM void
smb_panic(char * file,const char * func,int line)187211963SAfshin.Ardakani@Sun.COM smb_panic(char *file, const char *func, int line)
187311963SAfshin.Ardakani@Sun.COM {
187411963SAfshin.Ardakani@Sun.COM cmn_err(CE_PANIC, "%s:%s:%d\n", file, func, line);
187511963SAfshin.Ardakani@Sun.COM }
187612508Samw@Sun.COM
187712508Samw@Sun.COM /*
187812508Samw@Sun.COM * Creates an AVL tree and initializes the given smb_avl_t
187912508Samw@Sun.COM * structure using the passed args
188012508Samw@Sun.COM */
188112508Samw@Sun.COM void
smb_avl_create(smb_avl_t * avl,size_t size,size_t offset,smb_avl_nops_t * ops)188212508Samw@Sun.COM smb_avl_create(smb_avl_t *avl, size_t size, size_t offset, smb_avl_nops_t *ops)
188312508Samw@Sun.COM {
188412508Samw@Sun.COM ASSERT(avl);
188512508Samw@Sun.COM ASSERT(ops);
188612508Samw@Sun.COM
188712508Samw@Sun.COM rw_init(&avl->avl_lock, NULL, RW_DEFAULT, NULL);
188812508Samw@Sun.COM mutex_init(&avl->avl_mutex, NULL, MUTEX_DEFAULT, NULL);
188912508Samw@Sun.COM
189012508Samw@Sun.COM avl->avl_nops = ops;
189112508Samw@Sun.COM avl->avl_state = SMB_AVL_STATE_READY;
189212508Samw@Sun.COM avl->avl_refcnt = 0;
189312508Samw@Sun.COM (void) random_get_pseudo_bytes((uint8_t *)&avl->avl_sequence,
189412508Samw@Sun.COM sizeof (uint32_t));
189512508Samw@Sun.COM
189612508Samw@Sun.COM avl_create(&avl->avl_tree, ops->avln_cmp, size, offset);
189712508Samw@Sun.COM }
189812508Samw@Sun.COM
189912508Samw@Sun.COM /*
190012508Samw@Sun.COM * Destroys the specified AVL tree.
190112508Samw@Sun.COM * It waits for all the in-flight operations to finish
190212508Samw@Sun.COM * before destroying the AVL.
190312508Samw@Sun.COM */
190412508Samw@Sun.COM void
smb_avl_destroy(smb_avl_t * avl)190512508Samw@Sun.COM smb_avl_destroy(smb_avl_t *avl)
190612508Samw@Sun.COM {
190712508Samw@Sun.COM void *cookie = NULL;
190812508Samw@Sun.COM void *node;
190912508Samw@Sun.COM
191012508Samw@Sun.COM ASSERT(avl);
191112508Samw@Sun.COM
191212508Samw@Sun.COM mutex_enter(&avl->avl_mutex);
191312508Samw@Sun.COM if (avl->avl_state != SMB_AVL_STATE_READY) {
191412508Samw@Sun.COM mutex_exit(&avl->avl_mutex);
191512508Samw@Sun.COM return;
191612508Samw@Sun.COM }
191712508Samw@Sun.COM
191812508Samw@Sun.COM avl->avl_state = SMB_AVL_STATE_DESTROYING;
191912508Samw@Sun.COM
192012508Samw@Sun.COM while (avl->avl_refcnt > 0)
192112508Samw@Sun.COM (void) cv_wait(&avl->avl_cv, &avl->avl_mutex);
192212508Samw@Sun.COM mutex_exit(&avl->avl_mutex);
192312508Samw@Sun.COM
192412508Samw@Sun.COM rw_enter(&avl->avl_lock, RW_WRITER);
192512508Samw@Sun.COM while ((node = avl_destroy_nodes(&avl->avl_tree, &cookie)) != NULL)
192612508Samw@Sun.COM avl->avl_nops->avln_destroy(node);
192712508Samw@Sun.COM
192812508Samw@Sun.COM avl_destroy(&avl->avl_tree);
192912508Samw@Sun.COM rw_exit(&avl->avl_lock);
193012508Samw@Sun.COM
193112508Samw@Sun.COM rw_destroy(&avl->avl_lock);
193212508Samw@Sun.COM
193312508Samw@Sun.COM mutex_destroy(&avl->avl_mutex);
193412508Samw@Sun.COM bzero(avl, sizeof (smb_avl_t));
193512508Samw@Sun.COM }
193612508Samw@Sun.COM
193712508Samw@Sun.COM /*
193812508Samw@Sun.COM * Adds the given item to the AVL if it's
193912508Samw@Sun.COM * not already there.
194012508Samw@Sun.COM *
194112508Samw@Sun.COM * Returns:
194212508Samw@Sun.COM *
194312508Samw@Sun.COM * ENOTACTIVE AVL is not in READY state
194412508Samw@Sun.COM * EEXIST The item is already in AVL
194512508Samw@Sun.COM */
194612508Samw@Sun.COM int
smb_avl_add(smb_avl_t * avl,void * item)194712508Samw@Sun.COM smb_avl_add(smb_avl_t *avl, void *item)
194812508Samw@Sun.COM {
194912508Samw@Sun.COM avl_index_t where;
195012508Samw@Sun.COM
195112508Samw@Sun.COM ASSERT(avl);
195212508Samw@Sun.COM ASSERT(item);
195312508Samw@Sun.COM
195412508Samw@Sun.COM if (!smb_avl_hold(avl))
195512508Samw@Sun.COM return (ENOTACTIVE);
195612508Samw@Sun.COM
195712508Samw@Sun.COM rw_enter(&avl->avl_lock, RW_WRITER);
195812508Samw@Sun.COM if (avl_find(&avl->avl_tree, item, &where) != NULL) {
195912508Samw@Sun.COM rw_exit(&avl->avl_lock);
196012508Samw@Sun.COM smb_avl_rele(avl);
196112508Samw@Sun.COM return (EEXIST);
196212508Samw@Sun.COM }
196312508Samw@Sun.COM
196412508Samw@Sun.COM avl_insert(&avl->avl_tree, item, where);
196512508Samw@Sun.COM avl->avl_sequence++;
196612508Samw@Sun.COM rw_exit(&avl->avl_lock);
196712508Samw@Sun.COM
196812508Samw@Sun.COM smb_avl_rele(avl);
196912508Samw@Sun.COM return (0);
197012508Samw@Sun.COM }
197112508Samw@Sun.COM
197212508Samw@Sun.COM /*
197312508Samw@Sun.COM * Removes the given item from the AVL.
197412508Samw@Sun.COM * If no reference is left on the item
197512508Samw@Sun.COM * it will also be destroyed by calling the
197612508Samw@Sun.COM * registered destroy operation.
197712508Samw@Sun.COM */
197812508Samw@Sun.COM void
smb_avl_remove(smb_avl_t * avl,void * item)197912508Samw@Sun.COM smb_avl_remove(smb_avl_t *avl, void *item)
198012508Samw@Sun.COM {
198112508Samw@Sun.COM avl_index_t where;
198212508Samw@Sun.COM void *rm_item;
198312508Samw@Sun.COM
198412508Samw@Sun.COM ASSERT(avl);
198512508Samw@Sun.COM ASSERT(item);
198612508Samw@Sun.COM
198712508Samw@Sun.COM if (!smb_avl_hold(avl))
198812508Samw@Sun.COM return;
198912508Samw@Sun.COM
199012508Samw@Sun.COM rw_enter(&avl->avl_lock, RW_WRITER);
199112508Samw@Sun.COM if ((rm_item = avl_find(&avl->avl_tree, item, &where)) == NULL) {
199212508Samw@Sun.COM rw_exit(&avl->avl_lock);
199312508Samw@Sun.COM smb_avl_rele(avl);
199412508Samw@Sun.COM return;
199512508Samw@Sun.COM }
199612508Samw@Sun.COM
199712508Samw@Sun.COM avl_remove(&avl->avl_tree, rm_item);
199812508Samw@Sun.COM if (avl->avl_nops->avln_rele(rm_item))
199912508Samw@Sun.COM avl->avl_nops->avln_destroy(rm_item);
200012508Samw@Sun.COM avl->avl_sequence++;
200112508Samw@Sun.COM rw_exit(&avl->avl_lock);
200212508Samw@Sun.COM
200312508Samw@Sun.COM smb_avl_rele(avl);
200412508Samw@Sun.COM }
200512508Samw@Sun.COM
200612508Samw@Sun.COM /*
200712508Samw@Sun.COM * Looks up the AVL for the given item.
200812508Samw@Sun.COM * If the item is found a hold on the object
200912508Samw@Sun.COM * is taken before the pointer to it is
201012508Samw@Sun.COM * returned to the caller. The caller MUST
201112508Samw@Sun.COM * always call smb_avl_release() after it's done
201212508Samw@Sun.COM * using the returned object to release the hold
201312508Samw@Sun.COM * taken on the object.
201412508Samw@Sun.COM */
201512508Samw@Sun.COM void *
smb_avl_lookup(smb_avl_t * avl,void * item)201612508Samw@Sun.COM smb_avl_lookup(smb_avl_t *avl, void *item)
201712508Samw@Sun.COM {
201812508Samw@Sun.COM void *node = NULL;
201912508Samw@Sun.COM
202012508Samw@Sun.COM ASSERT(avl);
202112508Samw@Sun.COM ASSERT(item);
202212508Samw@Sun.COM
202312508Samw@Sun.COM if (!smb_avl_hold(avl))
202412508Samw@Sun.COM return (NULL);
202512508Samw@Sun.COM
202612508Samw@Sun.COM rw_enter(&avl->avl_lock, RW_READER);
202712508Samw@Sun.COM node = avl_find(&avl->avl_tree, item, NULL);
202812508Samw@Sun.COM if (node != NULL)
202912508Samw@Sun.COM avl->avl_nops->avln_hold(node);
203012508Samw@Sun.COM rw_exit(&avl->avl_lock);
203112508Samw@Sun.COM
203212508Samw@Sun.COM if (node == NULL)
203312508Samw@Sun.COM smb_avl_rele(avl);
203412508Samw@Sun.COM
203512508Samw@Sun.COM return (node);
203612508Samw@Sun.COM }
203712508Samw@Sun.COM
203812508Samw@Sun.COM /*
203912508Samw@Sun.COM * The hold on the given object is released.
204012508Samw@Sun.COM * This function MUST always be called after
204112508Samw@Sun.COM * smb_avl_lookup() and smb_avl_iterate() for
204212508Samw@Sun.COM * the returned object.
204312508Samw@Sun.COM *
204412508Samw@Sun.COM * If AVL is in DESTROYING state, the destroying
204512508Samw@Sun.COM * thread will be notified.
204612508Samw@Sun.COM */
204712508Samw@Sun.COM void
smb_avl_release(smb_avl_t * avl,void * item)204812508Samw@Sun.COM smb_avl_release(smb_avl_t *avl, void *item)
204912508Samw@Sun.COM {
205012508Samw@Sun.COM ASSERT(avl);
205112508Samw@Sun.COM ASSERT(item);
205212508Samw@Sun.COM
205312508Samw@Sun.COM if (avl->avl_nops->avln_rele(item))
205412508Samw@Sun.COM avl->avl_nops->avln_destroy(item);
205512508Samw@Sun.COM
205612508Samw@Sun.COM smb_avl_rele(avl);
205712508Samw@Sun.COM }
205812508Samw@Sun.COM
205912508Samw@Sun.COM /*
206012508Samw@Sun.COM * Initializes the given cursor for the AVL.
206112508Samw@Sun.COM * The cursor will be used to iterate through the AVL
206212508Samw@Sun.COM */
206312508Samw@Sun.COM void
smb_avl_iterinit(smb_avl_t * avl,smb_avl_cursor_t * cursor)206412508Samw@Sun.COM smb_avl_iterinit(smb_avl_t *avl, smb_avl_cursor_t *cursor)
206512508Samw@Sun.COM {
206612508Samw@Sun.COM ASSERT(avl);
206712508Samw@Sun.COM ASSERT(cursor);
206812508Samw@Sun.COM
206912508Samw@Sun.COM cursor->avlc_next = NULL;
207012508Samw@Sun.COM cursor->avlc_sequence = avl->avl_sequence;
207112508Samw@Sun.COM }
207212508Samw@Sun.COM
207312508Samw@Sun.COM /*
207412508Samw@Sun.COM * Iterates through the AVL using the given cursor.
207512508Samw@Sun.COM * It always starts at the beginning and then returns
207612508Samw@Sun.COM * a pointer to the next object on each subsequent call.
207712508Samw@Sun.COM *
207812508Samw@Sun.COM * If a new object is added to or removed from the AVL
207912508Samw@Sun.COM * between two calls to this function, the iteration
208012508Samw@Sun.COM * will terminate prematurely.
208112508Samw@Sun.COM *
208212508Samw@Sun.COM * The caller MUST always call smb_avl_release() after it's
208312508Samw@Sun.COM * done using the returned object to release the hold taken
208412508Samw@Sun.COM * on the object.
208512508Samw@Sun.COM */
208612508Samw@Sun.COM void *
smb_avl_iterate(smb_avl_t * avl,smb_avl_cursor_t * cursor)208712508Samw@Sun.COM smb_avl_iterate(smb_avl_t *avl, smb_avl_cursor_t *cursor)
208812508Samw@Sun.COM {
208912508Samw@Sun.COM void *node;
209012508Samw@Sun.COM
209112508Samw@Sun.COM ASSERT(avl);
209212508Samw@Sun.COM ASSERT(cursor);
209312508Samw@Sun.COM
209412508Samw@Sun.COM if (!smb_avl_hold(avl))
209512508Samw@Sun.COM return (NULL);
209612508Samw@Sun.COM
209712508Samw@Sun.COM rw_enter(&avl->avl_lock, RW_READER);
209812508Samw@Sun.COM if (cursor->avlc_sequence != avl->avl_sequence) {
209912508Samw@Sun.COM rw_exit(&avl->avl_lock);
210012508Samw@Sun.COM smb_avl_rele(avl);
210112508Samw@Sun.COM return (NULL);
210212508Samw@Sun.COM }
210312508Samw@Sun.COM
210412508Samw@Sun.COM if (cursor->avlc_next == NULL)
210512508Samw@Sun.COM node = avl_first(&avl->avl_tree);
210612508Samw@Sun.COM else
210712508Samw@Sun.COM node = AVL_NEXT(&avl->avl_tree, cursor->avlc_next);
210812508Samw@Sun.COM
210912508Samw@Sun.COM if (node != NULL)
211012508Samw@Sun.COM avl->avl_nops->avln_hold(node);
211112508Samw@Sun.COM
211212508Samw@Sun.COM cursor->avlc_next = node;
211312508Samw@Sun.COM rw_exit(&avl->avl_lock);
211412508Samw@Sun.COM
211512508Samw@Sun.COM if (node == NULL)
211612508Samw@Sun.COM smb_avl_rele(avl);
211712508Samw@Sun.COM
211812508Samw@Sun.COM return (node);
211912508Samw@Sun.COM }
212012508Samw@Sun.COM
212112508Samw@Sun.COM /*
212212508Samw@Sun.COM * Increments the AVL reference count in order to
212312508Samw@Sun.COM * prevent the avl from being destroyed while it's
212412508Samw@Sun.COM * being accessed.
212512508Samw@Sun.COM */
212612508Samw@Sun.COM static boolean_t
smb_avl_hold(smb_avl_t * avl)212712508Samw@Sun.COM smb_avl_hold(smb_avl_t *avl)
212812508Samw@Sun.COM {
212912508Samw@Sun.COM mutex_enter(&avl->avl_mutex);
213012508Samw@Sun.COM if (avl->avl_state != SMB_AVL_STATE_READY) {
213112508Samw@Sun.COM mutex_exit(&avl->avl_mutex);
213212508Samw@Sun.COM return (B_FALSE);
213312508Samw@Sun.COM }
213412508Samw@Sun.COM avl->avl_refcnt++;
213512508Samw@Sun.COM mutex_exit(&avl->avl_mutex);
213612508Samw@Sun.COM
213712508Samw@Sun.COM return (B_TRUE);
213812508Samw@Sun.COM }
213912508Samw@Sun.COM
214012508Samw@Sun.COM /*
214112508Samw@Sun.COM * Decrements the AVL reference count to release the
214212508Samw@Sun.COM * hold. If another thread is trying to destroy the
214312508Samw@Sun.COM * AVL and is waiting for the reference count to become
214412508Samw@Sun.COM * 0, it is signaled to wake up.
214512508Samw@Sun.COM */
214612508Samw@Sun.COM static void
smb_avl_rele(smb_avl_t * avl)214712508Samw@Sun.COM smb_avl_rele(smb_avl_t *avl)
214812508Samw@Sun.COM {
214912508Samw@Sun.COM mutex_enter(&avl->avl_mutex);
215012508Samw@Sun.COM ASSERT(avl->avl_refcnt > 0);
215112508Samw@Sun.COM avl->avl_refcnt--;
215212508Samw@Sun.COM if (avl->avl_state == SMB_AVL_STATE_DESTROYING)
215312508Samw@Sun.COM cv_broadcast(&avl->avl_cv);
215412508Samw@Sun.COM mutex_exit(&avl->avl_mutex);
215512508Samw@Sun.COM }
215612508Samw@Sun.COM
215712508Samw@Sun.COM /*
215812508Samw@Sun.COM * smb_latency_init
215912508Samw@Sun.COM */
216012508Samw@Sun.COM void
smb_latency_init(smb_latency_t * lat)216112508Samw@Sun.COM smb_latency_init(smb_latency_t *lat)
216212508Samw@Sun.COM {
216312508Samw@Sun.COM bzero(lat, sizeof (*lat));
216412508Samw@Sun.COM mutex_init(&lat->ly_mutex, NULL, MUTEX_SPIN, (void *)ipltospl(SPL7));
216512508Samw@Sun.COM }
216612508Samw@Sun.COM
216712508Samw@Sun.COM /*
216812508Samw@Sun.COM * smb_latency_destroy
216912508Samw@Sun.COM */
217012508Samw@Sun.COM void
smb_latency_destroy(smb_latency_t * lat)217112508Samw@Sun.COM smb_latency_destroy(smb_latency_t *lat)
217212508Samw@Sun.COM {
217312508Samw@Sun.COM mutex_destroy(&lat->ly_mutex);
217412508Samw@Sun.COM }
217512508Samw@Sun.COM
217612508Samw@Sun.COM /*
217712508Samw@Sun.COM * smb_latency_add_sample
217812508Samw@Sun.COM *
217912508Samw@Sun.COM * Uses the new sample to calculate the new mean and standard deviation. The
218012508Samw@Sun.COM * sample must be a scaled value.
218112508Samw@Sun.COM */
218212508Samw@Sun.COM void
smb_latency_add_sample(smb_latency_t * lat,hrtime_t sample)218312508Samw@Sun.COM smb_latency_add_sample(smb_latency_t *lat, hrtime_t sample)
218412508Samw@Sun.COM {
218512508Samw@Sun.COM hrtime_t a_mean;
218612508Samw@Sun.COM hrtime_t d_mean;
218712508Samw@Sun.COM
218812508Samw@Sun.COM mutex_enter(&lat->ly_mutex);
218912508Samw@Sun.COM lat->ly_a_nreq++;
219012508Samw@Sun.COM lat->ly_a_sum += sample;
219112508Samw@Sun.COM if (lat->ly_a_nreq != 0) {
219212508Samw@Sun.COM a_mean = lat->ly_a_sum / lat->ly_a_nreq;
219312508Samw@Sun.COM lat->ly_a_stddev =
219412508Samw@Sun.COM (sample - a_mean) * (sample - lat->ly_a_mean);
219512508Samw@Sun.COM lat->ly_a_mean = a_mean;
219612508Samw@Sun.COM }
219712508Samw@Sun.COM lat->ly_d_nreq++;
219812508Samw@Sun.COM lat->ly_d_sum += sample;
219912508Samw@Sun.COM if (lat->ly_d_nreq != 0) {
220012508Samw@Sun.COM d_mean = lat->ly_d_sum / lat->ly_d_nreq;
220112508Samw@Sun.COM lat->ly_d_stddev =
220212508Samw@Sun.COM (sample - d_mean) * (sample - lat->ly_d_mean);
220312508Samw@Sun.COM lat->ly_d_mean = d_mean;
220412508Samw@Sun.COM }
220512508Samw@Sun.COM mutex_exit(&lat->ly_mutex);
220612508Samw@Sun.COM }
220712508Samw@Sun.COM
220812508Samw@Sun.COM /*
220912508Samw@Sun.COM * smb_srqueue_init
221012508Samw@Sun.COM */
221112508Samw@Sun.COM void
smb_srqueue_init(smb_srqueue_t * srq)221212508Samw@Sun.COM smb_srqueue_init(smb_srqueue_t *srq)
221312508Samw@Sun.COM {
221412508Samw@Sun.COM bzero(srq, sizeof (*srq));
221512508Samw@Sun.COM mutex_init(&srq->srq_mutex, NULL, MUTEX_SPIN, (void *)ipltospl(SPL7));
221612508Samw@Sun.COM srq->srq_wlastupdate = srq->srq_rlastupdate = gethrtime_unscaled();
221712508Samw@Sun.COM }
221812508Samw@Sun.COM
221912508Samw@Sun.COM /*
222012508Samw@Sun.COM * smb_srqueue_destroy
222112508Samw@Sun.COM */
222212508Samw@Sun.COM void
smb_srqueue_destroy(smb_srqueue_t * srq)222312508Samw@Sun.COM smb_srqueue_destroy(smb_srqueue_t *srq)
222412508Samw@Sun.COM {
222512508Samw@Sun.COM mutex_destroy(&srq->srq_mutex);
222612508Samw@Sun.COM }
222712508Samw@Sun.COM
222812508Samw@Sun.COM /*
222912508Samw@Sun.COM * smb_srqueue_waitq_enter
223012508Samw@Sun.COM */
223112508Samw@Sun.COM void
smb_srqueue_waitq_enter(smb_srqueue_t * srq)223212508Samw@Sun.COM smb_srqueue_waitq_enter(smb_srqueue_t *srq)
223312508Samw@Sun.COM {
223412508Samw@Sun.COM hrtime_t new;
223512508Samw@Sun.COM hrtime_t delta;
223612508Samw@Sun.COM uint32_t wcnt;
223712508Samw@Sun.COM
223812508Samw@Sun.COM mutex_enter(&srq->srq_mutex);
223912508Samw@Sun.COM new = gethrtime_unscaled();
224012508Samw@Sun.COM delta = new - srq->srq_wlastupdate;
224112508Samw@Sun.COM srq->srq_wlastupdate = new;
224212508Samw@Sun.COM wcnt = srq->srq_wcnt++;
224312508Samw@Sun.COM if (wcnt != 0) {
224412508Samw@Sun.COM srq->srq_wlentime += delta * wcnt;
224512508Samw@Sun.COM srq->srq_wtime += delta;
224612508Samw@Sun.COM }
224712508Samw@Sun.COM mutex_exit(&srq->srq_mutex);
224812508Samw@Sun.COM }
224912508Samw@Sun.COM
225012508Samw@Sun.COM /*
225112508Samw@Sun.COM * smb_srqueue_runq_exit
225212508Samw@Sun.COM */
225312508Samw@Sun.COM void
smb_srqueue_runq_exit(smb_srqueue_t * srq)225412508Samw@Sun.COM smb_srqueue_runq_exit(smb_srqueue_t *srq)
225512508Samw@Sun.COM {
225612508Samw@Sun.COM hrtime_t new;
225712508Samw@Sun.COM hrtime_t delta;
225812508Samw@Sun.COM uint32_t rcnt;
225912508Samw@Sun.COM
226012508Samw@Sun.COM mutex_enter(&srq->srq_mutex);
226112508Samw@Sun.COM new = gethrtime_unscaled();
226212508Samw@Sun.COM delta = new - srq->srq_rlastupdate;
226312508Samw@Sun.COM srq->srq_rlastupdate = new;
226412508Samw@Sun.COM rcnt = srq->srq_rcnt--;
226512508Samw@Sun.COM ASSERT(rcnt > 0);
226612508Samw@Sun.COM srq->srq_rlentime += delta * rcnt;
226712508Samw@Sun.COM srq->srq_rtime += delta;
226812508Samw@Sun.COM mutex_exit(&srq->srq_mutex);
226912508Samw@Sun.COM }
227012508Samw@Sun.COM
227112508Samw@Sun.COM /*
227212508Samw@Sun.COM * smb_srqueue_waitq_to_runq
227312508Samw@Sun.COM */
227412508Samw@Sun.COM void
smb_srqueue_waitq_to_runq(smb_srqueue_t * srq)227512508Samw@Sun.COM smb_srqueue_waitq_to_runq(smb_srqueue_t *srq)
227612508Samw@Sun.COM {
227712508Samw@Sun.COM hrtime_t new;
227812508Samw@Sun.COM hrtime_t delta;
227912508Samw@Sun.COM uint32_t wcnt;
228012508Samw@Sun.COM uint32_t rcnt;
228112508Samw@Sun.COM
228212508Samw@Sun.COM mutex_enter(&srq->srq_mutex);
228312508Samw@Sun.COM new = gethrtime_unscaled();
228412508Samw@Sun.COM delta = new - srq->srq_wlastupdate;
228512508Samw@Sun.COM srq->srq_wlastupdate = new;
228612508Samw@Sun.COM wcnt = srq->srq_wcnt--;
228712508Samw@Sun.COM ASSERT(wcnt > 0);
228812508Samw@Sun.COM srq->srq_wlentime += delta * wcnt;
228912508Samw@Sun.COM srq->srq_wtime += delta;
229012508Samw@Sun.COM delta = new - srq->srq_rlastupdate;
229112508Samw@Sun.COM srq->srq_rlastupdate = new;
229212508Samw@Sun.COM rcnt = srq->srq_rcnt++;
229312508Samw@Sun.COM if (rcnt != 0) {
229412508Samw@Sun.COM srq->srq_rlentime += delta * rcnt;
229512508Samw@Sun.COM srq->srq_rtime += delta;
229612508Samw@Sun.COM }
229712508Samw@Sun.COM mutex_exit(&srq->srq_mutex);
229812508Samw@Sun.COM }
229912508Samw@Sun.COM
230012508Samw@Sun.COM /*
230112508Samw@Sun.COM * smb_srqueue_update
230212508Samw@Sun.COM *
230312508Samw@Sun.COM * Takes a snapshot of the smb_sr_stat_t structure passed in.
230412508Samw@Sun.COM */
230512508Samw@Sun.COM void
smb_srqueue_update(smb_srqueue_t * srq,smb_kstat_utilization_t * kd)230612508Samw@Sun.COM smb_srqueue_update(smb_srqueue_t *srq, smb_kstat_utilization_t *kd)
230712508Samw@Sun.COM {
230812508Samw@Sun.COM hrtime_t delta;
230912508Samw@Sun.COM hrtime_t snaptime;
231012508Samw@Sun.COM
231112508Samw@Sun.COM mutex_enter(&srq->srq_mutex);
231212508Samw@Sun.COM snaptime = gethrtime_unscaled();
231312508Samw@Sun.COM delta = snaptime - srq->srq_wlastupdate;
231412508Samw@Sun.COM srq->srq_wlastupdate = snaptime;
231512508Samw@Sun.COM if (srq->srq_wcnt != 0) {
231612508Samw@Sun.COM srq->srq_wlentime += delta * srq->srq_wcnt;
231712508Samw@Sun.COM srq->srq_wtime += delta;
231812508Samw@Sun.COM }
231912508Samw@Sun.COM delta = snaptime - srq->srq_rlastupdate;
232012508Samw@Sun.COM srq->srq_rlastupdate = snaptime;
232112508Samw@Sun.COM if (srq->srq_rcnt != 0) {
232212508Samw@Sun.COM srq->srq_rlentime += delta * srq->srq_rcnt;
232312508Samw@Sun.COM srq->srq_rtime += delta;
232412508Samw@Sun.COM }
232512508Samw@Sun.COM kd->ku_rlentime = srq->srq_rlentime;
232612508Samw@Sun.COM kd->ku_rtime = srq->srq_rtime;
232712508Samw@Sun.COM kd->ku_wlentime = srq->srq_wlentime;
232812508Samw@Sun.COM kd->ku_wtime = srq->srq_wtime;
232912508Samw@Sun.COM mutex_exit(&srq->srq_mutex);
233012508Samw@Sun.COM scalehrtime(&kd->ku_rlentime);
233112508Samw@Sun.COM scalehrtime(&kd->ku_rtime);
233212508Samw@Sun.COM scalehrtime(&kd->ku_wlentime);
233312508Samw@Sun.COM scalehrtime(&kd->ku_wtime);
233412508Samw@Sun.COM }
233512890SJoyce.McIntosh@Sun.COM
233612890SJoyce.McIntosh@Sun.COM void
smb_threshold_init(smb_cmd_threshold_t * ct,char * cmd,int threshold,int timeout)233712890SJoyce.McIntosh@Sun.COM smb_threshold_init(smb_cmd_threshold_t *ct, char *cmd, int threshold,
233812890SJoyce.McIntosh@Sun.COM int timeout)
233912890SJoyce.McIntosh@Sun.COM {
234012890SJoyce.McIntosh@Sun.COM bzero(ct, sizeof (smb_cmd_threshold_t));
234112890SJoyce.McIntosh@Sun.COM mutex_init(&ct->ct_mutex, NULL, MUTEX_DEFAULT, NULL);
234212890SJoyce.McIntosh@Sun.COM ct->ct_cmd = cmd;
234312890SJoyce.McIntosh@Sun.COM ct->ct_threshold = threshold;
234412890SJoyce.McIntosh@Sun.COM ct->ct_event = smb_event_create(timeout);
234512890SJoyce.McIntosh@Sun.COM ct->ct_event_id = smb_event_txid(ct->ct_event);
234612890SJoyce.McIntosh@Sun.COM
234712890SJoyce.McIntosh@Sun.COM if (smb_threshold_debug) {
234812890SJoyce.McIntosh@Sun.COM cmn_err(CE_NOTE, "smb_threshold_init[%s]: threshold (%d), "
234912890SJoyce.McIntosh@Sun.COM "timeout (%d)", cmd, threshold, timeout);
235012890SJoyce.McIntosh@Sun.COM }
235112890SJoyce.McIntosh@Sun.COM }
235212890SJoyce.McIntosh@Sun.COM
235312890SJoyce.McIntosh@Sun.COM /*
235412890SJoyce.McIntosh@Sun.COM * This function must be called prior to SMB_SERVER_STATE_STOPPING state
235512890SJoyce.McIntosh@Sun.COM * so that ct_event can be successfully removed from the event list.
235612890SJoyce.McIntosh@Sun.COM * It should not be called when the server mutex is held or when the
235712890SJoyce.McIntosh@Sun.COM * server is removed from the server list.
235812890SJoyce.McIntosh@Sun.COM */
235912890SJoyce.McIntosh@Sun.COM void
smb_threshold_fini(smb_cmd_threshold_t * ct)236012890SJoyce.McIntosh@Sun.COM smb_threshold_fini(smb_cmd_threshold_t *ct)
236112890SJoyce.McIntosh@Sun.COM {
236212890SJoyce.McIntosh@Sun.COM smb_event_destroy(ct->ct_event);
236312890SJoyce.McIntosh@Sun.COM mutex_destroy(&ct->ct_mutex);
236412890SJoyce.McIntosh@Sun.COM bzero(ct, sizeof (smb_cmd_threshold_t));
236512890SJoyce.McIntosh@Sun.COM }
236612890SJoyce.McIntosh@Sun.COM
236712890SJoyce.McIntosh@Sun.COM /*
236812890SJoyce.McIntosh@Sun.COM * This threshold mechanism can be used to limit the number of simultaneous
236912890SJoyce.McIntosh@Sun.COM * requests, which serves to limit the stress that can be applied to the
237012890SJoyce.McIntosh@Sun.COM * service and also allows the service to respond to requests before the
237112890SJoyce.McIntosh@Sun.COM * client times out and reports that the server is not responding,
237212890SJoyce.McIntosh@Sun.COM *
237312890SJoyce.McIntosh@Sun.COM * If the number of requests exceeds the threshold, new requests will be
237412890SJoyce.McIntosh@Sun.COM * stalled until the number drops back to the threshold. Stalled requests
237512890SJoyce.McIntosh@Sun.COM * will be notified as appropriate, in which case 0 will be returned.
237612890SJoyce.McIntosh@Sun.COM * If the timeout expires before the request is notified, a non-zero errno
237712890SJoyce.McIntosh@Sun.COM * value will be returned.
237812890SJoyce.McIntosh@Sun.COM *
237912890SJoyce.McIntosh@Sun.COM * To avoid a flood of messages, the message rate is throttled as well.
238012890SJoyce.McIntosh@Sun.COM */
238112890SJoyce.McIntosh@Sun.COM int
smb_threshold_enter(smb_cmd_threshold_t * ct)238212890SJoyce.McIntosh@Sun.COM smb_threshold_enter(smb_cmd_threshold_t *ct)
238312890SJoyce.McIntosh@Sun.COM {
238412890SJoyce.McIntosh@Sun.COM int rc;
238512890SJoyce.McIntosh@Sun.COM
238612890SJoyce.McIntosh@Sun.COM mutex_enter(&ct->ct_mutex);
238712890SJoyce.McIntosh@Sun.COM if (ct->ct_active_cnt >= ct->ct_threshold && ct->ct_event != NULL) {
238812890SJoyce.McIntosh@Sun.COM atomic_inc_32(&ct->ct_blocked_cnt);
238912890SJoyce.McIntosh@Sun.COM
239012890SJoyce.McIntosh@Sun.COM if (smb_threshold_debug) {
239112890SJoyce.McIntosh@Sun.COM cmn_err(CE_NOTE, "smb_threshold_enter[%s]: blocked "
239212890SJoyce.McIntosh@Sun.COM "(blocked ops: %u, inflight ops: %u)",
239312890SJoyce.McIntosh@Sun.COM ct->ct_cmd, ct->ct_blocked_cnt, ct->ct_active_cnt);
239412890SJoyce.McIntosh@Sun.COM }
239512890SJoyce.McIntosh@Sun.COM
239612890SJoyce.McIntosh@Sun.COM mutex_exit(&ct->ct_mutex);
239712890SJoyce.McIntosh@Sun.COM
239812890SJoyce.McIntosh@Sun.COM if ((rc = smb_event_wait(ct->ct_event)) != 0) {
239912890SJoyce.McIntosh@Sun.COM if (rc == ECANCELED)
240012890SJoyce.McIntosh@Sun.COM return (rc);
240112890SJoyce.McIntosh@Sun.COM
240212890SJoyce.McIntosh@Sun.COM mutex_enter(&ct->ct_mutex);
240312890SJoyce.McIntosh@Sun.COM if (ct->ct_active_cnt >= ct->ct_threshold) {
240412890SJoyce.McIntosh@Sun.COM
240512890SJoyce.McIntosh@Sun.COM if ((ct->ct_error_cnt %
240612890SJoyce.McIntosh@Sun.COM SMB_THRESHOLD_REPORT_THROTTLE) == 0) {
240712890SJoyce.McIntosh@Sun.COM cmn_err(CE_NOTE, "%s: server busy: "
240812890SJoyce.McIntosh@Sun.COM "threshold %d exceeded)",
240912890SJoyce.McIntosh@Sun.COM ct->ct_cmd, ct->ct_threshold);
241012890SJoyce.McIntosh@Sun.COM }
241112890SJoyce.McIntosh@Sun.COM
241212890SJoyce.McIntosh@Sun.COM atomic_inc_32(&ct->ct_error_cnt);
241312890SJoyce.McIntosh@Sun.COM mutex_exit(&ct->ct_mutex);
241412890SJoyce.McIntosh@Sun.COM return (rc);
241512890SJoyce.McIntosh@Sun.COM }
241612890SJoyce.McIntosh@Sun.COM
241712890SJoyce.McIntosh@Sun.COM mutex_exit(&ct->ct_mutex);
241812890SJoyce.McIntosh@Sun.COM
241912890SJoyce.McIntosh@Sun.COM }
242012890SJoyce.McIntosh@Sun.COM
242112890SJoyce.McIntosh@Sun.COM mutex_enter(&ct->ct_mutex);
242212890SJoyce.McIntosh@Sun.COM atomic_dec_32(&ct->ct_blocked_cnt);
242312890SJoyce.McIntosh@Sun.COM if (smb_threshold_debug) {
242412890SJoyce.McIntosh@Sun.COM cmn_err(CE_NOTE, "smb_threshold_enter[%s]: resumed "
242512890SJoyce.McIntosh@Sun.COM "(blocked ops: %u, inflight ops: %u)", ct->ct_cmd,
242612890SJoyce.McIntosh@Sun.COM ct->ct_blocked_cnt, ct->ct_active_cnt);
242712890SJoyce.McIntosh@Sun.COM }
242812890SJoyce.McIntosh@Sun.COM }
242912890SJoyce.McIntosh@Sun.COM
243012890SJoyce.McIntosh@Sun.COM atomic_inc_32(&ct->ct_active_cnt);
243112890SJoyce.McIntosh@Sun.COM mutex_exit(&ct->ct_mutex);
243212890SJoyce.McIntosh@Sun.COM return (0);
243312890SJoyce.McIntosh@Sun.COM }
243412890SJoyce.McIntosh@Sun.COM
243512890SJoyce.McIntosh@Sun.COM void
smb_threshold_exit(smb_cmd_threshold_t * ct,smb_server_t * sv)243612890SJoyce.McIntosh@Sun.COM smb_threshold_exit(smb_cmd_threshold_t *ct, smb_server_t *sv)
243712890SJoyce.McIntosh@Sun.COM {
243812890SJoyce.McIntosh@Sun.COM mutex_enter(&ct->ct_mutex);
243912890SJoyce.McIntosh@Sun.COM atomic_dec_32(&ct->ct_active_cnt);
244012890SJoyce.McIntosh@Sun.COM mutex_exit(&ct->ct_mutex);
244112890SJoyce.McIntosh@Sun.COM smb_event_notify(sv, ct->ct_event_id);
244212890SJoyce.McIntosh@Sun.COM }
2443