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