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