1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * CDDL HEADER START
3*0Sstevel@tonic-gate *
4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*0Sstevel@tonic-gate * with the License.
8*0Sstevel@tonic-gate *
9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate * and limitations under the License.
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate *
20*0Sstevel@tonic-gate * CDDL HEADER END
21*0Sstevel@tonic-gate */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24*0Sstevel@tonic-gate * Use is subject to license terms.
25*0Sstevel@tonic-gate */
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate #include <sys/param.h>
30*0Sstevel@tonic-gate #include <sys/systm.h>
31*0Sstevel@tonic-gate #include <sys/types.h>
32*0Sstevel@tonic-gate #include <sys/debug.h>
33*0Sstevel@tonic-gate #include <sys/errno.h>
34*0Sstevel@tonic-gate #include <sys/sysmacros.h>
35*0Sstevel@tonic-gate #include <sys/t_lock.h>
36*0Sstevel@tonic-gate #include <sys/kmem.h>
37*0Sstevel@tonic-gate #include <sys/lvm/md_trans.h>
38*0Sstevel@tonic-gate #include <sys/ddi.h>
39*0Sstevel@tonic-gate #include <sys/sunddi.h>
40*0Sstevel@tonic-gate #include <sys/file.h>
41*0Sstevel@tonic-gate #include <sys/proc.h>
42*0Sstevel@tonic-gate #include <sys/disp.h>
43*0Sstevel@tonic-gate #include <sys/lvm/md_notify.h>
44*0Sstevel@tonic-gate #include <sys/lvm/mdvar.h>
45*0Sstevel@tonic-gate
46*0Sstevel@tonic-gate #include <sys/sysevent/eventdefs.h>
47*0Sstevel@tonic-gate #include <sys/sysevent/svm.h>
48*0Sstevel@tonic-gate
49*0Sstevel@tonic-gate extern unit_t md_nunits;
50*0Sstevel@tonic-gate extern set_t md_nsets;
51*0Sstevel@tonic-gate extern md_set_t md_set[];
52*0Sstevel@tonic-gate
53*0Sstevel@tonic-gate extern md_ops_t trans_md_ops;
54*0Sstevel@tonic-gate extern major_t md_major;
55*0Sstevel@tonic-gate
56*0Sstevel@tonic-gate
57*0Sstevel@tonic-gate
58*0Sstevel@tonic-gate
59*0Sstevel@tonic-gate static kmutex_t ml_lock;
60*0Sstevel@tonic-gate static ml_unit_t *ul_list; /* List of all log units */
61*0Sstevel@tonic-gate static int md_nlogs;
62*0Sstevel@tonic-gate static kmutex_t ut_mutex; /* per log list of metatrans units */
63*0Sstevel@tonic-gate static kmutex_t oc_mutex; /* single threads opens/closes */
64*0Sstevel@tonic-gate
65*0Sstevel@tonic-gate static void md_free_cirbuf(cirbuf_ic_t *cb);
66*0Sstevel@tonic-gate
67*0Sstevel@tonic-gate #define IOWAIT(bp) sema_p(&bp->b_io)
68*0Sstevel@tonic-gate #define IODONE(bp) sema_v(&bp->b_io)
69*0Sstevel@tonic-gate
70*0Sstevel@tonic-gate void
_init_ldl(void)71*0Sstevel@tonic-gate _init_ldl(void)
72*0Sstevel@tonic-gate {
73*0Sstevel@tonic-gate mutex_init(&ut_mutex, NULL, MUTEX_DRIVER, NULL);
74*0Sstevel@tonic-gate mutex_init(&oc_mutex, NULL, MUTEX_DRIVER, NULL);
75*0Sstevel@tonic-gate mutex_init(&ml_lock, NULL, MUTEX_DRIVER, NULL);
76*0Sstevel@tonic-gate }
77*0Sstevel@tonic-gate
78*0Sstevel@tonic-gate void
_fini_ldl(void)79*0Sstevel@tonic-gate _fini_ldl(void)
80*0Sstevel@tonic-gate {
81*0Sstevel@tonic-gate mutex_destroy(&ut_mutex);
82*0Sstevel@tonic-gate mutex_destroy(&oc_mutex);
83*0Sstevel@tonic-gate mutex_destroy(&ml_lock);
84*0Sstevel@tonic-gate }
85*0Sstevel@tonic-gate
86*0Sstevel@tonic-gate static void
ldl_errorstate(ml_unit_t * ul)87*0Sstevel@tonic-gate ldl_errorstate(ml_unit_t *ul)
88*0Sstevel@tonic-gate {
89*0Sstevel@tonic-gate char *str;
90*0Sstevel@tonic-gate
91*0Sstevel@tonic-gate if (ldl_iserror(ul))
92*0Sstevel@tonic-gate str = "Error";
93*0Sstevel@tonic-gate else if (ldl_isherror(ul))
94*0Sstevel@tonic-gate str = "Hard Error";
95*0Sstevel@tonic-gate else
96*0Sstevel@tonic-gate str = "Okay";
97*0Sstevel@tonic-gate
98*0Sstevel@tonic-gate cmn_err(CE_WARN, "md: logging device: %s changed state to %s",
99*0Sstevel@tonic-gate md_devname(mddb_getsetnum(ul->un_recid), ul->un_dev, NULL, 0), str);
100*0Sstevel@tonic-gate }
101*0Sstevel@tonic-gate
102*0Sstevel@tonic-gate
103*0Sstevel@tonic-gate /*
104*0Sstevel@tonic-gate * atomically commit the log unit struct and any underlying metadevice struct
105*0Sstevel@tonic-gate */
106*0Sstevel@tonic-gate static void
logcommitdb(ml_unit_t * ul)107*0Sstevel@tonic-gate logcommitdb(ml_unit_t *ul)
108*0Sstevel@tonic-gate {
109*0Sstevel@tonic-gate mddb_recid_t recids[4];
110*0Sstevel@tonic-gate
111*0Sstevel@tonic-gate TRANSSTATS(ts_logcommitdb);
112*0Sstevel@tonic-gate
113*0Sstevel@tonic-gate uniqtime32(&ul->un_timestamp);
114*0Sstevel@tonic-gate
115*0Sstevel@tonic-gate /*
116*0Sstevel@tonic-gate * commit the log device and its child (if metadevice)
117*0Sstevel@tonic-gate */
118*0Sstevel@tonic-gate recids[0] = ul->un_recid;
119*0Sstevel@tonic-gate if (ul->un_status & LDL_METADEVICE) {
120*0Sstevel@tonic-gate struct mdc_unit *c = MD_UNIT(md_getminor(ul->un_dev));
121*0Sstevel@tonic-gate recids[1] = c->un_record_id;
122*0Sstevel@tonic-gate recids[2] = 0;
123*0Sstevel@tonic-gate } else
124*0Sstevel@tonic-gate recids[1] = 0;
125*0Sstevel@tonic-gate
126*0Sstevel@tonic-gate mddb_commitrecs_wrapper(recids);
127*0Sstevel@tonic-gate }
128*0Sstevel@tonic-gate
129*0Sstevel@tonic-gate static void
md_alloc_wrbuf(cirbuf_ic_t * cb,size_t bufsize)130*0Sstevel@tonic-gate md_alloc_wrbuf(cirbuf_ic_t *cb, size_t bufsize)
131*0Sstevel@tonic-gate {
132*0Sstevel@tonic-gate int i;
133*0Sstevel@tonic-gate buf_t *bp;
134*0Sstevel@tonic-gate
135*0Sstevel@tonic-gate /*
136*0Sstevel@tonic-gate * Clear previous allocation
137*0Sstevel@tonic-gate */
138*0Sstevel@tonic-gate if (cb->cb_nb)
139*0Sstevel@tonic-gate md_free_cirbuf(cb);
140*0Sstevel@tonic-gate
141*0Sstevel@tonic-gate bzero((caddr_t)cb, sizeof (*cb));
142*0Sstevel@tonic-gate rw_init(&cb->cb_rwlock.lock, NULL, RW_DRIVER, NULL);
143*0Sstevel@tonic-gate
144*0Sstevel@tonic-gate rw_enter(&cb->cb_rwlock.lock, RW_WRITER);
145*0Sstevel@tonic-gate
146*0Sstevel@tonic-gate /*
147*0Sstevel@tonic-gate * preallocate 3 bp's and put them on the free list.
148*0Sstevel@tonic-gate */
149*0Sstevel@tonic-gate for (i = 0; i < 3; ++i) {
150*0Sstevel@tonic-gate bp = md_trans_zalloc(sizeof (buf_t));
151*0Sstevel@tonic-gate sema_init(&bp->b_sem, 1, NULL, SEMA_DEFAULT, NULL);
152*0Sstevel@tonic-gate sema_init(&bp->b_io, 0, NULL, SEMA_DEFAULT, NULL);
153*0Sstevel@tonic-gate bp->b_offset = -1;
154*0Sstevel@tonic-gate bp->b_forw = cb->cb_free;
155*0Sstevel@tonic-gate cb->cb_free = bp;
156*0Sstevel@tonic-gate
157*0Sstevel@tonic-gate TRANSSTATS(ts_alloc_bp);
158*0Sstevel@tonic-gate }
159*0Sstevel@tonic-gate
160*0Sstevel@tonic-gate cb->cb_va = md_trans_alloc(bufsize);
161*0Sstevel@tonic-gate cb->cb_nb = bufsize;
162*0Sstevel@tonic-gate
163*0Sstevel@tonic-gate /*
164*0Sstevel@tonic-gate * first bp claims entire write buffer
165*0Sstevel@tonic-gate */
166*0Sstevel@tonic-gate bp = cb->cb_free;
167*0Sstevel@tonic-gate cb->cb_free = bp->b_forw;
168*0Sstevel@tonic-gate
169*0Sstevel@tonic-gate bp->b_forw = bp;
170*0Sstevel@tonic-gate bp->b_back = bp;
171*0Sstevel@tonic-gate cb->cb_bp = bp;
172*0Sstevel@tonic-gate bp->b_un.b_addr = cb->cb_va;
173*0Sstevel@tonic-gate bp->b_bufsize = cb->cb_nb;
174*0Sstevel@tonic-gate
175*0Sstevel@tonic-gate rw_exit(&cb->cb_rwlock.lock);
176*0Sstevel@tonic-gate }
177*0Sstevel@tonic-gate
178*0Sstevel@tonic-gate static void
md_alloc_rdbuf(cirbuf_ic_t * cb,size_t bufsize,size_t blksize)179*0Sstevel@tonic-gate md_alloc_rdbuf(cirbuf_ic_t *cb, size_t bufsize, size_t blksize)
180*0Sstevel@tonic-gate {
181*0Sstevel@tonic-gate caddr_t va;
182*0Sstevel@tonic-gate size_t nb;
183*0Sstevel@tonic-gate buf_t *bp;
184*0Sstevel@tonic-gate
185*0Sstevel@tonic-gate /*
186*0Sstevel@tonic-gate * Clear previous allocation
187*0Sstevel@tonic-gate */
188*0Sstevel@tonic-gate if (cb->cb_nb)
189*0Sstevel@tonic-gate md_free_cirbuf(cb);
190*0Sstevel@tonic-gate
191*0Sstevel@tonic-gate bzero((caddr_t)cb, sizeof (*cb));
192*0Sstevel@tonic-gate rw_init(&cb->cb_rwlock.lock, NULL, RW_DRIVER, NULL);
193*0Sstevel@tonic-gate
194*0Sstevel@tonic-gate rw_enter(&cb->cb_rwlock.lock, RW_WRITER);
195*0Sstevel@tonic-gate
196*0Sstevel@tonic-gate cb->cb_va = md_trans_alloc(bufsize);
197*0Sstevel@tonic-gate cb->cb_nb = bufsize;
198*0Sstevel@tonic-gate
199*0Sstevel@tonic-gate /*
200*0Sstevel@tonic-gate * preallocate N bufs that are hard-sized to blksize
201*0Sstevel@tonic-gate * in other words, the read buffer pool is a linked list
202*0Sstevel@tonic-gate * of statically sized bufs.
203*0Sstevel@tonic-gate */
204*0Sstevel@tonic-gate va = cb->cb_va;
205*0Sstevel@tonic-gate while ((nb = bufsize) != 0) {
206*0Sstevel@tonic-gate if (nb > blksize)
207*0Sstevel@tonic-gate nb = blksize;
208*0Sstevel@tonic-gate bp = md_trans_alloc(sizeof (buf_t));
209*0Sstevel@tonic-gate bzero((caddr_t)bp, sizeof (buf_t));
210*0Sstevel@tonic-gate sema_init(&bp->b_sem, 1, NULL, SEMA_DEFAULT, NULL);
211*0Sstevel@tonic-gate sema_init(&bp->b_io, 0, NULL, SEMA_DEFAULT, NULL);
212*0Sstevel@tonic-gate bp->b_un.b_addr = va;
213*0Sstevel@tonic-gate bp->b_bufsize = nb;
214*0Sstevel@tonic-gate bp->b_offset = -1;
215*0Sstevel@tonic-gate if (cb->cb_bp) {
216*0Sstevel@tonic-gate bp->b_forw = cb->cb_bp->b_forw;
217*0Sstevel@tonic-gate bp->b_back = cb->cb_bp;
218*0Sstevel@tonic-gate cb->cb_bp->b_forw->b_back = bp;
219*0Sstevel@tonic-gate cb->cb_bp->b_forw = bp;
220*0Sstevel@tonic-gate } else
221*0Sstevel@tonic-gate bp->b_forw = bp->b_back = bp;
222*0Sstevel@tonic-gate cb->cb_bp = bp;
223*0Sstevel@tonic-gate
224*0Sstevel@tonic-gate TRANSSTATS(ts_alloc_bp);
225*0Sstevel@tonic-gate
226*0Sstevel@tonic-gate bufsize -= nb;
227*0Sstevel@tonic-gate va += nb;
228*0Sstevel@tonic-gate }
229*0Sstevel@tonic-gate
230*0Sstevel@tonic-gate rw_exit(&cb->cb_rwlock.lock);
231*0Sstevel@tonic-gate }
232*0Sstevel@tonic-gate
233*0Sstevel@tonic-gate
234*0Sstevel@tonic-gate static void
md_free_cirbuf(cirbuf_ic_t * cb)235*0Sstevel@tonic-gate md_free_cirbuf(cirbuf_ic_t *cb)
236*0Sstevel@tonic-gate {
237*0Sstevel@tonic-gate buf_t *bp;
238*0Sstevel@tonic-gate
239*0Sstevel@tonic-gate if (cb->cb_nb == 0)
240*0Sstevel@tonic-gate return;
241*0Sstevel@tonic-gate
242*0Sstevel@tonic-gate rw_enter(&cb->cb_rwlock.lock, RW_WRITER);
243*0Sstevel@tonic-gate ASSERT(cb->cb_dirty == NULL);
244*0Sstevel@tonic-gate
245*0Sstevel@tonic-gate /*
246*0Sstevel@tonic-gate * free the active bufs
247*0Sstevel@tonic-gate */
248*0Sstevel@tonic-gate while ((bp = cb->cb_bp) != NULL) {
249*0Sstevel@tonic-gate if (bp == bp->b_forw)
250*0Sstevel@tonic-gate cb->cb_bp = NULL;
251*0Sstevel@tonic-gate else
252*0Sstevel@tonic-gate cb->cb_bp = bp->b_forw;
253*0Sstevel@tonic-gate bp->b_back->b_forw = bp->b_forw;
254*0Sstevel@tonic-gate bp->b_forw->b_back = bp->b_back;
255*0Sstevel@tonic-gate sema_destroy(&bp->b_sem);
256*0Sstevel@tonic-gate sema_destroy(&bp->b_io);
257*0Sstevel@tonic-gate md_trans_free(bp, sizeof (buf_t));
258*0Sstevel@tonic-gate }
259*0Sstevel@tonic-gate
260*0Sstevel@tonic-gate /*
261*0Sstevel@tonic-gate * free the free bufs
262*0Sstevel@tonic-gate */
263*0Sstevel@tonic-gate while ((bp = cb->cb_free) != NULL) {
264*0Sstevel@tonic-gate cb->cb_free = bp->b_forw;
265*0Sstevel@tonic-gate sema_destroy(&bp->b_sem);
266*0Sstevel@tonic-gate sema_destroy(&bp->b_io);
267*0Sstevel@tonic-gate md_trans_free(bp, sizeof (buf_t));
268*0Sstevel@tonic-gate }
269*0Sstevel@tonic-gate md_trans_free(cb->cb_va, cb->cb_nb);
270*0Sstevel@tonic-gate cb->cb_va = NULL;
271*0Sstevel@tonic-gate cb->cb_nb = 0;
272*0Sstevel@tonic-gate rw_exit(&cb->cb_rwlock.lock);
273*0Sstevel@tonic-gate rw_destroy(&cb->cb_rwlock.lock);
274*0Sstevel@tonic-gate }
275*0Sstevel@tonic-gate
276*0Sstevel@tonic-gate int
ldl_build_incore(ml_unit_t * ul,int snarfing)277*0Sstevel@tonic-gate ldl_build_incore(ml_unit_t *ul, int snarfing)
278*0Sstevel@tonic-gate {
279*0Sstevel@tonic-gate size_t bufsize;
280*0Sstevel@tonic-gate set_t setno;
281*0Sstevel@tonic-gate
282*0Sstevel@tonic-gate setno = mddb_getsetnum(ul->un_recid);
283*0Sstevel@tonic-gate
284*0Sstevel@tonic-gate ASSERT(ul->un_head_lof >= ul->un_bol_lof);
285*0Sstevel@tonic-gate ASSERT(ul->un_bol_lof);
286*0Sstevel@tonic-gate
287*0Sstevel@tonic-gate if (ul->un_status & LDL_BEING_RESET) {
288*0Sstevel@tonic-gate mddb_setrecprivate(ul->un_recid, MD_PRV_PENDCLEAN);
289*0Sstevel@tonic-gate return (1);
290*0Sstevel@tonic-gate }
291*0Sstevel@tonic-gate
292*0Sstevel@tonic-gate /*
293*0Sstevel@tonic-gate * If snarfing the log device,
294*0Sstevel@tonic-gate * then remake the device number
295*0Sstevel@tonic-gate * else (we are creating the log device)
296*0Sstevel@tonic-gate * set the driver name in the shared name space.
297*0Sstevel@tonic-gate */
298*0Sstevel@tonic-gate if (snarfing) {
299*0Sstevel@tonic-gate ul->un_dev = md_getdevnum(setno, mddb_getsidenum(setno),
300*0Sstevel@tonic-gate ul->un_key, MD_NOTRUST_DEVT);
301*0Sstevel@tonic-gate }
302*0Sstevel@tonic-gate
303*0Sstevel@tonic-gate /*
304*0Sstevel@tonic-gate * With the current device id implementation there is possibility
305*0Sstevel@tonic-gate * that we may have NODEV if the underlying can't be resolved at
306*0Sstevel@tonic-gate * snarf time. If this is the case we want to be consistent with
307*0Sstevel@tonic-gate * the normal behavior and continue to allow log to be put on the list.
308*0Sstevel@tonic-gate * We delay the resolve of the dev_t so we can resolve at the open
309*0Sstevel@tonic-gate * time of the log device by device id
310*0Sstevel@tonic-gate */
311*0Sstevel@tonic-gate if ((md_getmajor(ul->un_dev) == md_major) &&
312*0Sstevel@tonic-gate (md_dev_exists(ul->un_dev) == 0)) {
313*0Sstevel@tonic-gate return (1);
314*0Sstevel@tonic-gate }
315*0Sstevel@tonic-gate
316*0Sstevel@tonic-gate mutex_enter(&ml_lock);
317*0Sstevel@tonic-gate
318*0Sstevel@tonic-gate /*
319*0Sstevel@tonic-gate * initialize incore structs
320*0Sstevel@tonic-gate * LDL_FIND_TAIL flag indicates that all I/O must wait until the
321*0Sstevel@tonic-gate * tail has been found.
322*0Sstevel@tonic-gate */
323*0Sstevel@tonic-gate ul->un_opencnt = 0;
324*0Sstevel@tonic-gate ul->un_transcnt = 0;
325*0Sstevel@tonic-gate ul->un_resv = 0;
326*0Sstevel@tonic-gate ul->un_utlist = NULL;
327*0Sstevel@tonic-gate ul->un_logmap = NULL;
328*0Sstevel@tonic-gate ul->un_status |= LDL_FIND_TAIL;
329*0Sstevel@tonic-gate ul->un_status &= ~LDL_SCAN_ACTIVE;
330*0Sstevel@tonic-gate ASSERT(ul->un_devbsize == DEV_BSIZE);
331*0Sstevel@tonic-gate
332*0Sstevel@tonic-gate mutex_init(&ul->un_log_mutex, NULL, MUTEX_DRIVER, NULL);
333*0Sstevel@tonic-gate
334*0Sstevel@tonic-gate /*
335*0Sstevel@tonic-gate * allocate some read and write buffers
336*0Sstevel@tonic-gate */
337*0Sstevel@tonic-gate bufsize = md_ldl_bufsize(ul);
338*0Sstevel@tonic-gate ul->un_rdbuf.cb_nb = 0;
339*0Sstevel@tonic-gate md_alloc_rdbuf(&ul->un_rdbuf, bufsize, MAPBLOCKSIZE);
340*0Sstevel@tonic-gate ul->un_wrbuf.cb_nb = 0;
341*0Sstevel@tonic-gate md_alloc_wrbuf(&ul->un_wrbuf, bufsize);
342*0Sstevel@tonic-gate
343*0Sstevel@tonic-gate if (snarfing) {
344*0Sstevel@tonic-gate if (ul->un_error & LDL_ANYERROR) {
345*0Sstevel@tonic-gate ul->un_error = LDL_HERROR;
346*0Sstevel@tonic-gate ldl_errorstate(ul);
347*0Sstevel@tonic-gate } else
348*0Sstevel@tonic-gate ul->un_error = 0;
349*0Sstevel@tonic-gate }
350*0Sstevel@tonic-gate
351*0Sstevel@tonic-gate /* Put on the unit list */
352*0Sstevel@tonic-gate ul->un_next = ul_list;
353*0Sstevel@tonic-gate ul_list = ul;
354*0Sstevel@tonic-gate md_nlogs++;
355*0Sstevel@tonic-gate
356*0Sstevel@tonic-gate mutex_exit(&ml_lock);
357*0Sstevel@tonic-gate return (0);
358*0Sstevel@tonic-gate }
359*0Sstevel@tonic-gate
360*0Sstevel@tonic-gate ml_unit_t *
ldl_findlog(mddb_recid_t recid)361*0Sstevel@tonic-gate ldl_findlog(mddb_recid_t recid)
362*0Sstevel@tonic-gate {
363*0Sstevel@tonic-gate ml_unit_t *ul;
364*0Sstevel@tonic-gate
365*0Sstevel@tonic-gate /*
366*0Sstevel@tonic-gate * Find a unit struct by database recid
367*0Sstevel@tonic-gate */
368*0Sstevel@tonic-gate mutex_enter(&ml_lock);
369*0Sstevel@tonic-gate for (ul = ul_list; ul; ul = ul->un_next)
370*0Sstevel@tonic-gate if (ul->un_recid == recid)
371*0Sstevel@tonic-gate break;
372*0Sstevel@tonic-gate mutex_exit(&ml_lock);
373*0Sstevel@tonic-gate return (ul);
374*0Sstevel@tonic-gate }
375*0Sstevel@tonic-gate
376*0Sstevel@tonic-gate /*
377*0Sstevel@tonic-gate * ldl_utadd adds a metatrans device to the log's list of mt devices.
378*0Sstevel@tonic-gate * WARNING: top_end_sync() scans this list W/O locking for performance!!!
379*0Sstevel@tonic-gate */
380*0Sstevel@tonic-gate void
ldl_utadd(mt_unit_t * un)381*0Sstevel@tonic-gate ldl_utadd(mt_unit_t *un)
382*0Sstevel@tonic-gate {
383*0Sstevel@tonic-gate ml_unit_t *ul = un->un_l_unit;
384*0Sstevel@tonic-gate
385*0Sstevel@tonic-gate if (ul == NULL)
386*0Sstevel@tonic-gate return;
387*0Sstevel@tonic-gate
388*0Sstevel@tonic-gate mutex_enter(&ut_mutex);
389*0Sstevel@tonic-gate un->un_next = ul->un_utlist;
390*0Sstevel@tonic-gate ul->un_utlist = un;
391*0Sstevel@tonic-gate ASSERT((ul->un_logmap == NULL) || (ul->un_logmap == un->un_logmap));
392*0Sstevel@tonic-gate ul->un_logmap = un->un_logmap;
393*0Sstevel@tonic-gate mutex_exit(&ut_mutex);
394*0Sstevel@tonic-gate }
395*0Sstevel@tonic-gate
396*0Sstevel@tonic-gate /*
397*0Sstevel@tonic-gate * ldl_utdel removes a metatrans device to the log's list of mt devices.
398*0Sstevel@tonic-gate * WARNING: top_end_sync() scans this list W/O locking for performance!!!
399*0Sstevel@tonic-gate */
400*0Sstevel@tonic-gate static void
ldl_utdel(mt_unit_t * un)401*0Sstevel@tonic-gate ldl_utdel(mt_unit_t *un)
402*0Sstevel@tonic-gate {
403*0Sstevel@tonic-gate ml_unit_t *ul = un->un_l_unit;
404*0Sstevel@tonic-gate mt_unit_t **utp = &ul->un_utlist;
405*0Sstevel@tonic-gate
406*0Sstevel@tonic-gate mutex_enter(&ut_mutex);
407*0Sstevel@tonic-gate for (utp = &ul->un_utlist;
408*0Sstevel@tonic-gate *utp && (*utp != un);
409*0Sstevel@tonic-gate utp = &(*utp)->un_next);
410*0Sstevel@tonic-gate if (*utp)
411*0Sstevel@tonic-gate *utp = un->un_next;
412*0Sstevel@tonic-gate un->un_l_unit = NULL;
413*0Sstevel@tonic-gate mutex_exit(&ut_mutex);
414*0Sstevel@tonic-gate }
415*0Sstevel@tonic-gate
416*0Sstevel@tonic-gate mddb_recid_t
ldl_create(mdkey_t key,mt_unit_t * un)417*0Sstevel@tonic-gate ldl_create(mdkey_t key, mt_unit_t *un)
418*0Sstevel@tonic-gate {
419*0Sstevel@tonic-gate ml_unit_t *ul;
420*0Sstevel@tonic-gate mddb_recid_t recid;
421*0Sstevel@tonic-gate struct timeval32 tv;
422*0Sstevel@tonic-gate mddb_type_t typ1;
423*0Sstevel@tonic-gate set_t setno;
424*0Sstevel@tonic-gate
425*0Sstevel@tonic-gate setno = MD_UN2SET(un);
426*0Sstevel@tonic-gate
427*0Sstevel@tonic-gate /*
428*0Sstevel@tonic-gate * Find a unit struct for this key and set
429*0Sstevel@tonic-gate * If we found one then, we are done.
430*0Sstevel@tonic-gate * Else create one.
431*0Sstevel@tonic-gate */
432*0Sstevel@tonic-gate mutex_enter(&ml_lock);
433*0Sstevel@tonic-gate for (ul = ul_list; ul; ul = ul->un_next)
434*0Sstevel@tonic-gate if ((ul->un_key == key) &&
435*0Sstevel@tonic-gate (mddb_getsetnum(ul->un_recid) == setno))
436*0Sstevel@tonic-gate break;
437*0Sstevel@tonic-gate mutex_exit(&ml_lock);
438*0Sstevel@tonic-gate
439*0Sstevel@tonic-gate if (ul)
440*0Sstevel@tonic-gate return (ul->un_recid);
441*0Sstevel@tonic-gate
442*0Sstevel@tonic-gate typ1 = (mddb_type_t)md_getshared_key(setno,
443*0Sstevel@tonic-gate trans_md_ops.md_driver.md_drivername);
444*0Sstevel@tonic-gate recid = mddb_createrec(ML_UNIT_ONDSZ, typ1, LOG_REC,
445*0Sstevel@tonic-gate MD_CRO_32BIT | MD_CRO_TRANS_LOG, setno);
446*0Sstevel@tonic-gate if (recid < 0)
447*0Sstevel@tonic-gate return (recid);
448*0Sstevel@tonic-gate mddb_setrecprivate(recid, MD_PRV_GOTIT);
449*0Sstevel@tonic-gate
450*0Sstevel@tonic-gate ul = (ml_unit_t *)mddb_getrecaddr_resize(recid, sizeof (*ul), 0);
451*0Sstevel@tonic-gate
452*0Sstevel@tonic-gate ul->un_recid = recid;
453*0Sstevel@tonic-gate ul->un_key = key;
454*0Sstevel@tonic-gate ul->un_dev = md_getdevnum(setno, mddb_getsidenum(setno), key,
455*0Sstevel@tonic-gate MD_NOTRUST_DEVT);
456*0Sstevel@tonic-gate ul->un_bol_lof = (off32_t)dbtob(un->un_l_sblk);
457*0Sstevel@tonic-gate ul->un_eol_lof = ul->un_bol_lof + (off32_t)dbtob(un->un_l_nblks);
458*0Sstevel@tonic-gate ul->un_pwsblk = un->un_l_pwsblk;
459*0Sstevel@tonic-gate ul->un_nblks = un->un_l_nblks;
460*0Sstevel@tonic-gate ul->un_tblks = un->un_l_tblks;
461*0Sstevel@tonic-gate ul->un_maxresv = un->un_l_maxresv;
462*0Sstevel@tonic-gate ul->un_maxtransfer = (uint_t)dbtob(un->un_l_maxtransfer);
463*0Sstevel@tonic-gate ul->un_devbsize = DEV_BSIZE;
464*0Sstevel@tonic-gate
465*0Sstevel@tonic-gate /*
466*0Sstevel@tonic-gate * empty log
467*0Sstevel@tonic-gate */
468*0Sstevel@tonic-gate uniqtime32(&tv);
469*0Sstevel@tonic-gate ul->un_head_lof = ul->un_bol_lof;
470*0Sstevel@tonic-gate ul->un_tail_lof = ul->un_bol_lof;
471*0Sstevel@tonic-gate ul->un_head_ident = tv.tv_sec;
472*0Sstevel@tonic-gate ul->un_tail_ident = tv.tv_sec;
473*0Sstevel@tonic-gate
474*0Sstevel@tonic-gate if (md_getmajor(ul->un_dev) == md_major)
475*0Sstevel@tonic-gate ul->un_status |= LDL_METADEVICE;
476*0Sstevel@tonic-gate
477*0Sstevel@tonic-gate md_set_parent(ul->un_dev, (int)MD_MULTI_PARENT);
478*0Sstevel@tonic-gate (void) ldl_build_incore(ul, 0);
479*0Sstevel@tonic-gate logcommitdb(ul);
480*0Sstevel@tonic-gate return (recid);
481*0Sstevel@tonic-gate }
482*0Sstevel@tonic-gate
483*0Sstevel@tonic-gate int
ldl_open_dev(mt_unit_t * un,ml_unit_t * ul)484*0Sstevel@tonic-gate ldl_open_dev(mt_unit_t *un, ml_unit_t *ul)
485*0Sstevel@tonic-gate {
486*0Sstevel@tonic-gate int err = 0;
487*0Sstevel@tonic-gate md_dev64_t tmpdev;
488*0Sstevel@tonic-gate minor_t mnum = MD_SID(un);
489*0Sstevel@tonic-gate set_t setno = MD_MIN2SET(MD_SID(un));
490*0Sstevel@tonic-gate side_t side = mddb_getsidenum(setno);
491*0Sstevel@tonic-gate
492*0Sstevel@tonic-gate mutex_enter(&oc_mutex);
493*0Sstevel@tonic-gate
494*0Sstevel@tonic-gate if (ul->un_opencnt) {
495*0Sstevel@tonic-gate ul->un_opencnt++;
496*0Sstevel@tonic-gate mutex_exit(&oc_mutex);
497*0Sstevel@tonic-gate return (0);
498*0Sstevel@tonic-gate }
499*0Sstevel@tonic-gate
500*0Sstevel@tonic-gate tmpdev = ul->un_dev;
501*0Sstevel@tonic-gate /*
502*0Sstevel@tonic-gate * Do the open by device id if it is regular device
503*0Sstevel@tonic-gate */
504*0Sstevel@tonic-gate if ((md_getmajor(tmpdev) != md_major) &&
505*0Sstevel@tonic-gate md_devid_found(setno, side, ul->un_key) == 1) {
506*0Sstevel@tonic-gate tmpdev = md_resolve_bydevid(mnum, tmpdev, ul->un_key);
507*0Sstevel@tonic-gate }
508*0Sstevel@tonic-gate err = md_layered_open(mnum, &tmpdev, MD_OFLG_NULL);
509*0Sstevel@tonic-gate ul->un_dev = tmpdev;
510*0Sstevel@tonic-gate
511*0Sstevel@tonic-gate if (err == 0)
512*0Sstevel@tonic-gate ul->un_opencnt++;
513*0Sstevel@tonic-gate
514*0Sstevel@tonic-gate mutex_exit(&oc_mutex);
515*0Sstevel@tonic-gate return (err);
516*0Sstevel@tonic-gate }
517*0Sstevel@tonic-gate
518*0Sstevel@tonic-gate void
ldl_close_dev(ml_unit_t * ul)519*0Sstevel@tonic-gate ldl_close_dev(ml_unit_t *ul)
520*0Sstevel@tonic-gate {
521*0Sstevel@tonic-gate
522*0Sstevel@tonic-gate mutex_enter(&oc_mutex);
523*0Sstevel@tonic-gate
524*0Sstevel@tonic-gate ul->un_opencnt--;
525*0Sstevel@tonic-gate
526*0Sstevel@tonic-gate if (ul->un_opencnt) {
527*0Sstevel@tonic-gate mutex_exit(&oc_mutex);
528*0Sstevel@tonic-gate return;
529*0Sstevel@tonic-gate }
530*0Sstevel@tonic-gate
531*0Sstevel@tonic-gate /* Last reference to the log, close it */
532*0Sstevel@tonic-gate md_layered_close(ul->un_dev, MD_OFLG_NULL);
533*0Sstevel@tonic-gate
534*0Sstevel@tonic-gate mutex_exit(&oc_mutex);
535*0Sstevel@tonic-gate }
536*0Sstevel@tonic-gate
537*0Sstevel@tonic-gate
538*0Sstevel@tonic-gate /*
539*0Sstevel@tonic-gate * LOGSCAN STUFF
540*0Sstevel@tonic-gate */
541*0Sstevel@tonic-gate int
ldl_isherror(ml_unit_t * ul)542*0Sstevel@tonic-gate ldl_isherror(ml_unit_t *ul)
543*0Sstevel@tonic-gate {
544*0Sstevel@tonic-gate return ((ul != NULL) && (ul->un_error & LDL_HERROR));
545*0Sstevel@tonic-gate }
546*0Sstevel@tonic-gate
547*0Sstevel@tonic-gate int
ldl_iserror(ml_unit_t * ul)548*0Sstevel@tonic-gate ldl_iserror(ml_unit_t *ul)
549*0Sstevel@tonic-gate {
550*0Sstevel@tonic-gate return ((ul != NULL) && (ul->un_error & LDL_ERROR));
551*0Sstevel@tonic-gate }
552*0Sstevel@tonic-gate
553*0Sstevel@tonic-gate size_t
md_ldl_bufsize(ml_unit_t * ul)554*0Sstevel@tonic-gate md_ldl_bufsize(ml_unit_t *ul)
555*0Sstevel@tonic-gate {
556*0Sstevel@tonic-gate size_t bufsize;
557*0Sstevel@tonic-gate
558*0Sstevel@tonic-gate /*
559*0Sstevel@tonic-gate * initial guess is the maxtransfer value for this log device
560*0Sstevel@tonic-gate * reduce by number of logs
561*0Sstevel@tonic-gate * increase for sharing
562*0Sstevel@tonic-gate * increase if too small
563*0Sstevel@tonic-gate * decrease if too large
564*0Sstevel@tonic-gate */
565*0Sstevel@tonic-gate bufsize = ul->un_maxtransfer;
566*0Sstevel@tonic-gate if (md_nlogs)
567*0Sstevel@tonic-gate bufsize /= md_nlogs;
568*0Sstevel@tonic-gate if (ul->un_transcnt)
569*0Sstevel@tonic-gate bufsize *= ul->un_transcnt;
570*0Sstevel@tonic-gate bufsize = dbtob(btod(bufsize));
571*0Sstevel@tonic-gate if (bufsize < LDL_MINBUFSIZE)
572*0Sstevel@tonic-gate bufsize = LDL_MINBUFSIZE;
573*0Sstevel@tonic-gate if (bufsize > maxphys)
574*0Sstevel@tonic-gate bufsize = maxphys;
575*0Sstevel@tonic-gate if (bufsize > ul->un_maxtransfer)
576*0Sstevel@tonic-gate bufsize = ul->un_maxtransfer;
577*0Sstevel@tonic-gate return (bufsize);
578*0Sstevel@tonic-gate }
579*0Sstevel@tonic-gate
580*0Sstevel@tonic-gate /*
581*0Sstevel@tonic-gate * if necessary; open all underlying devices for ul and start threads
582*0Sstevel@tonic-gate * called at snarf, metainit, and open
583*0Sstevel@tonic-gate */
584*0Sstevel@tonic-gate void
ldl_open_underlying(mt_unit_t * un)585*0Sstevel@tonic-gate ldl_open_underlying(mt_unit_t *un)
586*0Sstevel@tonic-gate {
587*0Sstevel@tonic-gate ml_unit_t *ul = un->un_l_unit;
588*0Sstevel@tonic-gate int err = 0;
589*0Sstevel@tonic-gate
590*0Sstevel@tonic-gate
591*0Sstevel@tonic-gate /*
592*0Sstevel@tonic-gate * first, handle the case of detached logs
593*0Sstevel@tonic-gate */
594*0Sstevel@tonic-gate if (ul == NULL) {
595*0Sstevel@tonic-gate err = trans_open_all_devs(un);
596*0Sstevel@tonic-gate if (err == 0) {
597*0Sstevel@tonic-gate un->un_flags &= ~TRANS_NEED_OPEN;
598*0Sstevel@tonic-gate un->un_flags |= TRANS_OPENED;
599*0Sstevel@tonic-gate }
600*0Sstevel@tonic-gate }
601*0Sstevel@tonic-gate }
602*0Sstevel@tonic-gate
603*0Sstevel@tonic-gate /*
604*0Sstevel@tonic-gate * remove log unit struct from global linked list
605*0Sstevel@tonic-gate */
606*0Sstevel@tonic-gate static void
ldl_unlist(ml_unit_t * ul)607*0Sstevel@tonic-gate ldl_unlist(ml_unit_t *ul)
608*0Sstevel@tonic-gate {
609*0Sstevel@tonic-gate ml_unit_t **ulp;
610*0Sstevel@tonic-gate
611*0Sstevel@tonic-gate /*
612*0Sstevel@tonic-gate * remove from list
613*0Sstevel@tonic-gate */
614*0Sstevel@tonic-gate mutex_enter(&ml_lock);
615*0Sstevel@tonic-gate for (ulp = &ul_list; *ulp && (*ulp != ul); ulp = &(*ulp)->un_next);
616*0Sstevel@tonic-gate if (*ulp) {
617*0Sstevel@tonic-gate *ulp = ul->un_next;
618*0Sstevel@tonic-gate --md_nlogs;
619*0Sstevel@tonic-gate }
620*0Sstevel@tonic-gate mutex_exit(&ml_lock);
621*0Sstevel@tonic-gate }
622*0Sstevel@tonic-gate
623*0Sstevel@tonic-gate /*
624*0Sstevel@tonic-gate * get rid of a log unit from the database
625*0Sstevel@tonic-gate */
626*0Sstevel@tonic-gate void
ldl_cleanup(ml_unit_t * ul)627*0Sstevel@tonic-gate ldl_cleanup(ml_unit_t *ul)
628*0Sstevel@tonic-gate {
629*0Sstevel@tonic-gate sv_dev_t sv;
630*0Sstevel@tonic-gate
631*0Sstevel@tonic-gate /* Save the log key */
632*0Sstevel@tonic-gate sv.setno = mddb_getsetnum(ul->un_recid);
633*0Sstevel@tonic-gate sv.key = ul->un_key;
634*0Sstevel@tonic-gate
635*0Sstevel@tonic-gate mddb_deleterec_wrapper(ul->un_recid);
636*0Sstevel@tonic-gate md_rem_names(&sv, 1);
637*0Sstevel@tonic-gate }
638*0Sstevel@tonic-gate
639*0Sstevel@tonic-gate static void
ldl_delete(ml_unit_t * ul,int removing)640*0Sstevel@tonic-gate ldl_delete(ml_unit_t *ul, int removing)
641*0Sstevel@tonic-gate {
642*0Sstevel@tonic-gate
643*0Sstevel@tonic-gate /*
644*0Sstevel@tonic-gate * remove from list
645*0Sstevel@tonic-gate */
646*0Sstevel@tonic-gate ldl_unlist(ul);
647*0Sstevel@tonic-gate
648*0Sstevel@tonic-gate /*
649*0Sstevel@tonic-gate * free up resources
650*0Sstevel@tonic-gate */
651*0Sstevel@tonic-gate md_free_cirbuf(&ul->un_rdbuf);
652*0Sstevel@tonic-gate md_free_cirbuf(&ul->un_wrbuf);
653*0Sstevel@tonic-gate
654*0Sstevel@tonic-gate mutex_destroy(&ul->un_log_mutex);
655*0Sstevel@tonic-gate
656*0Sstevel@tonic-gate if (removing) {
657*0Sstevel@tonic-gate md_reset_parent(ul->un_dev);
658*0Sstevel@tonic-gate ul->un_status |= LDL_BEING_RESET;
659*0Sstevel@tonic-gate logcommitdb(ul);
660*0Sstevel@tonic-gate ldl_cleanup(ul);
661*0Sstevel@tonic-gate }
662*0Sstevel@tonic-gate }
663*0Sstevel@tonic-gate
664*0Sstevel@tonic-gate /*
665*0Sstevel@tonic-gate * detach log from trans device
666*0Sstevel@tonic-gate * caller insures that trans device is idle and will remain idle
667*0Sstevel@tonic-gate */
668*0Sstevel@tonic-gate /* ARGSUSED */
669*0Sstevel@tonic-gate int
ldl_reset(mt_unit_t * un,int removing,int force)670*0Sstevel@tonic-gate ldl_reset(mt_unit_t *un, int removing, int force)
671*0Sstevel@tonic-gate {
672*0Sstevel@tonic-gate ml_unit_t *ul = un->un_l_unit;
673*0Sstevel@tonic-gate
674*0Sstevel@tonic-gate if (ul == NULL)
675*0Sstevel@tonic-gate return (0);
676*0Sstevel@tonic-gate
677*0Sstevel@tonic-gate if (un->un_flags & TRANS_DETACHING) {
678*0Sstevel@tonic-gate un->un_flags &= ~TRANS_DETACHING;
679*0Sstevel@tonic-gate un->un_flags |= TRANS_DETACHED;
680*0Sstevel@tonic-gate trans_commit(un, 0);
681*0Sstevel@tonic-gate }
682*0Sstevel@tonic-gate
683*0Sstevel@tonic-gate /*
684*0Sstevel@tonic-gate * remove this metatrans device from the log's list of mt devices
685*0Sstevel@tonic-gate */
686*0Sstevel@tonic-gate ldl_utdel(un);
687*0Sstevel@tonic-gate
688*0Sstevel@tonic-gate /*
689*0Sstevel@tonic-gate * busy; do nothing
690*0Sstevel@tonic-gate */
691*0Sstevel@tonic-gate if (ul->un_utlist)
692*0Sstevel@tonic-gate return (0);
693*0Sstevel@tonic-gate
694*0Sstevel@tonic-gate ldl_delete(ul, removing);
695*0Sstevel@tonic-gate
696*0Sstevel@tonic-gate return (0);
697*0Sstevel@tonic-gate }
698