1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 /*
28 * A few excerpts from smb_kutil.c
29 */
30
31 #include <sys/param.h>
32 #include <sys/types.h>
33 #include <sys/atomic.h>
34 #include <sys/debug.h>
35 #include <sys/time.h>
36 #include <sys/stddef.h>
37 #include <smbsrv/smb_kproto.h>
38
39
40 /*
41 * smb_llist_constructor
42 *
43 * This function initializes a locked list.
44 */
45 void
smb_llist_constructor(smb_llist_t * ll,size_t size,size_t offset)46 smb_llist_constructor(
47 smb_llist_t *ll,
48 size_t size,
49 size_t offset)
50 {
51 rw_init(&ll->ll_lock, NULL, RW_DEFAULT, NULL);
52 mutex_init(&ll->ll_mutex, NULL, MUTEX_DEFAULT, NULL);
53 list_create(&ll->ll_list, size, offset);
54 list_create(&ll->ll_deleteq, sizeof (smb_dtor_t),
55 offsetof(smb_dtor_t, dt_lnd));
56 ll->ll_count = 0;
57 ll->ll_wrop = 0;
58 ll->ll_deleteq_count = 0;
59 ll->ll_flushing = B_FALSE;
60 }
61
62 /*
63 * Flush the delete queue and destroy a locked list.
64 */
65 void
smb_llist_destructor(smb_llist_t * ll)66 smb_llist_destructor(
67 smb_llist_t *ll)
68 {
69 /* smb_llist_flush(ll); */
70
71 ASSERT(ll->ll_count == 0);
72 ASSERT(ll->ll_deleteq_count == 0);
73
74 rw_destroy(&ll->ll_lock);
75 list_destroy(&ll->ll_list);
76 list_destroy(&ll->ll_deleteq);
77 mutex_destroy(&ll->ll_mutex);
78 }
79
80 void
smb_llist_enter(smb_llist_t * ll,krw_t mode)81 smb_llist_enter(smb_llist_t *ll, krw_t mode)
82 {
83 rw_enter(&ll->ll_lock, mode);
84 }
85
86 /*
87 * Exit the list lock and process the delete queue.
88 */
89 void
smb_llist_exit(smb_llist_t * ll)90 smb_llist_exit(smb_llist_t *ll)
91 {
92 rw_exit(&ll->ll_lock);
93 /* smb_llist_flush(ll); */
94 }
95
96 /*
97 * smb_llist_upgrade
98 *
99 * This function tries to upgrade the lock of the locked list. It assumes the
100 * locked has already been entered in RW_READER mode. It first tries using the
101 * Solaris function rw_tryupgrade(). If that call fails the lock is released
102 * and reentered in RW_WRITER mode. In that last case a window is opened during
103 * which the contents of the list may have changed. The return code indicates
104 * whether or not the list was modified when the lock was exited.
105 */
smb_llist_upgrade(smb_llist_t * ll)106 int smb_llist_upgrade(
107 smb_llist_t *ll)
108 {
109 uint64_t wrop;
110
111 if (rw_tryupgrade(&ll->ll_lock) != 0) {
112 return (0);
113 }
114 wrop = ll->ll_wrop;
115 rw_exit(&ll->ll_lock);
116 rw_enter(&ll->ll_lock, RW_WRITER);
117 return (wrop != ll->ll_wrop);
118 }
119
120 /*
121 * smb_llist_insert_head
122 *
123 * This function inserts the object passed a the beginning of the list. This
124 * function assumes the lock of the list has already been entered.
125 */
126 void
smb_llist_insert_head(smb_llist_t * ll,void * obj)127 smb_llist_insert_head(
128 smb_llist_t *ll,
129 void *obj)
130 {
131 list_insert_head(&ll->ll_list, obj);
132 ++ll->ll_wrop;
133 ++ll->ll_count;
134 }
135
136 /*
137 * smb_llist_insert_tail
138 *
139 * This function appends to the object passed to the list. This function assumes
140 * the lock of the list has already been entered.
141 *
142 */
143 void
smb_llist_insert_tail(smb_llist_t * ll,void * obj)144 smb_llist_insert_tail(
145 smb_llist_t *ll,
146 void *obj)
147 {
148 list_insert_tail(&ll->ll_list, obj);
149 ++ll->ll_wrop;
150 ++ll->ll_count;
151 }
152
153 /*
154 * smb_llist_remove
155 *
156 * This function removes the object passed from the list. This function assumes
157 * the lock of the list has already been entered.
158 */
159 void
smb_llist_remove(smb_llist_t * ll,void * obj)160 smb_llist_remove(
161 smb_llist_t *ll,
162 void *obj)
163 {
164 list_remove(&ll->ll_list, obj);
165 ++ll->ll_wrop;
166 --ll->ll_count;
167 }
168
169 /*
170 * smb_llist_get_count
171 *
172 * This function returns the number of elements in the specified list.
173 */
174 uint32_t
smb_llist_get_count(smb_llist_t * ll)175 smb_llist_get_count(
176 smb_llist_t *ll)
177 {
178 return (ll->ll_count);
179 }
180