1*c39526b7SPramod Gunjikar /*
2*c39526b7SPramod Gunjikar  * CDDL HEADER START
3*c39526b7SPramod Gunjikar  *
4*c39526b7SPramod Gunjikar  * The contents of this file are subject to the terms of the
5*c39526b7SPramod Gunjikar  * Common Development and Distribution License (the "License").
6*c39526b7SPramod Gunjikar  * You may not use this file except in compliance with the License.
7*c39526b7SPramod Gunjikar  *
8*c39526b7SPramod Gunjikar  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*c39526b7SPramod Gunjikar  * or http://www.opensolaris.org/os/licensing.
10*c39526b7SPramod Gunjikar  * See the License for the specific language governing permissions
11*c39526b7SPramod Gunjikar  * and limitations under the License.
12*c39526b7SPramod Gunjikar  *
13*c39526b7SPramod Gunjikar  * When distributing Covered Code, include this CDDL HEADER in each
14*c39526b7SPramod Gunjikar  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*c39526b7SPramod Gunjikar  * If applicable, add the following below this CDDL HEADER, with the
16*c39526b7SPramod Gunjikar  * fields enclosed by brackets "[]" replaced with your own identifying
17*c39526b7SPramod Gunjikar  * information: Portions Copyright [yyyy] [name of copyright owner]
18*c39526b7SPramod Gunjikar  *
19*c39526b7SPramod Gunjikar  * CDDL HEADER END
20*c39526b7SPramod Gunjikar  */
21*c39526b7SPramod Gunjikar 
22*c39526b7SPramod Gunjikar /*
23*c39526b7SPramod Gunjikar  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*c39526b7SPramod Gunjikar  */
25*c39526b7SPramod Gunjikar 
26*c39526b7SPramod Gunjikar /*
27*c39526b7SPramod Gunjikar  * User Objects.
28*c39526b7SPramod Gunjikar  *
29*c39526b7SPramod Gunjikar  * User objects are used to manage and protect resources that
30*c39526b7SPramod Gunjikar  * have been created for a user context.  Each user object
31*c39526b7SPramod Gunjikar  * maintains a reference count and a read/write mutex to
32*c39526b7SPramod Gunjikar  * provide the appropriate access to the object depending
33*c39526b7SPramod Gunjikar  * on the operation at hand.
34*c39526b7SPramod Gunjikar  *
35*c39526b7SPramod Gunjikar  * For example when initializing or creating a PD user object,
36*c39526b7SPramod Gunjikar  * the active context would hold a write lock, but to simply
37*c39526b7SPramod Gunjikar  * reference the PD object as in a CQ create operation, a
38*c39526b7SPramod Gunjikar  * read lock is only required.
39*c39526b7SPramod Gunjikar  *
40*c39526b7SPramod Gunjikar  * Each user object also maintains a "live" flag.  If this flag
41*c39526b7SPramod Gunjikar  * is not set, then lookups on this user object will fail
42*c39526b7SPramod Gunjikar  * even if it still resides in the associated user object
43*c39526b7SPramod Gunjikar  * management table.  This specifically handles the case
44*c39526b7SPramod Gunjikar  * where a get operation blocks and does not acquire the lock
45*c39526b7SPramod Gunjikar  * until after the object has been destroyed (but not yet
46*c39526b7SPramod Gunjikar  * released).  Destroy operations set the "live" flag to 0
47*c39526b7SPramod Gunjikar  * prior to dropping their write lock on the user object.
48*c39526b7SPramod Gunjikar  * This allows the reader to realize when it receives the
49*c39526b7SPramod Gunjikar  * lock that the object has been destroyed so it can then
50*c39526b7SPramod Gunjikar  * release it's reference to the user object, and allow it to
51*c39526b7SPramod Gunjikar  * be freed (the storage will not be freed until the last reference
52*c39526b7SPramod Gunjikar  * is released).
53*c39526b7SPramod Gunjikar  */
54*c39526b7SPramod Gunjikar #include	<sys/debug.h>
55*c39526b7SPramod Gunjikar #include	<sys/kmem.h>
56*c39526b7SPramod Gunjikar #include	<sys/sunddi.h>
57*c39526b7SPramod Gunjikar #include	<sys/ib/clients/of/sol_ofs/sol_ofs_common.h>
58*c39526b7SPramod Gunjikar 
59*c39526b7SPramod Gunjikar extern char	*sol_ofs_dbg_str;
60*c39526b7SPramod Gunjikar static sol_ofs_uobj_t *ofs_uobj_find(sol_ofs_uobj_table_t *,
61*c39526b7SPramod Gunjikar     uint_t, int);
62*c39526b7SPramod Gunjikar 
63*c39526b7SPramod Gunjikar /*
64*c39526b7SPramod Gunjikar  * Function:
65*c39526b7SPramod Gunjikar  *	sol_ofs_uobj_tbl_init
66*c39526b7SPramod Gunjikar  * Input:
67*c39526b7SPramod Gunjikar  *	uo_tbl	- A pointer to the user object resource management table
68*c39526b7SPramod Gunjikar  *		  to initialize.
69*c39526b7SPramod Gunjikar  * Output:
70*c39526b7SPramod Gunjikar  *	None
71*c39526b7SPramod Gunjikar  * Returns:
72*c39526b7SPramod Gunjikar  *	None
73*c39526b7SPramod Gunjikar  * Description:
74*c39526b7SPramod Gunjikar  * 	Initializes the specified user object resource managment table.
75*c39526b7SPramod Gunjikar  */
76*c39526b7SPramod Gunjikar void
sol_ofs_uobj_tbl_init(sol_ofs_uobj_table_t * uo_tbl,size_t uobj_sz)77*c39526b7SPramod Gunjikar sol_ofs_uobj_tbl_init(sol_ofs_uobj_table_t *uo_tbl, size_t uobj_sz)
78*c39526b7SPramod Gunjikar {
79*c39526b7SPramod Gunjikar 	ASSERT(uo_tbl != NULL);
80*c39526b7SPramod Gunjikar 
81*c39526b7SPramod Gunjikar 	rw_init(&uo_tbl->uobj_tbl_lock, NULL, RW_DRIVER, NULL);
82*c39526b7SPramod Gunjikar 	uo_tbl->uobj_tbl_used_blks = 0;
83*c39526b7SPramod Gunjikar 	uo_tbl->uobj_tbl_num_blks = 0;
84*c39526b7SPramod Gunjikar 	uo_tbl->uobj_tbl_uo_cnt = 0;
85*c39526b7SPramod Gunjikar 	uo_tbl->uobj_tbl_uo_sz = uobj_sz;
86*c39526b7SPramod Gunjikar 	uo_tbl->uobj_tbl_uo_root = NULL;
87*c39526b7SPramod Gunjikar }
88*c39526b7SPramod Gunjikar 
89*c39526b7SPramod Gunjikar /*
90*c39526b7SPramod Gunjikar  * Function:
91*c39526b7SPramod Gunjikar  *	sol_ofs_uobj_tbl_fini
92*c39526b7SPramod Gunjikar  * Input:
93*c39526b7SPramod Gunjikar  *	uo_tbl	- A pointer to the user object resource management table
94*c39526b7SPramod Gunjikar  *		  to be released.
95*c39526b7SPramod Gunjikar  * Output:
96*c39526b7SPramod Gunjikar  *	None
97*c39526b7SPramod Gunjikar  * Returns:
98*c39526b7SPramod Gunjikar  *	None
99*c39526b7SPramod Gunjikar  * Description:
100*c39526b7SPramod Gunjikar  * 	Releases any resources held by the specified user object resource
101*c39526b7SPramod Gunjikar  *	managment table.  The table is no longer valid upon return. NOTE:
102*c39526b7SPramod Gunjikar  *	the table should be empty when this routine is called, so this
103*c39526b7SPramod Gunjikar  *	really is more of just a sanity check.
104*c39526b7SPramod Gunjikar  */
105*c39526b7SPramod Gunjikar void
sol_ofs_uobj_tbl_fini(sol_ofs_uobj_table_t * uo_tbl)106*c39526b7SPramod Gunjikar sol_ofs_uobj_tbl_fini(sol_ofs_uobj_table_t *uo_tbl)
107*c39526b7SPramod Gunjikar {
108*c39526b7SPramod Gunjikar 	int			i, j;
109*c39526b7SPramod Gunjikar 	uint32_t	size;
110*c39526b7SPramod Gunjikar 	sol_ofs_uobj_blk_t	*blk;
111*c39526b7SPramod Gunjikar 
112*c39526b7SPramod Gunjikar 	ASSERT(uo_tbl != NULL);
113*c39526b7SPramod Gunjikar 
114*c39526b7SPramod Gunjikar 	rw_enter(&uo_tbl->uobj_tbl_lock, RW_WRITER);
115*c39526b7SPramod Gunjikar 
116*c39526b7SPramod Gunjikar 	if (uo_tbl->uobj_tbl_uo_cnt > 0) {
117*c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str,
118*c39526b7SPramod Gunjikar 		    "UOBJ TBL FINI: object count not zero (cnt=%d)",
119*c39526b7SPramod Gunjikar 		    uo_tbl->uobj_tbl_uo_cnt);
120*c39526b7SPramod Gunjikar 	}
121*c39526b7SPramod Gunjikar 
122*c39526b7SPramod Gunjikar 	/*
123*c39526b7SPramod Gunjikar 	 * Go through the roots looking for blocks to free.  Warn if any
124*c39526b7SPramod Gunjikar 	 * our found (there shouldn't be any).
125*c39526b7SPramod Gunjikar 	 */
126*c39526b7SPramod Gunjikar 	for (i = 0; i < uo_tbl->uobj_tbl_used_blks; i++) {
127*c39526b7SPramod Gunjikar 		blk = uo_tbl->uobj_tbl_uo_root[i];
128*c39526b7SPramod Gunjikar 		if (!blk) {
129*c39526b7SPramod Gunjikar 			continue;
130*c39526b7SPramod Gunjikar 		}
131*c39526b7SPramod Gunjikar 		for (j = 0; j < SOL_OFS_UO_BLKSZ; j++) {
132*c39526b7SPramod Gunjikar 			if (blk->ofs_uoblk_blks[j])   {
133*c39526b7SPramod Gunjikar 				/*
134*c39526b7SPramod Gunjikar 				 * This is an error, we may want to free
135*c39526b7SPramod Gunjikar 				 * ultimately sol_ofs_uobj_free
136*c39526b7SPramod Gunjikar 				 * (blk->ofs_uoblk_blks[j]);
137*c39526b7SPramod Gunjikar 				 */
138*c39526b7SPramod Gunjikar 				SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str,
139*c39526b7SPramod Gunjikar 				    "UOBJ TBL FINI: blk %p, slot %d non null",
140*c39526b7SPramod Gunjikar 				    blk, j);
141*c39526b7SPramod Gunjikar 			}
142*c39526b7SPramod Gunjikar 		}
143*c39526b7SPramod Gunjikar 		kmem_free(blk, sizeof (*blk));
144*c39526b7SPramod Gunjikar 	}
145*c39526b7SPramod Gunjikar 
146*c39526b7SPramod Gunjikar 	if (uo_tbl->uobj_tbl_uo_root) {
147*c39526b7SPramod Gunjikar 
148*c39526b7SPramod Gunjikar 		size = uo_tbl->uobj_tbl_num_blks *
149*c39526b7SPramod Gunjikar 		    sizeof (sol_ofs_uobj_blk_t *);
150*c39526b7SPramod Gunjikar 		kmem_free(uo_tbl->uobj_tbl_uo_root, size);
151*c39526b7SPramod Gunjikar 	}
152*c39526b7SPramod Gunjikar 
153*c39526b7SPramod Gunjikar 	rw_exit(&uo_tbl->uobj_tbl_lock);
154*c39526b7SPramod Gunjikar 	rw_destroy(&uo_tbl->uobj_tbl_lock);
155*c39526b7SPramod Gunjikar }
156*c39526b7SPramod Gunjikar 
157*c39526b7SPramod Gunjikar /*
158*c39526b7SPramod Gunjikar  * Function:
159*c39526b7SPramod Gunjikar  *	uverbs_uob_init
160*c39526b7SPramod Gunjikar  * Input:
161*c39526b7SPramod Gunjikar  * 	uobj        - Pointer to the user object to initialize.
162*c39526b7SPramod Gunjikar  *	user_handle - A user space handle to associates with the object.
163*c39526b7SPramod Gunjikar  *	              Generally used to identify object in asynchronous
164*c39526b7SPramod Gunjikar  *	              notifications.
165*c39526b7SPramod Gunjikar  *	uob_type   - The type of user object.
166*c39526b7SPramod Gunjikar  * Ouput:
167*c39526b7SPramod Gunjikar  *	uobj       - Initialized user object.
168*c39526b7SPramod Gunjikar  * Returns:
169*c39526b7SPramod Gunjikar  * 	None
170*c39526b7SPramod Gunjikar  * Description:
171*c39526b7SPramod Gunjikar  *	Initialize a new user object.  The object will have one reference
172*c39526b7SPramod Gunjikar  *	placed on it.
173*c39526b7SPramod Gunjikar  */
174*c39526b7SPramod Gunjikar void
sol_ofs_uobj_init(sol_ofs_uobj_t * uobj,uint64_t user_handle,sol_ofs_uobj_type_t uobj_type)175*c39526b7SPramod Gunjikar sol_ofs_uobj_init(sol_ofs_uobj_t *uobj,
176*c39526b7SPramod Gunjikar     uint64_t user_handle, sol_ofs_uobj_type_t  uobj_type)
177*c39526b7SPramod Gunjikar {
178*c39526b7SPramod Gunjikar 	uobj->uo_user_handle = user_handle;
179*c39526b7SPramod Gunjikar 	uobj->uo_refcnt = 1;
180*c39526b7SPramod Gunjikar 	uobj->uo_type = uobj_type;
181*c39526b7SPramod Gunjikar 	uobj->uo_id = -1;
182*c39526b7SPramod Gunjikar 	uobj->uo_live = 0;
183*c39526b7SPramod Gunjikar 	rw_init(&uobj->uo_lock, NULL, RW_DRIVER, NULL);
184*c39526b7SPramod Gunjikar 	mutex_init(&uobj->uo_reflock, NULL, MUTEX_DRIVER, NULL);
185*c39526b7SPramod Gunjikar }
186*c39526b7SPramod Gunjikar 
187*c39526b7SPramod Gunjikar /*
188*c39526b7SPramod Gunjikar  * Function:
189*c39526b7SPramod Gunjikar  *	ofs_uobj_fini
190*c39526b7SPramod Gunjikar  * Input:
191*c39526b7SPramod Gunjikar  * 	uobj        - Pointer to the user object to be cleaned up.
192*c39526b7SPramod Gunjikar  * Ouput:
193*c39526b7SPramod Gunjikar  *	None
194*c39526b7SPramod Gunjikar  * Returns:
195*c39526b7SPramod Gunjikar  * 	None
196*c39526b7SPramod Gunjikar  * Description:
197*c39526b7SPramod Gunjikar  *	Performs user object cleanup prior to releasing memory.
198*c39526b7SPramod Gunjikar  */
199*c39526b7SPramod Gunjikar static void
ofs_uobj_fini(sol_ofs_uobj_t * uobj)200*c39526b7SPramod Gunjikar ofs_uobj_fini(sol_ofs_uobj_t *uobj)
201*c39526b7SPramod Gunjikar {
202*c39526b7SPramod Gunjikar 	rw_destroy(&uobj->uo_lock);
203*c39526b7SPramod Gunjikar 	mutex_destroy(&uobj->uo_reflock);
204*c39526b7SPramod Gunjikar }
205*c39526b7SPramod Gunjikar 
206*c39526b7SPramod Gunjikar /*
207*c39526b7SPramod Gunjikar  * Function:
208*c39526b7SPramod Gunjikar  *	sol_ofs_uobj_ref
209*c39526b7SPramod Gunjikar  * Input:
210*c39526b7SPramod Gunjikar  * 	uobj        - Pointer to the user object
211*c39526b7SPramod Gunjikar  * Ouput:
212*c39526b7SPramod Gunjikar  *	None
213*c39526b7SPramod Gunjikar  * Returns:
214*c39526b7SPramod Gunjikar  * 	None
215*c39526b7SPramod Gunjikar  * Description:
216*c39526b7SPramod Gunjikar  *	Place a reference on the specified user object.
217*c39526b7SPramod Gunjikar  */
218*c39526b7SPramod Gunjikar void
sol_ofs_uobj_ref(sol_ofs_uobj_t * uobj)219*c39526b7SPramod Gunjikar sol_ofs_uobj_ref(sol_ofs_uobj_t *uobj)
220*c39526b7SPramod Gunjikar {
221*c39526b7SPramod Gunjikar 	mutex_enter(&uobj->uo_reflock);
222*c39526b7SPramod Gunjikar 	uobj->uo_refcnt++;
223*c39526b7SPramod Gunjikar 	ASSERT(uobj->uo_refcnt != 0);
224*c39526b7SPramod Gunjikar 	mutex_exit(&uobj->uo_reflock);
225*c39526b7SPramod Gunjikar }
226*c39526b7SPramod Gunjikar 
227*c39526b7SPramod Gunjikar /*
228*c39526b7SPramod Gunjikar  * Function:
229*c39526b7SPramod Gunjikar  *	sol_ofs_uobj_deref
230*c39526b7SPramod Gunjikar  * Input:
231*c39526b7SPramod Gunjikar  * 	uobj        - Pointer to the user object
232*c39526b7SPramod Gunjikar  *	free_func   - Pointer to release function, called if the
233*c39526b7SPramod Gunjikar  *                    last reference is removed for the user object.
234*c39526b7SPramod Gunjikar  * Ouput:
235*c39526b7SPramod Gunjikar  *	None
236*c39526b7SPramod Gunjikar  * Returns:
237*c39526b7SPramod Gunjikar  * 	None
238*c39526b7SPramod Gunjikar  * Description:
239*c39526b7SPramod Gunjikar  *	Remove a reference to a user object.  If a free function
240*c39526b7SPramod Gunjikar  *	was specified and the last reference is released, then the
241*c39526b7SPramod Gunjikar  *	free function is invoked to release the user object.
242*c39526b7SPramod Gunjikar  */
243*c39526b7SPramod Gunjikar void
sol_ofs_uobj_deref(sol_ofs_uobj_t * uobj,void (* free_func)(sol_ofs_uobj_t * uobj))244*c39526b7SPramod Gunjikar sol_ofs_uobj_deref(sol_ofs_uobj_t *uobj,
245*c39526b7SPramod Gunjikar     void (*free_func)(sol_ofs_uobj_t *uobj))
246*c39526b7SPramod Gunjikar {
247*c39526b7SPramod Gunjikar 	SOL_OFS_DPRINTF_L5(sol_ofs_dbg_str, "UOBJ_DEREF: uobj = %p, "
248*c39526b7SPramod Gunjikar 	    "refcnt=%d", uobj, uobj->uo_refcnt);
249*c39526b7SPramod Gunjikar 
250*c39526b7SPramod Gunjikar 	mutex_enter(&uobj->uo_reflock);
251*c39526b7SPramod Gunjikar 
252*c39526b7SPramod Gunjikar 	ASSERT(uobj->uo_refcnt != 0);
253*c39526b7SPramod Gunjikar 	uobj->uo_refcnt--;
254*c39526b7SPramod Gunjikar 	if (uobj->uo_refcnt == 0) {
255*c39526b7SPramod Gunjikar 		mutex_exit(&uobj->uo_reflock);
256*c39526b7SPramod Gunjikar 		if (free_func)
257*c39526b7SPramod Gunjikar 			free_func(uobj);
258*c39526b7SPramod Gunjikar 	} else {
259*c39526b7SPramod Gunjikar 		mutex_exit(&uobj->uo_reflock);
260*c39526b7SPramod Gunjikar 	}
261*c39526b7SPramod Gunjikar }
262*c39526b7SPramod Gunjikar 
263*c39526b7SPramod Gunjikar /*
264*c39526b7SPramod Gunjikar  * Function:
265*c39526b7SPramod Gunjikar  *	sol_ofs_uobj_add
266*c39526b7SPramod Gunjikar  * Input:
267*c39526b7SPramod Gunjikar  *	uo_tbl	- A pointer to the user object resource management table
268*c39526b7SPramod Gunjikar  *		  to which the object should be added.
269*c39526b7SPramod Gunjikar  *	uobj    - A pointer ot the user object to be added; a reference
270*c39526b7SPramod Gunjikar  *	          should exist on this object prior to addition, and the
271*c39526b7SPramod Gunjikar  *		  object should be removed prior to all references being
272*c39526b7SPramod Gunjikar  *		  removed.
273*c39526b7SPramod Gunjikar  * Output:
274*c39526b7SPramod Gunjikar  *	uobj	- The user object "uo_id" is updated and should be
275*c39526b7SPramod Gunjikar  *		  used in subsequent lookup operations.
276*c39526b7SPramod Gunjikar  * Returns:
277*c39526b7SPramod Gunjikar  *	DDI_SUCCESS on success, else error code.
278*c39526b7SPramod Gunjikar  * Description:
279*c39526b7SPramod Gunjikar  * 	Add a user object to the specified user object resource management
280*c39526b7SPramod Gunjikar  *	table.
281*c39526b7SPramod Gunjikar  *
282*c39526b7SPramod Gunjikar  */
283*c39526b7SPramod Gunjikar int
sol_ofs_uobj_add(sol_ofs_uobj_table_t * uo_tbl,sol_ofs_uobj_t * uobj)284*c39526b7SPramod Gunjikar sol_ofs_uobj_add(sol_ofs_uobj_table_t *uo_tbl, sol_ofs_uobj_t *uobj)
285*c39526b7SPramod Gunjikar {
286*c39526b7SPramod Gunjikar 	int		i, j, empty = -1;
287*c39526b7SPramod Gunjikar 	sol_ofs_uobj_blk_t	*blk;
288*c39526b7SPramod Gunjikar 
289*c39526b7SPramod Gunjikar 	rw_enter(&uo_tbl->uobj_tbl_lock, RW_WRITER);
290*c39526b7SPramod Gunjikar 
291*c39526b7SPramod Gunjikar 	/*
292*c39526b7SPramod Gunjikar 	 * Try to find an empty slot for the new user object.
293*c39526b7SPramod Gunjikar 	 */
294*c39526b7SPramod Gunjikar 	for (i = 0; i < uo_tbl->uobj_tbl_used_blks; i++) {
295*c39526b7SPramod Gunjikar 		blk = uo_tbl->uobj_tbl_uo_root[i];
296*c39526b7SPramod Gunjikar 		if (blk != NULL && blk->ofs_uo_blk_avail > 0) {
297*c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L5(sol_ofs_dbg_str,
298*c39526b7SPramod Gunjikar 			    "UOBJ ADD: table:%p, available blks:%d",
299*c39526b7SPramod Gunjikar 			    uo_tbl, blk->ofs_uo_blk_avail);
300*c39526b7SPramod Gunjikar 			for (j = 0; j < SOL_OFS_UO_BLKSZ; j++) {
301*c39526b7SPramod Gunjikar 				if (blk->ofs_uoblk_blks[j] == NULL) {
302*c39526b7SPramod Gunjikar 					blk->ofs_uoblk_blks[j] = uobj;
303*c39526b7SPramod Gunjikar 					uobj->uo_id = j + (i *
304*c39526b7SPramod Gunjikar 					    SOL_OFS_UO_BLKSZ);
305*c39526b7SPramod Gunjikar 					uobj->uo_uobj_sz =
306*c39526b7SPramod Gunjikar 					    uo_tbl->uobj_tbl_uo_sz;
307*c39526b7SPramod Gunjikar 					blk->ofs_uo_blk_avail--;
308*c39526b7SPramod Gunjikar 					uo_tbl->uobj_tbl_uo_cnt++;
309*c39526b7SPramod Gunjikar 					goto obj_added;
310*c39526b7SPramod Gunjikar 				}
311*c39526b7SPramod Gunjikar 			}
312*c39526b7SPramod Gunjikar 		} else if (blk == NULL && empty < 0) {
313*c39526b7SPramod Gunjikar 			/*
314*c39526b7SPramod Gunjikar 			 * Remember the first empty blk we came across.
315*c39526b7SPramod Gunjikar 			 */
316*c39526b7SPramod Gunjikar 			empty = i;
317*c39526b7SPramod Gunjikar 		}
318*c39526b7SPramod Gunjikar 	}
319*c39526b7SPramod Gunjikar 
320*c39526b7SPramod Gunjikar 	/*
321*c39526b7SPramod Gunjikar 	 * No entries were available, we must allocate a new block.  If we did
322*c39526b7SPramod Gunjikar 	 * not find a empty block available, then we must allocate/reallocate
323*c39526b7SPramod Gunjikar 	 * the root array (copying any existing blk pointers to it).
324*c39526b7SPramod Gunjikar 	 */
325*c39526b7SPramod Gunjikar 	if (empty < 0) {
326*c39526b7SPramod Gunjikar 		if (uo_tbl->uobj_tbl_used_blks == uo_tbl->uobj_tbl_num_blks) {
327*c39526b7SPramod Gunjikar 			sol_ofs_uobj_blk_t	**p;
328*c39526b7SPramod Gunjikar 			uint_t		newsz;
329*c39526b7SPramod Gunjikar 
330*c39526b7SPramod Gunjikar 			newsz = uo_tbl->uobj_tbl_num_blks + SOL_OFS_UO_BLKSZ;
331*c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L5(sol_ofs_dbg_str,
332*c39526b7SPramod Gunjikar 			    "UOBJ ADD: Increasing uobj table size to %d",
333*c39526b7SPramod Gunjikar 			    newsz);
334*c39526b7SPramod Gunjikar 
335*c39526b7SPramod Gunjikar 			p = kmem_zalloc(newsz * sizeof (*p), KM_NOSLEEP);
336*c39526b7SPramod Gunjikar 			if (!p) {
337*c39526b7SPramod Gunjikar 				SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str,
338*c39526b7SPramod Gunjikar 				    "UOBJ ADD: Mem alloc fail\n");
339*c39526b7SPramod Gunjikar 				rw_exit(&uo_tbl->uobj_tbl_lock);
340*c39526b7SPramod Gunjikar 				return (1);
341*c39526b7SPramod Gunjikar 			}
342*c39526b7SPramod Gunjikar 
343*c39526b7SPramod Gunjikar 			if (uo_tbl->uobj_tbl_uo_root) {
344*c39526b7SPramod Gunjikar 				uint_t	oldsz;
345*c39526b7SPramod Gunjikar 
346*c39526b7SPramod Gunjikar 				oldsz = (uint_t)uo_tbl->uobj_tbl_num_blks *
347*c39526b7SPramod Gunjikar 				    (int)(sizeof (*p));
348*c39526b7SPramod Gunjikar 				bcopy(uo_tbl->uobj_tbl_uo_root, p, oldsz);
349*c39526b7SPramod Gunjikar 				kmem_free(uo_tbl->uobj_tbl_uo_root, oldsz);
350*c39526b7SPramod Gunjikar 			}
351*c39526b7SPramod Gunjikar 			uo_tbl->uobj_tbl_uo_root = p;
352*c39526b7SPramod Gunjikar 			uo_tbl->uobj_tbl_num_blks = newsz;
353*c39526b7SPramod Gunjikar 		}
354*c39526b7SPramod Gunjikar 		empty = uo_tbl->uobj_tbl_used_blks;
355*c39526b7SPramod Gunjikar 		uo_tbl->uobj_tbl_used_blks++;
356*c39526b7SPramod Gunjikar 	}
357*c39526b7SPramod Gunjikar 
358*c39526b7SPramod Gunjikar 	/*
359*c39526b7SPramod Gunjikar 	 * There are enough free block pointers in the root, allocate
360*c39526b7SPramod Gunjikar 	 * a new block.
361*c39526b7SPramod Gunjikar 	 */
362*c39526b7SPramod Gunjikar 	blk = kmem_zalloc(sizeof (*blk), KM_NOSLEEP);
363*c39526b7SPramod Gunjikar 	if (!blk) {
364*c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str,
365*c39526b7SPramod Gunjikar 		    "UOBJ ADD: Mem alloc fail\n");
366*c39526b7SPramod Gunjikar 		rw_exit(&uo_tbl->uobj_tbl_lock);
367*c39526b7SPramod Gunjikar 		return (1);
368*c39526b7SPramod Gunjikar 	}
369*c39526b7SPramod Gunjikar 	ASSERT(uo_tbl->uobj_tbl_uo_root[empty] == NULL);
370*c39526b7SPramod Gunjikar 	uo_tbl->uobj_tbl_uo_root[empty] = blk;
371*c39526b7SPramod Gunjikar 	blk->ofs_uo_blk_avail = SOL_OFS_UO_BLKSZ - 1;
372*c39526b7SPramod Gunjikar 
373*c39526b7SPramod Gunjikar 	/*
374*c39526b7SPramod Gunjikar 	 * Use the first slot in this new block to add the new user object.
375*c39526b7SPramod Gunjikar 	 */
376*c39526b7SPramod Gunjikar 	uobj->uo_id = empty * SOL_OFS_UO_BLKSZ;
377*c39526b7SPramod Gunjikar 	blk->ofs_uoblk_blks[0] = uobj;
378*c39526b7SPramod Gunjikar 	uobj->uo_uobj_sz = uo_tbl->uobj_tbl_uo_sz;
379*c39526b7SPramod Gunjikar 	uo_tbl->uobj_tbl_uo_cnt++;
380*c39526b7SPramod Gunjikar 
381*c39526b7SPramod Gunjikar obj_added:
382*c39526b7SPramod Gunjikar 	rw_exit(&uo_tbl->uobj_tbl_lock);
383*c39526b7SPramod Gunjikar 	return (0);
384*c39526b7SPramod Gunjikar }
385*c39526b7SPramod Gunjikar 
386*c39526b7SPramod Gunjikar /*
387*c39526b7SPramod Gunjikar  * Function:
388*c39526b7SPramod Gunjikar  *	sol_ofs_uobj_remove
389*c39526b7SPramod Gunjikar  * Input:
390*c39526b7SPramod Gunjikar  *	uo_tbl	- A pointer to the user object resource management table
391*c39526b7SPramod Gunjikar  *		  from which the object should be removed.
392*c39526b7SPramod Gunjikar  *	uobj    - A pointer ot the user object to be removed.
393*c39526b7SPramod Gunjikar  * Output:
394*c39526b7SPramod Gunjikar  *	None
395*c39526b7SPramod Gunjikar  * Returns:
396*c39526b7SPramod Gunjikar  *	A pointer to the user object that was removed on success, otherwise
397*c39526b7SPramod Gunjikar  *	NULL.
398*c39526b7SPramod Gunjikar  * Description:
399*c39526b7SPramod Gunjikar  * 	Remove a user object from the specified user resource management
400*c39526b7SPramod Gunjikar  *	table.
401*c39526b7SPramod Gunjikar  *
402*c39526b7SPramod Gunjikar  *	The uobj uo_lock must be held as a writer before calling this.
403*c39526b7SPramod Gunjikar  */
404*c39526b7SPramod Gunjikar sol_ofs_uobj_t *
sol_ofs_uobj_remove(sol_ofs_uobj_table_t * uo_tbl,sol_ofs_uobj_t * uobj)405*c39526b7SPramod Gunjikar sol_ofs_uobj_remove(sol_ofs_uobj_table_t *uo_tbl, sol_ofs_uobj_t *uobj)
406*c39526b7SPramod Gunjikar {
407*c39526b7SPramod Gunjikar 	uint_t			i, j;
408*c39526b7SPramod Gunjikar 	sol_ofs_uobj_blk_t	*blk;
409*c39526b7SPramod Gunjikar 	sol_ofs_uobj_t		*p;
410*c39526b7SPramod Gunjikar 
411*c39526b7SPramod Gunjikar 	ASSERT(uo_tbl != NULL);
412*c39526b7SPramod Gunjikar 	ASSERT(uobj != NULL);
413*c39526b7SPramod Gunjikar 
414*c39526b7SPramod Gunjikar 	p = NULL;
415*c39526b7SPramod Gunjikar 	rw_enter(&uo_tbl->uobj_tbl_lock, RW_WRITER);
416*c39526b7SPramod Gunjikar 
417*c39526b7SPramod Gunjikar 	if (!uobj->uo_live) {
418*c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str,
419*c39526b7SPramod Gunjikar 		    "UOBJ REMOVE: object 0x%P, already removed", (void *)uobj);
420*c39526b7SPramod Gunjikar 		goto remove_done;
421*c39526b7SPramod Gunjikar 	}
422*c39526b7SPramod Gunjikar 
423*c39526b7SPramod Gunjikar 	if ((uo_tbl->uobj_tbl_uo_cnt == 0) || !(uo_tbl->uobj_tbl_uo_root)) {
424*c39526b7SPramod Gunjikar 		/*
425*c39526b7SPramod Gunjikar 		 * The table is empty, just return not found
426*c39526b7SPramod Gunjikar 		 * Don't panic, userland app could have double free'd
427*c39526b7SPramod Gunjikar 		 * let them deal with it.
428*c39526b7SPramod Gunjikar 		 */
429*c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str,
430*c39526b7SPramod Gunjikar 		    "UOBJ REMOVE: table 0x%P empty", (void *)uo_tbl);
431*c39526b7SPramod Gunjikar 		goto remove_done;
432*c39526b7SPramod Gunjikar 	}
433*c39526b7SPramod Gunjikar 
434*c39526b7SPramod Gunjikar 	i = uobj->uo_id / SOL_OFS_UO_BLKSZ;
435*c39526b7SPramod Gunjikar 	j = uobj->uo_id % SOL_OFS_UO_BLKSZ;
436*c39526b7SPramod Gunjikar 
437*c39526b7SPramod Gunjikar 	if (i >= uo_tbl->uobj_tbl_used_blks) {
438*c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str,
439*c39526b7SPramod Gunjikar 		    "UOBJ REMOVE: object id %d exceeds table size",
440*c39526b7SPramod Gunjikar 		    uobj->uo_id);
441*c39526b7SPramod Gunjikar 		goto remove_done;
442*c39526b7SPramod Gunjikar 	}
443*c39526b7SPramod Gunjikar 
444*c39526b7SPramod Gunjikar 	ASSERT(i < uo_tbl->uobj_tbl_num_blks);
445*c39526b7SPramod Gunjikar 
446*c39526b7SPramod Gunjikar 	blk = uo_tbl->uobj_tbl_uo_root[i];
447*c39526b7SPramod Gunjikar 	if (blk == NULL) {
448*c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str,
449*c39526b7SPramod Gunjikar 		    "UOBJ REMOVE: object id %d points to invalid root",
450*c39526b7SPramod Gunjikar 		    uobj->uo_id);
451*c39526b7SPramod Gunjikar 		goto remove_done;
452*c39526b7SPramod Gunjikar 	}
453*c39526b7SPramod Gunjikar 
454*c39526b7SPramod Gunjikar 	if (blk->ofs_uoblk_blks[j] == NULL) {
455*c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str,
456*c39526b7SPramod Gunjikar 		    "UOBJ REMOVE: object id %d points to invalid block",
457*c39526b7SPramod Gunjikar 		    uobj->uo_id);
458*c39526b7SPramod Gunjikar 		goto remove_done;
459*c39526b7SPramod Gunjikar 	}
460*c39526b7SPramod Gunjikar 
461*c39526b7SPramod Gunjikar 	/*
462*c39526b7SPramod Gunjikar 	 * Mark as dead
463*c39526b7SPramod Gunjikar 	 */
464*c39526b7SPramod Gunjikar 	uobj->uo_live = 0;
465*c39526b7SPramod Gunjikar 
466*c39526b7SPramod Gunjikar 	p = blk->ofs_uoblk_blks[j];
467*c39526b7SPramod Gunjikar 	blk->ofs_uoblk_blks[j] = NULL;
468*c39526b7SPramod Gunjikar 	blk->ofs_uo_blk_avail++;
469*c39526b7SPramod Gunjikar 	if (blk->ofs_uo_blk_avail == SOL_OFS_UO_BLKSZ) {
470*c39526b7SPramod Gunjikar 		kmem_free(blk, sizeof (*blk));
471*c39526b7SPramod Gunjikar 		uo_tbl->uobj_tbl_uo_root[i] = NULL;
472*c39526b7SPramod Gunjikar 	}
473*c39526b7SPramod Gunjikar 	uo_tbl->uobj_tbl_uo_cnt--;
474*c39526b7SPramod Gunjikar 
475*c39526b7SPramod Gunjikar remove_done:
476*c39526b7SPramod Gunjikar 	rw_exit(&uo_tbl->uobj_tbl_lock);
477*c39526b7SPramod Gunjikar 	return (p);
478*c39526b7SPramod Gunjikar }
479*c39526b7SPramod Gunjikar 
480*c39526b7SPramod Gunjikar /*
481*c39526b7SPramod Gunjikar  * Function:
482*c39526b7SPramod Gunjikar  *	ofs_uobj_find
483*c39526b7SPramod Gunjikar  * Input:
484*c39526b7SPramod Gunjikar  *	uo_tbl	- A pointer to the user object resource management table
485*c39526b7SPramod Gunjikar  *		  to be used for the lookup.
486*c39526b7SPramod Gunjikar  *	uo_id	- The user object ID to lookup.  This ID was set when
487*c39526b7SPramod Gunjikar  *		  the object was added to the resource management table.
488*c39526b7SPramod Gunjikar  *	add_ref	- A non zero value indicates that the user objects reference
489*c39526b7SPramod Gunjikar  *		  count should be updated to reflect and additional
490*c39526b7SPramod Gunjikar  *		  reference before it is returned.
491*c39526b7SPramod Gunjikar  * Output:
492*c39526b7SPramod Gunjikar  *	None
493*c39526b7SPramod Gunjikar  * Returns:
494*c39526b7SPramod Gunjikar  *	A pointer to the user object associated with the uo_id if found,
495*c39526b7SPramod Gunjikar  *	otherwise NULL.
496*c39526b7SPramod Gunjikar  * Description:
497*c39526b7SPramod Gunjikar  * 	Lookup and return a user object from the specified user resource
498*c39526b7SPramod Gunjikar  *	management table.
499*c39526b7SPramod Gunjikar  */
500*c39526b7SPramod Gunjikar static sol_ofs_uobj_t *
ofs_uobj_find(sol_ofs_uobj_table_t * uo_tbl,uint32_t uo_id,int add_ref)501*c39526b7SPramod Gunjikar ofs_uobj_find(sol_ofs_uobj_table_t *uo_tbl, uint32_t uo_id, int add_ref)
502*c39526b7SPramod Gunjikar {
503*c39526b7SPramod Gunjikar 	uint32_t		i, j;
504*c39526b7SPramod Gunjikar 	sol_ofs_uobj_blk_t	*blk;
505*c39526b7SPramod Gunjikar 	sol_ofs_uobj_t		*uobj;
506*c39526b7SPramod Gunjikar 
507*c39526b7SPramod Gunjikar 	ASSERT(uo_tbl != NULL);
508*c39526b7SPramod Gunjikar 	uobj = NULL;
509*c39526b7SPramod Gunjikar 
510*c39526b7SPramod Gunjikar 	rw_enter(&uo_tbl->uobj_tbl_lock, RW_READER);
511*c39526b7SPramod Gunjikar 
512*c39526b7SPramod Gunjikar 	if ((uo_tbl->uobj_tbl_uo_cnt == 0) || !(uo_tbl->uobj_tbl_uo_root)) {
513*c39526b7SPramod Gunjikar 		/*
514*c39526b7SPramod Gunjikar 		 * The table is empty, just return not found
515*c39526b7SPramod Gunjikar 		 * Don't panic, userland app could have double free'd
516*c39526b7SPramod Gunjikar 		 * let them deal with it.
517*c39526b7SPramod Gunjikar 		 */
518*c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str,
519*c39526b7SPramod Gunjikar 		    "UOBJ FIND: id %d in tbl 0x%P - tbl empty", uo_id,
520*c39526b7SPramod Gunjikar 		    (void *)uo_tbl);
521*c39526b7SPramod Gunjikar 		goto find_done;
522*c39526b7SPramod Gunjikar 	}
523*c39526b7SPramod Gunjikar 
524*c39526b7SPramod Gunjikar 	i = uo_id / SOL_OFS_UO_BLKSZ;
525*c39526b7SPramod Gunjikar 	j = uo_id % SOL_OFS_UO_BLKSZ;
526*c39526b7SPramod Gunjikar 
527*c39526b7SPramod Gunjikar 	if (i >= uo_tbl->uobj_tbl_used_blks) {
528*c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str,
529*c39526b7SPramod Gunjikar 		    "UOBJ FIND: Index not valid, %d", uo_id);
530*c39526b7SPramod Gunjikar 		goto find_done;
531*c39526b7SPramod Gunjikar 	}
532*c39526b7SPramod Gunjikar 
533*c39526b7SPramod Gunjikar 	/*
534*c39526b7SPramod Gunjikar 	 * Get the user object, and if valid perform a get (ref++).
535*c39526b7SPramod Gunjikar 	 * The caller issuing the find, must release the reference
536*c39526b7SPramod Gunjikar 	 * when done.
537*c39526b7SPramod Gunjikar 	 */
538*c39526b7SPramod Gunjikar 	blk = uo_tbl->uobj_tbl_uo_root[i];
539*c39526b7SPramod Gunjikar 	if (blk != NULL) {
540*c39526b7SPramod Gunjikar 		ASSERT(i < uo_tbl->uobj_tbl_num_blks);
541*c39526b7SPramod Gunjikar 
542*c39526b7SPramod Gunjikar 		uobj = blk->ofs_uoblk_blks[j];
543*c39526b7SPramod Gunjikar 
544*c39526b7SPramod Gunjikar 		if (uobj == NULL) {
545*c39526b7SPramod Gunjikar 			SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str,
546*c39526b7SPramod Gunjikar 			    "UOBJ FIND: Index %d not found, blk = %p",
547*c39526b7SPramod Gunjikar 			    uo_id, blk->ofs_uoblk_blks[j]);
548*c39526b7SPramod Gunjikar 		} else if (add_ref) {
549*c39526b7SPramod Gunjikar 			sol_ofs_uobj_ref(uobj);
550*c39526b7SPramod Gunjikar 		}
551*c39526b7SPramod Gunjikar 	} else {
552*c39526b7SPramod Gunjikar 		SOL_OFS_DPRINTF_L2(sol_ofs_dbg_str,
553*c39526b7SPramod Gunjikar 		    "UOBJ FIND: Uobject not found, %d", uo_id);
554*c39526b7SPramod Gunjikar 		goto find_done;
555*c39526b7SPramod Gunjikar 	}
556*c39526b7SPramod Gunjikar 
557*c39526b7SPramod Gunjikar find_done:
558*c39526b7SPramod Gunjikar 	rw_exit(&uo_tbl->uobj_tbl_lock);
559*c39526b7SPramod Gunjikar 	return (uobj);
560*c39526b7SPramod Gunjikar }
561*c39526b7SPramod Gunjikar 
562*c39526b7SPramod Gunjikar /*
563*c39526b7SPramod Gunjikar  * Function:
564*c39526b7SPramod Gunjikar  *	sol_ofs_uobj_get_read
565*c39526b7SPramod Gunjikar  * Input:
566*c39526b7SPramod Gunjikar  *	tbl         - Pointer to the user object managment table to
567*c39526b7SPramod Gunjikar  *	              be used in the lookup.
568*c39526b7SPramod Gunjikar  *	uo_id       - The ID to object mapping, assigned to the user
569*c39526b7SPramod Gunjikar  *	              object at addition to the table.
570*c39526b7SPramod Gunjikar  * Ouput:
571*c39526b7SPramod Gunjikar  *	None
572*c39526b7SPramod Gunjikar  * Returns:
573*c39526b7SPramod Gunjikar  * 	A pointer to the user object associated with uo_id or NULL
574*c39526b7SPramod Gunjikar  *      if the entry does not exist.
575*c39526b7SPramod Gunjikar  * Description:
576*c39526b7SPramod Gunjikar  *	Lookup a user object and place a reference on it.  Acquires
577*c39526b7SPramod Gunjikar  *	the object with a READ lock.  The reference and lock should
578*c39526b7SPramod Gunjikar  *	be released using the sol_ofs_uobj_put() call.
579*c39526b7SPramod Gunjikar  */
580*c39526b7SPramod Gunjikar sol_ofs_uobj_t *
sol_ofs_uobj_get_read(sol_ofs_uobj_table_t * tbl,uint32_t uo_id)581*c39526b7SPramod Gunjikar sol_ofs_uobj_get_read(sol_ofs_uobj_table_t *tbl, uint32_t uo_id)
582*c39526b7SPramod Gunjikar {
583*c39526b7SPramod Gunjikar 	sol_ofs_uobj_t *uobj;
584*c39526b7SPramod Gunjikar 
585*c39526b7SPramod Gunjikar 	uobj = ofs_uobj_find(tbl, uo_id, 1);
586*c39526b7SPramod Gunjikar 	if (!uobj)
587*c39526b7SPramod Gunjikar 		return (NULL);
588*c39526b7SPramod Gunjikar 
589*c39526b7SPramod Gunjikar 	rw_enter(&uobj->uo_lock, RW_READER);
590*c39526b7SPramod Gunjikar 
591*c39526b7SPramod Gunjikar 	/*
592*c39526b7SPramod Gunjikar 	 * If object was destroyed before we got the lock, just release
593*c39526b7SPramod Gunjikar 	 * our reference and indicate we didn't find the object.
594*c39526b7SPramod Gunjikar 	 */
595*c39526b7SPramod Gunjikar 	if (!uobj->uo_live) {
596*c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(uobj);
597*c39526b7SPramod Gunjikar 		return (NULL);
598*c39526b7SPramod Gunjikar 	}
599*c39526b7SPramod Gunjikar 	return (uobj);
600*c39526b7SPramod Gunjikar }
601*c39526b7SPramod Gunjikar 
602*c39526b7SPramod Gunjikar /*
603*c39526b7SPramod Gunjikar  * Function:
604*c39526b7SPramod Gunjikar  *	sol_ofs_uobj_get_write
605*c39526b7SPramod Gunjikar  * Input:
606*c39526b7SPramod Gunjikar  *	tbl         - Pointer to the user object managment table to
607*c39526b7SPramod Gunjikar  *	              be used in the lookup.
608*c39526b7SPramod Gunjikar  *	uo_id       - The ID to object mapping, assigned to the user
609*c39526b7SPramod Gunjikar  *	              object at addition to the table.
610*c39526b7SPramod Gunjikar  * Ouput:
611*c39526b7SPramod Gunjikar  *	None
612*c39526b7SPramod Gunjikar  * Returns:
613*c39526b7SPramod Gunjikar  * 	A pointer to the user object associated with uo_id or NULL
614*c39526b7SPramod Gunjikar  *      if the entry does not exist.
615*c39526b7SPramod Gunjikar  * Description:
616*c39526b7SPramod Gunjikar  *	Lookup a user object and place a reference on it.  Acquires
617*c39526b7SPramod Gunjikar  *	the object with a WRITE lock.  The reference and lock should
618*c39526b7SPramod Gunjikar  *	be released using the sol_ofs_uobj_put() call.
619*c39526b7SPramod Gunjikar  */
620*c39526b7SPramod Gunjikar sol_ofs_uobj_t *
sol_ofs_uobj_get_write(sol_ofs_uobj_table_t * tbl,uint32_t uo_id)621*c39526b7SPramod Gunjikar sol_ofs_uobj_get_write(sol_ofs_uobj_table_t *tbl, uint32_t uo_id)
622*c39526b7SPramod Gunjikar {
623*c39526b7SPramod Gunjikar 	sol_ofs_uobj_t *uobj;
624*c39526b7SPramod Gunjikar 
625*c39526b7SPramod Gunjikar 
626*c39526b7SPramod Gunjikar 	uobj = ofs_uobj_find(tbl, uo_id, 1);
627*c39526b7SPramod Gunjikar 	if (!uobj)
628*c39526b7SPramod Gunjikar 		return (NULL);
629*c39526b7SPramod Gunjikar 
630*c39526b7SPramod Gunjikar 	rw_enter(&uobj->uo_lock, RW_WRITER);
631*c39526b7SPramod Gunjikar 
632*c39526b7SPramod Gunjikar 	/*
633*c39526b7SPramod Gunjikar 	 * If object was destroyed before we got the lock, just release
634*c39526b7SPramod Gunjikar 	 * our reference and indicate we didn't find the object.
635*c39526b7SPramod Gunjikar 	 */
636*c39526b7SPramod Gunjikar 	if (!uobj->uo_live) {
637*c39526b7SPramod Gunjikar 		sol_ofs_uobj_put(uobj);
638*c39526b7SPramod Gunjikar 		return (NULL);
639*c39526b7SPramod Gunjikar 	}
640*c39526b7SPramod Gunjikar 	return (uobj);
641*c39526b7SPramod Gunjikar }
642*c39526b7SPramod Gunjikar 
643*c39526b7SPramod Gunjikar /*
644*c39526b7SPramod Gunjikar  * Function:
645*c39526b7SPramod Gunjikar  *	sol_ofs_uobj_free
646*c39526b7SPramod Gunjikar  * Input:
647*c39526b7SPramod Gunjikar  *	uobj	-  A pointer to the Solaris User Verbs kernel agent user
648*c39526b7SPramod Gunjikar  *	           object to be freed.
649*c39526b7SPramod Gunjikar  * Output:
650*c39526b7SPramod Gunjikar  *	None.
651*c39526b7SPramod Gunjikar  * Returns:
652*c39526b7SPramod Gunjikar  *	None.
653*c39526b7SPramod Gunjikar  * Description:
654*c39526b7SPramod Gunjikar  * 	Called when the user object is no longer referenced, it will release
655*c39526b7SPramod Gunjikar  *	any user object resources and free the container object memory.
656*c39526b7SPramod Gunjikar  *	NOTE: Currently there is a stipulation that the user object be the
657*c39526b7SPramod Gunjikar  *	first element of any user object specialization.
658*c39526b7SPramod Gunjikar  */
659*c39526b7SPramod Gunjikar void
sol_ofs_uobj_free(sol_ofs_uobj_t * uobj)660*c39526b7SPramod Gunjikar sol_ofs_uobj_free(sol_ofs_uobj_t *uobj)
661*c39526b7SPramod Gunjikar {
662*c39526b7SPramod Gunjikar 	size_t	sz;
663*c39526b7SPramod Gunjikar 
664*c39526b7SPramod Gunjikar 	ASSERT(uobj);
665*c39526b7SPramod Gunjikar 
666*c39526b7SPramod Gunjikar 	/*
667*c39526b7SPramod Gunjikar 	 * Cleanup common user object and then free memory using
668*c39526b7SPramod Gunjikar 	 * length based on associated object type.
669*c39526b7SPramod Gunjikar 	 */
670*c39526b7SPramod Gunjikar 	ofs_uobj_fini(uobj);
671*c39526b7SPramod Gunjikar 
672*c39526b7SPramod Gunjikar 	sz = uobj->uo_uobj_sz;
673*c39526b7SPramod Gunjikar 	if (sz)
674*c39526b7SPramod Gunjikar 		kmem_free(uobj, sz);
675*c39526b7SPramod Gunjikar }
676*c39526b7SPramod Gunjikar 
677*c39526b7SPramod Gunjikar /*
678*c39526b7SPramod Gunjikar  * Function:
679*c39526b7SPramod Gunjikar  *	sol_ofs_uobj_put
680*c39526b7SPramod Gunjikar  * Input:
681*c39526b7SPramod Gunjikar  * 	uobj        - Pointer to the user object
682*c39526b7SPramod Gunjikar  * Ouput:
683*c39526b7SPramod Gunjikar  *	None
684*c39526b7SPramod Gunjikar  * Returns:
685*c39526b7SPramod Gunjikar  * 	None
686*c39526b7SPramod Gunjikar  * Description:
687*c39526b7SPramod Gunjikar  *	Remove a lock associated with a user object, and decrement
688*c39526b7SPramod Gunjikar  *	the reference held. On the last deference the user object
689*c39526b7SPramod Gunjikar  *	will be freed.
690*c39526b7SPramod Gunjikar  */
691*c39526b7SPramod Gunjikar void
sol_ofs_uobj_put(sol_ofs_uobj_t * uobj)692*c39526b7SPramod Gunjikar sol_ofs_uobj_put(sol_ofs_uobj_t *uobj)
693*c39526b7SPramod Gunjikar {
694*c39526b7SPramod Gunjikar 	rw_exit(&uobj->uo_lock);
695*c39526b7SPramod Gunjikar 	sol_ofs_uobj_deref(uobj, sol_ofs_uobj_free);
696*c39526b7SPramod Gunjikar }
697