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
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
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
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
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
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
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
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
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
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
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
635 mutex_enter(&krdc->bmapmutex);
636
637 urdc = &rdc_u_info[krdc->index];
638 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
639 mutex_exit(&krdc->bmapmutex);
640 return (-1);
641 }
642
643 if (krdc->bitmapfd == NULL) {
644 mutex_exit(&krdc->bmapmutex);
645 return (-1);
646 }
647
648 if (data == NULL && krdc->dcio_bitmap == NULL) {
649 mutex_exit(&krdc->bmapmutex);
650 return (-1);
651 }
652
653 if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
654 cmn_err(CE_WARN, "!rdc_read_bitmap: %s reserve failed",
655 urdc->primary.file);
656 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
657 mutex_exit(&krdc->bmapmutex);
658 return (-1);
659 }
660
661 if (krdc->bmp_kstats) {
662 mutex_enter(krdc->bmp_kstats->ks_lock);
663 kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
664 mutex_exit(krdc->bmp_kstats->ks_lock);
665 }
666
667 sts = rdc_ns_io(krdc->bitmapfd, NSC_RDBUF, RDC_BITMAP_FBA,
668 data ? data->data : krdc->dcio_bitmap, krdc->bitmap_size);
669
670 if (krdc->bmp_kstats) {
671 mutex_enter(krdc->bmp_kstats->ks_lock);
672 kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
673 mutex_exit(krdc->bmp_kstats->ks_lock);
674 KSTAT_IO_PTR(krdc->bmp_kstats)->reads++;
675 KSTAT_IO_PTR(krdc->bmp_kstats)->nread += krdc->bitmap_size;
676 }
677
678 _rdc_rlse_devs(krdc, RDC_BMP);
679
680 if (!RDC_SUCCESS(sts)) {
681 cmn_err(CE_WARN, "!rdc_read_bitmap: %s read failed",
682 urdc->primary.file);
683 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "read failed");
684 mutex_exit(&krdc->bmapmutex);
685 return (-1);
686 }
687
688 mutex_exit(&krdc->bmapmutex);
689 return (0);
690 }
691
692 int
693 rdc_write_bitmap(rdc_k_info_t *krdc)
694 {
695 rdc_u_info_t *urdc;
696 int sts;
697
698 if (krdc == NULL) {
699 return (-1);
700 }
701
702 mutex_enter(&krdc->bmapmutex);
703
704 urdc = &rdc_u_info[krdc->index];
705 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
706 mutex_exit(&krdc->bmapmutex);
707 return (-1);
708 }
709
710 if (krdc->bitmapfd == NULL) {
711 mutex_exit(&krdc->bmapmutex);
712 return (-1);
713 }
714
715 if (krdc->dcio_bitmap == NULL) {
716 mutex_exit(&krdc->bmapmutex);
717 return (-1);
718 }
719
720 if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
721 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
722 mutex_exit(&krdc->bmapmutex);
723 return (-1);
724 }
725
726 if (krdc->bmp_kstats) {
727 mutex_enter(krdc->bmp_kstats->ks_lock);
728 kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
729 mutex_exit(krdc->bmp_kstats->ks_lock);
730 }
731
732 sts = rdc_ns_io(krdc->bitmapfd, rdc_wrflag, RDC_BITMAP_FBA,
733 krdc->dcio_bitmap, krdc->bitmap_size);
734
735 if (krdc->bmp_kstats) {
736 mutex_enter(krdc->bmp_kstats->ks_lock);
737 kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
738 mutex_exit(krdc->bmp_kstats->ks_lock);
739 KSTAT_IO_PTR(krdc->bmp_kstats)->writes++;
740 KSTAT_IO_PTR(krdc->bmp_kstats)->nwritten += krdc->bitmap_size;
741 }
742
743 _rdc_rlse_devs(krdc, RDC_BMP);
744
745 if (!RDC_SUCCESS(sts)) {
746 cmn_err(CE_WARN, "!rdc_write_bitmap: %s write failed",
747 urdc->primary.file);
748 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "write failed");
749 mutex_exit(&krdc->bmapmutex);
750 return (-1);
751 }
752
753 mutex_exit(&krdc->bmapmutex);
754 return (0);
755 }
756
757 int
758 rdc_write_bitmap_fba(rdc_k_info_t *krdc, nsc_off_t fba)
759 {
760 rdc_u_info_t *urdc;
761 int sts;
762
763 if (krdc == NULL) {
764 return (-1);
765 }
766
767 mutex_enter(&krdc->bmapmutex);
768
769 urdc = &rdc_u_info[krdc->index];
770 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
771 mutex_exit(&krdc->bmapmutex);
772 return (-1);
773 }
774
775 if (krdc->bitmapfd == NULL) {
776 mutex_exit(&krdc->bmapmutex);
777 return (-1);
778 }
779
780 if (krdc->dcio_bitmap == NULL) {
781 mutex_exit(&krdc->bmapmutex);
782 return (-1);
783 }
784
785 if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
786 cmn_err(CE_WARN, "!rdc_write_bitmap_fba: %s reserve failed",
787 urdc->primary.file);
788 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
789 mutex_exit(&krdc->bmapmutex);
790 return (-1);
791 }
792
793 if (krdc->bmp_kstats) {
794 mutex_enter(krdc->bmp_kstats->ks_lock);
795 kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
796 mutex_exit(krdc->bmp_kstats->ks_lock);
797 }
798 sts = rdc_ns_io(krdc->bitmapfd, rdc_wrflag, RDC_BITMAP_FBA + fba,
799 krdc->dcio_bitmap + fba * 512, 512);
800
801 if (krdc->bmp_kstats) {
802 mutex_enter(krdc->bmp_kstats->ks_lock);
803 kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
804 mutex_exit(krdc->bmp_kstats->ks_lock);
805 KSTAT_IO_PTR(krdc->bmp_kstats)->writes++;
806 KSTAT_IO_PTR(krdc->bmp_kstats)->nwritten += 512;
807 }
808
809 _rdc_rlse_devs(krdc, RDC_BMP);
810
811 if (!RDC_SUCCESS(sts)) {
812 cmn_err(CE_WARN, "!rdc_write_bitmap_fba: %s write failed",
813 urdc->primary.file);
814 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "write failed");
815 mutex_exit(&krdc->bmapmutex);
816 return (-1);
817 }
818
819 mutex_exit(&krdc->bmapmutex);
820 return (0);
821 }
822
823
824 static int
825 rdc_write_bitmap_pattern(rdc_k_info_t *krdc, const char pattern)
826 {
827 rdc_u_info_t *urdc;
828 char *buffer;
829 nsc_buf_t *h;
830 nsc_vec_t *v;
831 int rc;
832 size_t i;
833 nsc_size_t len;
834 int off;
835 size_t buffer_size;
836 size_t iolen;
837 nsc_size_t fba_req;
838 nsc_off_t fba_len, fba_pos;
839 nsc_size_t maxfbas = 0;
840 nsc_size_t tocopy;
841
842 if (krdc == NULL) {
843 return (-1);
844 }
845
846 mutex_enter(&krdc->bmapmutex);
847
848 urdc = &rdc_u_info[krdc->index];
849 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED) {
850 mutex_exit(&krdc->bmapmutex);
851 return (-1);
852 }
853
854 if (krdc->bitmapfd == NULL) {
855 mutex_exit(&krdc->bmapmutex);
856 return (-1);
857 }
858
859 if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
860 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reserve failed");
861 mutex_exit(&krdc->bmapmutex);
862 return (-1);
863 }
864
865 buffer_size = FBA_SIZE(1);
866 ASSERT(buffer_size < INT32_MAX);
867 buffer = kmem_alloc(buffer_size, KM_SLEEP);
868
869 for (i = 0; i < buffer_size; i++) {
870 buffer[i] = pattern;
871 }
872
873 rc = nsc_maxfbas(krdc->bitmapfd, 0, &maxfbas);
874 if (!RDC_SUCCESS(rc)) {
875 #ifdef DEBUG
876 cmn_err(CE_WARN,
877 "!rdc_write_bitmap_pattern: maxfbas failed (%d)", rc);
878 #endif
879 maxfbas = 256;
880 }
881
882 fba_req = FBA_LEN(krdc->bitmap_size); /* total FBAs left to copy */
883 fba_pos = RDC_BITMAP_FBA; /* current FBA position */
884 tocopy = krdc->bitmap_size; /* total bytes left to copy */
885 loop:
886 h = NULL;
887 fba_len = min(fba_req, maxfbas); /* FBAs to alloc this time */
888
889 rc = nsc_alloc_buf(krdc->bitmapfd, fba_pos, fba_len, rdc_wrflag, &h);
890 if (!RDC_SUCCESS(rc)) {
891 cmn_err(CE_WARN, "!rdc_write_bitmap_pattern: %s "
892 "write failed %d", urdc->primary.file, rc);
893 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "nsc_alloc_buf failed");
894 if (h) {
895 (void) nsc_free_handle(h);
896 }
897
898 _rdc_rlse_devs(krdc, RDC_BMP);
899 mutex_exit(&krdc->bmapmutex);
900 rc = -1;
901 goto finish;
902 }
903
904 /* bytes to copy this time */
905 len = min(tocopy, FBA_SIZE(fba_len));
906 v = h->sb_vec;
907 off = 0;
908
909 while (len) {
910 if (off >= v->sv_len) {
911 off = 0;
912 v++;
913 }
914
915 if (v->sv_addr == 0 || v->sv_len == 0) {
916 #ifdef DEBUG
917 cmn_err(CE_WARN,
918 "!rdc_write_bitmap_pattern: ran off end of handle");
919 #endif
920 break;
921 }
922
923 iolen = (size_t)min(len, buffer_size);
924
925 bcopy(buffer, (char *)(v->sv_addr + off), iolen);
926 off += iolen;
927 len -= iolen;
928 }
929
930 rc = nsc_write(h, h->sb_pos, h->sb_len, 0);
931 if (!RDC_SUCCESS(rc)) {
932 cmn_err(CE_WARN, "!rdc_write_bitmap_pattern: "
933 "%s write failed %d", urdc->primary.file, rc);
934 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "write failed");
935 (void) nsc_free_buf(h);
936 _rdc_rlse_devs(krdc, RDC_BMP);
937 mutex_exit(&krdc->bmapmutex);
938 rc = -1;
939 goto finish;
940 }
941
942 (void) nsc_free_buf(h);
943
944 fba_pos += fba_len;
945 fba_req -= fba_len;
946 tocopy -= FBA_SIZE(fba_len); /* adjust byte length remaining */
947 if (fba_req > 0)
948 goto loop;
949
950 _rdc_rlse_devs(krdc, RDC_BMP);
951 mutex_exit(&krdc->bmapmutex);
952 rc = 0;
953 finish:
954 kmem_free(buffer, buffer_size);
955 return (rc);
956 }
957
958
959 /*
960 * rdc_write_bitmap_fill()
961 *
962 * Write a bitmap full of 1's out to disk without touching the
963 * in-memory bitmap.
964 */
965 int
966 rdc_write_bitmap_fill(rdc_k_info_t *krdc)
967 {
968 return (rdc_write_bitmap_pattern(krdc, 0xff));
969 }
970
971
972 void
973 rdc_merge_bitmaps(rdc_k_info_t *src, rdc_k_info_t *dst)
974 {
975 if (src->dcio_bitmap == NULL || dst->dcio_bitmap == NULL)
976 return;
977
978 rdc_lor(src->dcio_bitmap, dst->dcio_bitmap,
979 min(src->bitmap_size, dst->bitmap_size));
980 if (dst->bitmap_write > 0)
981 (void) rdc_write_bitmap(dst);
982 }
983
984
985 /*
986 * bitmap size in bytes, vol_size fba's
987 */
988
989 size_t
990 rdc_ref_size_possible(nsc_size_t bitmap_size, nsc_size_t vol_size)
991 {
992 nsc_size_t ref_size;
993 nsc_size_t bitmap_end_fbas;
994
995 bitmap_end_fbas = RDC_BITMAP_FBA + FBA_LEN(bitmap_size);
996 ref_size = FBA_LEN(bitmap_size * BITS_IN_BYTE * sizeof (unsigned char));
997 if (bitmap_end_fbas + ref_size > vol_size)
998 return ((size_t)0);
999
1000 ref_size = FBA_LEN(bitmap_size * BITS_IN_BYTE * sizeof (unsigned int));
1001 if (bitmap_end_fbas + ref_size > vol_size)
1002 return (sizeof (unsigned char));
1003 return (sizeof (unsigned int));
1004 }
1005
1006 int
1007 rdc_move_bitmap(rdc_k_info_t *krdc, char *newbitmap)
1008 {
1009 rdc_u_info_t *urdc;
1010 nsc_fd_t *oldfd;
1011 nsc_fd_t *newfd = NULL;
1012 rdc_header_t header;
1013 int sts;
1014 nsc_size_t vol_size;
1015 nsc_size_t req_size;
1016 size_t ref_size;
1017
1018 if (krdc == NULL) {
1019 return (-1);
1020 }
1021
1022 if (krdc->bitmapfd == NULL) {
1023 return (-1);
1024 }
1025
1026 req_size = RDC_BITMAP_FBA + FBA_LEN(krdc->bitmap_size);
1027 if (RDC_IS_DISKQ(krdc->group)) {
1028 /* new volume must support at least the old refcntsize */
1029 req_size += FBA_LEN(krdc->bitmap_size * BITS_IN_BYTE *
1030 rdc_refcntsize(krdc));
1031 #ifdef DEBUG_REFCNT
1032 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1033 (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1034 #endif
1035 }
1036
1037 mutex_enter(&krdc->bmapmutex);
1038
1039 if (rdc_read_header(krdc, &header) < 0) {
1040 #ifdef DEBUG
1041 cmn_err(CE_WARN, "!rdc_move_bitmap: Read old header failed");
1042 #endif
1043 mutex_exit(&krdc->bmapmutex);
1044 return (-1);
1045 }
1046
1047 oldfd = krdc->bitmapfd;
1048
1049 newfd = nsc_open(newbitmap, NSC_RDCHR_ID|NSC_FILE|NSC_RDWR, 0, 0, 0);
1050 if (newfd == NULL) {
1051 newfd = nsc_open(newbitmap,
1052 NSC_RDCHR_ID|NSC_CACHE|NSC_DEVICE|NSC_RDWR, 0, 0, 0);
1053 if (newfd == NULL) {
1054 /* Can't open new bitmap */
1055 cmn_err(CE_WARN,
1056 "!rdc_move_bitmap: Cannot open new bitmap %s",
1057 newbitmap);
1058 goto fail;
1059 }
1060 }
1061
1062 sts = nsc_reserve(newfd, 0);
1063 if (!RDC_SUCCESS(sts)) {
1064 cmn_err(CE_WARN, "!rdc_move_bitmap: Reserve failed for %s",
1065 newbitmap);
1066 goto fail;
1067 }
1068 sts = nsc_partsize(newfd, &vol_size);
1069 nsc_release(newfd);
1070
1071 if (!RDC_SUCCESS(sts)) {
1072 cmn_err(CE_WARN,
1073 "!rdc_move_bitmap: nsc_partsize failed for %s", newbitmap);
1074 goto fail;
1075 }
1076
1077 ref_size = rdc_ref_size_possible(krdc->bitmap_size, vol_size);
1078
1079 if (vol_size < req_size) {
1080 cmn_err(CE_WARN,
1081 "!rdc_move_bitmap: bitmap %s too small: %" NSC_SZFMT
1082 " vs %" NSC_SZFMT " blocks", newbitmap, vol_size, req_size);
1083 goto fail;
1084 }
1085
1086 mutex_enter(&krdc->devices->id_rlock);
1087 krdc->bitmapfd = newfd; /* swap under lock */
1088 if (krdc->bmaprsrv > 0) {
1089 sts = nsc_reserve(krdc->bitmapfd, 0);
1090 if (!RDC_SUCCESS(sts)) {
1091 krdc->bitmapfd = oldfd; /* replace under lock */
1092 mutex_exit(&krdc->devices->id_rlock);
1093 cmn_err(CE_WARN,
1094 "!rdc_move_bitmap: Reserve failed for %s",
1095 newbitmap);
1096 goto fail;
1097 }
1098 }
1099 rdc_set_refcnt_ops(krdc, ref_size);
1100 #ifdef DEBUG_REFCNT
1101 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1102 (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1103 #endif
1104 mutex_exit(&krdc->devices->id_rlock);
1105
1106 /* Forget newfd now it is krdc->bitmapfd */
1107 newfd = NULL;
1108
1109 /* Put new bitmap name into header and user-visible data structure */
1110 urdc = &rdc_u_info[krdc->index];
1111 if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
1112 (void) strncpy(header.primary.bitmap, newbitmap, NSC_MAXPATH);
1113 (void) strncpy(urdc->primary.bitmap, newbitmap, NSC_MAXPATH);
1114 } else {
1115 (void) strncpy(header.secondary.bitmap, newbitmap, NSC_MAXPATH);
1116 (void) strncpy(urdc->secondary.bitmap, newbitmap, NSC_MAXPATH);
1117 }
1118
1119 if (rdc_write_header(krdc, &header) < 0) {
1120 cmn_err(CE_WARN,
1121 "!rdc_move_bitmap: Write header %s failed", newbitmap);
1122 goto fail;
1123 }
1124
1125 mutex_exit(&krdc->bmapmutex);
1126
1127 if (rdc_write_bitmap(krdc) < 0) {
1128 mutex_enter(&krdc->bmapmutex);
1129 cmn_err(CE_WARN,
1130 "!rdc_move_bitmap: Write bitmap %s failed", newbitmap);
1131 goto fail;
1132 }
1133
1134 /* Unintercept the old bitmap */
1135 if (krdc->b_tok) {
1136 int rc;
1137
1138 rdc_group_exit(krdc);
1139 rc = nsc_unregister_path(krdc->b_tok, 0);
1140 if (rc)
1141 cmn_err(CE_WARN, "!rdc_move_bitmap: "
1142 "unregister bitmap failed %d", rc);
1143 else
1144 krdc->b_tok = nsc_register_path(newbitmap,
1145 NSC_CACHE | NSC_DEVICE, _rdc_io_hc);
1146 rdc_group_enter(krdc);
1147 }
1148
1149 /* clear the old bitmap header */
1150 bzero(&header, sizeof (header));
1151
1152 sts = nsc_held(oldfd) ? 0 : nsc_reserve(oldfd, 0);
1153 if (sts == 0) {
1154
1155 if (krdc->bmp_kstats) {
1156 mutex_enter(krdc->bmp_kstats->ks_lock);
1157 kstat_runq_enter(KSTAT_IO_PTR(krdc->bmp_kstats));
1158 mutex_exit(krdc->bmp_kstats->ks_lock);
1159 }
1160
1161 sts = rdc_ns_io(oldfd, rdc_wrflag, 0,
1162 (uchar_t *)&header, sizeof (header));
1163
1164 if (krdc->bmp_kstats) {
1165 mutex_enter(krdc->bmp_kstats->ks_lock);
1166 kstat_runq_exit(KSTAT_IO_PTR(krdc->bmp_kstats));
1167 mutex_exit(krdc->bmp_kstats->ks_lock);
1168 KSTAT_IO_PTR(krdc->bmp_kstats)->writes++;
1169 KSTAT_IO_PTR(krdc->bmp_kstats)->nwritten +=
1170 sizeof (header);
1171 }
1172
1173 }
1174 #ifdef DEBUG
1175 if (sts != 0) {
1176 cmn_err(CE_WARN,
1177 "!rdc_move_bitmap: unable to clear bitmap header on %s",
1178 nsc_pathname(oldfd));
1179 }
1180 #endif
1181
1182 /* nsc_close will undo any reservation */
1183 if (nsc_close(oldfd) != 0) {
1184 #ifdef DEBUG
1185 cmn_err(CE_WARN, "!rdc_move_bitmap: close old bitmap failed");
1186 #else
1187 ;
1188 /*EMPTY*/
1189 #endif
1190 }
1191
1192 return (0);
1193
1194 fail:
1195 /* Close newfd if it was unused */
1196 if (newfd && newfd != krdc->bitmapfd) {
1197 (void) nsc_close(newfd);
1198 newfd = NULL;
1199 }
1200
1201 mutex_exit(&krdc->bmapmutex);
1202 return (-1);
1203 }
1204
1205
1206 void
1207 rdc_close_bitmap(rdc_k_info_t *krdc)
1208 {
1209
1210 if (krdc == NULL) {
1211 return;
1212 }
1213
1214 mutex_enter(&krdc->bmapmutex);
1215
1216 if (krdc->bitmapfd) {
1217 if (nsc_close(krdc->bitmapfd) != 0) {
1218 #ifdef DEBUG
1219 cmn_err(CE_WARN, "!nsc_close on bitmap failed");
1220 #else
1221 ;
1222 /*EMPTY*/
1223 #endif
1224 }
1225 krdc->bitmapfd = 0;
1226 }
1227
1228 mutex_exit(&krdc->bmapmutex);
1229 }
1230
1231 void
1232 rdc_free_bitmap(rdc_k_info_t *krdc, int cmd)
1233 {
1234 rdc_header_t header;
1235 rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
1236
1237 if (krdc == NULL) {
1238 return;
1239 }
1240
1241 mutex_enter(&krdc->bmapmutex);
1242
1243 if (cmd != RDC_CMD_SUSPEND) {
1244
1245 bzero((char *)&header, sizeof (rdc_header_t));
1246
1247 if (krdc->bitmapfd)
1248 (void) rdc_write_header(krdc, &header);
1249 } else {
1250 mutex_exit(&krdc->bmapmutex);
1251 /* gotta drop mutex, in case q needs to fail */
1252 if (RDC_IS_DISKQ(krdc->group) && rdc_suspend_diskq(krdc) < 0) {
1253 cmn_err(CE_WARN,
1254 "!rdc_free_bitmap: diskq suspend failed");
1255 }
1256
1257 mutex_enter(&krdc->bmapmutex);
1258 if (rdc_read_header(krdc, &header) < 0) {
1259 cmn_err(CE_WARN,
1260 "!rdc_free_bitmap: Read header failed");
1261 } else {
1262 rdc_fill_header(urdc, &header);
1263
1264 (void) rdc_write_header(krdc, &header);
1265 }
1266 }
1267
1268 mutex_exit(&krdc->bmapmutex);
1269
1270 if (krdc->dcio_bitmap != NULL) {
1271 if (cmd == RDC_CMD_SUSPEND) {
1272 if (krdc->bitmapfd)
1273 (void) rdc_write_bitmap(krdc);
1274 }
1275
1276 kmem_free(krdc->dcio_bitmap, krdc->bitmap_size);
1277 krdc->dcio_bitmap = NULL;
1278 }
1279 if (krdc->bitmap_ref != NULL) {
1280 kmem_free(krdc->bitmap_ref, (krdc->bitmap_size * BITS_IN_BYTE *
1281 BMAP_REF_PREF_SIZE));
1282 krdc->bitmap_ref = NULL;
1283 }
1284
1285 krdc->bitmap_size = 0;
1286 }
1287
1288 static int
1289 rdc_alloc_bitmap(rdc_k_info_t *krdc)
1290 {
1291 rdc_u_info_t *urdc;
1292 char *bitmapname;
1293 nsc_size_t bitmap_ref_size;
1294
1295 if (krdc == NULL) {
1296 return (-1);
1297 }
1298
1299 urdc = &rdc_u_info[krdc->index];
1300 if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1301 bitmapname = &urdc->primary.bitmap[0];
1302 else
1303 bitmapname = &urdc->secondary.bitmap[0];
1304
1305 if (krdc->dcio_bitmap) {
1306 #ifdef DEBUG
1307 cmn_err(CE_WARN,
1308 "!rdc_alloc_bitmap: bitmap %s already allocated",
1309 bitmapname);
1310 #endif
1311 return (0);
1312 }
1313
1314 if (urdc->volume_size == 0)
1315 return (-1);
1316
1317 krdc->bitmap_size = BMAP_LOG_BYTES(urdc->volume_size);
1318 /* Round up */
1319 krdc->bitmap_size = (krdc->bitmap_size + 511) / 512 * 512;
1320
1321 krdc->dcio_bitmap = (uchar_t *)kmem_zalloc(krdc->bitmap_size,
1322 KM_SLEEP);
1323 if (krdc->dcio_bitmap == NULL) {
1324 cmn_err(CE_WARN, "!rdc_alloc_bitmap: alloc %" NSC_SZFMT
1325 " failed for %s", krdc->bitmap_size, bitmapname);
1326 return (-1);
1327 }
1328
1329 /*
1330 * use largest ref count type size as we haven't opened the bitmap
1331 * volume yet to find out what has acutally be used.
1332 */
1333 bitmap_ref_size = krdc->bitmap_size * BITS_IN_BYTE * BMAP_REF_PREF_SIZE;
1334 if ((rdc_get_vflags(urdc) & RDC_PRIMARY) &&
1335 ((krdc->type_flag & RDC_ASYNCMODE) != 0)) {
1336 krdc->bitmap_ref = (uchar_t *)kmem_zalloc(bitmap_ref_size,
1337 KM_SLEEP);
1338 if (krdc->bitmap_ref == NULL) {
1339 cmn_err(CE_WARN,
1340 "!rdc_alloc_bitmap: ref alloc %" NSC_SZFMT
1341 " failed for %s",
1342 bitmap_ref_size, bitmapname);
1343 return (-1);
1344 }
1345 }
1346
1347 return (0);
1348 }
1349
1350
1351 static int
1352 rdc_open_bitmap(rdc_k_info_t *krdc)
1353 {
1354 rdc_u_info_t *urdc;
1355 int sts;
1356 uint_t hints = 0;
1357 nsc_size_t vol_size;
1358 char *bitmapname;
1359 nsc_size_t req_size;
1360 nsc_size_t bit_size;
1361
1362 urdc = &rdc_u_info[krdc->index];
1363 if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1364 bitmapname = &urdc->primary.bitmap[0];
1365 else
1366 bitmapname = &urdc->secondary.bitmap[0];
1367
1368 urdc->bits_set = 0;
1369
1370 bit_size = req_size = RDC_BITMAP_FBA + FBA_LEN(krdc->bitmap_size);
1371 if (RDC_IS_DISKQ(krdc->group)) {
1372 req_size += FBA_LEN(krdc->bitmap_size * BITS_IN_BYTE *
1373 sizeof (unsigned char));
1374 }
1375
1376 mutex_enter(&krdc->bmapmutex);
1377
1378 rdc_set_refcnt_ops(krdc, sizeof (unsigned char));
1379 #ifdef DEBUG_REFCNT
1380 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1381 (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1382 #endif
1383 if (krdc->bitmapfd == NULL)
1384 krdc->bitmapfd = nsc_open(bitmapname,
1385 NSC_RDCHR_ID|NSC_FILE|NSC_RDWR, 0, 0, 0);
1386 if (krdc->bitmapfd == NULL) {
1387 krdc->bitmapfd = nsc_open(bitmapname,
1388 NSC_RDCHR_ID|NSC_CACHE|NSC_DEVICE|NSC_RDWR, 0, 0, 0);
1389 if (krdc->bitmapfd == NULL) {
1390 cmn_err(CE_WARN, "!rdc_open_bitmap: Unable to open %s",
1391 bitmapname);
1392 goto fail;
1393 }
1394 }
1395
1396 sts = _rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL);
1397 if (!RDC_SUCCESS(sts)) {
1398 cmn_err(CE_WARN, "!rdc_open_bitmap: Reserve failed for %s",
1399 bitmapname);
1400 goto fail;
1401 }
1402 sts = nsc_partsize(krdc->bitmapfd, &vol_size);
1403 _rdc_rlse_devs(krdc, RDC_BMP);
1404
1405 if (!RDC_SUCCESS(sts)) {
1406 cmn_err(CE_WARN,
1407 "!rdc_open_bitmap: nsc_partsize failed for %s", bitmapname);
1408 goto fail;
1409 }
1410
1411 if (vol_size < req_size) {
1412 /* minimum size supports unsigned char reference counts */
1413 cmn_err(CE_WARN,
1414 "!rdc_open_bitmap: bitmap %s too small: %" NSC_SZFMT " vs %"
1415 NSC_SZFMT "blocks",
1416 bitmapname, vol_size, req_size);
1417 goto fail;
1418 }
1419
1420 if (rdc_bitmap_mode == RDC_BMP_NEVER) {
1421 krdc->bitmap_write = 0; /* forced off */
1422 } else if (rdc_bitmap_mode == RDC_BMP_ALWAYS ||
1423 (nsc_node_hints(&hints) == 0 && (hints & NSC_FORCED_WRTHRU) == 0)) {
1424 krdc->bitmap_write = 1; /* forced or autodetect on */
1425 } else {
1426 /* autodetect off */
1427 krdc->bitmap_write = 0;
1428 }
1429
1430 mutex_exit(&krdc->bmapmutex);
1431 if (RDC_IS_DISKQ(krdc->group) && (rdc_refcntsize(krdc) <
1432 BMAP_REF_PREF_SIZE)) {
1433 /* test for larger ref counts */
1434 #ifdef DEBUG_REFCNT
1435 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1436 (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1437 #endif
1438 req_size = bit_size;
1439 req_size += FBA_LEN(krdc->bitmap_size * BITS_IN_BYTE *
1440 sizeof (unsigned int));
1441 if (vol_size >= req_size)
1442 rdc_set_refcnt_ops(krdc, sizeof (unsigned int));
1443 }
1444 #ifdef DEBUG_REFCNT
1445 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1446 (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1447 #endif
1448 return (0);
1449
1450 fail:
1451 mutex_exit(&krdc->bmapmutex);
1452 return (-1);
1453 }
1454
1455 int
1456 rdc_enable_bitmap(rdc_k_info_t *krdc, int set)
1457 {
1458 rdc_header_t header;
1459 rdc_u_info_t *urdc;
1460 char *bitmapname;
1461
1462 urdc = &rdc_u_info[krdc->index];
1463
1464 if (rdc_alloc_bitmap(krdc) < 0)
1465 goto fail;
1466
1467 if (rdc_open_bitmap(krdc) < 0)
1468 goto fail;
1469
1470 if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1471 bitmapname = &urdc->primary.bitmap[0];
1472 else
1473 bitmapname = &urdc->secondary.bitmap[0];
1474
1475 mutex_enter(&krdc->bmapmutex);
1476
1477 rdc_clr_flags(urdc, RDC_BMP_FAILED);
1478 if (rdc_read_header(krdc, &header) < 0) {
1479 cmn_err(CE_WARN,
1480 "!rdc_enable_bitmap: Read header %s failed", bitmapname);
1481 mutex_exit(&krdc->bmapmutex);
1482 goto fail;
1483 }
1484
1485 rdc_fill_header(urdc, &header);
1486 rdc_set_refcnt_ops(krdc, (size_t)header.refcntsize);
1487
1488 if (set)
1489 (void) RDC_FILL_BITMAP(krdc, FALSE);
1490
1491 if (rdc_write_header(krdc, &header) < 0) {
1492 cmn_err(CE_WARN,
1493 "!rdc_enable_bitmap: Write header %s failed",
1494 bitmapname);
1495 mutex_exit(&krdc->bmapmutex);
1496 goto fail;
1497 }
1498 mutex_exit(&krdc->bmapmutex);
1499
1500 if (rdc_write_bitmap(krdc) < 0) {
1501 cmn_err(CE_WARN,
1502 "!rdc_enable_bitmap: Write bitmap %s failed",
1503 bitmapname);
1504 goto fail;
1505 }
1506
1507 return (0);
1508
1509 fail:
1510 rdc_free_bitmap(krdc, RDC_CMD_ENABLE);
1511 rdc_close_bitmap(krdc);
1512
1513 mutex_enter(&krdc->bmapmutex);
1514 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "I/O failed");
1515 mutex_exit(&krdc->bmapmutex);
1516 return (-1);
1517 }
1518
1519 static int
1520 _rdc_rdwr_refcnt(rdc_k_info_t *krdc, int rwflg)
1521 {
1522 rdc_u_info_t *urdc;
1523 int rc;
1524 nsc_off_t offset;
1525 nsc_size_t len;
1526
1527 urdc = &rdc_u_info[krdc->index];
1528
1529 #ifdef DEBUG_REFCNT
1530 cmn_err(CE_NOTE, "!rdc_rdwr_refcnt: %s refcount for %s",
1531 (rwflg == NSC_READ) ? "resuming" : "writing",
1532 urdc->primary.bitmap);
1533 #endif
1534 ASSERT(MUTEX_HELD(QLOCK((&krdc->group->diskq))));
1535 mutex_enter(&krdc->bmapmutex);
1536
1537 if (_rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL)) {
1538 cmn_err(CE_WARN, "!rdc_rdwr_refcnt: reserve failed");
1539 goto fail;
1540 }
1541
1542 if (krdc->bitmap_size == 0) {
1543 cmn_err(CE_WARN, "!rdc_rdwr_refcnt: NULL bitmap!");
1544 goto fail;
1545 }
1546
1547 offset = RDC_BITREF_FBA(krdc);
1548 len = krdc->bitmap_size * BITS_IN_BYTE * rdc_refcntsize(krdc);
1549
1550 rc = rdc_ns_io(krdc->bitmapfd, rwflg, offset,
1551 (uchar_t *)krdc->bitmap_ref, len);
1552
1553 if (!RDC_SUCCESS(rc)) {
1554 cmn_err(CE_WARN, "!unable to %s refcount from bitmap %s",
1555 (rwflg == NSC_READ) ? "retrieve" : "write",
1556 urdc->primary.bitmap);
1557 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "refcount I/O failed");
1558 goto fail;
1559 }
1560
1561 _rdc_rlse_devs(krdc, RDC_BMP);
1562
1563 mutex_exit(&krdc->bmapmutex);
1564
1565 #ifdef DEBUG_REFCNT
1566 cmn_err(CE_NOTE, "!rdc_rdwr_refcnt: %s refcount for %s",
1567 (rwflg == NSC_READ) ? "resumed" : "wrote",
1568 urdc->primary.bitmap);
1569 #endif
1570 return (0);
1571
1572 fail:
1573 _rdc_rlse_devs(krdc, RDC_BMP);
1574
1575 mutex_exit(&krdc->bmapmutex);
1576
1577 return (-1);
1578
1579 }
1580
1581 /*
1582 * rdc_read_refcount
1583 * read the stored refcount from disk
1584 * queue lock is held
1585 */
1586 int
1587 rdc_read_refcount(rdc_k_info_t *krdc)
1588 {
1589 int rc;
1590
1591 rc = _rdc_rdwr_refcnt(krdc, NSC_READ);
1592
1593 return (rc);
1594 }
1595
1596 /*
1597 * rdc_write_refcount
1598 * writes krdc->bitmap_ref to the diskq
1599 * called with qlock held
1600 */
1601 int
1602 rdc_write_refcount(rdc_k_info_t *krdc)
1603 {
1604 int rc;
1605
1606 rc = _rdc_rdwr_refcnt(krdc, NSC_WRBUF);
1607
1608 return (rc);
1609 }
1610
1611 static int
1612 rdc_resume_state(rdc_k_info_t *krdc, const rdc_header_t *header)
1613 {
1614 rdc_u_info_t *urdc;
1615 char *bitmapname;
1616
1617 urdc = &rdc_u_info[krdc->index];
1618 if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1619 bitmapname = &urdc->primary.bitmap[0];
1620 else
1621 bitmapname = &urdc->secondary.bitmap[0];
1622
1623 if (header->magic != RDC_HDR_MAGIC) {
1624 cmn_err(CE_WARN, "!rdc_resume_state: Bad magic in %s",
1625 bitmapname);
1626 return (-1);
1627 }
1628
1629 if (strncmp(urdc->primary.file, header->primary.file,
1630 NSC_MAXPATH) != 0) {
1631 #ifdef DEBUG
1632 cmn_err(CE_WARN,
1633 "!rdc_resume_state: Found %s Expected %s",
1634 header->primary.file, urdc->primary.file);
1635 #endif /* DEBUG */
1636 return (-1);
1637 }
1638
1639 if (strncmp(urdc->secondary.file, header->secondary.file,
1640 NSC_MAXPATH) != 0) {
1641 #ifdef DEBUG
1642 cmn_err(CE_WARN,
1643 "!rdc_resume_state: Found %s Expected %s",
1644 header->secondary.file, urdc->secondary.file);
1645 #endif /* DEBUG */
1646 return (-1);
1647 }
1648
1649 if (strncmp(urdc->primary.bitmap, header->primary.bitmap,
1650 NSC_MAXPATH) != 0) {
1651 #ifdef DEBUG
1652 cmn_err(CE_WARN,
1653 "!rdc_resume_state: Found %s Expected %s",
1654 header->primary.bitmap, urdc->primary.bitmap);
1655 #endif /* DEBUG */
1656 return (-1);
1657 }
1658
1659 if (strncmp(urdc->secondary.bitmap, header->secondary.bitmap,
1660 NSC_MAXPATH) != 0) {
1661 #ifdef DEBUG
1662 cmn_err(CE_WARN,
1663 "!rdc_resume_state: Found %s Expected %s",
1664 header->secondary.bitmap, urdc->secondary.bitmap);
1665 #endif /* DEBUG */
1666 return (-1);
1667 }
1668
1669 if (header->maxqfbas)
1670 urdc->maxqfbas = header->maxqfbas;
1671
1672 if (header->maxqitems)
1673 urdc->maxqitems = header->maxqitems;
1674
1675 if (header->autosync >= 0)
1676 urdc->autosync = header->autosync;
1677
1678 if (header->asyncthr)
1679 urdc->asyncthr = header->asyncthr;
1680
1681 rdc_many_enter(krdc);
1682 rdc_set_refcnt_ops(krdc, header->refcntsize);
1683 #ifdef DEBUG_REFCNT
1684 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1685 (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1686 #endif
1687 if (header->flags & RDC_VOL_FAILED)
1688 rdc_set_flags(urdc, RDC_VOL_FAILED);
1689 if (header->flags & RDC_QUEUING)
1690 rdc_set_flags(urdc, RDC_QUEUING);
1691
1692 rdc_clr_flags(urdc, RDC_SYNC_NEEDED | RDC_RSYNC_NEEDED);
1693 rdc_set_mflags(urdc, (header->flags & RDC_RSYNC_NEEDED));
1694 rdc_set_flags(urdc, (header->flags & RDC_SYNC_NEEDED));
1695 rdc_many_exit(krdc);
1696
1697 if (urdc->flags & RDC_VOL_FAILED) {
1698
1699 /* Our disk was failed so set all the bits in the bitmap */
1700
1701 if (RDC_FILL_BITMAP(krdc, TRUE) != 0) {
1702 cmn_err(CE_WARN,
1703 "!rdc_resume_state: Fill bitmap %s failed",
1704 bitmapname);
1705 return (-1);
1706 }
1707 rdc_many_enter(krdc);
1708 if (IS_STATE(urdc, RDC_QUEUING))
1709 rdc_clr_flags(urdc, RDC_QUEUING);
1710 rdc_many_exit(krdc);
1711 } else {
1712 /* Header was good, so read in the bitmap */
1713
1714 if (rdc_read_bitmap(krdc, NULL) < 0) {
1715 cmn_err(CE_WARN,
1716 "!rdc_resume_state: Read bitmap %s failed",
1717 bitmapname);
1718 return (-1);
1719 }
1720
1721 urdc->bits_set = RDC_COUNT_BITMAP(krdc);
1722
1723 /*
1724 * Check if another node went down with bits set, but
1725 * without setting logging mode.
1726 */
1727 if (urdc->bits_set != 0 &&
1728 (rdc_get_vflags(urdc) & RDC_ENABLED) &&
1729 !(rdc_get_vflags(urdc) & RDC_LOGGING)) {
1730 rdc_group_log(krdc, RDC_NOFLUSH | RDC_NOREMOTE, NULL);
1731 }
1732 }
1733
1734 /* if we are using a disk queue, read in the reference count bits */
1735 if (RDC_IS_DISKQ(krdc->group)) {
1736 disk_queue *q = &krdc->group->diskq;
1737 mutex_enter(QLOCK(q));
1738 if ((rdc_read_refcount(krdc) < 0)) {
1739 cmn_err(CE_WARN,
1740 "!rdc_resume_state: Resume bitmap %s's refcount"
1741 "failed",
1742 urdc->primary.bitmap);
1743 mutex_exit(QLOCK(q));
1744 rdc_many_enter(krdc);
1745 if (IS_STATE(urdc, RDC_QUEUING))
1746 rdc_clr_flags(urdc, RDC_QUEUING);
1747 rdc_many_exit(krdc);
1748 return (-1);
1749 }
1750 mutex_exit(QLOCK(q));
1751 }
1752
1753 return (0);
1754 }
1755
1756
1757 int
1758 rdc_resume_bitmap(rdc_k_info_t *krdc)
1759 {
1760 rdc_header_t header;
1761 rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
1762 char *bitmapname;
1763
1764 if (rdc_alloc_bitmap(krdc) < 0)
1765 goto allocfail;
1766
1767 if (rdc_open_bitmap(krdc) < 0)
1768 goto fail;
1769
1770 if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1771 bitmapname = &urdc->primary.bitmap[0];
1772 else
1773 bitmapname = &urdc->secondary.bitmap[0];
1774
1775 mutex_enter(&krdc->bmapmutex);
1776
1777 rdc_clr_flags(urdc, RDC_BMP_FAILED);
1778 if (rdc_read_header(krdc, &header) < 0) {
1779 cmn_err(CE_WARN,
1780 "!rdc_resume_bitmap: Read header %s failed", bitmapname);
1781 mutex_exit(&krdc->bmapmutex);
1782 goto fail;
1783 }
1784
1785 mutex_exit(&krdc->bmapmutex);
1786
1787 /* Resuming from the bitmap, so do some checking */
1788
1789 /*CONSTCOND*/
1790 ASSERT(FBA_LEN(sizeof (rdc_header_t)) <= RDC_BITMAP_FBA);
1791 /*CONSTCOND*/
1792 ASSERT(sizeof (rdc_header_t) >= sizeof (rdc_headerv2_t));
1793
1794 if (header.magic == RDC_HDR_V2) {
1795 rdc_headerv2_t *hdr_v2 = (rdc_headerv2_t *)&header;
1796 rdc_header_t new_header;
1797
1798 #ifdef DEBUG
1799 cmn_err(CE_WARN,
1800 "!rdc_resume_bitmap: Converting v2 header for bitmap %s",
1801 bitmapname);
1802 #endif
1803 bzero((char *)&new_header, sizeof (rdc_header_t));
1804
1805 new_header.autosync = -1;
1806 new_header.magic = RDC_HDR_MAGIC;
1807 new_header.syshostid = urdc->syshostid;
1808
1809 if (hdr_v2->volume_failed)
1810 new_header.flags |= RDC_VOL_FAILED;
1811 if (hdr_v2->sync_needed == RDC_SYNC)
1812 new_header.flags |= RDC_SYNC_NEEDED;
1813 if (hdr_v2->sync_needed == RDC_FULL_SYNC)
1814 new_header.flags |= RDC_SYNC_NEEDED;
1815 if (hdr_v2->sync_needed == RDC_REV_SYNC)
1816 new_header.flags |= RDC_RSYNC_NEEDED;
1817 if (rdc_get_vflags(urdc) & RDC_PRIMARY) {
1818 (void) strncpy(new_header.primary.file,
1819 hdr_v2->filename, NSC_MAXPATH);
1820 (void) strncpy(new_header.primary.bitmap,
1821 hdr_v2->bitmapname, NSC_MAXPATH);
1822 (void) strncpy(new_header.secondary.file,
1823 urdc->secondary.file, NSC_MAXPATH);
1824 (void) strncpy(new_header.secondary.bitmap,
1825 urdc->secondary.bitmap, NSC_MAXPATH);
1826 } else {
1827 (void) strncpy(new_header.secondary.file,
1828 hdr_v2->filename, NSC_MAXPATH);
1829 (void) strncpy(new_header.secondary.bitmap,
1830 hdr_v2->bitmapname, NSC_MAXPATH);
1831 (void) strncpy(new_header.primary.file,
1832 urdc->primary.file, NSC_MAXPATH);
1833 (void) strncpy(new_header.primary.bitmap,
1834 urdc->primary.bitmap, NSC_MAXPATH);
1835 }
1836
1837 bcopy(&new_header, &header, sizeof (rdc_header_t));
1838
1839 mutex_enter(&krdc->bmapmutex);
1840 if (rdc_write_header(krdc, &header) < 0) {
1841 mutex_exit(&krdc->bmapmutex);
1842 cmn_err(CE_WARN,
1843 "!rdc_resume_bitmap: Write header %s failed",
1844 bitmapname);
1845 goto fail;
1846 }
1847 mutex_exit(&krdc->bmapmutex);
1848
1849 } else if (header.magic == RDC_HDR_V3) {
1850 /*
1851 * just update asyncthr and magic, and then we're done
1852 */
1853 header.magic = RDC_HDR_MAGIC;
1854 header.asyncthr = RDC_ASYNCTHR;
1855 mutex_enter(&krdc->bmapmutex);
1856 if (rdc_write_header(krdc, &header) < 0) {
1857 mutex_exit(&krdc->bmapmutex);
1858 cmn_err(CE_WARN,
1859 "!rdc_resume_bitmap: Write header %s failed",
1860 bitmapname);
1861 goto fail;
1862 }
1863 mutex_exit(&krdc->bmapmutex);
1864 }
1865
1866 if (rdc_resume_state(krdc, &header) == 0)
1867 return (0);
1868
1869 rdc_close_bitmap(krdc);
1870
1871 fail:
1872 (void) RDC_FILL_BITMAP(krdc, FALSE);
1873 rdc_clr_flags(urdc, RDC_QUEUING);
1874 if (krdc->bitmap_ref)
1875 bzero(krdc->bitmap_ref, krdc->bitmap_size * BITS_IN_BYTE *
1876 rdc_refcntsize(krdc));
1877
1878 allocfail:
1879 mutex_enter(&krdc->bmapmutex);
1880 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "resume bitmap failed");
1881 mutex_exit(&krdc->bmapmutex);
1882
1883 return (-1);
1884 }
1885
1886 void
1887 rdc_std_zero_bitref(rdc_k_info_t *krdc)
1888 {
1889 nsc_size_t vol_size;
1890 int sts;
1891 size_t newrefcntsize;
1892
1893 if (krdc->bitmap_ref) {
1894 mutex_enter(&krdc->bmapmutex);
1895 bzero(krdc->bitmap_ref, krdc->bitmap_size * BITS_IN_BYTE *
1896 BMAP_REF_PREF_SIZE);
1897 if (RDC_IS_DISKQ(krdc->group) && rdc_refcntsize(krdc) !=
1898 BMAP_REF_PREF_SIZE) {
1899 /* see if we can upgrade the size of the ref counters */
1900 sts = _rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL);
1901 if (!RDC_SUCCESS(sts)) {
1902 goto nochange;
1903 }
1904 sts = nsc_partsize(krdc->bitmapfd, &vol_size);
1905
1906 newrefcntsize = rdc_ref_size_possible(krdc->bitmap_size,
1907 vol_size);
1908 if (newrefcntsize > rdc_refcntsize(krdc)) {
1909 rdc_set_refcnt_ops(krdc, newrefcntsize);
1910 #ifdef DEBUG_REFCNT
1911 cmn_err(CE_NOTE, "!sndr: refcntsize %d - %d:%s",
1912 (int)rdc_refcntsize(krdc), __LINE__, __FILE__);
1913 #endif
1914 }
1915 nochange:
1916 _rdc_rlse_devs(krdc, RDC_BMP);
1917 }
1918 mutex_exit(&krdc->bmapmutex);
1919 }
1920 }
1921
1922 int
1923 rdc_reset_bitmap(rdc_k_info_t *krdc)
1924 {
1925 rdc_u_info_t *urdc;
1926 rdc_header_t header;
1927 char *bitmapname;
1928
1929 urdc = &rdc_u_info[krdc->index];
1930 if (rdc_get_vflags(urdc) & RDC_PRIMARY)
1931 bitmapname = &urdc->primary.bitmap[0];
1932 else
1933 bitmapname = &urdc->secondary.bitmap[0];
1934
1935 mutex_enter(&krdc->bmapmutex);
1936
1937 rdc_clr_flags(urdc, RDC_BMP_FAILED);
1938 if (rdc_read_header(krdc, &header) < 0) {
1939 cmn_err(CE_WARN,
1940 "!rdc_reset_bitmap: Read header %s failed", bitmapname);
1941 goto fail_with_mutex;
1942 }
1943
1944 rdc_fill_header(urdc, &header);
1945
1946 if (rdc_write_header(krdc, &header) < 0) {
1947 cmn_err(CE_WARN,
1948 "!rdc_reset_bitmap: Write header %s failed",
1949 bitmapname);
1950 goto fail_with_mutex;
1951 }
1952 mutex_exit(&krdc->bmapmutex);
1953
1954 if (krdc->bitmap_write == -1)
1955 krdc->bitmap_write = 0;
1956
1957 if (krdc->bitmap_write == 0) {
1958 if (rdc_write_bitmap_fill(krdc) < 0) {
1959 cmn_err(CE_WARN,
1960 "!rdc_reset_bitmap: Write bitmap %s failed",
1961 bitmapname);
1962 goto fail;
1963 }
1964 krdc->bitmap_write = -1;
1965 } else if (rdc_write_bitmap(krdc) < 0) {
1966 cmn_err(CE_WARN,
1967 "!rdc_reset_bitmap: Write bitmap %s failed",
1968 bitmapname);
1969 goto fail;
1970 }
1971
1972 return (0);
1973
1974 fail:
1975 mutex_enter(&krdc->bmapmutex);
1976 fail_with_mutex:
1977 rdc_set_flags_log(urdc, RDC_BMP_FAILED, "reset failed");
1978 mutex_exit(&krdc->bmapmutex);
1979 #ifdef DEBUG
1980 cmn_err(CE_NOTE, "!SNDR: unable to reset bitmap for %s:%s",
1981 urdc->secondary.intf, urdc->secondary.file);
1982 #endif
1983 return (-1);
1984 }
1985
1986
1987 /*
1988 * General bitmap operations
1989 */
1990
1991 /*
1992 * rdc_set_bitmap_many()
1993 *
1994 * Used during reverse syncs to a 1-to-many primary to keep the 'many'
1995 * bitmaps up to date.
1996 */
1997 void
1998 rdc_set_bitmap_many(rdc_k_info_t *krdc, nsc_off_t pos, nsc_size_t len)
1999 {
2000 uint_t dummy;
2001
2002 #ifdef DEBUG
2003 rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2004 if (!(rdc_get_vflags(urdc) & RDC_PRIMARY)) {
2005 cmn_err(CE_PANIC, "rdc_set_bitmap_many: not primary, urdc %p",
2006 (void *) urdc);
2007 }
2008 #endif
2009
2010 if (IS_MANY(krdc)) {
2011 rdc_k_info_t *krd;
2012 rdc_u_info_t *urd;
2013
2014 rdc_many_enter(krdc);
2015
2016 for (krd = krdc->many_next; krd != krdc; krd = krd->many_next) {
2017 urd = &rdc_u_info[krd->index];
2018 if (!IS_ENABLED(urd))
2019 continue;
2020 ASSERT(urd->flags & RDC_PRIMARY);
2021 (void) RDC_SET_BITMAP(krd, pos, len, &dummy);
2022 }
2023
2024 rdc_many_exit(krdc);
2025 }
2026 }
2027
2028
2029 static int
2030 _rdc_net_bmap(const struct bmap6 *b6, net_bdata6 *bd6)
2031 {
2032 rdc_k_info_t *krdc = &rdc_k_info[b6->cd];
2033 struct timeval t;
2034 int e, ret;
2035 uint64_t left;
2036 uint64_t bmap_blksize;
2037
2038 bmap_blksize = krdc->rpc_version < RDC_VERSION7 ?
2039 BMAP_BLKSIZE : BMAP_BLKSIZEV7;
2040
2041 t.tv_sec = rdc_rpc_tmout;
2042 t.tv_usec = 0;
2043
2044 if (bd6->data.data_val == NULL) {
2045 return (EINVAL);
2046 }
2047
2048 left = b6->size;
2049 bd6->endoblk = 0;
2050 while (left) {
2051 if (left >= bmap_blksize)
2052 bd6->size = (int)bmap_blksize;
2053 else
2054 bd6->size = (int)left;
2055
2056 bd6->data.data_len = bd6->size;
2057
2058 if ((uint64_t)bd6->size > left) {
2059 left = 0;
2060 } else {
2061 left -= bd6->size;
2062 }
2063 /*
2064 * mark the last block sent.
2065 */
2066 if (left == 0) {
2067 bd6->endoblk = 1;
2068 }
2069 ASSERT(krdc->rpc_version);
2070 if (krdc->rpc_version <= RDC_VERSION5) {
2071 struct net_bdata bd;
2072 bd.cd = bd6->cd;
2073 bd.offset = bd6->offset;
2074 bd.size = bd6->size;
2075 bd.data.data_len = bd6->data.data_len;
2076 bd.data.data_val = bd6->data.data_val;
2077 e = rdc_clnt_call(krdc->lsrv, RDCPROC_BDATA,
2078 krdc->rpc_version, xdr_net_bdata, (char *)&bd,
2079 xdr_int, (char *)&ret, &t);
2080 } else {
2081 e = rdc_clnt_call(krdc->lsrv, RDCPROC_BDATA6,
2082 krdc->rpc_version, xdr_net_bdata6, (char *)bd6,
2083 xdr_int, (char *)&ret, &t);
2084 }
2085 if (e || ret) {
2086 if (e)
2087 ret = e;
2088 return (ret);
2089 }
2090 bd6->offset += bmap_blksize;
2091 bd6->data.data_val += bmap_blksize;
2092 }
2093 return (0);
2094 }
2095
2096
2097 /*
2098 * Standard bitmap operations (combined kmem/disk bitmaps).
2099 */
2100
2101 /*
2102 * rdc_std_set_bitmask(pos, len, &bitmask)
2103 * set a bitmask for this range. used to clear the correct
2104 * bits after flushing
2105 */
2106 static void
2107 rdc_std_set_bitmask(const nsc_off_t fba_pos, const nsc_size_t fba_len,
2108 uint_t *bitmask)
2109 {
2110 int first, st, en;
2111 if (bitmask)
2112 *bitmask = 0;
2113 else
2114 return;
2115
2116 first = st = FBA_TO_LOG_NUM(fba_pos);
2117 en = FBA_TO_LOG_NUM(fba_pos + fba_len - 1);
2118 while (st <= en) {
2119 BMAP_BIT_SET((uchar_t *)bitmask, st - first);
2120 st++;
2121 }
2122
2123 }
2124 /*
2125 * rdc_std_set_bitmap(krdc, fba_pos, fba_len, &bitmask)
2126 *
2127 * Mark modified segments in the dual copy file bitmap
2128 * to provide fast recovery
2129 * Note that bitmask allows for 32 segments, which at 32k per segment equals
2130 * 1 megabyte. If we ever allow more than this to be transferred in one
2131 * operation, or decrease the segment size, then this code will have to be
2132 * changed accordingly.
2133 */
2134
2135 static int
2136 rdc_std_set_bitmap(rdc_k_info_t *krdc, const nsc_off_t fba_pos,
2137 const nsc_size_t fba_len, uint_t *bitmask)
2138 {
2139 int first, st, en;
2140 int fbaset = 0;
2141 nsc_off_t fba = 0;
2142 int printerr = 10;
2143 int tries = RDC_FUTILE_ATTEMPTS;
2144 int queuing = RDC_QUEUING;
2145 rdc_u_info_t *urdc;
2146
2147 if (bitmask)
2148 *bitmask = 0;
2149 else
2150 return (-1);
2151
2152 urdc = &rdc_u_info[krdc->index];
2153 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED)
2154 return (-1);
2155
2156 if (krdc->bitmap_write == 0) {
2157 if (rdc_write_bitmap_fill(krdc) < 0)
2158 return (-1);
2159 krdc->bitmap_write = -1;
2160 }
2161 first = st = FBA_TO_LOG_NUM(fba_pos);
2162 en = FBA_TO_LOG_NUM(fba_pos + fba_len - 1);
2163 ASSERT(st <= en);
2164 while (st <= en) {
2165 int use_ref;
2166 again:
2167 mutex_enter(&krdc->bmapmutex);
2168
2169 if (krdc->dcio_bitmap == NULL) {
2170 #ifdef DEBUG
2171 cmn_err(CE_WARN, "!rdc_std_set_bitmap: "
2172 "recovery bitmaps not allocated");
2173 #endif
2174 mutex_exit(&krdc->bmapmutex);
2175 return (-1);
2176 }
2177
2178 use_ref = IS_PRIMARY(urdc) && IS_ASYNC(urdc) &&
2179 ((rdc_get_vflags(urdc) & RDC_QUEUING) ||
2180 !(rdc_get_vflags(urdc) & RDC_LOGGING));
2181
2182
2183 if (!BMAP_BIT_ISSET(krdc->dcio_bitmap, st)) {
2184 BMAP_BIT_SET(krdc->dcio_bitmap, st);
2185 if (use_ref) {
2186 ASSERT(BMAP_REF_ISSET(krdc, st) ==
2187 0);
2188 BMAP_REF_FORCE(krdc, st, 1);
2189 }
2190 BMAP_BIT_SET((uchar_t *)bitmask, st - first);
2191 urdc->bits_set++;
2192 if ((!fbaset) || fba != BIT_TO_FBA(st)) {
2193 if (fbaset && krdc->bitmap_write > 0) {
2194 mutex_exit(&krdc->bmapmutex);
2195 if (rdc_write_bitmap_fba(krdc, fba) < 0)
2196 return (-1);
2197 mutex_enter(&krdc->bmapmutex);
2198 }
2199 fba = BIT_TO_FBA(st);
2200 fbaset = 1;
2201 }
2202 } else {
2203 /*
2204 * Just bump reference count
2205 * For logging or syncing we do not care what the reference
2206 * is as it will be forced back on the state transition.
2207 */
2208 if (use_ref) {
2209 if (BMAP_REF_ISSET(krdc, st) ==
2210 BMAP_REF_MAXVAL(krdc)) {
2211 /*
2212 * Rollover of reference count.
2213 */
2214
2215 if (!(rdc_get_vflags(urdc) &
2216 RDC_VOL_FAILED)) {
2217 /*
2218 * Impose throttle to help dump
2219 * queue
2220 */
2221 mutex_exit(&krdc->bmapmutex);
2222 delay(4);
2223 rdc_bitmap_delay++;
2224 if (printerr--) {
2225 cmn_err(CE_WARN, "!SNDR: bitmap reference count maxed out for %s:%s",
2226 urdc->secondary.intf, urdc->secondary.file);
2227
2228 }
2229
2230 if ((tries-- <= 0) &&
2231 IS_STATE(urdc, queuing)) {
2232 cmn_err(CE_WARN, "!SNDR: giving up on reference count, logging set"
2233 " %s:%s", urdc->secondary.intf, urdc->secondary.file);
2234 rdc_group_enter(krdc);
2235 rdc_group_log(krdc,
2236 RDC_NOFLUSH |
2237 RDC_NOREMOTE|
2238 RDC_FORCE_GROUP,
2239 "ref count retry limit exceeded");
2240 rdc_group_exit(krdc);
2241 }
2242 goto again;
2243 }
2244 } else {
2245 BMAP_REF_SET(krdc, st);
2246 }
2247 }
2248 }
2249 mutex_exit(&krdc->bmapmutex);
2250 st++;
2251 }
2252 if (fbaset && krdc->bitmap_write > 0) {
2253 if (rdc_write_bitmap_fba(krdc, fba) < 0)
2254 return (-1);
2255 }
2256 return (0);
2257 }
2258
2259 static void
2260 rdc_std_clr_bitmap(rdc_k_info_t *krdc, const nsc_off_t fba_pos,
2261 const nsc_size_t fba_len, const uint_t bitmask, const int force)
2262 {
2263 int first, st, en;
2264 nsc_off_t fba = 0;
2265 int fbaset = 0;
2266 uint_t bm = bitmask;
2267 uchar_t *ptr = (uchar_t *)&bm;
2268 rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2269
2270 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED)
2271 return;
2272
2273 first = st = FBA_TO_LOG_NUM(fba_pos);
2274 en = FBA_TO_LOG_NUM(fba_pos + fba_len - 1);
2275 ASSERT(st <= en);
2276 while (st <= en) {
2277 mutex_enter(&krdc->bmapmutex);
2278
2279 if (krdc->dcio_bitmap == NULL) {
2280 #ifdef DEBUG
2281 cmn_err(CE_WARN, "!rdc_std_clr_bitmap: "
2282 "recovery bitmaps not allocated");
2283 #endif
2284 mutex_exit(&krdc->bmapmutex);
2285 return;
2286 }
2287
2288 if (((bitmask == 0xffffffff) ||
2289 (BMAP_BIT_ISSET(ptr, st - first))) &&
2290 BMAP_BIT_ISSET(krdc->dcio_bitmap, st)) {
2291
2292 int use_ref = IS_PRIMARY(urdc) && IS_ASYNC(urdc) &&
2293 ((rdc_get_vflags(urdc) & RDC_QUEUING) ||
2294 !(rdc_get_vflags(urdc) & RDC_LOGGING));
2295
2296 if (force || (use_ref == 0)) {
2297 if (krdc->bitmap_ref)
2298 BMAP_REF_FORCE(krdc, st, 0);
2299 } else if (use_ref) {
2300 if (BMAP_REF_ISSET(krdc, st) != 0)
2301 BMAP_REF_CLR(krdc, st);
2302
2303 }
2304
2305 if ((use_ref == 0) || (use_ref &&
2306 !BMAP_REF_ISSET(krdc, st))) {
2307 BMAP_BIT_CLR(krdc->dcio_bitmap, st);
2308
2309 urdc->bits_set--;
2310 if (!fbaset || fba != BIT_TO_FBA(st)) {
2311 if (fbaset &&
2312 krdc->bitmap_write > 0) {
2313 mutex_exit(&krdc->bmapmutex);
2314 if (rdc_write_bitmap_fba(krdc,
2315 fba) < 0)
2316 return;
2317 mutex_enter(&krdc->bmapmutex);
2318 }
2319 fba = BIT_TO_FBA(st);
2320 fbaset = 1;
2321 }
2322 }
2323 }
2324 mutex_exit(&krdc->bmapmutex);
2325 st++;
2326 }
2327 if (fbaset && krdc->bitmap_write > 0) {
2328 if (rdc_write_bitmap_fba(krdc, fba) < 0)
2329 return;
2330 }
2331 }
2332
2333 /*
2334 * make sure that this bit is set. if it isn't, set it
2335 * used when transitioning from async to sync while going
2336 * from rep to log. an overlapping sync write may unconditionally
2337 * clear the bit that has not been replicated. when the queue
2338 * is being dumped or this is called just to make sure pending stuff
2339 * is in the bitmap
2340 */
2341 void
2342 rdc_std_check_bit(rdc_k_info_t *krdc, nsc_off_t pos, nsc_size_t len)
2343 {
2344 int st;
2345 int en;
2346 nsc_off_t fba;
2347 rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2348 st = FBA_TO_LOG_NUM(pos);
2349 en = FBA_TO_LOG_NUM(pos + len - 1);
2350
2351 if (rdc_get_vflags(urdc) & RDC_BMP_FAILED)
2352 return;
2353
2354 while (st <= en) {
2355 mutex_enter(&krdc->bmapmutex);
2356
2357 if (krdc->dcio_bitmap == NULL) {
2358 #ifdef DEBUG
2359 cmn_err(CE_WARN, "!rdc_std_check_bit: "
2360 "recovery bitmaps not allocated");
2361 #endif
2362 mutex_exit(&krdc->bmapmutex);
2363 return;
2364 }
2365
2366 if (!BMAP_BIT_ISSET(krdc->dcio_bitmap, st)) {
2367 BMAP_BIT_SET(krdc->dcio_bitmap, st);
2368 if (krdc->bitmap_write > 0) {
2369 fba = BIT_TO_FBA(st);
2370 mutex_exit(&krdc->bmapmutex);
2371 (void) rdc_write_bitmap_fba(krdc, fba);
2372 mutex_enter(&krdc->bmapmutex);
2373 }
2374 urdc->bits_set++;
2375
2376 }
2377 mutex_exit(&krdc->bmapmutex);
2378 st++;
2379 }
2380
2381 }
2382
2383 /*
2384 * rdc_std_count_dirty(krdc):
2385 *
2386 * Determine the number of segments that need to be flushed, This should
2387 * agree with the number of segments logged, but since we don't lock when
2388 * we increment, we force these values to agree
2389 */
2390 static int
2391 rdc_std_count_dirty(rdc_k_info_t *krdc)
2392 {
2393 rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2394 int i, count, size;
2395
2396 if (krdc->dcio_bitmap == NULL) {
2397 #ifdef DEBUG
2398 cmn_err(CE_WARN,
2399 "!rdc_std_count_dirty: no bitmap configured for %s",
2400 urdc->primary.file);
2401 #endif
2402 return (0);
2403 }
2404
2405 count = 0;
2406 ASSERT(urdc->volume_size != 0);
2407 size = FBA_TO_LOG_LEN(urdc->volume_size);
2408 for (i = 0; i < size; i++)
2409 if (BMAP_BIT_ISSET(krdc->dcio_bitmap, i))
2410 count++;
2411
2412 if (count > size)
2413 count = size;
2414
2415 return (count);
2416 }
2417
2418
2419 static int
2420 rdc_std_bit_isset(rdc_k_info_t *krdc, const int bit)
2421 {
2422 return (BMAP_BIT_ISSET(krdc->dcio_bitmap, bit));
2423 }
2424
2425
2426 /*
2427 * rdc_std_fill_bitmap(krdc, write)
2428 *
2429 * Called to force bitmaps to a fully dirty state
2430 */
2431 static int
2432 rdc_std_fill_bitmap(rdc_k_info_t *krdc, const int write)
2433 {
2434 rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2435 int i, size;
2436
2437 if (krdc->dcio_bitmap == NULL) {
2438 #ifdef DEBUG
2439 cmn_err(CE_WARN,
2440 "!rdc_std_fill_bitmap: no bitmap configured for %s",
2441 urdc->primary.file);
2442 #endif
2443 return (-1);
2444 }
2445
2446 ASSERT(urdc->volume_size != 0);
2447 size = FBA_TO_LOG_LEN(urdc->volume_size);
2448 for (i = 0; i < size; i++)
2449 BMAP_BIT_SET(krdc->dcio_bitmap, i);
2450
2451 urdc->bits_set = size;
2452
2453 if (write)
2454 return (rdc_write_bitmap(krdc));
2455
2456 return (0);
2457 }
2458
2459
2460 /*
2461 * rdc_std_zero_bitmap(krdc)
2462 *
2463 * Called on the secondary after a sync has completed to force bitmaps
2464 * to a fully clean state
2465 */
2466 static void
2467 rdc_std_zero_bitmap(rdc_k_info_t *krdc)
2468 {
2469 rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
2470 int i, size;
2471
2472 if (krdc->dcio_bitmap == NULL) {
2473 #ifdef DEBUG
2474 cmn_err(CE_WARN,
2475 "!rdc_std_zero_bitmap: no bitmap configured for %s",
2476 urdc->primary.file);
2477 #endif
2478 return;
2479 }
2480 #ifdef DEBUG
2481 cmn_err(CE_NOTE, "!Clearing bitmap for %s", urdc->secondary.file);
2482 #endif
2483
2484 ASSERT(urdc->volume_size != 0);
2485 size = FBA_TO_LOG_LEN(urdc->volume_size);
2486 for (i = 0; i < size; i++)
2487 BMAP_BIT_CLR(krdc->dcio_bitmap, i);
2488 if (krdc->bitmap_write > 0)
2489 (void) rdc_write_bitmap(krdc);
2490
2491 urdc->bits_set = 0;
2492 }
2493
2494
2495 /*
2496 * rdc_std_net_bmap()
2497 *
2498 * WARNING acts as both client and server
2499 */
2500 static int
2501 rdc_std_net_bmap(const struct bmap6 *b)
2502 {
2503 rdc_k_info_t *krdc = &rdc_k_info[b->cd];
2504 struct net_bdata6 bd;
2505
2506 bd.data.data_val = (char *)krdc->dcio_bitmap;
2507 bd.cd = b->dual;
2508 bd.offset = 0;
2509
2510 return (_rdc_net_bmap(b, &bd));
2511 }
2512
2513
2514 /*
2515 * rdc_std_net_bdata
2516 */
2517 static int
2518 rdc_std_net_bdata(const struct net_bdata6 *bd)
2519 {
2520 rdc_k_info_t *krdc = &rdc_k_info[bd->cd];
2521
2522 rdc_lor((uchar_t *)bd->data.data_val,
2523 (uchar_t *)(((char *)krdc->dcio_bitmap) + bd->offset), bd->size);
2524
2525 return (0);
2526 }
2527
2528
2529 static struct rdc_bitmap_ops rdc_std_bitmap_ops = {
2530 rdc_std_set_bitmap,
2531 rdc_std_clr_bitmap,
2532 rdc_std_count_dirty,
2533 rdc_std_bit_isset,
2534 rdc_std_fill_bitmap,
2535 rdc_std_zero_bitmap,
2536 rdc_std_net_bmap,
2537 rdc_std_net_bdata,
2538 rdc_std_zero_bitref,
2539 rdc_std_set_bitmask,
2540 rdc_std_check_bit
2541 };
2542
2543
2544 void
2545 rdc_bitmap_init()
2546 {
2547 rdc_bitmap_ops = &rdc_std_bitmap_ops;
2548 rdc_wrflag = NSC_WRITE;
2549 }
2550
2551 static void
2552 rdc_bmap_ref_byte_set(rdc_k_info_t *krdc, int ind)
2553 {
2554 unsigned char *bmap = (unsigned char *)krdc->bitmap_ref;
2555
2556 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned char));
2557 bmap[ind]++;
2558 }
2559
2560 static void
2561 rdc_bmap_ref_byte_clr(rdc_k_info_t *krdc, int ind)
2562 {
2563 unsigned char *bmap = (unsigned char *)krdc->bitmap_ref;
2564
2565 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned char));
2566 bmap[ind]--;
2567 }
2568
2569 static unsigned int
2570 rdc_bmap_ref_byte_isset(rdc_k_info_t *krdc, int ind)
2571 {
2572 unsigned char *bmap = (unsigned char *)krdc->bitmap_ref;
2573
2574 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned char));
2575 return ((unsigned int)(bmap[ind]));
2576 }
2577
2578 static void
2579 rdc_bmap_ref_byte_force(rdc_k_info_t *krdc, int ind, unsigned int val)
2580 {
2581 unsigned char *bmap = (unsigned char *)krdc->bitmap_ref;
2582
2583 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned char));
2584 bmap[ind] = (unsigned char) val;
2585 }
2586
2587 /* ARGSUSED */
2588 static unsigned int
2589 rdc_bmap_ref_byte_maxval(rdc_k_info_t *krdc)
2590 {
2591 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned char));
2592 return ((unsigned int)(UINT8_MAX));
2593 }
2594
2595 struct bm_ref_ops rdc_ref_byte_ops = {
2596 rdc_bmap_ref_byte_set,
2597 rdc_bmap_ref_byte_clr,
2598 rdc_bmap_ref_byte_isset,
2599 rdc_bmap_ref_byte_force,
2600 rdc_bmap_ref_byte_maxval,
2601 sizeof (unsigned char)
2602 };
2603
2604 static void
2605 rdc_bmap_ref_int_set(rdc_k_info_t *krdc, int ind)
2606 {
2607 unsigned int *bmap = (unsigned int *)krdc->bitmap_ref;
2608
2609 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned int));
2610 bmap[ind]++;
2611 }
2612
2613 static void
2614 rdc_bmap_ref_int_clr(rdc_k_info_t *krdc, int ind)
2615 {
2616 unsigned int *bmap = (unsigned int *)krdc->bitmap_ref;
2617
2618 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned int));
2619 bmap[ind]--;
2620 }
2621
2622 static unsigned int
2623 rdc_bmap_ref_int_isset(rdc_k_info_t *krdc, int ind)
2624 {
2625 unsigned int *bmap = (unsigned int *)krdc->bitmap_ref;
2626
2627 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned int));
2628 return ((bmap[ind]));
2629 }
2630
2631 static void
2632 rdc_bmap_ref_int_force(rdc_k_info_t *krdc, int ind, unsigned int val)
2633 {
2634 unsigned int *bmap = (unsigned int *)krdc->bitmap_ref;
2635
2636 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned int));
2637 bmap[ind] = val;
2638 }
2639
2640 /* ARGSUSED */
2641 static unsigned int
2642 rdc_bmap_ref_int_maxval(rdc_k_info_t *krdc)
2643 {
2644 ASSERT(BMAP_REF_SIZE(krdc) == sizeof (unsigned int));
2645 return ((unsigned int)(UINT_MAX));
2646 }
2647
2648 struct bm_ref_ops rdc_ref_int_ops = {
2649 rdc_bmap_ref_int_set,
2650 rdc_bmap_ref_int_clr,
2651 rdc_bmap_ref_int_isset,
2652 rdc_bmap_ref_int_force,
2653 rdc_bmap_ref_int_maxval,
2654 sizeof (unsigned int)
2655 };