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 };