xref: /onnv-gate/usr/src/uts/common/io/lvm/trans/trans_log.c (revision 0:68f95e015346)
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