xref: /titanic_50/usr/src/uts/common/avs/ns/rdc/rdc_bitmap.c (revision 3270659f55e0928d6edec3d26217cc29398a8149)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/types.h>
27 #include <sys/ksynch.h>
28 #include <sys/cmn_err.h>
29 #include <sys/kmem.h>
30 #include <sys/stat.h>
31 #include <sys/errno.h>
32 
33 #include "../solaris/nsc_thread.h"
34 #ifdef DS_DDICT
35 #include "../contract.h"
36 #endif
37 #include <sys/nsctl/nsctl.h>
38 
39 #include <sys/kmem.h>
40 #include <sys/cmn_err.h>
41 #include <sys/ddi.h>
42 
43 #include "rdc_io.h"
44 #include "rdc_bitmap.h"
45 #include "rdc_clnt.h"
46 #include "rdc_diskq.h"
47 
48 #include <sys/unistat/spcs_s.h>
49 #include <sys/unistat/spcs_s_k.h>
50 #include <sys/unistat/spcs_errors.h>
51 
52 #ifndef UINT8_MAX
53 #define	UINT8_MAX 255
54 #endif
55 
56 #ifndef UINT_MAX
57 #define	UINT_MAX 0xffffffff
58 #endif
59 
60 /*
61  * RDC bitmap functions.
62  */
63 
64 /*
65  * RDC cluster integration notes.
66  *
67  * 1. Configuration
68  *
69  * 1.1. Change 'rdc_bitmap_mode' in /usr/kernel/drv/rdc.conf to '1'.
70  *
71  * 2. Operation
72  *
73  * 2.1. SunCluster ensures that only one physical host has any rdc
74  *	controlled device imported at any one time.  Hence rdc will
75  *	only be active on a single node for any set at a time.
76  *
77  * 2.2. So operation from the kernel perspective looks just like
78  *	operation on a single, standalone, node.
79  *
80  */
81 
82 struct rdc_bitmap_ops *rdc_bitmap_ops;		/* the bitmap ops switch */
83 static int rdc_wrflag;				/* write flag for io */
84 int rdc_bitmap_delay = 0;
85 extern nsc_io_t *_rdc_io_hc;
86 
87 int rdc_suspend_diskq(rdc_k_info_t *krdc);
88 
89 /*
90  * rdc_ns_io
91  *	Perform read or write on an underlying ns device
92  *
93  * fd		- nsc file descriptor
94  * flag		- nsc io direction and characteristics flag
95  * fba_pos	- offset from beginning of device in FBAs
96  * io_addr	- pointer to data buffer
97  * io_len	- length of io in bytes
98  */
99 
100 int
rdc_ns_io(nsc_fd_t * fd,int flag,nsc_off_t fba_pos,uchar_t * io_addr,nsc_size_t io_len)101 rdc_ns_io(nsc_fd_t *fd, int flag, nsc_off_t fba_pos, uchar_t *io_addr,
102     nsc_size_t io_len)
103 {
104 	nsc_buf_t *tmp;
105 	nsc_vec_t *vecp;
106 	uchar_t	*vaddr;
107 	size_t	copy_len;
108 	int	vlen;
109 	int	rc;
110 	nsc_size_t	fba_req, fba_len;
111 	nsc_size_t	maxfbas = 0;
112 	nsc_size_t	tocopy;
113 	unsigned char *toaddr;
114 
115 	rc = nsc_maxfbas(fd, 0, &maxfbas);
116 	if (!RDC_SUCCESS(rc)) {
117 #ifdef DEBUG
118 		cmn_err(CE_WARN, "!rdc_ns_io: maxfbas failed (%d)", rc);
119 #endif
120 		maxfbas = 256;
121 	}
122 	toaddr = io_addr;
123 	fba_req = FBA_LEN(io_len);
124 loop:
125 	tmp = NULL;
126 	fba_len = min(fba_req, maxfbas);
127 	tocopy = min(io_len, FBA_SIZE(fba_len));
128 	ASSERT(tocopy < INT32_MAX);
129 
130 	rc = nsc_alloc_buf(fd, fba_pos, fba_len, flag, &tmp);
131 	if (!RDC_SUCCESS(rc)) {
132 		if (tmp) {
133 			(void) nsc_free_buf(tmp);
134 		}
135 		return (EIO);
136 	}
137 
138 	if ((flag & NSC_WRITE) != 0 && (flag & NSC_READ) == 0 &&
139 	    FBA_OFF(io_len) != 0) {
140 		/*
141 		 * Not overwriting all of the last FBA, so read in the
142 		 * old contents now before we overwrite it with the new
143 		 * data.
144 		 */
145 		rc = nsc_read(tmp, fba_pos+FBA_NUM(io_len), 1, 0);
146 		if (!RDC_SUCCESS(rc)) {
147 			(void) nsc_free_buf(tmp);
148 			return (EIO);
149 		}
150 	}
151 
152 	vecp = tmp->sb_vec;
153 	vlen = vecp->sv_len;
154 	vaddr = vecp->sv_addr;
155 
156 	while (tocopy > 0) {
157 		if (vecp->sv_addr == 0 || vecp->sv_len == 0) {
158 #ifdef DEBUG
159 			cmn_err(CE_WARN, "!rdc_ns_io: ran off end of handle");
160 #endif
161 			break;
162 		}
163 
164 		copy_len = (size_t)min(vlen, (int)tocopy);
165 
166 		if (flag & NSC_WRITE)
167 			bcopy(toaddr, vaddr, copy_len);
168 		else
169 			bcopy(vaddr, toaddr, copy_len);
170 
171 		toaddr += copy_len;
172 		io_addr += copy_len;	/* adjust position in callers buffer */
173 		io_len -= copy_len;	/* adjust total byte length remaining */
174 		tocopy -= copy_len;	/* adjust chunk byte length remaining */
175 		vaddr += copy_len;	/* adjust location in sv_vec_t */
176 		vlen -= copy_len;	/* adjust length left in sv_vec_t */
177 
178 		if (vlen <= 0) {
179 			vecp++;
180 			vaddr = vecp->sv_addr;
181 			vlen = vecp->sv_len;
182 		}
183 	}
184 
185 	if (flag & NSC_WRITE) {
186 		rc = nsc_write(tmp, tmp->sb_pos, tmp->sb_len, 0);
187 		if (!RDC_SUCCESS(rc)) {
188 			(void) nsc_free_buf(tmp);
189 			return (rc);
190 		}
191 	}
192 
193 	(void) nsc_free_buf(tmp);
194 
195 	fba_pos += fba_len;
196 	fba_req -= fba_len;
197 	if (fba_req > 0)
198 		goto loop;
199 
200 	return (0);
201 }
202 
203 /*
204  * Must be called with krdc->bmapmutex held.
205  */
206 static void
rdc_fill_header(rdc_u_info_t * urdc,rdc_header_t * header)207 rdc_fill_header(rdc_u_info_t *urdc, rdc_header_t *header)
208 {
209 	rdc_k_info_t *krdc = &rdc_k_info[urdc->index];
210 #ifdef DEBUG
211 	ASSERT(MUTEX_HELD(&krdc->bmapmutex));
212 #endif
213 
214 	header->magic = RDC_HDR_MAGIC;
215 	(void) strncpy(header->primary.file, urdc->primary.file, NSC_MAXPATH);
216 	(void) strncpy(header->primary.bitmap, urdc->primary.bitmap,
217 	    NSC_MAXPATH);
218 	(void) strncpy(header->secondary.file, urdc->secondary.file,
219 	    NSC_MAXPATH);
220 	(void) strncpy(header->secondary.bitmap, urdc->secondary.bitmap,
221 	    NSC_MAXPATH);
222 	header->flags = urdc->flags | urdc->sync_flags | urdc->bmap_flags;
223 	header->autosync = urdc->autosync;
224 	header->maxqfbas = urdc->maxqfbas;
225 	header->maxqitems = urdc->maxqitems;
226 	header->asyncthr = urdc->asyncthr;
227 	header->syshostid = urdc->syshostid;
228 	header->refcntsize = rdc_refcntsize(krdc);
229 #ifdef DEBUG_REFCNT
230 	cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
231 	    (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
232 #endif
233 }
234 
235 /*
236  * Must be called with krdc->bmapmutex held.
237  */
238 static int
rdc_read_header(rdc_k_info_t * krdc,rdc_header_t * header)239 rdc_read_header(rdc_k_info_t *krdc, rdc_header_t *header)
240 {
241 	int sts;
242 	rdc_u_info_t *urdc;
243 	union {
244 		rdc_header_t *current;
245 		rdc_headerv4_t *v4;
246 	} u_hdrp;
247 
248 	if (krdc == NULL) {
249 		return (-1);
250 	}
251 
252 	ASSERT(MUTEX_HELD(&krdc->bmapmutex));
253 
254 	urdc = &rdc_u_info[krdc->index];
255 	if (rdc_get_vflags(urdc) & RDC_BMP_FAILED)
256 		return (-1);
257 
258 	if (krdc->bitmapfd == NULL) {
259 		return (-1);
260 	}
261 	if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
262 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
263 		return (-1);
264 	}
265 
266 	if (krdc->bmp_kstats) {
267 		mutex_enter(krdc->bmp_kstats->ks_lock);
268 		kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
269 		mutex_exit(krdc->bmp_kstats->ks_lock);
270 	}
271 
272 	sts = rdc_ns_io(krdc->bitmapfd, NSC_RDBUF, 0, (uchar_t *)header,
273 	    sizeof (rdc_header_t));
274 
275 	if (krdc->bmp_kstats) {
276 		mutex_enter(krdc->bmp_kstats->ks_lock);
277 		kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
278 		mutex_exit(krdc->bmp_kstats->ks_lock);
279 		KSTAT_IO_PTR(krdc->bmp_kstats)->reads++;
280 		KSTAT_IO_PTR(krdc->bmp_kstats)->nread += sizeof (rdc_header_t);
281 	}
282 
283 	if (!RDC_SUCCESS(sts)) {
284 		cmn_err(CE_WARN, "!rdc_read_header: %s read failed %d",
285 		    urdc->primary.file, sts);
286 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "read header failed");
287 	}
288 
289 	_rdc_rlse_devs(krdc, RDC_BMP);
290 
291 	if (!RDC_SUCCESS(sts))
292 		return (-1);
293 	switch (header->magic) {
294 	case RDC_HDR_V4:
295 		/*
296 		 * old header format - upgrade incore copy, disk copy will
297 		 * be changed when state is re-written.
298 		 */
299 #ifdef DEBUG
300 		cmn_err(CE_NOTE, "!sndr: old style (V4) bit map header");
301 #endif
302 		header->magic = RDC_HDR_MAGIC;
303 		u_hdrp.current = header;
304 		/* copy down items moved by new maxq??? sizes */
305 		u_hdrp.current->asyncthr = u_hdrp.v4->asyncthr;
306 		u_hdrp.current->syshostid = u_hdrp.v4->syshostid;
307 		u_hdrp.current->maxqitems = u_hdrp.v4->maxqitems;
308 		u_hdrp.current->maxqfbas = u_hdrp.v4->maxqfbas;
309 		u_hdrp.current->refcntsize = 1;	/* new field */
310 #ifdef DEBUG_REFCNT
311 	cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
312 	    (int)u_hdrp.current->refcntsize, __LINE__, __FILE__);
313 #endif
314 		return (0);
315 	case RDC_HDR_MAGIC:
316 		/* current header type */
317 		return (0);
318 	default:
319 		/* not a header we currently understand */
320 		return (0);
321 	}
322 }
323 
324 /*
325  * Must be called with krdc->bmapmutex held.
326  */
327 static int
rdc_write_header(rdc_k_info_t * krdc,rdc_header_t * header)328 rdc_write_header(rdc_k_info_t *krdc, rdc_header_t *header)
329 {
330 	rdc_u_info_t *urdc;
331 	int sts;
332 
333 	if (krdc == NULL) {
334 		return (-1);
335 	}
336 
337 	ASSERT(MUTEX_HELD(&krdc->bmapmutex));
338 
339 	urdc = &rdc_u_info[krdc->index];
340 	if (rdc_get_vflags(urdc) & RDC_BMP_FAILED)
341 		return (-1);
342 
343 	if (krdc->bitmapfd == NULL) {
344 		return (-1);
345 	}
346 
347 	if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
348 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
349 		return (-1);
350 	}
351 
352 	if (krdc->bmp_kstats) {
353 		mutex_enter(krdc->bmp_kstats->ks_lock);
354 		kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
355 		mutex_exit(krdc->bmp_kstats->ks_lock);
356 	}
357 
358 	sts = rdc_ns_io(krdc->bitmapfd, rdc_wrflag, 0, (uchar_t *)header,
359 	    sizeof (rdc_header_t));
360 
361 	if (krdc->bmp_kstats) {
362 		mutex_enter(krdc->bmp_kstats->ks_lock);
363 		kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
364 		mutex_exit(krdc->bmp_kstats->ks_lock);
365 		KSTAT_IO_PTR(krdc->bmp_kstats)->writes++;
366 		KSTAT_IO_PTR(krdc->bmp_kstats)->nwritten +=
367 		    sizeof (rdc_header_t);
368 	}
369 
370 	if (!RDC_SUCCESS(sts)) {
371 		cmn_err(CE_WARN, "!rdc_write_header: %s write failed %d",
372 		    urdc->primary.file, sts);
373 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "write failed");
374 	}
375 
376 	_rdc_rlse_devs(krdc, RDC_BMP);
377 
378 	if (!RDC_SUCCESS(sts))
379 		return (-1);
380 	else
381 		return (0);
382 }
383 
384 struct bm_ref_ops rdc_ref_byte_ops;
385 struct bm_ref_ops rdc_ref_int_ops;
386 
387 static void
rdc_set_refcnt_ops(rdc_k_info_t * krdc,size_t refcntsize)388 rdc_set_refcnt_ops(rdc_k_info_t *krdc, size_t refcntsize)
389 {
390 	switch (refcntsize) {
391 	default:
392 		/* FALLTHRU */
393 	case sizeof (unsigned char):
394 		krdc->bm_refs = &rdc_ref_byte_ops;
395 		break;
396 	case sizeof (unsigned int):
397 		krdc->bm_refs = &rdc_ref_int_ops;
398 		break;
399 	}
400 #ifdef DEBUG_REFCNT
401 	cmn_err(CE_NOTE, "!sndr: set refcnt ops for refcntsize %d - %d:%s",
402 	    (int)refcntsize, __LINE__, __FILE__);
403 #endif
404 }
405 
406 size_t
rdc_refcntsize(rdc_k_info_t * krdc)407 rdc_refcntsize(rdc_k_info_t *krdc)
408 {
409 	if (krdc->bm_refs == &rdc_ref_int_ops)
410 		return (sizeof (unsigned int));
411 	return (sizeof (unsigned char));
412 }
413 
414 int
rdc_read_state(rdc_k_info_t * krdc,int * statep,int * hostidp)415 rdc_read_state(rdc_k_info_t *krdc, int *statep, int *hostidp)
416 {
417 	rdc_header_t header;
418 	rdc_u_info_t *urdc;
419 	int sts;
420 
421 	if (krdc == NULL) {
422 		return (-1);
423 	}
424 
425 	mutex_enter(&krdc->bmapmutex);
426 
427 	urdc = &rdc_u_info[krdc->index];
428 	if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
429 		mutex_exit(&krdc->bmapmutex);
430 		return (-1);
431 	}
432 
433 	if (krdc->bitmapfd == NULL) {
434 		mutex_exit(&krdc->bmapmutex);
435 		return (-1);
436 	}
437 
438 	sts = rdc_read_header(krdc, &header);
439 	mutex_exit(&krdc->bmapmutex);
440 
441 	if (!RDC_SUCCESS(sts)) {
442 		return (-1);
443 	}
444 
445 	switch (header.magic) {
446 	case RDC_HDR_MAGIC:
447 		*statep = header.flags;
448 		*hostidp = header.syshostid;
449 		rdc_set_refcnt_ops(krdc, header.refcntsize);
450 #ifdef DEBUG_REFCNT
451 	cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
452 	    (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
453 #endif
454 		sts = 0;
455 		break;
456 	default:
457 		sts = -1;
458 		break;
459 	}
460 
461 	return (sts);
462 }
463 
464 int
rdc_clear_state(rdc_k_info_t * krdc)465 rdc_clear_state(rdc_k_info_t *krdc)
466 {
467 	rdc_u_info_t *urdc;
468 	int sts;
469 	rdc_header_t header;
470 
471 	if (krdc == NULL) {
472 		return (-1);
473 	}
474 
475 	mutex_enter(&krdc->bmapmutex);
476 
477 	urdc = &rdc_u_info[krdc->index];
478 	if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
479 		mutex_exit(&krdc->bmapmutex);
480 		return (-1);
481 	}
482 
483 	if (krdc->bitmapfd == NULL) {
484 		mutex_exit(&krdc->bmapmutex);
485 		return (-1);
486 	}
487 
488 	if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
489 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
490 		mutex_exit(&krdc->bmapmutex);
491 		return (-1);
492 	}
493 
494 	bzero(&header, sizeof (header));
495 
496 	if (krdc->bmp_kstats) {
497 		mutex_enter(krdc->bmp_kstats->ks_lock);
498 		kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
499 		mutex_exit(krdc->bmp_kstats->ks_lock);
500 	}
501 
502 	sts = rdc_ns_io(krdc->bitmapfd, rdc_wrflag, 0,
503 	    (uchar_t *)&header, sizeof (header));
504 
505 	if (krdc->bmp_kstats) {
506 		mutex_enter(krdc->bmp_kstats->ks_lock);
507 		kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
508 		mutex_exit(krdc->bmp_kstats->ks_lock);
509 		KSTAT_IO_PTR(krdc->bmp_kstats)->writes++;
510 		KSTAT_IO_PTR(krdc->bmp_kstats)->nwritten +=
511 		    sizeof (rdc_header_t);
512 	}
513 
514 	if (!RDC_SUCCESS(sts)) {
515 		cmn_err(CE_WARN, "!rdc_clear_state: %s write failed",
516 		    urdc->primary.file);
517 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "write failed");
518 	}
519 
520 	_rdc_rlse_devs(krdc, RDC_BMP);
521 	mutex_exit(&krdc->bmapmutex);
522 
523 	if (!RDC_SUCCESS(sts))
524 		return (-1);
525 	else
526 		return (0);
527 }
528 
529 void
rdc_write_state(rdc_u_info_t * urdc)530 rdc_write_state(rdc_u_info_t *urdc)
531 {
532 	rdc_k_info_t *krdc;
533 	int sts;
534 	rdc_header_t header;
535 
536 	if (urdc == NULL) {
537 		return;
538 	}
539 
540 	krdc = &rdc_k_info[urdc->index];
541 
542 	mutex_enter(&krdc->bmapmutex);
543 
544 	if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
545 		mutex_exit(&krdc->bmapmutex);
546 		return;
547 	}
548 
549 	if (krdc->bitmapfd == NULL) {
550 		mutex_exit(&krdc->bmapmutex);
551 		return;
552 	}
553 
554 	if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
555 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
556 		mutex_exit(&krdc->bmapmutex);
557 		return;
558 	}
559 
560 	if (krdc->bmp_kstats) {
561 		mutex_enter(krdc->bmp_kstats->ks_lock);
562 		kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
563 		mutex_exit(krdc->bmp_kstats->ks_lock);
564 	}
565 
566 	sts = rdc_ns_io(krdc->bitmapfd, NSC_RDBUF, 0, (uchar_t *)&header,
567 	    sizeof (header));
568 
569 	if (krdc->bmp_kstats) {
570 		mutex_enter(krdc->bmp_kstats->ks_lock);
571 		kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
572 		mutex_exit(krdc->bmp_kstats->ks_lock);
573 		KSTAT_IO_PTR(krdc->bmp_kstats)->reads++;
574 		KSTAT_IO_PTR(krdc->bmp_kstats)->nread += sizeof (header);
575 	}
576 
577 	if (!RDC_SUCCESS(sts)) {
578 		cmn_err(CE_WARN, "!rdc_write_state: %s read failed",
579 		    urdc->primary.file);
580 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "read failed");
581 		goto done;
582 	}
583 
584 	rdc_fill_header(urdc, &header);
585 
586 	if (krdc->bmp_kstats) {
587 		mutex_enter(krdc->bmp_kstats->ks_lock);
588 		kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
589 		mutex_exit(krdc->bmp_kstats->ks_lock);
590 	}
591 
592 	sts = rdc_ns_io(krdc->bitmapfd, rdc_wrflag, 0,
593 	    (uchar_t *)&header, sizeof (header));
594 
595 	if (krdc->bmp_kstats) {
596 		mutex_enter(krdc->bmp_kstats->ks_lock);
597 		kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
598 		mutex_exit(krdc->bmp_kstats->ks_lock);
599 		KSTAT_IO_PTR(krdc->bmp_kstats)->writes++;
600 		KSTAT_IO_PTR(krdc->bmp_kstats)->nwritten += sizeof (header);
601 	}
602 
603 	if (!RDC_SUCCESS(sts)) {
604 		cmn_err(CE_WARN, "!rdc_write_state: %s write failed",
605 		    urdc->primary.file);
606 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "write failed");
607 	}
608 
609 done:
610 	_rdc_rlse_devs(krdc, RDC_BMP);
611 	mutex_exit(&krdc->bmapmutex);
612 }
613 
614 
615 struct bitmapdata {
616 	uchar_t	*data;
617 	size_t	len;
618 };
619 
620 static int
rdc_read_bitmap(rdc_k_info_t * krdc,struct bitmapdata * data)621 rdc_read_bitmap(rdc_k_info_t *krdc, struct bitmapdata *data)
622 {
623 	rdc_u_info_t *urdc;
624 	int sts;
625 
626 	if (krdc == NULL) {
627 		return (-1);
628 	}
629 
630 	if (data != NULL) {
631 		data->data = kmem_alloc(krdc->bitmap_size, KM_SLEEP);
632 		data->len = krdc->bitmap_size;
633 
634 		if (data->data == NULL) {
635 			return (-1);
636 		}
637 	}
638 
639 	mutex_enter(&krdc->bmapmutex);
640 
641 	urdc = &rdc_u_info[krdc->index];
642 	if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
643 		mutex_exit(&krdc->bmapmutex);
644 		return (-1);
645 	}
646 
647 	if (krdc->bitmapfd == NULL) {
648 		mutex_exit(&krdc->bmapmutex);
649 		return (-1);
650 	}
651 
652 	if (data == NULL && krdc->dcio_bitmap == NULL) {
653 		mutex_exit(&krdc->bmapmutex);
654 		return (-1);
655 	}
656 
657 	if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
658 		cmn_err(CE_WARN, "!rdc_read_bitmap: %s reserve failed",
659 		    urdc->primary.file);
660 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
661 		mutex_exit(&krdc->bmapmutex);
662 		return (-1);
663 	}
664 
665 	if (krdc->bmp_kstats) {
666 		mutex_enter(krdc->bmp_kstats->ks_lock);
667 		kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
668 		mutex_exit(krdc->bmp_kstats->ks_lock);
669 	}
670 
671 	sts = rdc_ns_io(krdc->bitmapfd, NSC_RDBUF, RDC_BITMAP_FBA,
672 	    data ? data->data : krdc->dcio_bitmap, krdc->bitmap_size);
673 
674 	if (krdc->bmp_kstats) {
675 		mutex_enter(krdc->bmp_kstats->ks_lock);
676 		kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
677 		mutex_exit(krdc->bmp_kstats->ks_lock);
678 		KSTAT_IO_PTR(krdc->bmp_kstats)->reads++;
679 		KSTAT_IO_PTR(krdc->bmp_kstats)->nread += krdc->bitmap_size;
680 	}
681 
682 	_rdc_rlse_devs(krdc, RDC_BMP);
683 
684 	if (!RDC_SUCCESS(sts)) {
685 		cmn_err(CE_WARN, "!rdc_read_bitmap: %s read failed",
686 		    urdc->primary.file);
687 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "read failed");
688 		mutex_exit(&krdc->bmapmutex);
689 		return (-1);
690 	}
691 
692 	mutex_exit(&krdc->bmapmutex);
693 	return (0);
694 }
695 
696 int
rdc_write_bitmap(rdc_k_info_t * krdc)697 rdc_write_bitmap(rdc_k_info_t *krdc)
698 {
699 	rdc_u_info_t *urdc;
700 	int sts;
701 
702 	if (krdc == NULL) {
703 		return (-1);
704 	}
705 
706 	mutex_enter(&krdc->bmapmutex);
707 
708 	urdc = &rdc_u_info[krdc->index];
709 	if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
710 		mutex_exit(&krdc->bmapmutex);
711 		return (-1);
712 	}
713 
714 	if (krdc->bitmapfd == NULL) {
715 		mutex_exit(&krdc->bmapmutex);
716 		return (-1);
717 	}
718 
719 	if (krdc->dcio_bitmap == NULL) {
720 		mutex_exit(&krdc->bmapmutex);
721 		return (-1);
722 	}
723 
724 	if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
725 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
726 		mutex_exit(&krdc->bmapmutex);
727 		return (-1);
728 	}
729 
730 	if (krdc->bmp_kstats) {
731 		mutex_enter(krdc->bmp_kstats->ks_lock);
732 		kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
733 		mutex_exit(krdc->bmp_kstats->ks_lock);
734 	}
735 
736 	sts = rdc_ns_io(krdc->bitmapfd, rdc_wrflag, RDC_BITMAP_FBA,
737 	    krdc->dcio_bitmap, krdc->bitmap_size);
738 
739 	if (krdc->bmp_kstats) {
740 		mutex_enter(krdc->bmp_kstats->ks_lock);
741 		kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
742 		mutex_exit(krdc->bmp_kstats->ks_lock);
743 		KSTAT_IO_PTR(krdc->bmp_kstats)->writes++;
744 		KSTAT_IO_PTR(krdc->bmp_kstats)->nwritten += krdc->bitmap_size;
745 	}
746 
747 	_rdc_rlse_devs(krdc, RDC_BMP);
748 
749 	if (!RDC_SUCCESS(sts)) {
750 		cmn_err(CE_WARN, "!rdc_write_bitmap: %s write failed",
751 		    urdc->primary.file);
752 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "write failed");
753 		mutex_exit(&krdc->bmapmutex);
754 		return (-1);
755 	}
756 
757 	mutex_exit(&krdc->bmapmutex);
758 	return (0);
759 }
760 
761 int
rdc_write_bitmap_fba(rdc_k_info_t * krdc,nsc_off_t fba)762 rdc_write_bitmap_fba(rdc_k_info_t *krdc, nsc_off_t fba)
763 {
764 	rdc_u_info_t *urdc;
765 	int sts;
766 
767 	if (krdc == NULL) {
768 		return (-1);
769 	}
770 
771 	mutex_enter(&krdc->bmapmutex);
772 
773 	urdc = &rdc_u_info[krdc->index];
774 	if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
775 		mutex_exit(&krdc->bmapmutex);
776 		return (-1);
777 	}
778 
779 	if (krdc->bitmapfd == NULL) {
780 		mutex_exit(&krdc->bmapmutex);
781 		return (-1);
782 	}
783 
784 	if (krdc->dcio_bitmap == NULL) {
785 		mutex_exit(&krdc->bmapmutex);
786 		return (-1);
787 	}
788 
789 	if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
790 		cmn_err(CE_WARN, "!rdc_write_bitmap_fba: %s reserve failed",
791 		    urdc->primary.file);
792 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
793 		mutex_exit(&krdc->bmapmutex);
794 		return (-1);
795 	}
796 
797 	if (krdc->bmp_kstats) {
798 		mutex_enter(krdc->bmp_kstats->ks_lock);
799 		kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
800 		mutex_exit(krdc->bmp_kstats->ks_lock);
801 	}
802 	sts = rdc_ns_io(krdc->bitmapfd, rdc_wrflag, RDC_BITMAP_FBA + fba,
803 	    krdc->dcio_bitmap + fba * 512, 512);
804 
805 	if (krdc->bmp_kstats) {
806 		mutex_enter(krdc->bmp_kstats->ks_lock);
807 		kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
808 		mutex_exit(krdc->bmp_kstats->ks_lock);
809 		KSTAT_IO_PTR(krdc->bmp_kstats)->writes++;
810 		KSTAT_IO_PTR(krdc->bmp_kstats)->nwritten += 512;
811 	}
812 
813 	_rdc_rlse_devs(krdc, RDC_BMP);
814 
815 	if (!RDC_SUCCESS(sts)) {
816 		cmn_err(CE_WARN, "!rdc_write_bitmap_fba: %s write failed",
817 		    urdc->primary.file);
818 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "write failed");
819 		mutex_exit(&krdc->bmapmutex);
820 		return (-1);
821 	}
822 
823 	mutex_exit(&krdc->bmapmutex);
824 	return (0);
825 }
826 
827 
828 static int
rdc_write_bitmap_pattern(rdc_k_info_t * krdc,const char pattern)829 rdc_write_bitmap_pattern(rdc_k_info_t *krdc, const char pattern)
830 {
831 	rdc_u_info_t *urdc;
832 	char *buffer;
833 	nsc_buf_t *h;
834 	nsc_vec_t *v;
835 	int rc;
836 	size_t i;
837 	nsc_size_t len;
838 	int  off;
839 	size_t buffer_size;
840 	size_t iolen;
841 	nsc_size_t	fba_req;
842 	nsc_off_t	fba_len, fba_pos;
843 	nsc_size_t	maxfbas = 0;
844 	nsc_size_t	tocopy;
845 
846 	if (krdc == NULL) {
847 		return (-1);
848 	}
849 
850 	mutex_enter(&krdc->bmapmutex);
851 
852 	urdc = &rdc_u_info[krdc->index];
853 	if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
854 		mutex_exit(&krdc->bmapmutex);
855 		return (-1);
856 	}
857 
858 	if (krdc->bitmapfd == NULL) {
859 		mutex_exit(&krdc->bmapmutex);
860 		return (-1);
861 	}
862 
863 	if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
864 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
865 		mutex_exit(&krdc->bmapmutex);
866 		return (-1);
867 	}
868 
869 	buffer_size = FBA_SIZE(1);
870 	ASSERT(buffer_size < INT32_MAX);
871 	buffer = kmem_alloc(buffer_size, KM_SLEEP);
872 
873 	for (i = 0; i < buffer_size; i++) {
874 		buffer[i] = pattern;
875 	}
876 
877 	rc = nsc_maxfbas(krdc->bitmapfd, 0, &maxfbas);
878 	if (!RDC_SUCCESS(rc)) {
879 #ifdef DEBUG
880 		cmn_err(CE_WARN,
881 		    "!rdc_write_bitmap_pattern: maxfbas failed (%d)", rc);
882 #endif
883 		maxfbas = 256;
884 	}
885 
886 	fba_req = FBA_LEN(krdc->bitmap_size);	/* total FBAs left to copy */
887 	fba_pos = RDC_BITMAP_FBA;		/* current FBA position */
888 	tocopy = krdc->bitmap_size;		/* total bytes left to copy */
889 loop:
890 	h = NULL;
891 	fba_len = min(fba_req, maxfbas);	/* FBAs to alloc this time */
892 
893 	rc = nsc_alloc_buf(krdc->bitmapfd, fba_pos, fba_len, rdc_wrflag, &h);
894 	if (!RDC_SUCCESS(rc)) {
895 		cmn_err(CE_WARN, "!rdc_write_bitmap_pattern: %s "
896 		    "write failed %d", urdc->primary.file, rc);
897 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "nsc_alloc_buf failed");
898 		if (h) {
899 			(void) nsc_free_handle(h);
900 		}
901 
902 		_rdc_rlse_devs(krdc, RDC_BMP);
903 		mutex_exit(&krdc->bmapmutex);
904 		rc = -1;
905 		goto finish;
906 	}
907 
908 				/* bytes to copy this time */
909 	len = min(tocopy, FBA_SIZE(fba_len));
910 	v = h->sb_vec;
911 	off = 0;
912 
913 	while (len) {
914 		if (off >= v->sv_len) {
915 			off = 0;
916 			v++;
917 		}
918 
919 		if (v->sv_addr == 0 || v->sv_len == 0) {
920 #ifdef DEBUG
921 			cmn_err(CE_WARN,
922 			    "!rdc_write_bitmap_pattern: ran off end of handle");
923 #endif
924 			break;
925 		}
926 
927 		iolen = (size_t)min(len, buffer_size);
928 
929 		bcopy(buffer, (char *)(v->sv_addr + off), iolen);
930 		off += iolen;
931 		len -= iolen;
932 	}
933 
934 	rc = nsc_write(h, h->sb_pos, h->sb_len, 0);
935 	if (!RDC_SUCCESS(rc)) {
936 		cmn_err(CE_WARN, "!rdc_write_bitmap_pattern: "
937 		    "%s write failed %d", urdc->primary.file, rc);
938 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "write failed");
939 		(void) nsc_free_buf(h);
940 		_rdc_rlse_devs(krdc, RDC_BMP);
941 		mutex_exit(&krdc->bmapmutex);
942 		rc = -1;
943 		goto finish;
944 	}
945 
946 	(void) nsc_free_buf(h);
947 
948 	fba_pos += fba_len;
949 	fba_req -= fba_len;
950 	tocopy -= FBA_SIZE(fba_len);    /* adjust byte length remaining */
951 	if (fba_req > 0)
952 		goto loop;
953 
954 	_rdc_rlse_devs(krdc, RDC_BMP);
955 	mutex_exit(&krdc->bmapmutex);
956 	rc = 0;
957 finish:
958 	kmem_free(buffer, buffer_size);
959 	return (rc);
960 }
961 
962 
963 /*
964  * rdc_write_bitmap_fill()
965  *
966  * Write a bitmap full of 1's out to disk without touching the
967  * in-memory bitmap.
968  */
969 int
rdc_write_bitmap_fill(rdc_k_info_t * krdc)970 rdc_write_bitmap_fill(rdc_k_info_t *krdc)
971 {
972 	return (rdc_write_bitmap_pattern(krdc, 0xff));
973 }
974 
975 
976 void
rdc_merge_bitmaps(rdc_k_info_t * src,rdc_k_info_t * dst)977 rdc_merge_bitmaps(rdc_k_info_t *src, rdc_k_info_t *dst)
978 {
979 	if (src->dcio_bitmap == NULL || dst->dcio_bitmap == NULL)
980 		return;
981 
982 	rdc_lor(src->dcio_bitmap, dst->dcio_bitmap,
983 	    min(src->bitmap_size, dst->bitmap_size));
984 	if (dst->bitmap_write > 0)
985 		(void) rdc_write_bitmap(dst);
986 }
987 
988 
989 /*
990  * bitmap size in bytes, vol_size fba's
991  */
992 
993 size_t
rdc_ref_size_possible(nsc_size_t bitmap_size,nsc_size_t vol_size)994 rdc_ref_size_possible(nsc_size_t bitmap_size, nsc_size_t vol_size)
995 {
996 	nsc_size_t ref_size;
997 	nsc_size_t bitmap_end_fbas;
998 
999 	bitmap_end_fbas = RDC_BITMAP_FBA + FBA_LEN(bitmap_size);
1000 	ref_size = FBA_LEN(bitmap_size * BITS_IN_BYTE * sizeof (unsigned char));
1001 	if (bitmap_end_fbas + ref_size > vol_size)
1002 		return ((size_t)0);
1003 
1004 	ref_size = FBA_LEN(bitmap_size * BITS_IN_BYTE * sizeof (unsigned int));
1005 	if (bitmap_end_fbas + ref_size > vol_size)
1006 		return (sizeof (unsigned char));
1007 	return (sizeof (unsigned int));
1008 }
1009 
1010 int
rdc_move_bitmap(rdc_k_info_t * krdc,char * newbitmap)1011 rdc_move_bitmap(rdc_k_info_t *krdc, char *newbitmap)
1012 {
1013 	rdc_u_info_t *urdc;
1014 	nsc_fd_t *oldfd;
1015 	nsc_fd_t *newfd = NULL;
1016 	rdc_header_t header;
1017 	int sts;
1018 	nsc_size_t vol_size;
1019 	nsc_size_t req_size;
1020 	size_t ref_size;
1021 
1022 	if (krdc == NULL) {
1023 		return (-1);
1024 	}
1025 
1026 	if (krdc->bitmapfd == NULL) {
1027 		return (-1);
1028 	}
1029 
1030 	req_size = RDC_BITMAP_FBA + FBA_LEN(krdc->bitmap_size);
1031 	if (RDC_IS_DISKQ(krdc->group)) {
1032 		/* new volume must support at least the old refcntsize */
1033 		req_size += FBA_LEN(krdc->bitmap_size * BITS_IN_BYTE *
1034 		    rdc_refcntsize(krdc));
1035 #ifdef DEBUG_REFCNT
1036 	cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1037 	    (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1038 #endif
1039 	}
1040 
1041 	mutex_enter(&krdc->bmapmutex);
1042 
1043 	if (rdc_read_header(krdc, &header) < 0) {
1044 #ifdef DEBUG
1045 		cmn_err(CE_WARN, "!rdc_move_bitmap: Read old header failed");
1046 #endif
1047 		mutex_exit(&krdc->bmapmutex);
1048 		return (-1);
1049 	}
1050 
1051 	oldfd = krdc->bitmapfd;
1052 
1053 	newfd = nsc_open(newbitmap, NSC_RDCHR_ID|NSC_FILE|NSC_RDWR, 0, 0, 0);
1054 	if (newfd == NULL) {
1055 		newfd = nsc_open(newbitmap,
1056 		    NSC_RDCHR_ID|NSC_CACHE|NSC_DEVICE|NSC_RDWR, 0, 0, 0);
1057 		if (newfd == NULL) {
1058 			/* Can't open new bitmap */
1059 			cmn_err(CE_WARN,
1060 			    "!rdc_move_bitmap: Cannot open new bitmap %s",
1061 			    newbitmap);
1062 			goto fail;
1063 		}
1064 	}
1065 
1066 	sts = nsc_reserve(newfd, 0);
1067 	if (!RDC_SUCCESS(sts)) {
1068 		cmn_err(CE_WARN, "!rdc_move_bitmap: Reserve failed for %s",
1069 		    newbitmap);
1070 		goto fail;
1071 	}
1072 	sts = nsc_partsize(newfd, &vol_size);
1073 	nsc_release(newfd);
1074 
1075 	if (!RDC_SUCCESS(sts)) {
1076 		cmn_err(CE_WARN,
1077 		    "!rdc_move_bitmap: nsc_partsize failed for %s", newbitmap);
1078 		goto fail;
1079 	}
1080 
1081 	ref_size = rdc_ref_size_possible(krdc->bitmap_size, vol_size);
1082 
1083 	if (vol_size < req_size) {
1084 		cmn_err(CE_WARN,
1085 		    "!rdc_move_bitmap: bitmap %s too small: %" NSC_SZFMT
1086 		    " vs %" NSC_SZFMT " blocks", newbitmap, vol_size, req_size);
1087 		goto fail;
1088 	}
1089 
1090 	mutex_enter(&krdc->devices->id_rlock);
1091 	krdc->bitmapfd = newfd;			/* swap under lock */
1092 	if (krdc->bmaprsrv > 0) {
1093 		sts = nsc_reserve(krdc->bitmapfd, 0);
1094 		if (!RDC_SUCCESS(sts)) {
1095 			krdc->bitmapfd = oldfd;	/* replace under lock */
1096 			mutex_exit(&krdc->devices->id_rlock);
1097 			cmn_err(CE_WARN,
1098 			    "!rdc_move_bitmap: Reserve failed for %s",
1099 			    newbitmap);
1100 			goto fail;
1101 		}
1102 	}
1103 	rdc_set_refcnt_ops(krdc, ref_size);
1104 #ifdef DEBUG_REFCNT
1105 	cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1106 	    (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1107 #endif
1108 	mutex_exit(&krdc->devices->id_rlock);
1109 
1110 	/* Forget newfd now it is krdc->bitmapfd */
1111 	newfd = NULL;
1112 
1113 	/* Put new bitmap name into header and user-visible data structure */
1114 	urdc = &rdc_u_info[krdc->index];
1115 	if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
1116 		(void) strncpy(header.primary.bitmap, newbitmap, NSC_MAXPATH);
1117 		(void) strncpy(urdc->primary.bitmap, newbitmap, NSC_MAXPATH);
1118 	} else {
1119 		(void) strncpy(header.secondary.bitmap, newbitmap, NSC_MAXPATH);
1120 		(void) strncpy(urdc->secondary.bitmap, newbitmap, NSC_MAXPATH);
1121 	}
1122 
1123 	if (rdc_write_header(krdc, &header) < 0) {
1124 		cmn_err(CE_WARN,
1125 		    "!rdc_move_bitmap: Write header %s failed", newbitmap);
1126 		goto fail;
1127 	}
1128 
1129 	mutex_exit(&krdc->bmapmutex);
1130 
1131 	if (rdc_write_bitmap(krdc) < 0) {
1132 		mutex_enter(&krdc->bmapmutex);
1133 		cmn_err(CE_WARN,
1134 		    "!rdc_move_bitmap: Write bitmap %s failed", newbitmap);
1135 		goto fail;
1136 	}
1137 
1138 	/* Unintercept the old bitmap */
1139 	if (krdc->b_tok) {
1140 		int rc;
1141 
1142 		rdc_group_exit(krdc);
1143 		rc = nsc_unregister_path(krdc->b_tok, 0);
1144 		if (rc)
1145 			cmn_err(CE_WARN, "!rdc_move_bitmap: "
1146 			    "unregister bitmap failed %d", rc);
1147 		else
1148 			krdc->b_tok = nsc_register_path(newbitmap,
1149 			    NSC_CACHE | NSC_DEVICE, _rdc_io_hc);
1150 		rdc_group_enter(krdc);
1151 	}
1152 
1153 	/* clear the old bitmap header */
1154 	bzero(&header, sizeof (header));
1155 
1156 	sts = nsc_held(oldfd) ? 0 : nsc_reserve(oldfd, 0);
1157 	if (sts == 0) {
1158 
1159 		if (krdc->bmp_kstats) {
1160 			mutex_enter(krdc->bmp_kstats->ks_lock);
1161 			kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
1162 			mutex_exit(krdc->bmp_kstats->ks_lock);
1163 		}
1164 
1165 		sts = rdc_ns_io(oldfd, rdc_wrflag, 0,
1166 		    (uchar_t *)&header, sizeof (header));
1167 
1168 		if (krdc->bmp_kstats) {
1169 			mutex_enter(krdc->bmp_kstats->ks_lock);
1170 			kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
1171 			mutex_exit(krdc->bmp_kstats->ks_lock);
1172 			KSTAT_IO_PTR(krdc->bmp_kstats)->writes++;
1173 			KSTAT_IO_PTR(krdc->bmp_kstats)->nwritten +=
1174 			    sizeof (header);
1175 		}
1176 
1177 	}
1178 #ifdef DEBUG
1179 	if (sts != 0) {
1180 		cmn_err(CE_WARN,
1181 		    "!rdc_move_bitmap: unable to clear bitmap header on %s",
1182 		    nsc_pathname(oldfd));
1183 	}
1184 #endif
1185 
1186 	/* nsc_close will undo any reservation */
1187 	if (nsc_close(oldfd) != 0) {
1188 #ifdef DEBUG
1189 		cmn_err(CE_WARN, "!rdc_move_bitmap: close old bitmap failed");
1190 #else
1191 		;
1192 		/*EMPTY*/
1193 #endif
1194 	}
1195 
1196 	return (0);
1197 
1198 fail:
1199 	/* Close newfd if it was unused */
1200 	if (newfd && newfd != krdc->bitmapfd) {
1201 		(void) nsc_close(newfd);
1202 		newfd = NULL;
1203 	}
1204 
1205 	mutex_exit(&krdc->bmapmutex);
1206 	return (-1);
1207 }
1208 
1209 
1210 void
rdc_close_bitmap(rdc_k_info_t * krdc)1211 rdc_close_bitmap(rdc_k_info_t *krdc)
1212 {
1213 
1214 	if (krdc == NULL) {
1215 		return;
1216 	}
1217 
1218 	mutex_enter(&krdc->bmapmutex);
1219 
1220 	if (krdc->bitmapfd) {
1221 		if (nsc_close(krdc->bitmapfd) != 0) {
1222 #ifdef DEBUG
1223 			cmn_err(CE_WARN, "!nsc_close on bitmap failed");
1224 #else
1225 			;
1226 			/*EMPTY*/
1227 #endif
1228 		}
1229 		krdc->bitmapfd = 0;
1230 	}
1231 
1232 	mutex_exit(&krdc->bmapmutex);
1233 }
1234 
1235 void
rdc_free_bitmap(rdc_k_info_t * krdc,int cmd)1236 rdc_free_bitmap(rdc_k_info_t *krdc, int cmd)
1237 {
1238 	rdc_header_t header;
1239 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
1240 
1241 	if (krdc == NULL) {
1242 		return;
1243 	}
1244 
1245 	mutex_enter(&krdc->bmapmutex);
1246 
1247 	if (cmd != RDC_CMD_SUSPEND) {
1248 
1249 		bzero((char *)&header, sizeof (rdc_header_t));
1250 
1251 		if (krdc->bitmapfd)
1252 			(void) rdc_write_header(krdc, &header);
1253 	} else {
1254 		mutex_exit(&krdc->bmapmutex);
1255 		/* gotta drop mutex, in case q needs to fail */
1256 		if (RDC_IS_DISKQ(krdc->group) && rdc_suspend_diskq(krdc) < 0) {
1257 			cmn_err(CE_WARN,
1258 			    "!rdc_free_bitmap: diskq suspend failed");
1259 		}
1260 
1261 		mutex_enter(&krdc->bmapmutex);
1262 		if (rdc_read_header(krdc, &header) < 0) {
1263 			cmn_err(CE_WARN,
1264 			    "!rdc_free_bitmap: Read header failed");
1265 		} else {
1266 			rdc_fill_header(urdc, &header);
1267 
1268 			(void) rdc_write_header(krdc, &header);
1269 		}
1270 	}
1271 
1272 	mutex_exit(&krdc->bmapmutex);
1273 
1274 	if (krdc->dcio_bitmap != NULL) {
1275 		if (cmd == RDC_CMD_SUSPEND) {
1276 			if (krdc->bitmapfd)
1277 				(void) rdc_write_bitmap(krdc);
1278 		}
1279 
1280 		kmem_free(krdc->dcio_bitmap, krdc->bitmap_size);
1281 		krdc->dcio_bitmap = NULL;
1282 	}
1283 	if (krdc->bitmap_ref != NULL) {
1284 		kmem_free(krdc->bitmap_ref, (krdc->bitmap_size * BITS_IN_BYTE *
1285 		    BMAP_REF_PREF_SIZE));
1286 		krdc->bitmap_ref = NULL;
1287 	}
1288 
1289 	krdc->bitmap_size = 0;
1290 }
1291 
1292 static int
rdc_alloc_bitmap(rdc_k_info_t * krdc)1293 rdc_alloc_bitmap(rdc_k_info_t *krdc)
1294 {
1295 	rdc_u_info_t *urdc;
1296 	char *bitmapname;
1297 	nsc_size_t bitmap_ref_size;
1298 
1299 	if (krdc == NULL) {
1300 		return (-1);
1301 	}
1302 
1303 	urdc = &rdc_u_info[krdc->index];
1304 	if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1305 		bitmapname = &urdc->primary.bitmap[0];
1306 	else
1307 		bitmapname = &urdc->secondary.bitmap[0];
1308 
1309 	if (krdc->dcio_bitmap) {
1310 #ifdef DEBUG
1311 		cmn_err(CE_WARN,
1312 		    "!rdc_alloc_bitmap: bitmap %s already allocated",
1313 		    bitmapname);
1314 #endif
1315 		return (0);
1316 	}
1317 
1318 	if (urdc->volume_size == 0)
1319 		return (-1);
1320 
1321 	krdc->bitmap_size = BMAP_LOG_BYTES(urdc->volume_size);
1322 	/* Round up */
1323 	krdc->bitmap_size = (krdc->bitmap_size + 511) / 512 * 512;
1324 
1325 	krdc->dcio_bitmap = (uchar_t *)kmem_zalloc(krdc->bitmap_size,
1326 	    KM_SLEEP);
1327 	if (krdc->dcio_bitmap == NULL) {
1328 		cmn_err(CE_WARN, "!rdc_alloc_bitmap: alloc %" NSC_SZFMT
1329 		    " failed for %s", krdc->bitmap_size, bitmapname);
1330 		return (-1);
1331 	}
1332 
1333 	/*
1334 	 * use largest ref count type size as we haven't opened the bitmap
1335 	 * volume yet to find out what has acutally be used.
1336 	 */
1337 	bitmap_ref_size = krdc->bitmap_size * BITS_IN_BYTE * BMAP_REF_PREF_SIZE;
1338 	if ((rdc_get_vflags(urdc) & RDC_PRIMARY) &&
1339 	    ((krdc->type_flag & RDC_ASYNCMODE) != 0)) {
1340 		krdc->bitmap_ref = (uchar_t *)kmem_zalloc(bitmap_ref_size,
1341 		    KM_SLEEP);
1342 		if (krdc->bitmap_ref == NULL) {
1343 			cmn_err(CE_WARN,
1344 			    "!rdc_alloc_bitmap: ref alloc %" NSC_SZFMT
1345 			    " failed for %s",
1346 			    bitmap_ref_size, bitmapname);
1347 			return (-1);
1348 		}
1349 	}
1350 
1351 	return (0);
1352 }
1353 
1354 
1355 static int
rdc_open_bitmap(rdc_k_info_t * krdc)1356 rdc_open_bitmap(rdc_k_info_t *krdc)
1357 {
1358 	rdc_u_info_t *urdc;
1359 	int sts;
1360 	uint_t hints = 0;
1361 	nsc_size_t vol_size;
1362 	char *bitmapname;
1363 	nsc_size_t req_size;
1364 	nsc_size_t bit_size;
1365 
1366 	urdc = &rdc_u_info[krdc->index];
1367 	if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1368 		bitmapname = &urdc->primary.bitmap[0];
1369 	else
1370 		bitmapname = &urdc->secondary.bitmap[0];
1371 
1372 	urdc->bits_set = 0;
1373 
1374 	bit_size = req_size = RDC_BITMAP_FBA + FBA_LEN(krdc->bitmap_size);
1375 	if (RDC_IS_DISKQ(krdc->group)) {
1376 		req_size += FBA_LEN(krdc->bitmap_size * BITS_IN_BYTE *
1377 		    sizeof (unsigned char));
1378 	}
1379 
1380 	mutex_enter(&krdc->bmapmutex);
1381 
1382 	rdc_set_refcnt_ops(krdc, sizeof (unsigned char));
1383 #ifdef DEBUG_REFCNT
1384 	cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1385 	    (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1386 #endif
1387 	if (krdc->bitmapfd == NULL)
1388 		krdc->bitmapfd = nsc_open(bitmapname,
1389 		    NSC_RDCHR_ID|NSC_FILE|NSC_RDWR, 0, 0, 0);
1390 	if (krdc->bitmapfd == NULL) {
1391 		krdc->bitmapfd = nsc_open(bitmapname,
1392 		    NSC_RDCHR_ID|NSC_CACHE|NSC_DEVICE|NSC_RDWR, 0, 0, 0);
1393 		if (krdc->bitmapfd == NULL) {
1394 			cmn_err(CE_WARN, "!rdc_open_bitmap: Unable to open %s",
1395 			    bitmapname);
1396 			goto fail;
1397 		}
1398 	}
1399 
1400 	sts = _rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL);
1401 	if (!RDC_SUCCESS(sts)) {
1402 		cmn_err(CE_WARN, "!rdc_open_bitmap: Reserve failed for %s",
1403 		    bitmapname);
1404 		goto fail;
1405 	}
1406 	sts = nsc_partsize(krdc->bitmapfd, &vol_size);
1407 	_rdc_rlse_devs(krdc, RDC_BMP);
1408 
1409 	if (!RDC_SUCCESS(sts)) {
1410 		cmn_err(CE_WARN,
1411 		    "!rdc_open_bitmap: nsc_partsize failed for %s", bitmapname);
1412 		goto fail;
1413 	}
1414 
1415 	if (vol_size < req_size) {
1416 		/* minimum size supports unsigned char reference counts */
1417 		cmn_err(CE_WARN,
1418 		    "!rdc_open_bitmap: bitmap %s too small: %" NSC_SZFMT " vs %"
1419 		    NSC_SZFMT "blocks",
1420 		    bitmapname, vol_size, req_size);
1421 		goto fail;
1422 	}
1423 
1424 	if (rdc_bitmap_mode == RDC_BMP_NEVER) {
1425 		krdc->bitmap_write = 0;		/* forced off */
1426 	} else if (rdc_bitmap_mode == RDC_BMP_ALWAYS ||
1427 	    (nsc_node_hints(&hints) == 0 && (hints & NSC_FORCED_WRTHRU) == 0)) {
1428 		krdc->bitmap_write = 1;		/* forced or autodetect on */
1429 	} else {
1430 		/* autodetect off */
1431 		krdc->bitmap_write = 0;
1432 	}
1433 
1434 	mutex_exit(&krdc->bmapmutex);
1435 	if (RDC_IS_DISKQ(krdc->group) && (rdc_refcntsize(krdc) <
1436 	    BMAP_REF_PREF_SIZE)) {
1437 		/* test for larger ref counts */
1438 #ifdef DEBUG_REFCNT
1439 	cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1440 	    (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1441 #endif
1442 		req_size = bit_size;
1443 		req_size += FBA_LEN(krdc->bitmap_size * BITS_IN_BYTE *
1444 		    sizeof (unsigned int));
1445 		if (vol_size >= req_size)
1446 			rdc_set_refcnt_ops(krdc, sizeof (unsigned int));
1447 	}
1448 #ifdef DEBUG_REFCNT
1449 	cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1450 	    (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1451 #endif
1452 	return (0);
1453 
1454 fail:
1455 	mutex_exit(&krdc->bmapmutex);
1456 	return (-1);
1457 }
1458 
1459 int
rdc_enable_bitmap(rdc_k_info_t * krdc,int set)1460 rdc_enable_bitmap(rdc_k_info_t *krdc, int set)
1461 {
1462 	rdc_header_t header;
1463 	rdc_u_info_t *urdc;
1464 	char *bitmapname;
1465 
1466 	urdc = &rdc_u_info[krdc->index];
1467 
1468 	if (rdc_alloc_bitmap(krdc) < 0)
1469 		goto fail;
1470 
1471 	if (rdc_open_bitmap(krdc) < 0)
1472 		goto fail;
1473 
1474 	if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1475 		bitmapname = &urdc->primary.bitmap[0];
1476 	else
1477 		bitmapname = &urdc->secondary.bitmap[0];
1478 
1479 	mutex_enter(&krdc->bmapmutex);
1480 
1481 	rdc_clr_flags(urdc, RDC_BMP_FAILED);
1482 	if (rdc_read_header(krdc, &header) < 0) {
1483 		cmn_err(CE_WARN,
1484 		    "!rdc_enable_bitmap: Read header %s failed", bitmapname);
1485 		mutex_exit(&krdc->bmapmutex);
1486 		goto fail;
1487 	}
1488 
1489 	rdc_fill_header(urdc, &header);
1490 	rdc_set_refcnt_ops(krdc, (size_t)header.refcntsize);
1491 
1492 	if (set)
1493 		(void) RDC_FILL_BITMAP(krdc, FALSE);
1494 
1495 	if (rdc_write_header(krdc, &header) < 0) {
1496 		cmn_err(CE_WARN,
1497 		    "!rdc_enable_bitmap: Write header %s failed",
1498 		    bitmapname);
1499 		mutex_exit(&krdc->bmapmutex);
1500 		goto fail;
1501 	}
1502 	mutex_exit(&krdc->bmapmutex);
1503 
1504 	if (rdc_write_bitmap(krdc) < 0) {
1505 		cmn_err(CE_WARN,
1506 		    "!rdc_enable_bitmap: Write bitmap %s failed",
1507 		    bitmapname);
1508 		goto fail;
1509 	}
1510 
1511 	return (0);
1512 
1513 fail:
1514 	rdc_free_bitmap(krdc, RDC_CMD_ENABLE);
1515 	rdc_close_bitmap(krdc);
1516 
1517 	mutex_enter(&krdc->bmapmutex);
1518 	rdc_set_flags_log(urdc, RDC_BMP_FAILED, "I/O failed");
1519 	mutex_exit(&krdc->bmapmutex);
1520 	return (-1);
1521 }
1522 
1523 static int
_rdc_rdwr_refcnt(rdc_k_info_t * krdc,int rwflg)1524 _rdc_rdwr_refcnt(rdc_k_info_t *krdc, int rwflg)
1525 {
1526 	rdc_u_info_t *urdc;
1527 	int rc;
1528 	nsc_off_t offset;
1529 	nsc_size_t len;
1530 
1531 	urdc = &rdc_u_info[krdc->index];
1532 
1533 #ifdef DEBUG_REFCNT
1534 	cmn_err(CE_NOTE, "!rdc_rdwr_refcnt: %s refcount for %s",
1535 	    (rwflg == NSC_READ) ? "resuming" : "writing",
1536 	    urdc->primary.bitmap);
1537 #endif
1538 	ASSERT(MUTEX_HELD(QLOCK((&krdc->group->diskq))));
1539 	mutex_enter(&krdc->bmapmutex);
1540 
1541 	if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
1542 		cmn_err(CE_WARN, "!rdc_rdwr_refcnt: reserve failed");
1543 		goto fail;
1544 	}
1545 
1546 	if (krdc->bitmap_size == 0) {
1547 		cmn_err(CE_WARN, "!rdc_rdwr_refcnt: NULL bitmap!");
1548 		goto fail;
1549 	}
1550 
1551 	offset = RDC_BITREF_FBA(krdc);
1552 	len = krdc->bitmap_size * BITS_IN_BYTE * rdc_refcntsize(krdc);
1553 
1554 	rc = rdc_ns_io(krdc->bitmapfd, rwflg, offset,
1555 	    (uchar_t *)krdc->bitmap_ref, len);
1556 
1557 	if (!RDC_SUCCESS(rc)) {
1558 		cmn_err(CE_WARN, "!unable to %s refcount from bitmap %s",
1559 		    (rwflg == NSC_READ) ? "retrieve" : "write",
1560 		    urdc->primary.bitmap);
1561 		rdc_set_flags_log(urdc, RDC_BMP_FAILED, "refcount I/O failed");
1562 		goto fail;
1563 	}
1564 
1565 	_rdc_rlse_devs(krdc, RDC_BMP);
1566 
1567 	mutex_exit(&krdc->bmapmutex);
1568 
1569 #ifdef DEBUG_REFCNT
1570 	cmn_err(CE_NOTE, "!rdc_rdwr_refcnt: %s refcount for %s",
1571 	    (rwflg == NSC_READ) ? "resumed" : "wrote",
1572 	    urdc->primary.bitmap);
1573 #endif
1574 	return (0);
1575 
1576 	fail:
1577 	_rdc_rlse_devs(krdc, RDC_BMP);
1578 
1579 	mutex_exit(&krdc->bmapmutex);
1580 
1581 	return (-1);
1582 
1583 }
1584 
1585 /*
1586  * rdc_read_refcount
1587  * read the stored refcount from disk
1588  * queue lock is held
1589  */
1590 int
rdc_read_refcount(rdc_k_info_t * krdc)1591 rdc_read_refcount(rdc_k_info_t *krdc)
1592 {
1593 	int	rc;
1594 
1595 	rc = _rdc_rdwr_refcnt(krdc, NSC_READ);
1596 
1597 	return (rc);
1598 }
1599 
1600 /*
1601  * rdc_write_refcount
1602  * writes krdc->bitmap_ref to the diskq
1603  * called with qlock held
1604  */
1605 int
rdc_write_refcount(rdc_k_info_t * krdc)1606 rdc_write_refcount(rdc_k_info_t *krdc)
1607 {
1608 	int	rc;
1609 
1610 	rc = _rdc_rdwr_refcnt(krdc, NSC_WRBUF);
1611 
1612 	return (rc);
1613 }
1614 
1615 static int
rdc_resume_state(rdc_k_info_t * krdc,const rdc_header_t * header)1616 rdc_resume_state(rdc_k_info_t *krdc, const rdc_header_t *header)
1617 {
1618 	rdc_u_info_t *urdc;
1619 	char *bitmapname;
1620 
1621 	urdc = &rdc_u_info[krdc->index];
1622 	if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1623 		bitmapname = &urdc->primary.bitmap[0];
1624 	else
1625 		bitmapname = &urdc->secondary.bitmap[0];
1626 
1627 	if (header->magic != RDC_HDR_MAGIC) {
1628 		cmn_err(CE_WARN, "!rdc_resume_state: Bad magic in %s",
1629 		    bitmapname);
1630 		return (-1);
1631 	}
1632 
1633 	if (strncmp(urdc->primary.file, header->primary.file,
1634 	    NSC_MAXPATH) != 0) {
1635 #ifdef DEBUG
1636 		cmn_err(CE_WARN,
1637 		    "!rdc_resume_state: Found %s Expected %s",
1638 		    header->primary.file, urdc->primary.file);
1639 #endif /* DEBUG */
1640 		return (-1);
1641 	}
1642 
1643 	if (strncmp(urdc->secondary.file, header->secondary.file,
1644 	    NSC_MAXPATH) != 0) {
1645 #ifdef DEBUG
1646 		cmn_err(CE_WARN,
1647 		    "!rdc_resume_state: Found %s Expected %s",
1648 		    header->secondary.file, urdc->secondary.file);
1649 #endif /* DEBUG */
1650 		return (-1);
1651 	}
1652 
1653 	if (strncmp(urdc->primary.bitmap, header->primary.bitmap,
1654 	    NSC_MAXPATH) != 0) {
1655 #ifdef DEBUG
1656 		cmn_err(CE_WARN,
1657 		    "!rdc_resume_state: Found %s Expected %s",
1658 		    header->primary.bitmap, urdc->primary.bitmap);
1659 #endif /* DEBUG */
1660 		return (-1);
1661 	}
1662 
1663 	if (strncmp(urdc->secondary.bitmap, header->secondary.bitmap,
1664 	    NSC_MAXPATH) != 0) {
1665 #ifdef DEBUG
1666 		cmn_err(CE_WARN,
1667 		    "!rdc_resume_state: Found %s Expected %s",
1668 		    header->secondary.bitmap, urdc->secondary.bitmap);
1669 #endif /* DEBUG */
1670 		return (-1);
1671 	}
1672 
1673 	if (header->maxqfbas)
1674 		urdc->maxqfbas = header->maxqfbas;
1675 
1676 	if (header->maxqitems)
1677 		urdc->maxqitems = header->maxqitems;
1678 
1679 	if (header->autosync >= 0)
1680 		urdc->autosync = header->autosync;
1681 
1682 	if (header->asyncthr)
1683 		urdc->asyncthr = header->asyncthr;
1684 
1685 	rdc_many_enter(krdc);
1686 	rdc_set_refcnt_ops(krdc, header->refcntsize);
1687 #ifdef DEBUG_REFCNT
1688 	cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1689 	    (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1690 #endif
1691 	if (header->flags & RDC_VOL_FAILED)
1692 		rdc_set_flags(urdc, RDC_VOL_FAILED);
1693 	if (header->flags & RDC_QUEUING)
1694 		rdc_set_flags(urdc, RDC_QUEUING);
1695 
1696 	rdc_clr_flags(urdc, RDC_SYNC_NEEDED | RDC_RSYNC_NEEDED);
1697 	rdc_set_mflags(urdc, (header->flags & RDC_RSYNC_NEEDED));
1698 	rdc_set_flags(urdc, (header->flags & RDC_SYNC_NEEDED));
1699 	rdc_many_exit(krdc);
1700 
1701 	if (urdc->flags & RDC_VOL_FAILED) {
1702 
1703 		/* Our disk was failed so set all the bits in the bitmap */
1704 
1705 		if (RDC_FILL_BITMAP(krdc, TRUE) != 0) {
1706 			cmn_err(CE_WARN,
1707 			    "!rdc_resume_state: Fill bitmap %s failed",
1708 			    bitmapname);
1709 			return (-1);
1710 		}
1711 		rdc_many_enter(krdc);
1712 		if (IS_STATE(urdc, RDC_QUEUING))
1713 			rdc_clr_flags(urdc, RDC_QUEUING);
1714 		rdc_many_exit(krdc);
1715 	} else {
1716 		/* Header was good, so read in the bitmap */
1717 
1718 		if (rdc_read_bitmap(krdc, NULL) < 0) {
1719 			cmn_err(CE_WARN,
1720 			    "!rdc_resume_state: Read bitmap %s failed",
1721 			    bitmapname);
1722 			return (-1);
1723 		}
1724 
1725 		urdc->bits_set = RDC_COUNT_BITMAP(krdc);
1726 
1727 		/*
1728 		 * Check if another node went down with bits set, but
1729 		 * without setting logging mode.
1730 		 */
1731 		if (urdc->bits_set != 0 &&
1732 		    (rdc_get_vflags(urdc) & RDC_ENABLED) &&
1733 		    !(rdc_get_vflags(urdc) & RDC_LOGGING)) {
1734 			rdc_group_log(krdc, RDC_NOFLUSH | RDC_NOREMOTE, NULL);
1735 		}
1736 	}
1737 
1738 	/* if we are using a disk queue, read in the reference count bits */
1739 	if (RDC_IS_DISKQ(krdc->group)) {
1740 		disk_queue *q = &krdc->group->diskq;
1741 		mutex_enter(QLOCK(q));
1742 		if ((rdc_read_refcount(krdc) < 0)) {
1743 			cmn_err(CE_WARN,
1744 			    "!rdc_resume_state: Resume bitmap %s's refcount"
1745 			    "failed",
1746 			    urdc->primary.bitmap);
1747 			mutex_exit(QLOCK(q));
1748 			rdc_many_enter(krdc);
1749 			if (IS_STATE(urdc, RDC_QUEUING))
1750 				rdc_clr_flags(urdc, RDC_QUEUING);
1751 			rdc_many_exit(krdc);
1752 			return (-1);
1753 		}
1754 		mutex_exit(QLOCK(q));
1755 	}
1756 
1757 	return (0);
1758 }
1759 
1760 
1761 int
rdc_resume_bitmap(rdc_k_info_t * krdc)1762 rdc_resume_bitmap(rdc_k_info_t *krdc)
1763 {
1764 	rdc_header_t header;
1765 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
1766 	char *bitmapname;
1767 
1768 	if (rdc_alloc_bitmap(krdc) < 0)
1769 		goto allocfail;
1770 
1771 	if (rdc_open_bitmap(krdc) < 0)
1772 		goto fail;
1773 
1774 	if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1775 		bitmapname = &urdc->primary.bitmap[0];
1776 	else
1777 		bitmapname = &urdc->secondary.bitmap[0];
1778 
1779 	mutex_enter(&krdc->bmapmutex);
1780 
1781 	rdc_clr_flags(urdc, RDC_BMP_FAILED);
1782 	if (rdc_read_header(krdc, &header) < 0) {
1783 		cmn_err(CE_WARN,
1784 		    "!rdc_resume_bitmap: Read header %s failed", bitmapname);
1785 		mutex_exit(&krdc->bmapmutex);
1786 		goto fail;
1787 	}
1788 
1789 	mutex_exit(&krdc->bmapmutex);
1790 
1791 	/* Resuming from the bitmap, so do some checking */
1792 
1793 	/*CONSTCOND*/
1794 	ASSERT(FBA_LEN(sizeof (rdc_header_t)) <= RDC_BITMAP_FBA);
1795 	/*CONSTCOND*/
1796 	ASSERT(sizeof (rdc_header_t) >= sizeof (rdc_headerv2_t));
1797 
1798 	if (header.magic == RDC_HDR_V2) {
1799 		rdc_headerv2_t *hdr_v2 = (rdc_headerv2_t *)&header;
1800 		rdc_header_t new_header;
1801 
1802 #ifdef DEBUG
1803 		cmn_err(CE_WARN,
1804 		    "!rdc_resume_bitmap: Converting v2 header for bitmap %s",
1805 		    bitmapname);
1806 #endif
1807 		bzero((char *)&new_header, sizeof (rdc_header_t));
1808 
1809 		new_header.autosync = -1;
1810 		new_header.magic = RDC_HDR_MAGIC;
1811 		new_header.syshostid = urdc->syshostid;
1812 
1813 		if (hdr_v2->volume_failed)
1814 			new_header.flags |= RDC_VOL_FAILED;
1815 		if (hdr_v2->sync_needed == RDC_SYNC)
1816 			new_header.flags |= RDC_SYNC_NEEDED;
1817 		if (hdr_v2->sync_needed == RDC_FULL_SYNC)
1818 			new_header.flags |= RDC_SYNC_NEEDED;
1819 		if (hdr_v2->sync_needed == RDC_REV_SYNC)
1820 			new_header.flags |= RDC_RSYNC_NEEDED;
1821 		if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
1822 			(void) strncpy(new_header.primary.file,
1823 			    hdr_v2->filename, NSC_MAXPATH);
1824 			(void) strncpy(new_header.primary.bitmap,
1825 			    hdr_v2->bitmapname, NSC_MAXPATH);
1826 			(void) strncpy(new_header.secondary.file,
1827 			    urdc->secondary.file, NSC_MAXPATH);
1828 			(void) strncpy(new_header.secondary.bitmap,
1829 			    urdc->secondary.bitmap, NSC_MAXPATH);
1830 		} else {
1831 			(void) strncpy(new_header.secondary.file,
1832 			    hdr_v2->filename, NSC_MAXPATH);
1833 			(void) strncpy(new_header.secondary.bitmap,
1834 			    hdr_v2->bitmapname, NSC_MAXPATH);
1835 			(void) strncpy(new_header.primary.file,
1836 			    urdc->primary.file, NSC_MAXPATH);
1837 			(void) strncpy(new_header.primary.bitmap,
1838 			    urdc->primary.bitmap, NSC_MAXPATH);
1839 		}
1840 
1841 		bcopy(&new_header, &header, sizeof (rdc_header_t));
1842 
1843 		mutex_enter(&krdc->bmapmutex);
1844 		if (rdc_write_header(krdc, &header) < 0) {
1845 			mutex_exit(&krdc->bmapmutex);
1846 			cmn_err(CE_WARN,
1847 			    "!rdc_resume_bitmap: Write header %s failed",
1848 			    bitmapname);
1849 			goto fail;
1850 		}
1851 		mutex_exit(&krdc->bmapmutex);
1852 
1853 	} else if (header.magic == RDC_HDR_V3) {
1854 		/*
1855 		 * just update asyncthr and magic, and then we're done
1856 		 */
1857 		header.magic = RDC_HDR_MAGIC;
1858 		header.asyncthr = RDC_ASYNCTHR;
1859 		mutex_enter(&krdc->bmapmutex);
1860 		if (rdc_write_header(krdc, &header) < 0) {
1861 			mutex_exit(&krdc->bmapmutex);
1862 			cmn_err(CE_WARN,
1863 			    "!rdc_resume_bitmap: Write header %s failed",
1864 			    bitmapname);
1865 			goto fail;
1866 		}
1867 		mutex_exit(&krdc->bmapmutex);
1868 	}
1869 
1870 	if (rdc_resume_state(krdc, &header) == 0)
1871 		return (0);
1872 
1873 	rdc_close_bitmap(krdc);
1874 
1875 fail:
1876 	(void) RDC_FILL_BITMAP(krdc, FALSE);
1877 	rdc_clr_flags(urdc, RDC_QUEUING);
1878 	if (krdc->bitmap_ref)
1879 		bzero(krdc->bitmap_ref, krdc->bitmap_size * BITS_IN_BYTE *
1880 		    rdc_refcntsize(krdc));
1881 
1882 allocfail:
1883 	mutex_enter(&krdc->bmapmutex);
1884 	rdc_set_flags_log(urdc, RDC_BMP_FAILED, "resume bitmap failed");
1885 	mutex_exit(&krdc->bmapmutex);
1886 
1887 	return (-1);
1888 }
1889 
1890 void
rdc_std_zero_bitref(rdc_k_info_t * krdc)1891 rdc_std_zero_bitref(rdc_k_info_t *krdc)
1892 {
1893 	nsc_size_t vol_size;
1894 	int sts;
1895 	size_t newrefcntsize;
1896 
1897 	if (krdc->bitmap_ref) {
1898 		mutex_enter(&krdc->bmapmutex);
1899 		bzero(krdc->bitmap_ref, krdc->bitmap_size * BITS_IN_BYTE *
1900 		    BMAP_REF_PREF_SIZE);
1901 		if (RDC_IS_DISKQ(krdc->group) && rdc_refcntsize(krdc) !=
1902 		    BMAP_REF_PREF_SIZE) {
1903 			/* see if we can upgrade the size of the ref counters */
1904 			sts = _rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL);
1905 			if (!RDC_SUCCESS(sts)) {
1906 				goto nochange;
1907 			}
1908 			sts = nsc_partsize(krdc->bitmapfd, &vol_size);
1909 
1910 			newrefcntsize = rdc_ref_size_possible(krdc->bitmap_size,
1911 			    vol_size);
1912 			if (newrefcntsize > rdc_refcntsize(krdc)) {
1913 				rdc_set_refcnt_ops(krdc, newrefcntsize);
1914 #ifdef DEBUG_REFCNT
1915 	cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1916 	    (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1917 #endif
1918 			}
1919 nochange:
1920 			_rdc_rlse_devs(krdc, RDC_BMP);
1921 		}
1922 		mutex_exit(&krdc->bmapmutex);
1923 	}
1924 }
1925 
1926 int
rdc_reset_bitmap(rdc_k_info_t * krdc)1927 rdc_reset_bitmap(rdc_k_info_t *krdc)
1928 {
1929 	rdc_u_info_t *urdc;
1930 	rdc_header_t header;
1931 	char *bitmapname;
1932 
1933 	urdc = &rdc_u_info[krdc->index];
1934 	if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1935 		bitmapname = &urdc->primary.bitmap[0];
1936 	else
1937 		bitmapname = &urdc->secondary.bitmap[0];
1938 
1939 	mutex_enter(&krdc->bmapmutex);
1940 
1941 	rdc_clr_flags(urdc, RDC_BMP_FAILED);
1942 	if (rdc_read_header(krdc, &header) < 0) {
1943 		cmn_err(CE_WARN,
1944 		    "!rdc_reset_bitmap: Read header %s failed", bitmapname);
1945 		goto fail_with_mutex;
1946 	}
1947 
1948 	rdc_fill_header(urdc, &header);
1949 
1950 	if (rdc_write_header(krdc, &header) < 0) {
1951 		cmn_err(CE_WARN,
1952 		    "!rdc_reset_bitmap: Write header %s failed",
1953 		    bitmapname);
1954 		goto fail_with_mutex;
1955 	}
1956 	mutex_exit(&krdc->bmapmutex);
1957 
1958 	if (krdc->bitmap_write == -1)
1959 		krdc->bitmap_write = 0;
1960 
1961 	if (krdc->bitmap_write == 0) {
1962 		if (rdc_write_bitmap_fill(krdc) < 0) {
1963 			cmn_err(CE_WARN,
1964 			    "!rdc_reset_bitmap: Write bitmap %s failed",
1965 			    bitmapname);
1966 			goto fail;
1967 		}
1968 		krdc->bitmap_write = -1;
1969 	} else if (rdc_write_bitmap(krdc) < 0) {
1970 		cmn_err(CE_WARN,
1971 		    "!rdc_reset_bitmap: Write bitmap %s failed",
1972 		    bitmapname);
1973 		goto fail;
1974 	}
1975 
1976 	return (0);
1977 
1978 fail:
1979 	mutex_enter(&krdc->bmapmutex);
1980 fail_with_mutex:
1981 	rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reset failed");
1982 	mutex_exit(&krdc->bmapmutex);
1983 #ifdef DEBUG
1984 	cmn_err(CE_NOTE, "!SNDR: unable to reset bitmap for %s:%s",
1985 	    urdc->secondary.intf, urdc->secondary.file);
1986 #endif
1987 	return (-1);
1988 }
1989 
1990 
1991 /*
1992  * General bitmap operations
1993  */
1994 
1995 /*
1996  * rdc_set_bitmap_many()
1997  *
1998  * Used during reverse syncs to a 1-to-many primary to keep the 'many'
1999  * bitmaps up to date.
2000  */
2001 void
rdc_set_bitmap_many(rdc_k_info_t * krdc,nsc_off_t pos,nsc_size_t len)2002 rdc_set_bitmap_many(rdc_k_info_t *krdc, nsc_off_t pos, nsc_size_t len)
2003 {
2004 	uint_t dummy;
2005 
2006 #ifdef DEBUG
2007 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2008 	if (!(rdc_get_vflags(urdc) & RDC_PRIMARY)) {
2009 		cmn_err(CE_PANIC, "rdc_set_bitmap_many: not primary, urdc %p",
2010 		    (void *) urdc);
2011 	}
2012 #endif
2013 
2014 	if (IS_MANY(krdc)) {
2015 		rdc_k_info_t *krd;
2016 		rdc_u_info_t *urd;
2017 
2018 		rdc_many_enter(krdc);
2019 
2020 		for (krd = krdc->many_next; krd != krdc; krd = krd->many_next) {
2021 			urd = &rdc_u_info[krd->index];
2022 			if (!IS_ENABLED(urd))
2023 				continue;
2024 			ASSERT(urd->flags & RDC_PRIMARY);
2025 			(void) RDC_SET_BITMAP(krd, pos, len, &dummy);
2026 		}
2027 
2028 		rdc_many_exit(krdc);
2029 	}
2030 }
2031 
2032 
2033 static int
_rdc_net_bmap(const struct bmap6 * b6,net_bdata6 * bd6)2034 _rdc_net_bmap(const struct bmap6 *b6, net_bdata6 *bd6)
2035 {
2036 	rdc_k_info_t *krdc = &rdc_k_info[b6->cd];
2037 	struct timeval t;
2038 	int e, ret;
2039 	uint64_t left;
2040 	uint64_t bmap_blksize;
2041 
2042 	bmap_blksize = krdc->rpc_version < RDC_VERSION7 ?
2043 	    BMAP_BLKSIZE : BMAP_BLKSIZEV7;
2044 
2045 	t.tv_sec = rdc_rpc_tmout;
2046 	t.tv_usec = 0;
2047 
2048 	if (bd6->data.data_val == NULL) {
2049 		return (EINVAL);
2050 	}
2051 
2052 	left = b6->size;
2053 	bd6->endoblk = 0;
2054 	while (left) {
2055 		if (left >= bmap_blksize)
2056 			bd6->size = (int)bmap_blksize;
2057 		else
2058 			bd6->size = (int)left;
2059 
2060 		bd6->data.data_len = bd6->size;
2061 
2062 		if ((uint64_t)bd6->size > left) {
2063 			left = 0;
2064 		} else {
2065 			left -= bd6->size;
2066 		}
2067 		/*
2068 		 * mark the last block sent.
2069 		 */
2070 		if (left == 0) {
2071 			bd6->endoblk = 1;
2072 		}
2073 		ASSERT(krdc->rpc_version);
2074 		if (krdc->rpc_version <= RDC_VERSION5) {
2075 			struct net_bdata bd;
2076 			bd.cd = bd6->cd;
2077 			bd.offset = bd6->offset;
2078 			bd.size = bd6->size;
2079 			bd.data.data_len = bd6->data.data_len;
2080 			bd.data.data_val = bd6->data.data_val;
2081 			e = rdc_clnt_call(krdc->lsrv, RDCPROC_BDATA,
2082 			    krdc->rpc_version, xdr_net_bdata, (char *)&bd,
2083 			    xdr_int, (char *)&ret, &t);
2084 		} else {
2085 			e = rdc_clnt_call(krdc->lsrv, RDCPROC_BDATA6,
2086 			    krdc->rpc_version, xdr_net_bdata6, (char *)bd6,
2087 			    xdr_int, (char *)&ret, &t);
2088 		}
2089 		if (e || ret) {
2090 			if (e)
2091 				ret = e;
2092 			return (ret);
2093 		}
2094 		bd6->offset += bmap_blksize;
2095 		bd6->data.data_val += bmap_blksize;
2096 	}
2097 	return (0);
2098 }
2099 
2100 
2101 /*
2102  * Standard bitmap operations (combined kmem/disk bitmaps).
2103  */
2104 
2105 /*
2106  * rdc_std_set_bitmask(pos, len, &bitmask)
2107  * set a bitmask for this range. used to clear the correct
2108  * bits after flushing
2109  */
2110 static void
rdc_std_set_bitmask(const nsc_off_t fba_pos,const nsc_size_t fba_len,uint_t * bitmask)2111 rdc_std_set_bitmask(const nsc_off_t fba_pos, const nsc_size_t fba_len,
2112     uint_t *bitmask)
2113 {
2114 	int first, st, en;
2115 	if (bitmask)
2116 		*bitmask = 0;
2117 	else
2118 		return;
2119 
2120 	first = st = FBA_TO_LOG_NUM(fba_pos);
2121 	en = FBA_TO_LOG_NUM(fba_pos + fba_len - 1);
2122 	while (st <= en) {
2123 		BMAP_BIT_SET((uchar_t *)bitmask, st - first);
2124 		st++;
2125 	}
2126 
2127 }
2128 /*
2129  * rdc_std_set_bitmap(krdc, fba_pos, fba_len, &bitmask)
2130  *
2131  * Mark modified segments in the dual copy file bitmap
2132  * to provide fast recovery
2133  * Note that bitmask allows for 32 segments, which at 32k per segment equals
2134  * 1 megabyte. If we ever allow more than this to be transferred in one
2135  * operation, or decrease the segment size, then this code will have to be
2136  * changed accordingly.
2137  */
2138 
2139 static int
rdc_std_set_bitmap(rdc_k_info_t * krdc,const nsc_off_t fba_pos,const nsc_size_t fba_len,uint_t * bitmask)2140 rdc_std_set_bitmap(rdc_k_info_t *krdc, const nsc_off_t fba_pos,
2141     const nsc_size_t fba_len, uint_t *bitmask)
2142 {
2143 	int first, st, en;
2144 	int fbaset = 0;
2145 	nsc_off_t fba = 0;
2146 	int printerr = 10;
2147 	int tries = RDC_FUTILE_ATTEMPTS;
2148 	int queuing = RDC_QUEUING;
2149 	rdc_u_info_t *urdc;
2150 
2151 	if (bitmask)
2152 		*bitmask = 0;
2153 	else
2154 		return (-1);
2155 
2156 	urdc = &rdc_u_info[krdc->index];
2157 	if (rdc_get_vflags(urdc) & RDC_BMP_FAILED)
2158 		return (-1);
2159 
2160 	if (krdc->bitmap_write == 0) {
2161 		if (rdc_write_bitmap_fill(krdc) < 0)
2162 			return (-1);
2163 		krdc->bitmap_write = -1;
2164 	}
2165 	first = st = FBA_TO_LOG_NUM(fba_pos);
2166 	en = FBA_TO_LOG_NUM(fba_pos + fba_len - 1);
2167 	ASSERT(st <= en);
2168 	while (st <= en) {
2169 		int use_ref;
2170 again:
2171 		mutex_enter(&krdc->bmapmutex);
2172 
2173 		if (krdc->dcio_bitmap == NULL) {
2174 #ifdef DEBUG
2175 			cmn_err(CE_WARN, "!rdc_std_set_bitmap: "
2176 			    "recovery bitmaps not allocated");
2177 #endif
2178 			mutex_exit(&krdc->bmapmutex);
2179 			return (-1);
2180 		}
2181 
2182 		use_ref = IS_PRIMARY(urdc) && IS_ASYNC(urdc) &&
2183 		    ((rdc_get_vflags(urdc) & RDC_QUEUING) ||
2184 		    !(rdc_get_vflags(urdc) & RDC_LOGGING));
2185 
2186 
2187 		if (!BMAP_BIT_ISSET(krdc->dcio_bitmap, st)) {
2188 			BMAP_BIT_SET(krdc->dcio_bitmap, st);
2189 			if (use_ref) {
2190 				ASSERT(BMAP_REF_ISSET(krdc, st) ==
2191 				    0);
2192 				BMAP_REF_FORCE(krdc, st, 1);
2193 			}
2194 			BMAP_BIT_SET((uchar_t *)bitmask, st - first);
2195 			urdc->bits_set++;
2196 			if ((!fbaset) || fba != BIT_TO_FBA(st)) {
2197 				if (fbaset && krdc->bitmap_write > 0) {
2198 					mutex_exit(&krdc->bmapmutex);
2199 					if (rdc_write_bitmap_fba(krdc, fba) < 0)
2200 						return (-1);
2201 					mutex_enter(&krdc->bmapmutex);
2202 				}
2203 				fba = BIT_TO_FBA(st);
2204 				fbaset = 1;
2205 			}
2206 		} else {
2207 		/*
2208 		 * Just bump reference count
2209 		 * For logging or syncing we do not care what the reference
2210 		 * is as it will be forced back on the state transition.
2211 		 */
2212 			if (use_ref) {
2213 				if (BMAP_REF_ISSET(krdc, st) ==
2214 				    BMAP_REF_MAXVAL(krdc)) {
2215 					/*
2216 					 * Rollover of reference count.
2217 					 */
2218 
2219 					if (!(rdc_get_vflags(urdc) &
2220 					    RDC_VOL_FAILED)) {
2221 						/*
2222 						 * Impose throttle to help dump
2223 						 * queue
2224 						 */
2225 						mutex_exit(&krdc->bmapmutex);
2226 						delay(4);
2227 						rdc_bitmap_delay++;
2228 						if (printerr--) {
2229 	cmn_err(CE_WARN, "!SNDR: bitmap reference count maxed out for %s:%s",
2230 	    urdc->secondary.intf, urdc->secondary.file);
2231 
2232 						}
2233 
2234 						if ((tries-- <= 0) &&
2235 						    IS_STATE(urdc, queuing)) {
2236 	cmn_err(CE_WARN, "!SNDR: giving up on reference count, logging set"
2237 	    " %s:%s", urdc->secondary.intf, urdc->secondary.file);
2238 							rdc_group_enter(krdc);
2239 							rdc_group_log(krdc,
2240 							    RDC_NOFLUSH |
2241 							    RDC_NOREMOTE|
2242 							    RDC_FORCE_GROUP,
2243 					    "ref count retry limit exceeded");
2244 							rdc_group_exit(krdc);
2245 						}
2246 						goto again;
2247 					}
2248 				} else {
2249 					BMAP_REF_SET(krdc, st);
2250 				}
2251 			}
2252 		}
2253 		mutex_exit(&krdc->bmapmutex);
2254 		st++;
2255 	}
2256 	if (fbaset && krdc->bitmap_write > 0) {
2257 		if (rdc_write_bitmap_fba(krdc, fba) < 0)
2258 			return (-1);
2259 	}
2260 	return (0);
2261 }
2262 
2263 static void
rdc_std_clr_bitmap(rdc_k_info_t * krdc,const nsc_off_t fba_pos,const nsc_size_t fba_len,const uint_t bitmask,const int force)2264 rdc_std_clr_bitmap(rdc_k_info_t *krdc, const nsc_off_t fba_pos,
2265     const nsc_size_t fba_len, const uint_t bitmask, const int force)
2266 {
2267 	int first, st, en;
2268 	nsc_off_t fba = 0;
2269 	int fbaset = 0;
2270 	uint_t bm = bitmask;
2271 	uchar_t *ptr = (uchar_t *)&bm;
2272 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2273 
2274 	if (rdc_get_vflags(urdc) & RDC_BMP_FAILED)
2275 		return;
2276 
2277 	first = st = FBA_TO_LOG_NUM(fba_pos);
2278 	en = FBA_TO_LOG_NUM(fba_pos + fba_len - 1);
2279 	ASSERT(st <= en);
2280 	while (st <= en) {
2281 		mutex_enter(&krdc->bmapmutex);
2282 
2283 		if (krdc->dcio_bitmap == NULL) {
2284 #ifdef DEBUG
2285 			cmn_err(CE_WARN, "!rdc_std_clr_bitmap: "
2286 			    "recovery bitmaps not allocated");
2287 #endif
2288 			mutex_exit(&krdc->bmapmutex);
2289 			return;
2290 		}
2291 
2292 		if (((bitmask == 0xffffffff) ||
2293 		    (BMAP_BIT_ISSET(ptr, st - first))) &&
2294 		    BMAP_BIT_ISSET(krdc->dcio_bitmap, st)) {
2295 
2296 			int use_ref = IS_PRIMARY(urdc) && IS_ASYNC(urdc) &&
2297 			    ((rdc_get_vflags(urdc) & RDC_QUEUING) ||
2298 			    !(rdc_get_vflags(urdc) & RDC_LOGGING));
2299 
2300 			if (force || (use_ref == 0)) {
2301 				if (krdc->bitmap_ref)
2302 					BMAP_REF_FORCE(krdc, st, 0);
2303 			} else if (use_ref) {
2304 				if (BMAP_REF_ISSET(krdc, st) != 0)
2305 					BMAP_REF_CLR(krdc, st);
2306 
2307 			}
2308 
2309 			if ((use_ref == 0) || (use_ref &&
2310 			    !BMAP_REF_ISSET(krdc, st))) {
2311 				BMAP_BIT_CLR(krdc->dcio_bitmap, st);
2312 
2313 				urdc->bits_set--;
2314 				if (!fbaset || fba != BIT_TO_FBA(st)) {
2315 					if (fbaset &&
2316 					    krdc->bitmap_write > 0) {
2317 						mutex_exit(&krdc->bmapmutex);
2318 						if (rdc_write_bitmap_fba(krdc,
2319 						    fba) < 0)
2320 							return;
2321 						mutex_enter(&krdc->bmapmutex);
2322 					}
2323 					fba = BIT_TO_FBA(st);
2324 					fbaset = 1;
2325 				}
2326 			}
2327 		}
2328 		mutex_exit(&krdc->bmapmutex);
2329 		st++;
2330 	}
2331 	if (fbaset && krdc->bitmap_write > 0) {
2332 		if (rdc_write_bitmap_fba(krdc, fba) < 0)
2333 			return;
2334 	}
2335 }
2336 
2337 /*
2338  * make sure that this bit is set. if it isn't, set it
2339  * used when transitioning from async to sync while going
2340  * from rep to log. an overlapping sync write may unconditionally
2341  * clear the bit that has not been replicated. when the queue
2342  * is being dumped or this is called just to make sure pending stuff
2343  * is in the bitmap
2344  */
2345 void
rdc_std_check_bit(rdc_k_info_t * krdc,nsc_off_t pos,nsc_size_t len)2346 rdc_std_check_bit(rdc_k_info_t *krdc, nsc_off_t pos, nsc_size_t len)
2347 {
2348 	int st;
2349 	int en;
2350 	nsc_off_t fba;
2351 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2352 	st = FBA_TO_LOG_NUM(pos);
2353 	en = FBA_TO_LOG_NUM(pos + len - 1);
2354 
2355 	if (rdc_get_vflags(urdc) & RDC_BMP_FAILED)
2356 		return;
2357 
2358 	while (st <= en) {
2359 		mutex_enter(&krdc->bmapmutex);
2360 
2361 		if (krdc->dcio_bitmap == NULL) {
2362 #ifdef DEBUG
2363 			cmn_err(CE_WARN, "!rdc_std_check_bit: "
2364 			    "recovery bitmaps not allocated");
2365 #endif
2366 			mutex_exit(&krdc->bmapmutex);
2367 			return;
2368 		}
2369 
2370 		if (!BMAP_BIT_ISSET(krdc->dcio_bitmap, st)) {
2371 			BMAP_BIT_SET(krdc->dcio_bitmap, st);
2372 			if (krdc->bitmap_write > 0) {
2373 				fba = BIT_TO_FBA(st);
2374 				mutex_exit(&krdc->bmapmutex);
2375 				(void) rdc_write_bitmap_fba(krdc, fba);
2376 				mutex_enter(&krdc->bmapmutex);
2377 			}
2378 			urdc->bits_set++;
2379 
2380 		}
2381 		mutex_exit(&krdc->bmapmutex);
2382 		st++;
2383 	}
2384 
2385 }
2386 
2387 /*
2388  * rdc_std_count_dirty(krdc):
2389  *
2390  * Determine the number of segments that need to be flushed, This should
2391  * agree with the number of segments logged, but since we don't lock when
2392  * we increment, we force these values to agree
2393  */
2394 static int
rdc_std_count_dirty(rdc_k_info_t * krdc)2395 rdc_std_count_dirty(rdc_k_info_t *krdc)
2396 {
2397 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2398 	int i, count, size;
2399 
2400 	if (krdc->dcio_bitmap == NULL) {
2401 #ifdef DEBUG
2402 		cmn_err(CE_WARN,
2403 		    "!rdc_std_count_dirty: no bitmap configured for %s",
2404 		    urdc->primary.file);
2405 #endif
2406 		return (0);
2407 	}
2408 
2409 	count = 0;
2410 	ASSERT(urdc->volume_size != 0);
2411 	size = FBA_TO_LOG_LEN(urdc->volume_size);
2412 	for (i = 0; i < size; i++)
2413 		if (BMAP_BIT_ISSET(krdc->dcio_bitmap, i))
2414 			count++;
2415 
2416 	if (count > size)
2417 		count = size;
2418 
2419 	return (count);
2420 }
2421 
2422 
2423 static int
rdc_std_bit_isset(rdc_k_info_t * krdc,const int bit)2424 rdc_std_bit_isset(rdc_k_info_t *krdc, const int bit)
2425 {
2426 	return (BMAP_BIT_ISSET(krdc->dcio_bitmap, bit));
2427 }
2428 
2429 
2430 /*
2431  * rdc_std_fill_bitmap(krdc, write)
2432  *
2433  * Called to force bitmaps to a fully dirty state
2434  */
2435 static int
rdc_std_fill_bitmap(rdc_k_info_t * krdc,const int write)2436 rdc_std_fill_bitmap(rdc_k_info_t *krdc, const int write)
2437 {
2438 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2439 	int i, size;
2440 
2441 	if (krdc->dcio_bitmap == NULL) {
2442 #ifdef DEBUG
2443 		cmn_err(CE_WARN,
2444 		    "!rdc_std_fill_bitmap: no bitmap configured for %s",
2445 		    urdc->primary.file);
2446 #endif
2447 		return (-1);
2448 	}
2449 
2450 	ASSERT(urdc->volume_size != 0);
2451 	size = FBA_TO_LOG_LEN(urdc->volume_size);
2452 	for (i = 0; i < size; i++)
2453 		BMAP_BIT_SET(krdc->dcio_bitmap, i);
2454 
2455 	urdc->bits_set = size;
2456 
2457 	if (write)
2458 		return (rdc_write_bitmap(krdc));
2459 
2460 	return (0);
2461 }
2462 
2463 
2464 /*
2465  * rdc_std_zero_bitmap(krdc)
2466  *
2467  * Called on the secondary after a sync has completed to force bitmaps
2468  * to a fully clean state
2469  */
2470 static void
rdc_std_zero_bitmap(rdc_k_info_t * krdc)2471 rdc_std_zero_bitmap(rdc_k_info_t *krdc)
2472 {
2473 	rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2474 	int i, size;
2475 
2476 	if (krdc->dcio_bitmap == NULL) {
2477 #ifdef DEBUG
2478 		cmn_err(CE_WARN,
2479 		    "!rdc_std_zero_bitmap: no bitmap configured for %s",
2480 		    urdc->primary.file);
2481 #endif
2482 		return;
2483 	}
2484 #ifdef DEBUG
2485 	cmn_err(CE_NOTE, "!Clearing bitmap for %s", urdc->secondary.file);
2486 #endif
2487 
2488 	ASSERT(urdc->volume_size != 0);
2489 	size = FBA_TO_LOG_LEN(urdc->volume_size);
2490 	for (i = 0; i < size; i++)
2491 		BMAP_BIT_CLR(krdc->dcio_bitmap, i);
2492 	if (krdc->bitmap_write > 0)
2493 		(void) rdc_write_bitmap(krdc);
2494 
2495 	urdc->bits_set = 0;
2496 }
2497 
2498 
2499 /*
2500  * rdc_std_net_bmap()
2501  *
2502  * WARNING acts as both client and server
2503  */
2504 static int
rdc_std_net_bmap(const struct bmap6 * b)2505 rdc_std_net_bmap(const struct bmap6 *b)
2506 {
2507 	rdc_k_info_t *krdc = &rdc_k_info[b->cd];
2508 	struct net_bdata6 bd;
2509 
2510 	bd.data.data_val = (char *)krdc->dcio_bitmap;
2511 	bd.cd = b->dual;
2512 	bd.offset = 0;
2513 
2514 	return (_rdc_net_bmap(b, &bd));
2515 }
2516 
2517 
2518 /*
2519  * rdc_std_net_bdata
2520  */
2521 static int
rdc_std_net_bdata(const struct net_bdata6 * bd)2522 rdc_std_net_bdata(const struct net_bdata6 *bd)
2523 {
2524 	rdc_k_info_t *krdc = &rdc_k_info[bd->cd];
2525 
2526 	rdc_lor((uchar_t *)bd->data.data_val,
2527 	    (uchar_t *)(((char *)krdc->dcio_bitmap) + bd->offset), bd->size);
2528 
2529 	return (0);
2530 }
2531 
2532 
2533 static struct rdc_bitmap_ops rdc_std_bitmap_ops = {
2534 	rdc_std_set_bitmap,
2535 	rdc_std_clr_bitmap,
2536 	rdc_std_count_dirty,
2537 	rdc_std_bit_isset,
2538 	rdc_std_fill_bitmap,
2539 	rdc_std_zero_bitmap,
2540 	rdc_std_net_bmap,
2541 	rdc_std_net_bdata,
2542 	rdc_std_zero_bitref,
2543 	rdc_std_set_bitmask,
2544 	rdc_std_check_bit
2545 };
2546 
2547 
2548 void
rdc_bitmap_init()2549 rdc_bitmap_init()
2550 {
2551 	rdc_bitmap_ops = &rdc_std_bitmap_ops;
2552 	rdc_wrflag = NSC_WRITE;
2553 }
2554 
2555 static void
rdc_bmap_ref_byte_set(rdc_k_info_t * krdc,int ind)2556 rdc_bmap_ref_byte_set(rdc_k_info_t *krdc, int ind)
2557 {
2558 	unsigned char *bmap = (unsigned char *)krdc->bitmap_ref;
2559 
2560 	ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned char));
2561 	bmap[ind]++;
2562 }
2563 
2564 static void
rdc_bmap_ref_byte_clr(rdc_k_info_t * krdc,int ind)2565 rdc_bmap_ref_byte_clr(rdc_k_info_t *krdc, int ind)
2566 {
2567 	unsigned char *bmap = (unsigned char *)krdc->bitmap_ref;
2568 
2569 	ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned char));
2570 	bmap[ind]--;
2571 }
2572 
2573 static unsigned int
rdc_bmap_ref_byte_isset(rdc_k_info_t * krdc,int ind)2574 rdc_bmap_ref_byte_isset(rdc_k_info_t *krdc, int ind)
2575 {
2576 	unsigned char *bmap = (unsigned char *)krdc->bitmap_ref;
2577 
2578 	ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned char));
2579 	return ((unsigned int)(bmap[ind]));
2580 }
2581 
2582 static void
rdc_bmap_ref_byte_force(rdc_k_info_t * krdc,int ind,unsigned int val)2583 rdc_bmap_ref_byte_force(rdc_k_info_t *krdc, int ind, unsigned int val)
2584 {
2585 	unsigned char *bmap = (unsigned char *)krdc->bitmap_ref;
2586 
2587 	ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned char));
2588 	bmap[ind] = (unsigned char) val;
2589 }
2590 
2591 /* ARGSUSED */
2592 static unsigned int
rdc_bmap_ref_byte_maxval(rdc_k_info_t * krdc)2593 rdc_bmap_ref_byte_maxval(rdc_k_info_t *krdc)
2594 {
2595 	ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned char));
2596 	return ((unsigned int)(UINT8_MAX));
2597 }
2598 
2599 struct bm_ref_ops rdc_ref_byte_ops = {
2600 	rdc_bmap_ref_byte_set,
2601 	rdc_bmap_ref_byte_clr,
2602 	rdc_bmap_ref_byte_isset,
2603 	rdc_bmap_ref_byte_force,
2604 	rdc_bmap_ref_byte_maxval,
2605 	sizeof (unsigned char)
2606 };
2607 
2608 static void
rdc_bmap_ref_int_set(rdc_k_info_t * krdc,int ind)2609 rdc_bmap_ref_int_set(rdc_k_info_t *krdc, int ind)
2610 {
2611 	unsigned int *bmap = (unsigned int *)krdc->bitmap_ref;
2612 
2613 	ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned int));
2614 	bmap[ind]++;
2615 }
2616 
2617 static void
rdc_bmap_ref_int_clr(rdc_k_info_t * krdc,int ind)2618 rdc_bmap_ref_int_clr(rdc_k_info_t *krdc, int ind)
2619 {
2620 	unsigned int *bmap = (unsigned int *)krdc->bitmap_ref;
2621 
2622 	ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned int));
2623 	bmap[ind]--;
2624 }
2625 
2626 static unsigned int
rdc_bmap_ref_int_isset(rdc_k_info_t * krdc,int ind)2627 rdc_bmap_ref_int_isset(rdc_k_info_t *krdc, int ind)
2628 {
2629 	unsigned int *bmap = (unsigned int *)krdc->bitmap_ref;
2630 
2631 	ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned int));
2632 	return ((bmap[ind]));
2633 }
2634 
2635 static void
rdc_bmap_ref_int_force(rdc_k_info_t * krdc,int ind,unsigned int val)2636 rdc_bmap_ref_int_force(rdc_k_info_t *krdc, int ind, unsigned int val)
2637 {
2638 	unsigned int *bmap = (unsigned int *)krdc->bitmap_ref;
2639 
2640 	ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned int));
2641 	bmap[ind] = val;
2642 }
2643 
2644 /* ARGSUSED */
2645 static unsigned int
rdc_bmap_ref_int_maxval(rdc_k_info_t * krdc)2646 rdc_bmap_ref_int_maxval(rdc_k_info_t *krdc)
2647 {
2648 	ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned int));
2649 	return ((unsigned int)(UINT_MAX));
2650 }
2651 
2652 struct bm_ref_ops rdc_ref_int_ops = {
2653 	rdc_bmap_ref_int_set,
2654 	rdc_bmap_ref_int_clr,
2655 	rdc_bmap_ref_int_isset,
2656 	rdc_bmap_ref_int_force,
2657 	rdc_bmap_ref_int_maxval,
2658 	sizeof (unsigned int)
2659 };
2660