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