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