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