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 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 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 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 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 970 rdc_write_bitmap_fill(rdc_k_info_t *krdc) 971 { 972 return (rdc_write_bitmap_pattern(krdc, 0xff)); 973 } 974 975 976 void 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 2549 rdc_bitmap_init() 2550 { 2551 rdc_bitmap_ops = &rdc_std_bitmap_ops; 2552 rdc_wrflag = NSC_WRITE; 2553 } 2554 2555 static void 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 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 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 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 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 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 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 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 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 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 };