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/time.h>
  28 #include <sys/ksynch.h>
  29 #include <sys/kmem.h>
  30 #include <sys/errno.h>
  31 #include <sys/cmn_err.h>
  32 #include <sys/debug.h>
  33 #include <sys/ddi.h>
  34 #include <sys/nsc_thread.h>
  35 #include <sys/sysmacros.h>
  36 #include <sys/unistat/spcs_s.h>
  37 #include <sys/unistat/spcs_errors.h>
  38 
  39 #include <sys/unistat/spcs_s_k.h>
  40 #include <sys/nsctl/nsctl.h>
  41 #include "dsw.h"
  42 #include "dsw_dev.h"
  43 #include "../rdc/rdc_update.h"
  44 #include <sys/nskernd.h>
  45 
  46 #include <sys/sdt.h>              /* dtrace is S10 or later */
  47 
  48 #ifdef DS_DDICT
  49 #include "../contract.h"
  50 #endif
  51 
  52 /*
  53  * Instant Image
  54  *
  55  * This file contains the core implementation of II.
  56  *
  57  * II is implemented as a simple filter module that pushes itself between
  58  * user (SV, STE, etc.) and SDBC or NET.
  59  *
  60  */
  61 
  62 
  63 #define REMOTE_VOL(s, ip)       (((s) && ((ip->bi_flags)&DSW_SHDEXPORT)) || \
  64                                     (!(s)&&((ip->bi_flags)&DSW_SHDIMPORT)))
  65 
  66 #define total_ref(ip)   ((ip->bi_shdref + ip->bi_shdrref + ip->bi_bmpref) + \
  67                             (NSHADOWS(ip) ? 0 : ip->bi_mstref + ip->bi_mstrref))
  68 
  69 
  70 #define II_TAIL_COPY(d, s, m, t)        bcopy(&(s.m), &(d.m), \
  71                                         sizeof (d) - (uintptr_t)&((t *)0)->m)
  72 extern dev_info_t *ii_dip;
  73 
  74 #define II_LINK_CLUSTER(ip, cluster) \
  75         _ii_ll_add(ip, &_ii_cluster_mutex, &_ii_cluster_top, cluster, \
  76             &ip->bi_cluster)
  77 #define II_UNLINK_CLUSTER(ip) \
  78         _ii_ll_remove(ip, &_ii_cluster_mutex, &_ii_cluster_top, &ip->bi_cluster)
  79 
  80 #define II_LINK_GROUP(ip, group) \
  81         _ii_ll_add(ip, &_ii_group_mutex, &_ii_group_top, group, &ip->bi_group)
  82 #define II_UNLINK_GROUP(ip) \
  83         _ii_ll_remove(ip, &_ii_group_mutex, &_ii_group_top, &ip->bi_group)
  84 
  85 _ii_info_t *_ii_info_top;
  86 _ii_info_t *_ii_mst_top = 0;
  87 _ii_overflow_t  *_ii_overflow_top;
  88 _ii_lsthead_t *_ii_cluster_top;
  89 _ii_lsthead_t *_ii_group_top;
  90 
  91 int     ii_debug;               /* level of cmn_err noise */
  92 int     ii_bitmap;              /* bitmap operations switch */
  93 uint_t  ii_header = 16;         /* Undocumented tunable (with adb!), start */
  94                                 /* of area cleared in volume when a dependent */
  95                                 /* shadow is disabled. */
  96                                 /* max # of chunks in copy loop before delay */
  97 int     ii_throttle_unit = MIN_THROTTLE_UNIT;
  98                                 /* length of delay during update loop */
  99 int     ii_throttle_delay = MIN_THROTTLE_DELAY;
 100 int     ii_copy_direct = 1;
 101 int     ii_nconcopy = 10;       /* default value when starting with no cache */
 102 kmutex_t _ii_cluster_mutex;
 103 kmutex_t _ii_group_mutex;
 104 
 105 static int _ii_shutting_down = 0;
 106 static nsc_io_t *_ii_io, *_ii_ior;
 107 static nsc_mem_t *_ii_local_mem;
 108 static nsc_def_t _ii_fd_def[], _ii_io_def[], _ii_ior_def[];
 109 static kmutex_t _ii_info_mutex;
 110 static kmutex_t _ii_overflow_mutex;
 111 static kmutex_t _ii_config_mutex;
 112 static _ii_bmp_ops_t alloc_buf_bmp, kmem_buf_bmp;
 113 static nsc_svc_t *ii_volume_update;     /* IIVolumeUpdate token */
 114 static nsc_svc_t *ii_report_luns;       /* IIReportLuns token */
 115 static nsc_svc_t *ii_get_initiators;    /* IIGetInitiators token */
 116 static ksema_t  _ii_concopy_sema;
 117 static int      _ii_concopy_init = 0;
 118 static int      _ii_instance = 0;
 119 
 120 void _ii_deinit_dev();
 121 
 122 static void _ii_info_free(_ii_info_t *ip);
 123 static void _ii_info_freeshd(_ii_info_t *ip);
 124 static void ii_sibling_free(_ii_info_t *ip);
 125 ii_header_t *_ii_bm_header_get(_ii_info_t *ip, nsc_buf_t **tmp);
 126 int _ii_bm_header_put(ii_header_t *hdr, _ii_info_t *ip,
 127     nsc_buf_t *tmp);
 128 static void _ii_bm_header_free(ii_header_t *hdr, _ii_info_t *ip,
 129     nsc_buf_t *tmp);
 130 static int _ii_copyvol(_ii_info_t *, int, int, spcs_s_info_t, int);
 131 static void _ii_stopvol(_ii_info_t *ip);
 132 static int _ii_stopcopy(_ii_info_t *ip);
 133 static _ii_info_t *_ii_find_set(char *volume);
 134 static _ii_info_t *_ii_find_vol(char *, int);
 135 static _ii_overflow_t *_ii_find_overflow(char *volume);
 136 static void _ii_ioctl_done(_ii_info_t *ip);
 137 static void _ii_lock_chunk(_ii_info_t *ip, chunkid_t);
 138 static void _ii_unlock_chunks(_ii_info_t *ip, chunkid_t, int);
 139 void _ii_error(_ii_info_t *ip, int error_type);
 140 static nsc_buf_t *_ii_alloc_handle(void (*d_cb)(), void (*r_cb)(),
 141     void (*w_cb)(), ii_fd_t *bfd);
 142 static int _ii_free_handle(ii_buf_t *h, ii_fd_t *bfd);
 143 extern nsc_size_t ii_btsize(nsc_size_t);
 144 extern int ii_tinit(_ii_info_t *);
 145 extern chunkid_t ii_tsearch(_ii_info_t *, chunkid_t);
 146 extern void ii_tdelete(_ii_info_t *, chunkid_t);
 147 extern void ii_reclaim_overflow(_ii_info_t *);
 148 static void ii_overflow_free(_ii_info_t *ip, int disable);
 149 static int ii_overflow_attach(_ii_info_t *, char *, int);
 150 int _ii_nsc_io(_ii_info_t *, int, nsc_fd_t *, int, nsc_off_t, unsigned char *,
 151         nsc_size_t);
 152 static nsc_path_t *_ii_register_path(char *path, int type, nsc_io_t *io);
 153 static int _ii_unregister_path(nsc_path_t *sp, int flag, char *type);
 154 static int _ii_reserve_begin(_ii_info_t *ip);
 155 static int _ii_wait_for_it(_ii_info_t *ip);
 156 static void _ii_reserve_end(_ii_info_t *ip);
 157 static kstat_t *_ii_overflow_kstat_create(_ii_info_t *ip, _ii_overflow_t *op);
 158 static int _ii_ll_add(_ii_info_t *, kmutex_t *, _ii_lsthead_t **, char *,
 159     char **);
 160 static int _ii_ll_remove(_ii_info_t *, kmutex_t *, _ii_lsthead_t **, char **);
 161 #define _ii_unlock_chunk(ip, chunk)     _ii_unlock_chunks(ip, chunk, 1)
 162 extern const int dsw_major_rev;
 163 extern const int dsw_minor_rev;
 164 extern const int dsw_micro_rev;
 165 extern const int dsw_baseline_rev;
 166 
 167 /*
 168  * These constants are used by ii_overflow_free() to indicate how the
 169  * reclamation should take place.
 170  *      NO_RECLAIM: just detach the overflow from the set; do not
 171  *              attempt to reclaim chunks, do not decrement the
 172  *              used-by count
 173  *      RECLAIM: reclaim all chunks before decrementing the used-by count
 174  *      INIT_OVR: decrement the used-by count only; do not reclaim chunks
 175  */
 176 
 177 #define NO_RECLAIM 0
 178 #define RECLAIM 1
 179 #define INIT_OVR 2
 180 
 181 struct  copy_args {                     /* arguments passed to copy process */
 182         _ii_info_t *ip;
 183         int flag;
 184         int rtype;
 185         int wait;
 186         spcs_s_info_t kstatus;
 187         int rc;
 188 };
 189 
 190 /* set-specific kstats info */
 191 ii_kstat_set_t ii_kstat_set = {
 192         { DSW_SKSTAT_SIZE, KSTAT_DATA_ULONG },
 193         { DSW_SKSTAT_MTIME, KSTAT_DATA_ULONG },
 194         { DSW_SKSTAT_FLAGS, KSTAT_DATA_ULONG },
 195         { DSW_SKSTAT_THROTTLE_UNIT, KSTAT_DATA_ULONG },
 196         { DSW_SKSTAT_THROTTLE_DELAY, KSTAT_DATA_ULONG },
 197         { DSW_SKSTAT_SHDCHKS, KSTAT_DATA_ULONG },
 198         { DSW_SKSTAT_SHDCHKUSED, KSTAT_DATA_ULONG },
 199         { DSW_SKSTAT_SHDBITS, KSTAT_DATA_ULONG },
 200         { DSW_SKSTAT_COPYBITS, KSTAT_DATA_ULONG },
 201         { DSW_SKSTAT_MSTA, KSTAT_DATA_CHAR },
 202         { DSW_SKSTAT_MSTB, KSTAT_DATA_CHAR },
 203         { DSW_SKSTAT_MSTC, KSTAT_DATA_CHAR },
 204         { DSW_SKSTAT_MSTD, KSTAT_DATA_CHAR },
 205         { DSW_SKSTAT_SETA, KSTAT_DATA_CHAR },
 206         { DSW_SKSTAT_SETB, KSTAT_DATA_CHAR },
 207         { DSW_SKSTAT_SETC, KSTAT_DATA_CHAR },
 208         { DSW_SKSTAT_SETD, KSTAT_DATA_CHAR },
 209         { DSW_SKSTAT_BMPA, KSTAT_DATA_CHAR },
 210         { DSW_SKSTAT_BMPB, KSTAT_DATA_CHAR },
 211         { DSW_SKSTAT_BMPC, KSTAT_DATA_CHAR },
 212         { DSW_SKSTAT_BMPD, KSTAT_DATA_CHAR },
 213         { DSW_SKSTAT_OVRA, KSTAT_DATA_CHAR },
 214         { DSW_SKSTAT_OVRB, KSTAT_DATA_CHAR },
 215         { DSW_SKSTAT_OVRC, KSTAT_DATA_CHAR },
 216         { DSW_SKSTAT_OVRD, KSTAT_DATA_CHAR },
 217         { DSW_SKSTAT_MSTIO, KSTAT_DATA_CHAR },
 218         { DSW_SKSTAT_SHDIO, KSTAT_DATA_CHAR },
 219         { DSW_SKSTAT_BMPIO, KSTAT_DATA_CHAR },
 220         { DSW_SKSTAT_OVRIO, KSTAT_DATA_CHAR },
 221 };
 222 
 223 /*
 224  * _ii_init_dev
 225  *      Initialise the shadow driver
 226  *
 227  */
 228 
 229 int
 230 _ii_init_dev()
 231 {
 232         _ii_io = nsc_register_io("ii", NSC_II_ID|NSC_REFCNT|NSC_FILTER,
 233             _ii_io_def);
 234         if (_ii_io == NULL)
 235                 cmn_err(CE_WARN, "!ii: nsc_register_io failed.");
 236 
 237         _ii_ior = nsc_register_io("ii-raw", NSC_IIR_ID|NSC_REFCNT|NSC_FILTER,
 238             _ii_ior_def);
 239         if (_ii_ior == NULL)
 240                 cmn_err(CE_WARN, "!ii: nsc_register_io r failed.");
 241 
 242         _ii_local_mem = nsc_register_mem("ii:kmem", NSC_MEM_LOCAL, 0);
 243         if (_ii_local_mem == NULL)
 244                 cmn_err(CE_WARN, "!ii: nsc_register_mem failed.");
 245 
 246 
 247         if (!_ii_io || !_ii_ior || !_ii_local_mem) {
 248                 _ii_deinit_dev();
 249                 return (ENOMEM);
 250         }
 251 
 252         mutex_init(&_ii_info_mutex, NULL, MUTEX_DRIVER, NULL);
 253         mutex_init(&_ii_overflow_mutex, NULL, MUTEX_DRIVER, NULL);
 254         mutex_init(&_ii_config_mutex, NULL, MUTEX_DRIVER, NULL);
 255         mutex_init(&_ii_cluster_mutex, NULL, MUTEX_DRIVER, NULL);
 256         mutex_init(&_ii_group_mutex, NULL, MUTEX_DRIVER, NULL);
 257 
 258         ii_volume_update = nsc_register_svc("RDCVolumeUpdated", 0);
 259         ii_report_luns = nsc_register_svc("IIReportLuns", 0);
 260         ii_get_initiators = nsc_register_svc("IIGetInitiators", 0);
 261 
 262         if (!ii_volume_update || !ii_report_luns || !ii_get_initiators) {
 263                 _ii_deinit_dev();
 264                 return (ENOMEM);
 265         }
 266 
 267         return (0);
 268 }
 269 
 270 
 271 /*
 272  * _ii_deinit_dev
 273  *      De-initialise the shadow driver
 274  *
 275  */
 276 
 277 void
 278 _ii_deinit_dev()
 279 {
 280 
 281         if (_ii_io)
 282                 (void) nsc_unregister_io(_ii_io, 0);
 283 
 284         if (_ii_ior)
 285                 (void) nsc_unregister_io(_ii_ior, 0);
 286 
 287         if (_ii_local_mem)
 288                 (void) nsc_unregister_mem(_ii_local_mem);
 289 
 290         if (ii_volume_update)
 291                 (void) nsc_unregister_svc(ii_volume_update);
 292 
 293         if (ii_report_luns)
 294                 (void) nsc_unregister_svc(ii_report_luns);
 295 
 296         if (ii_get_initiators)
 297                 (void) nsc_unregister_svc(ii_get_initiators);
 298 
 299         mutex_destroy(&_ii_info_mutex);
 300         mutex_destroy(&_ii_overflow_mutex);
 301         mutex_destroy(&_ii_config_mutex);
 302         mutex_destroy(&_ii_cluster_mutex);
 303         mutex_destroy(&_ii_group_mutex);
 304         if (_ii_concopy_init)
 305                 sema_destroy(&_ii_concopy_sema);
 306         _ii_concopy_init = 0;
 307 
 308 }
 309 
 310 static char *
 311 ii_pathname(nsc_fd_t *fd)
 312 {
 313         char *rc;
 314 
 315         if (fd == NULL || (rc = nsc_pathname(fd)) == NULL)
 316                 return ("");
 317         else
 318                 return (rc);
 319 }
 320 
 321 
 322 /*
 323  * _ii_rlse_d
 324  *      Internal mechanics of _ii_rlse_devs().  Takes care of
 325  *      resetting the ownership information as required.
 326  */
 327 
 328 static void
 329 _ii_rlse_d(ip, mst, raw)
 330 _ii_info_t *ip;
 331 int mst, raw;
 332 {
 333         _ii_info_dev_t *cip;
 334         _ii_info_dev_t *rip;
 335 
 336         rip = mst ? (ip->bi_mstrdev) : &(ip->bi_shdrdev);
 337         cip = mst ? (ip->bi_mstdev) : &(ip->bi_shddev);
 338 
 339         DTRACE_PROBE2(_ii_rlse_d_type,
 340                         _ii_info_dev_t *, rip,
 341                         _ii_info_dev_t *, cip);
 342 
 343 
 344         if (RSRV(cip)) {
 345                 if (raw) {
 346                         ASSERT(cip->bi_orsrv > 0);
 347                         cip->bi_orsrv--;
 348                 } else {
 349                         ASSERT(cip->bi_rsrv > 0);
 350                         cip->bi_rsrv--;
 351                 }
 352 
 353                 if (cip->bi_rsrv > 0) {
 354                         nsc_set_owner(cip->bi_fd, cip->bi_iodev);
 355                 } else if (cip->bi_orsrv > 0) {
 356                         nsc_set_owner(cip->bi_fd, rip->bi_iodev);
 357                 } else {
 358                         nsc_set_owner(cip->bi_fd, NULL);
 359                 }
 360 
 361                 if (!RSRV(cip)) {
 362                         nsc_release(cip->bi_fd);
 363                 }
 364         } else {
 365                 if (raw) {
 366                         ASSERT(rip->bi_rsrv > 0);
 367                         rip->bi_rsrv--;
 368                 } else {
 369                         ASSERT(rip->bi_orsrv > 0);
 370                         rip->bi_orsrv--;
 371                 }
 372 
 373                 if (rip->bi_rsrv > 0) {
 374                         nsc_set_owner(rip->bi_fd, rip->bi_iodev);
 375                 } else if (rip->bi_orsrv > 0) {
 376                         nsc_set_owner(rip->bi_fd, cip->bi_iodev);
 377                 } else {
 378                         nsc_set_owner(rip->bi_fd, NULL);
 379                 }
 380 
 381                 if (!RSRV(rip)) {
 382                         rip->bi_flag = 0;
 383                         nsc_release(rip->bi_fd);
 384                         cv_broadcast(&ip->bi_releasecv);
 385                 }
 386         }
 387 
 388 }
 389 
 390 
 391 /*
 392  * _ii_rlse_devs
 393  *      Release named underlying devices.
 394  *
 395  *      NOTE: the 'devs' argument must be the same as that passed to
 396  *      the preceding _ii_rsrv_devs call.
 397  */
 398 
 399 void
 400 _ii_rlse_devs(ip, devs)
 401 _ii_info_t *ip;
 402 int devs;
 403 {
 404 
 405         ASSERT(!(devs & (MST|SHD)));
 406 
 407         ASSERT(ip->bi_head != (_ii_info_t *)0xdeadbeef);
 408         if (!ip) {
 409                 cmn_err(CE_WARN, "!ii: _ii_rlse_devs null ip");
 410                 return;
 411         }
 412 
 413         mutex_enter(&ip->bi_rsrvmutex);
 414 
 415         DTRACE_PROBE(_ii_rlse_devs_mutex);
 416 
 417         if ((devs&(MST|MSTR)) != 0 && (ip->bi_flags&DSW_SHDIMPORT) == 0) {
 418                 if (NSHADOWS(ip) && ip != ip->bi_master)
 419                         _ii_rlse_devs(ip->bi_master, devs&(MST|MSTR));
 420                 else
 421                         _ii_rlse_d(ip, 1, (devs&MSTR));
 422         }
 423 
 424         if ((devs&(SHD|SHDR)) != 0 && (ip->bi_flags&DSW_SHDEXPORT) == 0) {
 425                 _ii_rlse_d(ip, 0, (devs&SHDR));
 426         }
 427 
 428         if ((devs&BMP) != 0 && ip->bi_bmpfd) {
 429                 if (--(ip->bi_bmprsrv) == 0)
 430                         nsc_release(ip->bi_bmpfd);
 431         }
 432 
 433         ASSERT(ip->bi_bmprsrv >= 0);
 434         ASSERT(ip->bi_shdrsrv >= 0);
 435         ASSERT(ip->bi_shdrrsrv >= 0);
 436         mutex_exit(&ip->bi_rsrvmutex);
 437 
 438 }
 439 
 440 
 441 /*
 442  * _ii_rsrv_d
 443  *      Reserve device flagged, unless its companion is already reserved,
 444  *      in that case increase the reserve on the companion.
 445  */
 446 
 447 static int
 448 _ii_rsrv_d(int raw, _ii_info_dev_t *rid, _ii_info_dev_t *cid, int flag,
 449     _ii_info_t *ip)
 450 {
 451         _ii_info_dev_t *p = NULL;
 452         int other = 0;
 453         int rc;
 454 
 455         /*
 456          * If user wants to do a cache reserve and it's already
 457          * raw reserved, we need to do a real nsc_reserve, so wait
 458          * until the release has been done.
 459          */
 460         if (RSRV(rid) && (flag == II_EXTERNAL) &&
 461             (raw == 0) && (rid->bi_flag != II_EXTERNAL)) {
 462                 ip->bi_release++;
 463                 while (RSRV(rid)) {
 464                         DTRACE_PROBE1(_ii_rsrv_d_wait, _ii_info_dev_t *, rid);
 465                         cv_wait(&ip->bi_releasecv, &ip->bi_rsrvmutex);
 466                         DTRACE_PROBE1(_ii_rsrv_d_resume, _ii_info_dev_t *, rid);
 467                 }
 468                 ip->bi_release--;
 469         }
 470 
 471         if (RSRV(rid)) {
 472                 p = rid;
 473                 if (!raw) {
 474                         other = 1;
 475                 }
 476         } else if (RSRV(cid)) {
 477                 p = cid;
 478                 if (raw) {
 479                         other = 1;
 480                 }
 481         }
 482 
 483         if (p) {
 484                 if (other) {
 485                         p->bi_orsrv++;
 486                 } else {
 487                         p->bi_rsrv++;
 488                 }
 489 
 490                 if (p->bi_iodev) {
 491                         nsc_set_owner(p->bi_fd, p->bi_iodev);
 492                 }
 493 
 494                 return (0);
 495         }
 496         p = raw ? rid : cid;
 497 
 498         if ((rc = nsc_reserve(p->bi_fd, 0)) == 0) {
 499                 if (p->bi_iodev) {
 500                         nsc_set_owner(p->bi_fd, p->bi_iodev);
 501                 }
 502                 p->bi_rsrv++;
 503                 if (raw)
 504                         p->bi_flag = flag;
 505         }
 506 
 507         return (rc);
 508 }
 509 
 510 /*
 511  * _ii_rsrv_devs
 512  *      Reserve named underlying devices.
 513  *
 514  */
 515 
 516 int
 517 _ii_rsrv_devs(_ii_info_t *ip, int devs, int flag)
 518 {
 519         int rc = 0;
 520         int got = 0;
 521 
 522         ASSERT(!(devs & (MST|SHD)));
 523 
 524         if (!ip) {
 525                 cmn_err(CE_WARN, "!ii: _ii_rsrv_devs null ip");
 526                 return (EINVAL);
 527         }
 528 
 529         mutex_enter(&ip->bi_rsrvmutex);
 530 
 531         DTRACE_PROBE(_ii_rsrv_devs_mutex);
 532 
 533         if (rc == 0 && (devs&(MST|MSTR)) != 0 &&
 534             (ip->bi_flags&DSW_SHDIMPORT) == 0) {
 535                 DTRACE_PROBE(_ii_rsrv_devs_master);
 536                 if (NSHADOWS(ip) && ip != ip->bi_master) {
 537                         if ((rc = _ii_rsrv_devs(ip->bi_master, devs&(MST|MSTR),
 538                             flag)) != 0) {
 539                                 cmn_err(CE_WARN,
 540                                     "!ii: nsc_reserve multi-master failed");
 541                         } else {
 542                                 got |= devs&(MST|MSTR);
 543                         }
 544                 } else {
 545                         if ((rc = _ii_rsrv_d((devs&MSTR) != 0, ip->bi_mstrdev,
 546                             ip->bi_mstdev, flag, ip)) != 0) {
 547                                 cmn_err(CE_WARN,
 548                                     "!ii: nsc_reserve master failed %d", rc);
 549                         } else {
 550                                 got |= (devs&(MST|MSTR));
 551                         }
 552                 }
 553         }
 554 
 555         if (rc == 0 && (devs&(SHD|SHDR)) != 0 &&
 556             (ip->bi_flags&DSW_SHDEXPORT) == 0) {
 557                 DTRACE_PROBE(_ii_rsrv_devs_shadow);
 558                 if ((rc = _ii_rsrv_d((devs&SHDR) != 0, &ip->bi_shdrdev,
 559                     &ip->bi_shddev, flag, ip)) != 0) {
 560                         cmn_err(CE_WARN,
 561                             "!ii: nsc_reserve shadow failed %d", rc);
 562                 } else {
 563                         got |= (devs&(SHD|SHDR));
 564                 }
 565         }
 566 
 567         if (rc == 0 && (devs&BMP) != 0 && ip->bi_bmpfd) {
 568                 DTRACE_PROBE(_ii_rsrv_devs_bitmap);
 569                 if ((ip->bi_bmprsrv == 0) &&
 570                     (rc = nsc_reserve(ip->bi_bmpfd, 0)) != 0) {
 571                         cmn_err(CE_WARN,
 572                             "!ii: nsc_reserve bitmap failed %d", rc);
 573                 } else {
 574                         (ip->bi_bmprsrv)++;
 575                         got |= BMP;
 576                 }
 577         }
 578         mutex_exit(&ip->bi_rsrvmutex);
 579         if (rc != 0 && got != 0)
 580                 _ii_rlse_devs(ip, got);
 581 
 582         return (rc);
 583 }
 584 
 585 static int
 586 _ii_reserve_begin(_ii_info_t *ip)
 587 {
 588         int rc;
 589 
 590         mutex_enter(&ip->bi_rlsemutex);
 591         if ((rc = _ii_wait_for_it(ip)) == 0) {
 592                 ++ip->bi_rsrvcnt;
 593         }
 594         mutex_exit(&ip->bi_rlsemutex);
 595 
 596         return (rc);
 597 }
 598 
 599 static int
 600 _ii_wait_for_it(_ii_info_t *ip)
 601 {
 602         int nosig;
 603 
 604         nosig = 1;
 605         while (ip->bi_rsrvcnt > 0) {
 606                 nosig = cv_wait_sig(&ip->bi_reservecv, &ip->bi_rlsemutex);
 607                 if (!nosig) {
 608                         break;
 609                 }
 610         }
 611 
 612         return (nosig? 0 : EINTR);
 613 }
 614 
 615 static void
 616 _ii_reserve_end(_ii_info_t *ip)
 617 {
 618         mutex_enter(&ip->bi_rlsemutex);
 619         if (ip->bi_rsrvcnt <= 0) {
 620                 mutex_exit(&ip->bi_rlsemutex);
 621                 return;
 622         }
 623         --ip->bi_rsrvcnt;
 624         mutex_exit(&ip->bi_rlsemutex);
 625         cv_broadcast(&ip->bi_reservecv);
 626 
 627 }
 628 
 629 static int
 630 ii_fill_copy_bmp(_ii_info_t *ip)
 631 {
 632         int rc;
 633         chunkid_t max_chunk, chunk_num;
 634 
 635         if ((rc = II_FILL_COPY_BMP(ip)) != 0)
 636                 return (rc);
 637         /*
 638          * make certain that the last bits of the last byte of the bitmap
 639          * aren't filled as they may be copied out to the user.
 640          */
 641 
 642         chunk_num = ip->bi_size / DSW_SIZE;
 643         if ((ip->bi_size % DSW_SIZE) != 0)
 644                 ++chunk_num;
 645 
 646         max_chunk = chunk_num;
 647         if ((max_chunk & 0x7) != 0)
 648                 max_chunk = (max_chunk + 7) & ~7;
 649 
 650         DTRACE_PROBE2(_ii_fill_copy_bmp_chunks, chunkid_t, chunk_num,
 651             chunkid_t, max_chunk);
 652 
 653         for (; chunk_num < max_chunk; chunk_num++) {
 654                 (void) II_CLR_COPY_BIT(ip, chunk_num);
 655         }
 656 
 657         return (0);
 658 }
 659 
 660 static int
 661 ii_update_denied(_ii_info_t *ip, spcs_s_info_t kstatus,
 662                                 int direction, int all)
 663 {
 664         rdc_update_t update;
 665         int size;
 666         unsigned char *bmp;
 667 
 668         update.volume = direction == CV_SHD2MST ? ii_pathname(MSTFD(ip)) :
 669             ip->bi_keyname;
 670         update.denied = 0;
 671         update.protocol = RDC_SVC_ONRETURN;
 672         update.size = size = FBA_SIZE(DSW_BM_FBA_LEN(ip->bi_size));
 673         update.status = kstatus;
 674         update.bitmap = bmp = kmem_alloc(update.size, KM_SLEEP);
 675         if (bmp == NULL) {
 676                 spcs_s_add(kstatus, ENOMEM);
 677                 return (1);
 678         }
 679 
 680         DTRACE_PROBE2(_ii_update_denied, int, all, int, size);
 681 
 682         if (all) {
 683                 while (size-- > 0)
 684                         *bmp++ = (unsigned char)0xff;
 685         } else {
 686                 if (II_CHANGE_BMP(ip, update.bitmap) != 0) {
 687                         /* failed to read bitmap */
 688                         spcs_s_add(kstatus, EIO);
 689                         update.denied = 1;
 690                 }
 691         }
 692 
 693         /* check that no user of volume objects */
 694         if (update.denied == 0) {
 695                 (void) nsc_call_svc(ii_volume_update, (intptr_t)&update);
 696         }
 697         kmem_free(update.bitmap, FBA_SIZE(DSW_BM_FBA_LEN(ip->bi_size)));
 698 
 699         return (update.denied);
 700 }
 701 
 702 static int
 703 ii_need_same_size(_ii_info_t *ip)
 704 {
 705         rdc_update_t update;
 706 
 707         update.volume = ip->bi_keyname;
 708         update.denied = 0;
 709         update.protocol = RDC_SVC_VOL_ENABLED;
 710 
 711         (void) nsc_call_svc(ii_volume_update, (intptr_t)&update);
 712 
 713         return (update.denied);
 714 }
 715 
 716 /*
 717  * ii_volume:   check if vol is already known to Instant Image and return
 718  *      volume type if it is.
 719  */
 720 
 721 static int
 722 ii_volume(char *vol, int locked)
 723 {
 724         _ii_info_t *ip;
 725         _ii_overflow_t  *op;
 726         int rc = NONE;
 727 
 728         /* scan overflow volume list */
 729         mutex_enter(&_ii_overflow_mutex);
 730 
 731         DTRACE_PROBE(_ii_volume_mutex);
 732 
 733         for (op = _ii_overflow_top; op; op = op->ii_next) {
 734                 if (strcmp(vol, op->ii_volname) == 0)
 735                         break;
 736         }
 737         mutex_exit(&_ii_overflow_mutex);
 738         if (op) {
 739                 return (OVR);
 740         }
 741 
 742         if (!locked) {
 743                 mutex_enter(&_ii_info_mutex);
 744         }
 745 
 746         DTRACE_PROBE(_ii_volume_mutex2);
 747 
 748         for (ip = _ii_info_top; ip; ip = ip->bi_next) {
 749                 if (strcmp(vol, ii_pathname(ip->bi_mstfd)) == 0) {
 750                         rc = MST;
 751                         break;
 752                 }
 753                 if (strcmp(vol, ip->bi_keyname)  == 0) {
 754                         rc = SHD;
 755                         break;
 756                 }
 757                 if (strcmp(vol, ii_pathname(ip->bi_bmpfd)) == 0) {
 758                         rc = BMP;
 759                         break;
 760                 }
 761         }
 762         DTRACE_PROBE1(_ii_volume_data, int, rc);
 763 
 764         if (!locked) {
 765                 mutex_exit(&_ii_info_mutex);
 766         }
 767 
 768         return (rc);
 769 }
 770 
 771 /*
 772  * ii_open_shadow: open shadow volume for both cached and raw access,
 773  *      if the normal device open fails attempt a file open to allow
 774  *      shadowing into a file.
 775  */
 776 
 777 static int
 778 ii_open_shadow(_ii_info_t *ip, char *shadow_vol)
 779 {
 780         int rc = 0;
 781         int file_rc = 0;
 782 
 783         ip->bi_shdfd = nsc_open(shadow_vol,
 784             NSC_IIR_ID|NSC_DEVICE|NSC_RDWR, _ii_fd_def,
 785             (blind_t)&(ip->bi_shddev), &rc);
 786         if (!ip->bi_shdfd) {
 787                 ip->bi_shdfd = nsc_open(shadow_vol,
 788                     NSC_IIR_ID|NSC_FILE|NSC_RDWR, _ii_fd_def,
 789                     (blind_t)&(ip->bi_shddev), &file_rc);
 790                 file_rc = 1;
 791                 if (!ip->bi_shdfd) {
 792                         return (rc);
 793                 }
 794                 DTRACE_PROBE(_ii_open_shadow);
 795         }
 796         else
 797                 DTRACE_PROBE(_ii_open_shadow);
 798 
 799         if (file_rc == 0) {
 800                 ip->bi_shdrfd = nsc_open(shadow_vol,
 801                     NSC_IIR_ID|NSC_DEVICE|NSC_RDWR, _ii_fd_def,
 802                     (blind_t)&(ip->bi_shdrdev), &rc);
 803                 DTRACE_PROBE(_ii_open_shadow);
 804         } else {
 805                 ip->bi_shdrfd = nsc_open(shadow_vol,
 806                     NSC_IIR_ID|NSC_FILE|NSC_RDWR, _ii_fd_def,
 807                     (blind_t)&(ip->bi_shdrdev), &rc);
 808                 DTRACE_PROBE(_ii_open_shadow);
 809         }
 810 
 811         if (!ip->bi_shdrfd) {
 812                 (void) nsc_close(ip->bi_shdfd);
 813                 DTRACE_PROBE(_ii_open_shadow);
 814                 return (rc);
 815         }
 816 
 817         return (0);
 818 }
 819 
 820 static void
 821 ii_register_shd(_ii_info_t *ip)
 822 {
 823         ip->bi_shd_tok = _ii_register_path(ip->bi_keyname,
 824             NSC_CACHE, _ii_io);
 825         ip->bi_shdr_tok = _ii_register_path(ip->bi_keyname,
 826             NSC_DEVICE, _ii_ior);
 827 
 828 }
 829 
 830 static void
 831 ii_register_mst(_ii_info_t *ip)
 832 {
 833         ip->bi_mst_tok = _ii_register_path(ii_pathname(ip->bi_mstfd),
 834             NSC_CACHE, _ii_io);
 835         ip->bi_mstr_tok = _ii_register_path(ii_pathname(ip->bi_mstrfd),
 836             NSC_DEVICE, _ii_ior);
 837 
 838 }
 839 
 840 static int
 841 ii_register_ok(_ii_info_t *ip)
 842 {
 843         int rc;
 844         int sibling;
 845         int exported;
 846 
 847         rc = 1;
 848         sibling = NSHADOWS(ip) && ip != ip->bi_head;
 849         exported = ip->bi_flags & DSW_SHDEXPORT;
 850 
 851         if ((ip->bi_bmpfd && !ip->bi_bmp_tok) || (!exported && (
 852             !ip->bi_shd_tok || !ip->bi_shdr_tok)))
 853                 rc = 0;
 854         else if (!sibling && (!ip->bi_mst_tok || !ip->bi_mstr_tok))
 855                 rc = 0;
 856 
 857         return (rc);
 858 }
 859 
 860 #ifndef DISABLE_KSTATS
 861 
 862 /*
 863  * _ii_kstat_create
 864  *      Create and install kstat_io data
 865  *
 866  * Calling/Exit State:
 867  *      Returns 0 if kstats couldn't be created, otherwise it returns
 868  *      a pointer to the created kstat_t.
 869  */
 870 
 871 static kstat_t *
 872 _ii_kstat_create(_ii_info_t *ip, char *type)
 873 {
 874         kstat_t *result;
 875         char name[ IOSTAT_NAME_LEN ];
 876         int setnum;
 877         char *nptr;
 878         static int mstnum = 0;
 879         static int shdbmpnum = -1;
 880 
 881         switch (*type) {
 882         case 'm':
 883                 setnum = mstnum++;
 884                 nptr = ip->bi_kstat_io.mstio;
 885                 break;
 886         case 's':
 887                 /* assumption: shadow kstats created before bitmap */
 888                 setnum = ++shdbmpnum;
 889                 nptr = ip->bi_kstat_io.shdio;
 890                 break;
 891         case 'b':
 892                 setnum = shdbmpnum;
 893                 nptr = ip->bi_kstat_io.bmpio;
 894                 break;
 895         default:
 896                 cmn_err(CE_WARN, "!Unable to determine kstat type (%c)", *type);
 897                 setnum = -1;
 898                 break;
 899         }
 900         /*
 901          * The name of the kstat, defined below, is designed to work
 902          * with the 'iostat -x' command.  This command leaves only
 903          * 9 characters for the name, and the kstats built in to Solaris
 904          * all seem to be of the form <service><number>.  For that
 905          * reason, we have chosen ii<type><number>, where <type> is
 906          * m, s, b, or o (for master, shadow, bitmap, and overflow
 907          * respectively), and the number is monotonically increasing from
 908          * 0 for each time one of those <type>s are created.  Note that
 909          * the shadow and bitmap are always created in pairs and so, for
 910          * any given set, they will have the same <number>.
 911          */
 912         (void) sprintf(name, "ii%c%d", *type, setnum);
 913         (void) strncpy(nptr, name, IOSTAT_NAME_LEN);
 914         result = kstat_create("ii", 0, name, "disk", KSTAT_TYPE_IO, 1, 0);
 915         if (result) {
 916                 result->ks_private = ip;
 917                 result->ks_lock = &ip->bi_kstat_io.statmutex;
 918                 kstat_install(result);
 919         } else {
 920                 cmn_err(CE_WARN, "!Unable to create %s kstats for set %s", type,
 921                     ip->bi_keyname);
 922         }
 923 
 924         return (result);
 925 }
 926 
 927 /*
 928  * _ii_overflow_kstat_create
 929  *      Create and install kstat_io data for an overflow volume
 930  *
 931  * Calling/Exit State:
 932  *      Returns 0 if kstats couldn't be created, otherwise it returns
 933  *      a pointer to the created kstat_t.
 934  *
 935  * See comments in _ii_kstat_create for additional information.
 936  *
 937  */
 938 static kstat_t *
 939 _ii_overflow_kstat_create(_ii_info_t *ip, _ii_overflow_t *op)
 940 {
 941         kstat_t *result;
 942         char *nptr;
 943         char name [IOSTAT_NAME_LEN];
 944         static int ovrnum = 0;
 945         int setnum = ovrnum++;
 946 
 947         nptr = ip->bi_kstat_io.ovrio;
 948 
 949         (void) sprintf(name, "iio%d", setnum);
 950         (void) strncpy(nptr, name, IOSTAT_NAME_LEN);
 951 
 952         mutex_init(&op->ii_kstat_mutex, NULL, MUTEX_DRIVER, NULL);
 953 
 954         if ((result =
 955             kstat_create("ii", 0, name, "disk", KSTAT_TYPE_IO, 1, 0))) {
 956                 result->ks_private = ip;
 957                 result->ks_lock = &op->ii_kstat_mutex;
 958                 kstat_install(result);
 959         } else {
 960                 mutex_destroy(&op->ii_kstat_mutex);
 961                 cmn_err(CE_WARN, "!Unabled to create overflow kstat for set "
 962                     "%s", ip->bi_keyname);
 963         }
 964 
 965         return (result);
 966 }
 967 
 968 #endif
 969 
 970 static void
 971 ii_str_kstat_copy(char *str, char *p1, char *p2, char *p3, char *p4)
 972 {
 973         static int whinged = 0;
 974         char *part[ 4 ];
 975         char fulldata[ DSW_NAMELEN ];
 976         int i, offset, remain;
 977         int num_parts;
 978         int leftover;
 979         int kscharsize = KSTAT_DATA_CHAR_LEN - 1;
 980 
 981         /*
 982          * NOTE: the following lines must be changed if DSW_NAMELEN
 983          * ever changes.  You'll need a part[] for every kscharsize
 984          * characters (or fraction thereof).  The ii_kstat_set_t
 985          * definition in dsw_dev.h will also need new ovr_? entries.
 986          */
 987         part[ 0 ] = p1;
 988         part[ 1 ] = p2;
 989         part[ 2 ] = p3;
 990         part[ 3 ] = p4;
 991 
 992         bzero(fulldata, DSW_NAMELEN);
 993         if (str) {
 994                 (void) strncpy(fulldata, str, DSW_NAMELEN);
 995         }
 996 
 997         num_parts = DSW_NAMELEN / kscharsize;
 998         leftover = DSW_NAMELEN % kscharsize;
 999         if (leftover) {
1000                 ++num_parts;
1001         }
1002 
1003         if (num_parts > sizeof (part) / sizeof (part[0])) {
1004                 /*
1005                  * DSW_NAMELEN is 64 and kscharsize is 15.
1006                  * It's always "whinged"
1007                  */
1008                 if (!whinged) {
1009 #ifdef DEBUG
1010                         cmn_err(CE_WARN, "!May not have enough room "
1011                             "to store volume name in kstats");
1012 #endif
1013                         whinged = 1;
1014                 }
1015                 num_parts = sizeof (part) / sizeof (part[0]);
1016         }
1017 
1018         offset = 0;
1019         remain = DSW_NAMELEN;
1020         for (i = 0; i < num_parts; i++) {
1021                 int to_copy = remain > kscharsize? kscharsize : remain;
1022                 bcopy(&fulldata[ offset ], part[ i ], to_copy);
1023                 offset += to_copy;
1024                 remain -= to_copy;
1025         }
1026 }
1027 
1028 static int
1029 ii_set_stats_update(kstat_t *ksp, int rw)
1030 {
1031         _ii_info_t *ip = (_ii_info_t *)ksp->ks_private;
1032         ii_kstat_set_t *kp = (ii_kstat_set_t *)ksp->ks_data;
1033 
1034         if (KSTAT_WRITE == rw) {
1035                 return (EACCES);
1036         }
1037 
1038         /* copy values over */
1039         kp->size.value.ul = ip->bi_size;
1040         kp->flags.value.ul = ip->bi_flags;
1041         kp->unit.value.ul = ip->bi_throttle_unit;
1042         kp->delay.value.ul = ip->bi_throttle_delay;
1043         kp->mtime.value.ul = ip->bi_mtime;
1044 
1045         /* update bitmap counters if necessary */
1046         if (ip->bi_state & DSW_CNTCPYBITS) {
1047                 ip->bi_copybits = 0;
1048                 if (_ii_rsrv_devs(ip, BMP, II_INTERNAL) == 0) {
1049                         ip->bi_state &= ~DSW_CNTCPYBITS;
1050                         II_CNT_BITS(ip, ip->bi_copyfba,
1051                             &ip->bi_copybits,
1052                             DSW_BM_SIZE_BYTES(ip));
1053                         _ii_rlse_devs(ip, BMP);
1054                 }
1055         }
1056 
1057         if (ip->bi_state & DSW_CNTSHDBITS) {
1058                 ip->bi_shdbits = 0;
1059                 if (_ii_rsrv_devs(ip, BMP, II_INTERNAL) == 0) {
1060                         ip->bi_state &= ~DSW_CNTSHDBITS;
1061                         II_CNT_BITS(ip, ip->bi_shdfba,
1062                             &ip->bi_shdbits,
1063                             DSW_BM_SIZE_BYTES(ip));
1064                         _ii_rlse_devs(ip, BMP);
1065                 }
1066         }
1067 
1068         kp->copybits.value.ul = ip->bi_copybits;
1069         kp->shdbits.value.ul = ip->bi_shdbits;
1070 
1071         /* copy volume names */
1072         ii_str_kstat_copy(ii_pathname(MSTFD(ip)),
1073             kp->mst_a.value.c, kp->mst_b.value.c,
1074             kp->mst_c.value.c, kp->mst_d.value.c);
1075 
1076         ii_str_kstat_copy(ip->bi_keyname, kp->set_a.value.c, kp->set_b.value.c,
1077             kp->set_c.value.c, kp->set_d.value.c);
1078 
1079         ii_str_kstat_copy(ii_pathname(ip->bi_bmpfd),
1080             kp->bmp_a.value.c, kp->bmp_b.value.c,
1081             kp->bmp_c.value.c, kp->bmp_d.value.c);
1082 
1083         if (ip->bi_overflow) {
1084                 ii_str_kstat_copy(ip->bi_overflow->ii_volname,
1085                     kp->ovr_a.value.c, kp->ovr_b.value.c, kp->ovr_c.value.c,
1086                     kp->ovr_d.value.c);
1087                 (void) strlcpy(kp->ovr_io.value.c, ip->bi_kstat_io.ovrio,
1088                     KSTAT_DATA_CHAR_LEN);
1089         } else {
1090                 ii_str_kstat_copy("", kp->ovr_a.value.c, kp->ovr_b.value.c,
1091                     kp->ovr_c.value.c, kp->ovr_d.value.c);
1092                 bzero(kp->ovr_io.value.c, KSTAT_DATA_CHAR_LEN);
1093         }
1094         if ((ip->bi_flags) & DSW_TREEMAP) {
1095                 kp->shdchks.value.ul = ip->bi_shdchks;
1096                 kp->shdchkused.value.ul = ip->bi_shdchkused;
1097         } else {
1098                 kp->shdchks.value.ul = 0;
1099                 kp->shdchkused.value.ul = 0;
1100         }
1101         /* make sure value.c are always null terminated */
1102         (void) strlcpy(kp->mst_io.value.c, ip->bi_kstat_io.mstio,
1103             KSTAT_DATA_CHAR_LEN);
1104         (void) strlcpy(kp->shd_io.value.c, ip->bi_kstat_io.shdio,
1105             KSTAT_DATA_CHAR_LEN);
1106         (void) strlcpy(kp->bmp_io.value.c, ip->bi_kstat_io.bmpio,
1107             KSTAT_DATA_CHAR_LEN);
1108 
1109         return (0);
1110 }
1111 
1112 /*
1113  * _ii_config
1114  *      Configure an II device pair
1115  *
1116  * Calling/Exit State:
1117  *      Returns 0 if the pairing was configured, otherwise an
1118  *      error code. The ioctl data stucture is copied out to the user
1119  *      and contains any additional error information, and the master
1120  *      and shadow volume names if not supplied by the user.
1121  *
1122  * Description:
1123  *      Reads the user configuration structure and attempts
1124  *      to establish an II pairing. The snapshot of the master
1125  *      device is established at this point in time.
1126  */
1127 
1128 int
1129 _ii_config(intptr_t arg, int ilp32, int *rvp, int iflags)
1130 {
1131         dsw_config_t uconf;
1132         dsw_config32_t *uconf32;
1133         _ii_info_t *ip, *hip, **ipp;
1134         int rc;
1135         int type;
1136         int nshadows;
1137         int add_to_mst_top;
1138         int import;
1139         int existing;
1140         int resized;
1141         nsc_size_t mst_size, shd_size, bmp_size;
1142         nsc_off_t shdfba;
1143         nsc_off_t copyfba;
1144         int keylen, keyoffset;
1145         ii_header_t *bm_header;
1146         nsc_buf_t *tmp;
1147         spcs_s_info_t kstatus;
1148         spcs_s_info32_t ustatus32;
1149         int rtype;
1150         uint_t hints;
1151 
1152         /* Import is a once only operation like an enable */
1153         ASSERT((iflags&(II_EXISTING|II_IMPORT)) != (II_EXISTING|II_IMPORT));
1154         existing = (iflags&II_EXISTING) != 0;
1155         import = (iflags&II_IMPORT) != 0;
1156         *rvp = 0;
1157         if (ilp32) {
1158                 uconf32 = kmem_zalloc(sizeof (dsw_config32_t), KM_SLEEP);
1159                 if (uconf32 == NULL) {
1160                         return (ENOMEM);
1161                 }
1162                 if (copyin((void *)arg, uconf32, sizeof (*uconf32)) < 0)
1163                         return (EFAULT);
1164                 II_TAIL_COPY(uconf, (*uconf32), master_vol, dsw_config_t);
1165                 uconf.status = (spcs_s_info_t)uconf32->status;
1166                 ustatus32 = uconf32->status;
1167                 kmem_free(uconf32, sizeof (dsw_config32_t));
1168         } else if (copyin((void *)arg, &uconf, sizeof (uconf)) < 0)
1169                 return (EFAULT);
1170 
1171         DTRACE_PROBE3(_ii_config_info, char *, uconf.master_vol,
1172             char *, uconf.shadow_vol, char *, uconf.bitmap_vol);
1173 
1174         kstatus = spcs_s_kcreate();
1175         if (kstatus == NULL)
1176                 return (ENOMEM);
1177 
1178         if (_ii_shutting_down)
1179                 return (spcs_s_ocopyoutf(&kstatus, uconf.status,
1180                     DSW_ESHUTDOWN));
1181 
1182         if (uconf.bitmap_vol[0] == 0)
1183                 return (spcs_s_ocopyoutf(&kstatus, uconf.status, DSW_EEMPTY));
1184 
1185         mutex_enter(&_ii_config_mutex);
1186         ip = nsc_kmem_zalloc(sizeof (*ip), KM_SLEEP, _ii_local_mem);
1187         if (!ip) {
1188                 mutex_exit(&_ii_config_mutex);
1189                 return (spcs_s_ocopyoutf(&kstatus, uconf.status, ENOMEM));
1190         }
1191         ip->bi_mstdev = nsc_kmem_zalloc(sizeof (*ip->bi_mstdev), KM_SLEEP,
1192             _ii_local_mem);
1193         ip->bi_mstrdev = nsc_kmem_zalloc(sizeof (*ip->bi_mstdev), KM_SLEEP,
1194             _ii_local_mem);
1195         if (ip->bi_mstdev == NULL || ip->bi_mstrdev == NULL) {
1196                 mutex_exit(&_ii_config_mutex);
1197                 _ii_info_free(ip);
1198                 return (spcs_s_ocopyoutf(&kstatus, uconf.status, ENOMEM));
1199         }
1200 
1201         ip->bi_disabled = 1; /* mark as disabled until we are ready to go */
1202         mutex_init(&ip->bi_mutex, NULL, MUTEX_DRIVER, NULL);
1203         mutex_init(&ip->bi_bmpmutex, NULL, MUTEX_DRIVER, NULL);
1204         mutex_init(&ip->bi_rsrvmutex, NULL, MUTEX_DRIVER, NULL);
1205         mutex_init(&ip->bi_rlsemutex, NULL, MUTEX_DRIVER, NULL);
1206         mutex_init(&ip->bi_chksmutex, NULL, MUTEX_DRIVER, NULL);
1207         cv_init(&ip->bi_copydonecv, NULL, CV_DRIVER, NULL);
1208         cv_init(&ip->bi_reservecv, NULL, CV_DRIVER, NULL);
1209         cv_init(&ip->bi_releasecv, NULL, CV_DRIVER, NULL);
1210         cv_init(&ip->bi_ioctlcv, NULL, CV_DRIVER, NULL);
1211         cv_init(&ip->bi_closingcv, NULL, CV_DRIVER, NULL);
1212         cv_init(&ip->bi_busycv, NULL, CV_DRIVER, NULL);
1213         rw_init(&ip->bi_busyrw, NULL, RW_DRIVER, NULL);
1214         rw_init(&ip->bi_linkrw, NULL, RW_DRIVER, NULL);
1215         (void) strncpy(ip->bi_keyname, uconf.shadow_vol, DSW_NAMELEN);
1216         ip->bi_keyname[DSW_NAMELEN-1] = '\0';
1217         ip->bi_throttle_unit = ii_throttle_unit;
1218         ip->bi_throttle_delay = ii_throttle_delay;
1219 
1220         /* First check the list to see if uconf.bitmap_vol's already there */
1221 
1222         if (ii_volume(uconf.bitmap_vol, 0) != NONE) {
1223                 DTRACE_PROBE(_ii_config_bmp_found);
1224                 mutex_exit(&_ii_config_mutex);
1225                 _ii_info_free(ip);
1226                 return (spcs_s_ocopyoutf(&kstatus, uconf.status, DSW_EINUSE));
1227         }
1228 
1229         ip->bi_bmpfd = nsc_open(uconf.bitmap_vol,
1230             NSC_IIR_ID|NSC_FILE|NSC_RDWR, NULL, (blind_t)&(ip->bi_bmpdev), &rc);
1231         if (!ip->bi_bmpfd)
1232                 ip->bi_bmpfd = nsc_open(uconf.bitmap_vol,
1233                     NSC_IIR_ID|NSC_CACHE|NSC_DEVICE|NSC_RDWR, NULL,
1234                     (blind_t)&(ip->bi_bmpdev), &rc);
1235         if (!ip->bi_bmpfd && !existing) {
1236                 mutex_exit(&_ii_config_mutex);
1237                 _ii_info_free(ip);
1238                 spcs_s_add(kstatus, rc);
1239                 DTRACE_PROBE(_ii_config_no_bmp);
1240                 return (spcs_s_ocopyoutf(&kstatus, uconf.status, DSW_EOPEN));
1241         }
1242 
1243         if (import) {
1244                 uconf.flag = DSW_GOLDEN;
1245                 II_FLAG_SETX(DSW_SHDIMPORT|DSW_GOLDEN, ip);
1246         }
1247 
1248         if (existing) {
1249 
1250                 DTRACE_PROBE(_ii_config_existing);
1251                 /*
1252                  * ii_config is used by enable, import and resume (existing)
1253                  * If not importing or resuming, then this must be enable.
1254                  * Indicate this fact for SNMP use.
1255                  */
1256 
1257                 if (!ip->bi_bmpfd) {
1258                         /*
1259                          * Couldn't read bitmap, mark master and shadow as
1260                          * unusable.
1261                          */
1262                         II_FLAG_ASSIGN(DSW_BMPOFFLINE|DSW_MSTOFFLINE|
1263                             DSW_SHDOFFLINE, ip);
1264 
1265                         /*
1266                          * Set cluster tag for this element so it can
1267                          * be suspended later
1268                          */
1269                         (void) II_LINK_CLUSTER(ip, uconf.cluster_tag);
1270 
1271                         /* need to check on master, might be shared */
1272                         goto header_checked;
1273                 }
1274                 /* check the header */
1275                 (void) _ii_rsrv_devs(ip, BMP, II_INTERNAL);
1276 
1277                 /* get first block of bit map */
1278                 mutex_enter(&ip->bi_mutex);
1279                 bm_header = _ii_bm_header_get(ip, &tmp);
1280                 mutex_exit(&ip->bi_mutex);
1281                 if (bm_header == NULL) {
1282                         if (ii_debug > 0)
1283                                 cmn_err(CE_WARN,
1284                                     "!ii: _ii_bm_header_get returned NULL");
1285                         mutex_exit(&_ii_config_mutex);
1286                         _ii_info_free(ip);
1287                         return (spcs_s_ocopyoutf(&kstatus, uconf.status,
1288                             DSW_EHDRBMP));
1289                 }
1290 
1291                 if (bm_header->ii_magic != DSW_DIRTY &&
1292                     bm_header->ii_magic != DSW_CLEAN) {
1293                         mutex_exit(&_ii_config_mutex);
1294                         _ii_bm_header_free(bm_header, ip, tmp);
1295                         _ii_info_free(ip);
1296                         return (spcs_s_ocopyoutf(&kstatus, uconf.status,
1297                             DSW_EINVALBMP));
1298                 }
1299 
1300                 II_FLAG_ASSIGN(bm_header->ii_state, ip);
1301                 /* Restore copy throttle parameters, if header version is 3 */
1302                 if (bm_header->ii_version >= 3) { /* II_HEADER_VERSION */
1303                         ip->bi_throttle_delay = bm_header->ii_throttle_delay;
1304                         ip->bi_throttle_unit  = bm_header->ii_throttle_unit;
1305                 }
1306 
1307                 /* Restore cluster & group names, if header version is 4 */
1308                 if (bm_header->ii_version >= 4) {
1309                         /* cluster */
1310                         if (*bm_header->clstr_name) {
1311                                 (void) strncpy(uconf.cluster_tag,
1312                                     bm_header->clstr_name, DSW_NAMELEN);
1313                                 (void) II_LINK_CLUSTER(ip, uconf.cluster_tag);
1314                         }
1315 
1316                         /* group */
1317                         if (*bm_header->group_name) {
1318                                 (void) strncpy(uconf.group_name,
1319                                     bm_header->group_name, DSW_NAMELEN);
1320                                 (void) II_LINK_GROUP(ip, uconf.group_name);
1321                         }
1322                 }
1323                 /* restore latest modification time, if header version >= 5 */
1324                 if (bm_header->ii_version >= 5) {
1325                         ip->bi_mtime = bm_header->ii_mtime;
1326                 }
1327 
1328                 /* Fetch master and shadow names from bitmap header */
1329                 if (uconf.master_vol[0] == 0)
1330                         (void) strncpy(uconf.master_vol, bm_header->master_vol,
1331                             DSW_NAMELEN);
1332                 if (uconf.shadow_vol[0] == 0)
1333                         (void) strncpy(uconf.shadow_vol, bm_header->shadow_vol,
1334                             DSW_NAMELEN);
1335 
1336                 /* return the fetched names to the user */
1337                 if (ilp32) {
1338                         uconf32 = kmem_zalloc(sizeof (dsw_config32_t),
1339                             KM_SLEEP);
1340                         if (uconf32 == NULL) {
1341                                 mutex_exit(&_ii_config_mutex);
1342                                 _ii_bm_header_free(bm_header, ip, tmp);
1343                                 _ii_rlse_devs(ip, BMP);
1344                                 _ii_info_free(ip);
1345                                 return (ENOMEM);
1346                         }
1347                         uconf32->status = ustatus32;
1348                         II_TAIL_COPY((*uconf32), uconf, master_vol,
1349                             dsw_config32_t);
1350                         rc = copyout(uconf32, (void *)arg, sizeof (*uconf32));
1351                         kmem_free(uconf32, sizeof (dsw_config32_t));
1352                 } else {
1353                         rc = copyout(&uconf, (void *)arg, sizeof (uconf));
1354                 }
1355                 if (rc) {
1356                         mutex_exit(&_ii_config_mutex);
1357                         _ii_bm_header_free(bm_header, ip, tmp);
1358                         _ii_rlse_devs(ip, BMP);
1359                         _ii_info_free(ip);
1360                         return (EFAULT);
1361                 }
1362 
1363                 if (strncmp(bm_header->bitmap_vol, uconf.bitmap_vol,
1364                     DSW_NAMELEN) || ((!(ip->bi_flags&DSW_SHDIMPORT)) &&
1365                     strncmp(bm_header->master_vol, uconf.master_vol,
1366                     DSW_NAMELEN)) || strncmp(bm_header->shadow_vol,
1367                     uconf.shadow_vol, DSW_NAMELEN)) {
1368                         mutex_exit(&_ii_config_mutex);
1369                         _ii_bm_header_free(bm_header, ip, tmp);
1370                         _ii_rlse_devs(ip, BMP);
1371                         _ii_info_free(ip);
1372                         return (spcs_s_ocopyoutf(&kstatus, uconf.status,
1373                             DSW_EMISMATCH));
1374                 }
1375                 shdfba = bm_header->ii_shdfba;
1376                 copyfba = bm_header->ii_copyfba;
1377                 if ((ip->bi_flags)&DSW_TREEMAP) {
1378                         if (ii_debug > 0)
1379                                 cmn_err(CE_NOTE,
1380                                     "!II: Resuming short shadow volume");
1381 
1382                         ip->bi_mstchks = bm_header->ii_mstchks;
1383                         ip->bi_shdchks = bm_header->ii_shdchks;
1384                         ip->bi_shdchkused = bm_header->ii_shdchkused;
1385                         ip->bi_shdfchk = bm_header->ii_shdfchk;
1386 
1387                         if (bm_header->overflow_vol[0] != 0)
1388                                 if ((rc = ii_overflow_attach(ip,
1389                                     bm_header->overflow_vol, 0)) != 0) {
1390                                         mutex_exit(&_ii_config_mutex);
1391                                         _ii_bm_header_free(bm_header, ip, tmp);
1392                                         _ii_rlse_devs(ip, BMP);
1393                                         _ii_info_free(ip);
1394                                         return (spcs_s_ocopyoutf(&kstatus,
1395                                             uconf.status, rc));
1396                         }
1397                 }
1398                 _ii_bm_header_free(bm_header, ip, tmp);
1399                 _ii_rlse_devs(ip, BMP);
1400         }
1401 header_checked:
1402 
1403         if (ip->bi_flags&DSW_SHDIMPORT)
1404                 (void) strcpy(uconf.master_vol, "<imported shadow>");
1405         if (!uconf.master_vol[0] || !uconf.shadow_vol[0]) {
1406                 mutex_exit(&_ii_config_mutex);
1407                 _ii_info_free(ip);
1408                 return (spcs_s_ocopyoutf(&kstatus, uconf.status, DSW_EEMPTY));
1409         }
1410 
1411         /* check that no volume has been given twice */
1412         if (strncmp(uconf.master_vol, uconf.shadow_vol, DSW_NAMELEN) == 0) {
1413                 mutex_exit(&_ii_config_mutex);
1414                 _ii_info_free(ip);
1415                 return (spcs_s_ocopyoutf(&kstatus, uconf.status, DSW_EOPEN));
1416         }
1417 
1418         if (strncmp(uconf.master_vol, uconf.bitmap_vol, DSW_NAMELEN) == 0) {
1419                 mutex_exit(&_ii_config_mutex);
1420                 _ii_info_free(ip);
1421                 return (spcs_s_ocopyoutf(&kstatus, uconf.status, DSW_EOPEN));
1422         }
1423 
1424         if (strncmp(uconf.bitmap_vol, uconf.shadow_vol, DSW_NAMELEN) == 0) {
1425                 mutex_exit(&_ii_config_mutex);
1426                 _ii_info_free(ip);
1427                 return (spcs_s_ocopyoutf(&kstatus, uconf.status, DSW_EOPEN));
1428         }
1429 
1430         /* check that master is not already a bitmap, shadow or overflow */
1431         type = ii_volume(uconf.master_vol, 1);
1432         if (type != NONE && type != MST) {
1433                 mutex_exit(&_ii_config_mutex);
1434                 _ii_info_free(ip);
1435                 return (spcs_s_ocopyoutf(&kstatus, uconf.status, DSW_EINUSE));
1436         }
1437 
1438         /* check that shadow is not used as anything else */
1439         type = ii_volume(uconf.shadow_vol, 1);
1440         if (type != NONE && type != SHD) {
1441                 mutex_exit(&_ii_config_mutex);
1442                 _ii_info_free(ip);
1443                 return (spcs_s_ocopyoutf(&kstatus, uconf.status, DSW_EINUSE));
1444         }
1445 
1446         /* Setup the table bitmap operations table */
1447         switch (ii_bitmap) {
1448         case II_KMEM:
1449                 if (ii_debug > 0)
1450                         cmn_err(CE_NOTE, "!ii: using volatile bitmaps");
1451                 ip->bi_bitmap_ops = &kmem_buf_bmp;
1452                 break;
1453         case II_FWC:
1454                 hints = 0;
1455                 (void) nsc_node_hints(&hints);
1456                 if ((hints & NSC_FORCED_WRTHRU) == 0)
1457                         ip->bi_bitmap_ops = &kmem_buf_bmp;
1458                 else
1459                         ip->bi_bitmap_ops = &alloc_buf_bmp;
1460                 if (ii_debug > 0) {
1461                         cmn_err(CE_NOTE, "!ii: chosen to use %s bitmaps",
1462                             ip->bi_bitmap_ops == &kmem_buf_bmp ?
1463                             "volatile" : "persistent");
1464                 }
1465                 break;
1466         case II_WTHRU:
1467         default:
1468                 if (ii_debug > 0)
1469                         cmn_err(CE_NOTE, "!ii: using persistent bitmaps");
1470                 ip->bi_bitmap_ops = &alloc_buf_bmp;
1471                 break;
1472         }
1473 
1474         /*
1475          * If we found aother shadow volume with the same name,
1476          * If this is an resume operation,
1477          * If this shadow is in the exported state
1478          * then try an on the fly join instead
1479          */
1480         for (hip = _ii_info_top; hip; hip = hip->bi_next)
1481                 if (strcmp(uconf.shadow_vol, hip->bi_keyname) == 0)
1482                                 break;
1483         if ((hip) && (type == SHD) && existing &&
1484             (ip->bi_flags & DSW_SHDEXPORT)) {
1485 
1486                 /*
1487                  * Stop any copy in progress
1488                  */
1489                 while (_ii_stopcopy(hip) == EINTR)
1490                         ;
1491 
1492                 /*
1493                  * Start the imported shadow teardown
1494                  */
1495                 mutex_enter(&hip->bi_mutex);
1496 
1497                 /* disable accesss to imported shadow */
1498                 hip->bi_disabled = 1;
1499 
1500                 /* Wait for any I/O's to complete */
1501                 while (hip->bi_ioctl) {
1502                         hip->bi_state |= DSW_IOCTL;
1503                         cv_wait(&hip->bi_ioctlcv, &hip->bi_mutex);
1504                 }
1505                 mutex_exit(&hip->bi_mutex);
1506 
1507                 /* this rw_enter forces us to drain all active IO */
1508                 rw_enter(&hip->bi_linkrw, RW_WRITER);
1509                 rw_exit(&hip->bi_linkrw);
1510 
1511                 /* remove ip from _ii_info_top linked list */
1512                 mutex_enter(&_ii_info_mutex);
1513                 for (ipp = &_ii_info_top; *ipp; ipp = &((*ipp)->bi_next)) {
1514                         if (hip == *ipp) {
1515                                 *ipp = hip->bi_next;
1516                                 break;
1517                         }
1518                 }
1519                 if (hip->bi_kstat) {
1520                         kstat_delete(hip->bi_kstat);
1521                         hip->bi_kstat = NULL;
1522                 }
1523                 mutex_exit(&_ii_info_mutex);
1524 
1525                 /* Gain access to both bitmap volumes */
1526                 rtype = BMP;
1527                 if (((rc = _ii_rsrv_devs(hip, rtype, II_INTERNAL)) != 0) ||
1528                     ((rc = _ii_rsrv_devs(ip, rtype, II_INTERNAL)) != 0)) {
1529                         mutex_exit(&_ii_config_mutex);
1530                         _ii_info_free(ip);
1531                         return (spcs_s_ocopyoutf(&kstatus, uconf.status, rc));
1532                 }
1533 
1534                 /* Merge imported bitmap */
1535                 rc = II_JOIN_BMP(ip, hip);
1536 
1537                 /* Release access to bitmap volume */
1538                 _ii_rlse_devs(hip, rtype);
1539                 ii_sibling_free(hip);
1540 
1541                 /* Clear the fact that we are exported */
1542                 mutex_enter(&ip->bi_mutex);
1543                 II_FLAG_CLR(DSW_SHDEXPORT, ip);
1544 
1545                 /* Release resources */
1546                 mutex_exit(&ip->bi_mutex);
1547                 _ii_rlse_devs(ip, BMP);
1548 
1549         } else if (type != NONE) {
1550                 mutex_exit(&_ii_config_mutex);
1551                 _ii_info_free(ip);
1552                 return (spcs_s_ocopyoutf(&kstatus, uconf.status, DSW_EINUSE));
1553         }
1554 
1555         /*
1556          * Handle non-exported shadow
1557          */
1558         if ((ip->bi_flags & DSW_SHDEXPORT) == 0) {
1559                 if ((rc = ii_open_shadow(ip, uconf.shadow_vol)) != 0) {
1560                         mutex_exit(&_ii_config_mutex);
1561                         _ii_info_free(ip);
1562                         spcs_s_add(kstatus, rc);
1563                         return (spcs_s_ocopyoutf(&kstatus, uconf.status,
1564                             DSW_EOPEN));
1565                 }
1566         }
1567 
1568         /*
1569          * allocate _ii_concopy_sema and set to a value that won't allow
1570          * all cache to be allocated by copy loops.
1571          */
1572 
1573         if (_ii_concopy_init == 0 && ip->bi_bmpfd != NULL) {
1574                 int asize = 0, wsize;
1575                 nsc_size_t cfbas, maxfbas;
1576 
1577                 (void) nsc_cache_sizes(&asize, &wsize);
1578 
1579                 if (asize > 0) {
1580                         cfbas = FBA_NUM(asize);
1581                         (void) _ii_rsrv_devs(ip, BMP, II_INTERNAL);
1582                         rc = nsc_maxfbas(ip->bi_bmpfd, 0, &maxfbas);
1583                         _ii_rlse_devs(ip, BMP);
1584                         if (!II_SUCCESS(rc))
1585                                 maxfbas = 1024;         /* i.e. _SD_MAX_FBAS */
1586                         ii_nconcopy = cfbas / (maxfbas * 2) / 3;
1587                 }
1588                 if (ii_nconcopy < 2)
1589                         ii_nconcopy = 2;
1590                 ASSERT(ii_nconcopy > 0);
1591                 sema_init(&_ii_concopy_sema, ii_nconcopy, NULL,
1592                     SEMA_DRIVER, NULL);
1593                 _ii_concopy_init = 1;
1594         }
1595 
1596         /* check for shared master volume */
1597         for (hip = _ii_mst_top; hip; hip = hip->bi_nextmst)
1598                 if (strcmp(uconf.master_vol, ii_pathname(hip->bi_mstfd)) == 0)
1599                         break;
1600         add_to_mst_top = (hip == NULL);
1601         if (!hip)
1602                 for (hip = _ii_info_top; hip; hip = hip->bi_next)
1603                         if (strcmp(uconf.master_vol,
1604                             ii_pathname(hip->bi_mstfd)) == 0)
1605                                 break;
1606         nshadows = (hip != NULL);
1607 
1608         /* Check if master is offline */
1609         if (hip) {
1610                 if (hip->bi_flags & DSW_MSTOFFLINE) {
1611                         mutex_exit(&_ii_config_mutex);
1612                         _ii_info_free(ip);
1613                         return (spcs_s_ocopyoutf(&kstatus, uconf.status,
1614                             DSW_EOFFLINE));
1615                 }
1616         }
1617 
1618         if (!nshadows && (ip->bi_flags&DSW_SHDIMPORT) == 0) {
1619                 ip->bi_mstfd = nsc_open(uconf.master_vol,
1620                     NSC_IIR_ID|NSC_DEVICE|NSC_RDWR, _ii_fd_def,
1621                     (blind_t)(ip->bi_mstdev), &rc);
1622                 if (!ip->bi_mstfd) {
1623                         mutex_exit(&_ii_config_mutex);
1624                         _ii_info_free(ip);
1625                         spcs_s_add(kstatus, rc);
1626                         return (spcs_s_ocopyoutf(&kstatus, uconf.status,
1627                             DSW_EOPEN));
1628                 }
1629 
1630                 ip->bi_mstrfd = nsc_open(uconf.master_vol,
1631                     NSC_IIR_ID|NSC_DEVICE|NSC_RDWR, _ii_fd_def,
1632                     (blind_t)(ip->bi_mstrdev), &rc);
1633                 if (!ip->bi_mstrfd) {
1634                         mutex_exit(&_ii_config_mutex);
1635                         _ii_info_free(ip);
1636                         spcs_s_add(kstatus, rc);
1637                         return (spcs_s_ocopyoutf(&kstatus, uconf.status,
1638                             DSW_EOPEN));
1639                 }
1640         }
1641 
1642         ip->bi_head = ip;
1643         ip->bi_master = ip;
1644 
1645         mutex_enter(&_ii_info_mutex);
1646         ip->bi_next = _ii_info_top;
1647         _ii_info_top = ip;
1648         if (nshadows) {
1649                 /* link new shadow group together with others sharing master */
1650                 if (ii_debug > 0)
1651                         cmn_err(CE_NOTE,
1652                             "!II: shadow %s shares master %s with other shadow"
1653                             " groups", uconf.shadow_vol, uconf.master_vol);
1654                 hip = hip->bi_head;
1655                 nsc_kmem_free(ip->bi_mstrdev, sizeof (*ip->bi_mstrdev));
1656                 nsc_kmem_free(ip->bi_mstdev, sizeof (*ip->bi_mstdev));
1657                 ip->bi_mstrdev = hip->bi_mstrdev;
1658                 ip->bi_mstdev = hip->bi_mstdev;
1659                 ip->bi_head = hip;
1660                 ip->bi_sibling = hip->bi_sibling;
1661                 if (add_to_mst_top) {
1662                         hip->bi_nextmst = _ii_mst_top;
1663                         _ii_mst_top = hip;
1664                 }
1665                 hip->bi_sibling = ip;
1666                 ip->bi_master = ip->bi_head->bi_master;
1667         }
1668         mutex_exit(&_ii_info_mutex);
1669         mutex_exit(&_ii_config_mutex);
1670 
1671         keylen = strlen(ip->bi_keyname);
1672         if (keylen > KSTAT_STRLEN - 1) {
1673                 keyoffset = keylen + 1 - KSTAT_STRLEN;
1674         } else {
1675                 keyoffset = 0;
1676         }
1677         ip->bi_kstat = kstat_create("ii", _ii_instance++,
1678             &ip->bi_keyname[ keyoffset ], "iiset", KSTAT_TYPE_NAMED,
1679             sizeof (ii_kstat_set) / sizeof (kstat_named_t),
1680             KSTAT_FLAG_VIRTUAL);
1681         if (ip->bi_kstat) {
1682                 ip->bi_kstat->ks_data = &ii_kstat_set;
1683                 ip->bi_kstat->ks_update = ii_set_stats_update;
1684                 ip->bi_kstat->ks_private = ip;
1685                 kstat_install(ip->bi_kstat);
1686         } else {
1687                 cmn_err(CE_WARN, "!Unable to create set-specific kstats");
1688         }
1689 
1690 #ifndef DISABLE_KSTATS
1691         /* create kstats information */
1692         mutex_init(&ip->bi_kstat_io.statmutex, NULL, MUTEX_DRIVER, NULL);
1693         if (ip == ip->bi_master) {
1694                 ip->bi_kstat_io.master = _ii_kstat_create(ip, "master");
1695         } else {
1696                 ip->bi_kstat_io.master = ip->bi_master->bi_kstat_io.master;
1697                 (void) strlcpy(ip->bi_kstat_io.mstio,
1698                     ip->bi_master->bi_kstat_io.mstio, KSTAT_DATA_CHAR_LEN);
1699         }
1700         ip->bi_kstat_io.shadow = _ii_kstat_create(ip, "shadow");
1701         ip->bi_kstat_io.bitmap = _ii_kstat_create(ip, "bitmap");
1702 #endif
1703 
1704         (void) _ii_reserve_begin(ip);
1705         rtype = MSTR|SHDR|BMP;
1706         if ((rc = _ii_rsrv_devs(ip, rtype, II_INTERNAL)) != 0) {
1707                 spcs_s_add(kstatus, rc);
1708                 rc = DSW_ERSRVFAIL;
1709                 goto fail;
1710         }
1711 
1712         if (ip->bi_flags&DSW_SHDIMPORT) {
1713                 rc = 0;         /* no master for imported volumes */
1714                 mst_size = 0;
1715         } else
1716                 rc = nsc_partsize(MSTFD(ip), &mst_size);
1717         if (rc == 0 && (ip->bi_flags&DSW_SHDEXPORT) == 0)
1718                 rc = nsc_partsize(SHDFD(ip), &shd_size);
1719         if (!ip->bi_bmpfd)
1720                 rc = EINVAL;
1721         if (rc == 0)
1722                 rc = nsc_partsize(ip->bi_bmpfd, &bmp_size);
1723 
1724         if (ip->bi_flags&DSW_SHDIMPORT)
1725                 ip->bi_size = shd_size;
1726         else
1727                 ip->bi_size = mst_size;
1728 
1729         if ((((ip->bi_flags&DSW_SHDIMPORT) != DSW_SHDIMPORT) &&
1730             (mst_size < 1)) ||
1731             (((ip->bi_flags&DSW_SHDEXPORT) != DSW_SHDEXPORT) &&
1732             (shd_size < 1)) ||
1733             ((rc == 0) && (bmp_size < 1))) {
1734                 /* could be really zero, or could be > 1 TB; fail the enable */
1735                 rc = EINVAL;
1736         }
1737 
1738         if (rc != 0) {  /* rc set means an nsc_partsize() failed */
1739                 /*
1740                  * If existing group, mark bitmap as offline and set
1741                  * bmp_size to "right size".
1742                  */
1743                 if (existing) {
1744                         bmp_size = 2 * DSW_BM_FBA_LEN(mst_size) +
1745                             DSW_SHD_BM_OFFSET;
1746                         goto no_more_bmp_tests;
1747                 }
1748                 spcs_s_add(kstatus, rc);
1749                 rc = DSW_EPARTSIZE;
1750                 _ii_rlse_devs(ip, rtype);
1751                 _ii_reserve_end(ip);
1752                 goto fail;
1753         }
1754 
1755         if (ip->bi_flags&DSW_SHDIMPORT)
1756                 mst_size = shd_size;
1757         if (ip->bi_flags&DSW_SHDEXPORT)
1758                 shd_size = mst_size;
1759         /*
1760          * Check with RDC if the master & shadow sizes are different.
1761          * Once II is enabled, the shadow size will be made to appear
1762          * the same as the master, and this will panic RDC if we're
1763          * changing sizes on it.
1764          */
1765         resized = (shd_size != mst_size);
1766         if (resized && ii_need_same_size(ip)) {
1767                 cmn_err(CE_WARN, "!Cannot enable II set: would change volume "
1768                     "size on RDC");
1769                 rc = DSW_EOPACKAGE;
1770                 _ii_rlse_devs(ip, rtype);
1771                 _ii_reserve_end(ip);
1772                 goto fail;
1773         }
1774         if (bmp_size < 2 * DSW_BM_FBA_LEN(mst_size) + DSW_SHD_BM_OFFSET) {
1775                 /* bitmap volume too small */
1776                 if (ii_debug > 0)
1777                         cmn_err(CE_NOTE,
1778                             "!ii: invalid sizes: bmp %" NSC_SZFMT " mst %"
1779                             NSC_SZFMT " %" NSC_SZFMT "",
1780                             bmp_size, mst_size, DSW_BM_FBA_LEN(mst_size));
1781                 rc = DSW_EBMPSIZE;
1782                 _ii_rlse_devs(ip, rtype);
1783                 _ii_reserve_end(ip);
1784                 goto fail;
1785         }
1786         if ((shd_size < mst_size) && (uconf.flag&DSW_GOLDEN) != 0) {
1787                 /* shadow volume too small */
1788                 if (ii_debug > 0)
1789                         cmn_err(CE_NOTE, "!shd size too small (%" NSC_SZFMT
1790                             ") for independent set's master (%" NSC_SZFMT ")",
1791                             shd_size, mst_size);
1792                 rc = DSW_ESHDSIZE;
1793                 _ii_rlse_devs(ip, rtype);
1794                 _ii_reserve_end(ip);
1795                 goto fail;
1796         }
1797 
1798         ip->bi_busy = kmem_zalloc(1 + (ip->bi_size / (DSW_SIZE * DSW_BITS)),
1799             KM_SLEEP);
1800         if (!ip->bi_busy) {
1801                 rc = ENOMEM;
1802                 _ii_rlse_devs(ip, rtype);
1803                 _ii_reserve_end(ip);
1804                 goto fail;
1805         }
1806 
1807         if (existing == 0) {
1808 
1809                 DTRACE_PROBE(_ii_config);
1810 
1811                 /* first time this shadow has been set up */
1812                 mutex_enter(&ip->bi_mutex);
1813                 bm_header = _ii_bm_header_get(ip, &tmp);
1814                 mutex_exit(&ip->bi_mutex);
1815                 if (bm_header == NULL) {
1816                         if (ii_debug > 0)
1817                                 cmn_err(CE_WARN,
1818                                     "!ii: _ii_bm_header_get returned NULL");
1819                         rc = DSW_EHDRBMP;
1820                         _ii_rlse_devs(ip, rtype);
1821                         _ii_reserve_end(ip);
1822                         goto fail;
1823                 }
1824                 bzero(bm_header, sizeof (*bm_header));
1825                 /* copy pathnames into it */
1826                 (void) strncpy(bm_header->master_vol, uconf.master_vol,
1827                     DSW_NAMELEN);
1828                 (void) strncpy(bm_header->shadow_vol, uconf.shadow_vol,
1829                     DSW_NAMELEN);
1830                 (void) strncpy(bm_header->bitmap_vol, uconf.bitmap_vol,
1831                     DSW_NAMELEN);
1832                 (void) strncpy(bm_header->clstr_name, uconf.cluster_tag,
1833                     DSW_NAMELEN);
1834                 (void) strncpy(bm_header->group_name, uconf.group_name,
1835                     DSW_NAMELEN);
1836 
1837                 if (uconf.cluster_tag[0] != 0)
1838                         (void) II_LINK_CLUSTER(ip, uconf.cluster_tag);
1839 
1840                 if (uconf.group_name[0] != 0)
1841                         (void) II_LINK_GROUP(ip, uconf.group_name);
1842 
1843 
1844                 bm_header->ii_state = (uconf.flag & DSW_GOLDEN);
1845                 II_FLAG_ASSIGN(bm_header->ii_state, ip);
1846 
1847                 if (import) {
1848                         II_FLAG_SETX(DSW_SHDIMPORT, ip);
1849                         bm_header->ii_state |= DSW_SHDIMPORT;
1850                 }
1851                 if (resized) {
1852                         II_FLAG_SETX(DSW_RESIZED, ip);
1853                         bm_header->ii_state |= DSW_RESIZED;
1854                 }
1855                 bm_header->ii_type = (uconf.flag & DSW_GOLDEN) ?
1856                     DSW_GOLDEN_TYPE : DSW_QUICK_TYPE;
1857                 bm_header->ii_magic = DSW_DIRTY;
1858                 bm_header->ii_version = II_HEADER_VERSION;
1859                 bm_header->ii_shdfba = DSW_SHD_BM_OFFSET;
1860                 bm_header->ii_copyfba = DSW_COPY_BM_OFFSET;
1861                 bm_header->ii_throttle_delay = ip->bi_throttle_delay;
1862                 bm_header->ii_throttle_unit = ip->bi_throttle_unit;
1863                 ip->bi_shdfba = bm_header->ii_shdfba;
1864                 ip->bi_copyfba = bm_header->ii_copyfba;
1865                 ip->bi_mtime = ddi_get_time();
1866 
1867                 /* write it to disk */
1868                 mutex_enter(&ip->bi_mutex);
1869                 rc = _ii_bm_header_put(bm_header, ip, tmp);
1870                 mutex_exit(&ip->bi_mutex);
1871                 if (!II_SUCCESS(rc)) {
1872                         spcs_s_add(kstatus, rc);
1873                         rc = DSW_EHDRBMP;
1874                         _ii_rlse_devs(ip, rtype);
1875                         _ii_reserve_end(ip);
1876                         goto fail;
1877                 }
1878                 if ((shd_size < mst_size) && (uconf.flag & DSW_GOLDEN) == 0) {
1879                 /*
1880                  * shadow volume smaller than master, must use a dependent
1881                  * copy with a bitmap file stored mapping for chunk locations.
1882                  */
1883                                         /* number of chunks in shadow volume */
1884                         nsc_size_t shd_chunks;
1885                         nsc_size_t bmp_chunks;
1886                         nsc_size_t tmp_chunks;
1887 
1888                         if (ii_debug > 1)
1889                                 cmn_err(CE_NOTE, "!ii: using tree index on %s",
1890                                     uconf.master_vol);
1891                         shd_chunks = shd_size / DSW_SIZE;
1892                         /* do not add in partial chunk at end */
1893 
1894                         ip->bi_mstchks = mst_size / DSW_SIZE;
1895                         if (mst_size % DSW_SIZE != 0)
1896                                 ip->bi_mstchks++;
1897                         bmp_chunks = ii_btsize(bmp_size - ip->bi_copyfba -
1898                             DSW_BM_FBA_LEN(ip->bi_size));
1899                         tmp_chunks = ip->bi_copyfba +
1900                             DSW_BM_FBA_LEN(ip->bi_size);
1901                         if (bmp_chunks < (nsc_size_t)ip->bi_mstchks) {
1902                                 if (ii_debug > -1) {
1903                                         cmn_err(CE_NOTE, "!ii: bitmap vol too"
1904                                             "small: %" NSC_SZFMT " vs. %"
1905                                             NSC_SZFMT, bmp_size,
1906                                             tmp_chunks);
1907                                 }
1908                                 spcs_s_add(kstatus, rc);
1909                                 rc = DSW_EHDRBMP;
1910                                 _ii_rlse_devs(ip, rtype);
1911                                 _ii_reserve_end(ip);
1912                                 goto fail;
1913                         }
1914                         mutex_enter(&ip->bi_mutex);
1915                         II_FLAG_SET(DSW_TREEMAP, ip);
1916                         mutex_exit(&ip->bi_mutex);
1917 
1918                         /* following values are written to header by ii_tinit */
1919 #if (defined(NSC_MULTI_TERABYTE) && !defined(II_MULTIMULTI_TERABYTE))
1920                         ASSERT(shd_chunks <= INT32_MAX);
1921                         ASSERT(mst_size / DSW_SIZE <= INT32_MAX);
1922 #endif
1923                         ip->bi_mstchks = mst_size / DSW_SIZE;
1924                         if (mst_size % DSW_SIZE != 0)
1925                                 ip->bi_mstchks++;
1926 #ifdef  II_MULTIMULTI_TERABYTE
1927                         ip->bi_shdchks = shd_chunks;
1928 #else
1929                         /* still have 31 bit chunkid's */
1930                         ip->bi_shdchks = (chunkid_t)shd_chunks;
1931 #endif
1932                         ip->bi_shdchkused = 0;
1933                         rc = ii_tinit(ip);
1934                 } else {
1935                         ip->bi_shdchks = shd_size / DSW_SIZE;
1936                         ip->bi_shdchkused = 0;
1937                 }
1938                 if (rc == 0)
1939                         rc = II_LOAD_BMP(ip, 1);
1940                 if (rc == 0)
1941                         rc = II_ZEROBM(ip);
1942                 if (rc == 0)
1943                         rc = II_COPYBM(ip);     /* also clear copy bitmap */
1944                 if (rc == 0 && (uconf.flag & DSW_GOLDEN) && !import)
1945                         rc = ii_fill_copy_bmp(ip);
1946                 if (rc) {
1947                         spcs_s_add(kstatus, rc);
1948                         rc = DSW_EHDRBMP;
1949                         _ii_rlse_devs(ip, rtype);
1950                         goto fail;
1951                 }
1952                 /* check that changing shadow won't upset RDC */
1953                 if (ii_update_denied(ip, kstatus, 0, 1)) {
1954                         rc = DSW_EOPACKAGE;
1955                         _ii_rlse_devs(ip, rtype);
1956                         _ii_reserve_end(ip);
1957                         goto fail;
1958                 }
1959                 ip->bi_disabled = 0; /* all okay and ready, we can go now */
1960                 _ii_rlse_devs(ip, rtype);
1961                 /* no _ii_reserve_end() here - we must register first */
1962                 ip->bi_bmp_tok = _ii_register_path(ii_pathname(ip->bi_bmpfd),
1963                     NSC_CACHE|NSC_DEVICE, _ii_io);
1964                 if (!nshadows)
1965                         ii_register_mst(ip);
1966                 ii_register_shd(ip);
1967 
1968                 if (!ii_register_ok(ip)) {
1969                         ip->bi_disabled = 1; /* argh */
1970                         rc = DSW_EREGISTER;
1971                         goto fail;
1972                 }
1973                 /* no _ii_reserve_begin() here -- we're still in process */
1974                 (void) _ii_rsrv_devs(ip, rtype, II_INTERNAL);
1975 
1976                 if (ii_debug > 0)
1977                         cmn_err(CE_NOTE, "!ii: config: master %s shadow %s",
1978                             uconf.master_vol, uconf.shadow_vol);
1979                 rc = 0;
1980                 if ((uconf.flag & DSW_GOLDEN) && !import) {
1981                         mutex_enter(&ip->bi_mutex);
1982                         II_FLAG_SET(DSW_COPYINGM | DSW_COPYINGP, ip);
1983                         ip->bi_ioctl++;      /* we are effectively in an ioctl */
1984                         mutex_exit(&ip->bi_mutex);
1985                         rc = _ii_copyvol(ip, 0, rtype, kstatus, 1);
1986                 }
1987                 _ii_rlse_devs(ip, rtype);
1988                 _ii_reserve_end(ip);
1989 
1990                 ++iigkstat.num_sets.value.ul;
1991 
1992                 return (spcs_s_ocopyoutf(&kstatus, uconf.status, rc));
1993         }
1994 
1995         ip->bi_shdchks = shd_size / DSW_SIZE;
1996         ip->bi_shdfba = shdfba;
1997         ip->bi_copyfba = copyfba;
1998         rc = II_LOAD_BMP(ip, 0);                /* reload saved bitmap */
1999         mutex_enter(&ip->bi_mutex);
2000         if (rc == 0)
2001                 bm_header = _ii_bm_header_get(ip, &tmp);
2002         mutex_exit(&ip->bi_mutex);
2003         if (rc || bm_header == NULL) {
2004                 if (existing) {
2005                         goto no_more_bmp_tests;
2006                 }
2007                 rc = DSW_EHDRBMP;
2008                 goto fail;
2009         }
2010 
2011         /*
2012          * If the header is dirty and it wasn't kept on persistent storage
2013          * then the bitmaps must be assumed to be bad.
2014          */
2015         if (bm_header->ii_magic == DSW_DIRTY &&
2016             ip->bi_bitmap_ops != &alloc_buf_bmp) {
2017                 type = bm_header->ii_type;
2018                 _ii_bm_header_free(bm_header, ip, tmp);
2019                 if (type == DSW_GOLDEN_TYPE) {
2020                         if ((ip->bi_flags & DSW_COPYINGM) != 0)
2021                                 _ii_error(ip, DSW_SHDOFFLINE);
2022                         else if ((ip->bi_flags & DSW_COPYINGS) != 0)
2023                                 _ii_error(ip, DSW_MSTOFFLINE);
2024                         else {
2025                                 /* No copying, so they're just different */
2026                                 rc = ii_fill_copy_bmp(ip);
2027                                 if (rc) {
2028                                         spcs_s_add(kstatus, rc);
2029                                         rc = DSW_EHDRBMP;
2030                                         goto fail;
2031                                 }
2032                         }
2033                 } else
2034                         _ii_error(ip, DSW_SHDOFFLINE);
2035 
2036                 mutex_enter(&ip->bi_mutex);
2037                 bm_header = _ii_bm_header_get(ip, &tmp);
2038                 mutex_exit(&ip->bi_mutex);
2039                 if (bm_header == NULL) {
2040                         rc = DSW_EHDRBMP;
2041                         goto fail;
2042                 }
2043         }
2044 
2045         bm_header->ii_magic = DSW_DIRTY;
2046         mutex_enter(&ip->bi_mutex);
2047         rc = _ii_bm_header_put(bm_header, ip, tmp);
2048         mutex_exit(&ip->bi_mutex);
2049         if (!II_SUCCESS(rc)) {
2050                 spcs_s_add(kstatus, rc);
2051                 rc = DSW_EHDRBMP;
2052                 goto fail;
2053         }
2054 
2055         ip->bi_bmp_tok = _ii_register_path(ii_pathname(ip->bi_bmpfd),
2056             NSC_CACHE|NSC_DEVICE, _ii_io);
2057 no_more_bmp_tests:
2058         _ii_rlse_devs(ip, rtype);
2059         ip->bi_disabled = 0; /* all okay and ready, we can go now */
2060         if (!nshadows)
2061                 ii_register_mst(ip);
2062         if ((ip->bi_flags & DSW_SHDEXPORT) == 0)
2063                 ii_register_shd(ip);
2064 
2065         if (!ii_register_ok(ip)) {
2066                 rc = DSW_EREGISTER;
2067                 goto fail;
2068         }
2069         _ii_reserve_end(ip);
2070 
2071         if (ii_debug > 0)
2072                 cmn_err(CE_NOTE, "!ii: config: master %s shadow %s",
2073                     uconf.master_vol, uconf.shadow_vol);
2074 
2075         rc = 0;
2076         if (ip->bi_flags & DSW_COPYINGP) {
2077                 /* Copy was in progress, so continue it */
2078                 (void) _ii_rsrv_devs(ip, rtype, II_INTERNAL);
2079                 mutex_enter(&ip->bi_mutex);
2080                 ip->bi_ioctl++;              /* we are effectively in an ioctl */
2081                 mutex_exit(&ip->bi_mutex);
2082                 rc = _ii_copyvol(ip, ((ip->bi_flags & DSW_COPYINGS) != 0) ?
2083                     CV_SHD2MST : 0, rtype, kstatus, 0);
2084         }
2085 
2086         ++iigkstat.num_sets.value.ul;
2087 
2088         return (spcs_s_ocopyoutf(&kstatus, uconf.status, rc));
2089 
2090 fail:
2091         /* remove ip from _ii_info_top linked list */
2092         mutex_enter(&_ii_info_mutex);
2093         for (ipp = &_ii_info_top; *ipp; ipp = &((*ipp)->bi_next)) {
2094                 if (ip == *ipp) {
2095                         *ipp = ip->bi_next;
2096                         break;
2097                 }
2098         }
2099         mutex_exit(&_ii_info_mutex);
2100         ii_sibling_free(ip);
2101 
2102         return (spcs_s_ocopyoutf(&kstatus, uconf.status, rc));
2103 }
2104 
2105 static int
2106 _ii_perform_disable(char *setname, spcs_s_info_t *kstatusp, int reclaim)
2107 {
2108         _ii_info_t **xip, *ip;
2109         _ii_overflow_t *op;
2110         nsc_buf_t *tmp = NULL;
2111         int rc;
2112         ii_header_t *bm_header;
2113         int rtype;
2114 
2115         mutex_enter(&_ii_info_mutex);
2116         ip = _ii_find_set(setname);
2117         if (ip == NULL) {
2118                 mutex_exit(&_ii_info_mutex);
2119                 return (DSW_ENOTFOUND);
2120         }
2121 
2122         if ((ip->bi_flags & DSW_GOLDEN) &&
2123             ((ip->bi_flags & DSW_COPYINGP) != 0)) {
2124                 /*
2125                  * Cannot disable an independent copy while still copying
2126                  * as it means that a data dependency exists.
2127                  */
2128                 mutex_exit(&_ii_info_mutex);
2129                 _ii_ioctl_done(ip);
2130                 mutex_exit(&ip->bi_mutex);
2131                 DTRACE_PROBE(_ii_perform_disable_end_DSW_EDEPENDENCY);
2132                 return (DSW_EDEPENDENCY);
2133         }
2134 
2135         if ((ip->bi_flags & DSW_GOLDEN) == 0 &&
2136             ii_update_denied(ip, *kstatusp, 0, 1)) {
2137                 /* Cannot disable a dependent shadow while RDC is unsure */
2138                 mutex_exit(&_ii_info_mutex);
2139                 _ii_ioctl_done(ip);
2140                 mutex_exit(&ip->bi_mutex);
2141                 DTRACE_PROBE(DSW_EOPACKAGE);
2142                 return (DSW_EOPACKAGE);
2143         }
2144 
2145         if (((ip->bi_flags & DSW_RESIZED) == DSW_RESIZED) &&
2146             ii_need_same_size(ip)) {
2147                 /* We can't disable the set whilst RDC is using it */
2148                 mutex_exit(&_ii_info_mutex);
2149                 _ii_ioctl_done(ip);
2150                 mutex_exit(&ip->bi_mutex);
2151                 cmn_err(CE_WARN, "!Cannot disable II set: would change "
2152                     "volume size on RDC");
2153                 DTRACE_PROBE(DSW_EOPACKAGE_resize);
2154                 return (DSW_EOPACKAGE);
2155         }
2156 
2157         ip->bi_disabled = 1;
2158         if (NSHADOWS(ip) && (ip->bi_master == ip)) {
2159                 ip->bi_flags &= (~DSW_COPYING);
2160                 ip->bi_state |= DSW_MULTIMST;
2161         }
2162         mutex_exit(&_ii_info_mutex);
2163 
2164         _ii_ioctl_done(ip);
2165         mutex_exit(&ip->bi_mutex);
2166 
2167         _ii_stopvol(ip);
2168 
2169         rtype = SHDR|BMP;
2170         if ((rc = _ii_rsrv_devs(ip, rtype, II_INTERNAL)) != 0) {
2171                 spcs_s_add(*kstatusp, rc);
2172                 DTRACE_PROBE(DSW_ERSRVFAIL);
2173                 return (DSW_ERSRVFAIL);
2174         }
2175 
2176         if ((ii_header < 128) &&
2177             (((ip->bi_flags & DSW_GOLDEN) == 0) ||
2178             (ip->bi_flags & DSW_COPYING))) {
2179                 /*
2180                  * Not a full copy so attempt to prevent use of partial copy
2181                  * by clearing where the first ufs super-block would be
2182                  * located. Solaris often incorporates the disk header into
2183                  * the start of the first slice, so avoid clearing the very
2184                  * first 16 blocks of the volume.
2185                  */
2186 
2187                 if (ii_debug > 1)
2188                         cmn_err(CE_NOTE, "!ii: Shadow copy invalidated");
2189                 II_READ_START(ip, shadow);
2190                 rc = nsc_alloc_buf(SHDFD(ip), ii_header, 128 - ii_header,
2191                     NSC_RDWRBUF, &tmp);
2192                 II_READ_END(ip, shadow, rc, 128 - ii_header);
2193                 if (II_SUCCESS(rc)) {
2194                         rc = nsc_zero(tmp, ii_header, 128 - ii_header, 0);
2195                         if (II_SUCCESS(rc)) {
2196                                 II_NSC_WRITE(ip, shadow, rc, tmp, ii_header,
2197                                     (128 - ii_header), 0);
2198                         }
2199                 }
2200                 if (tmp)
2201                         (void) nsc_free_buf(tmp);
2202                 if (!II_SUCCESS(rc))
2203                         _ii_error(ip, DSW_SHDOFFLINE);
2204         }
2205 
2206         /* this rw_enter forces us to drain all active IO */
2207         rw_enter(&ip->bi_linkrw, RW_WRITER);
2208         rw_exit(&ip->bi_linkrw);
2209 
2210         /* remove ip from _ii_info_top linked list */
2211         mutex_enter(&_ii_info_mutex);
2212         for (xip = &_ii_info_top; *xip; xip = &((*xip)->bi_next)) {
2213                 if (ip == *xip) {
2214                         *xip = ip->bi_next;
2215                         break;
2216                 }
2217         }
2218         if (ip->bi_kstat) {
2219                 kstat_delete(ip->bi_kstat);
2220                 ip->bi_kstat = NULL;
2221         }
2222         mutex_exit(&_ii_info_mutex);
2223 
2224         rc = II_SAVE_BMP(ip, 1);
2225         mutex_enter(&ip->bi_mutex);
2226         if (rc == 0)
2227                 bm_header = _ii_bm_header_get(ip, &tmp);
2228         if (rc == 0 && bm_header) {
2229                 if (ii_debug > 1)
2230                         cmn_err(CE_NOTE, "!ii: Invalid header written");
2231                 bm_header->ii_magic = DSW_INVALID;
2232                 /* write it to disk */
2233                 (void) _ii_bm_header_put(bm_header, ip, tmp);
2234         }
2235         mutex_exit(&ip->bi_mutex);
2236 
2237         op = ip->bi_overflow;
2238         if (op && (reclaim == -1)) {
2239                 reclaim = (op->ii_drefcnt == 1? NO_RECLAIM : RECLAIM);
2240         }
2241 
2242         if ((op != NULL) && (op->ii_hversion >= 1) &&
2243             (op->ii_hmagic == II_OMAGIC)) {
2244                 mutex_enter(&_ii_overflow_mutex);
2245                 if (ip->bi_flags & DSW_OVRHDRDRTY) {
2246                         mutex_enter(&ip->bi_mutex);
2247                         ip->bi_flags &= ~DSW_OVRHDRDRTY;
2248                         mutex_exit(&ip->bi_mutex);
2249                         ASSERT(op->ii_urefcnt > 0);
2250                         op->ii_urefcnt--;
2251                 }
2252                 if (op->ii_urefcnt == 0) {
2253                         op->ii_flags &= ~IIO_CNTR_INVLD;
2254                         op->ii_unused = op->ii_nchunks - 1;
2255                 }
2256                 mutex_exit(&_ii_overflow_mutex);
2257         }
2258         ii_overflow_free(ip, reclaim);
2259         _ii_rlse_devs(ip, rtype);
2260 
2261         ii_sibling_free(ip);
2262 
2263         --iigkstat.num_sets.value.ul;
2264         return (0);
2265 }
2266 
2267 /*
2268  * _ii_disable
2269  *      Deconfigures an II pair
2270  *
2271  * Calling/Exit State:
2272  *      Returns 0 if the pair was disabled. Otherwise an error code
2273  *      is returned and any additional error information is copied
2274  *      out to the user.
2275  *
2276  * Description:
2277  *      Reads the user configuration structure and attempts to
2278  *      deconfigure that pairing based on the master device pathname.
2279  */
2280 
2281 int
2282 _ii_disable(intptr_t arg, int ilp32, int *rvp)
2283 {
2284         dsw_ioctl_t uparms;
2285         dsw_ioctl32_t uparms32;
2286         _ii_overflow_t *op;
2287         int rc, rerr;
2288         spcs_s_info_t kstatus;
2289         uint64_t hash;
2290         int reclaim;
2291         _ii_lsthead_t *oldhead, **head;
2292         _ii_lstinfo_t *np, **xnp, *oldp;
2293 
2294         *rvp = 0;
2295 
2296         if (ilp32) {
2297                 if (copyin((void *)arg, &uparms32, sizeof (uparms32)) < 0)
2298                         return (EFAULT);
2299                 II_TAIL_COPY(uparms, uparms32, shadow_vol, dsw_ioctl_t);
2300                 uparms.status = (spcs_s_info_t)uparms32.status;
2301         } else if (copyin((void *)arg, &uparms, sizeof (uparms)) < 0)
2302                 return (EFAULT);
2303 
2304         kstatus = spcs_s_kcreate();
2305         if (kstatus == NULL)
2306                 return (ENOMEM);
2307 
2308         if (!uparms.shadow_vol[0])
2309                 return (spcs_s_ocopyoutf(&kstatus, uparms.status, DSW_EEMPTY));
2310 
2311         DTRACE_PROBE2(_ii_disable_info, char *, uparms.shadow_vol,
2312             int, uparms.flags);
2313 
2314         /* group or single set? */
2315         if (uparms.flags & CV_IS_GROUP) {
2316                 hash = nsc_strhash(uparms.shadow_vol);
2317                 mutex_enter(&_ii_group_mutex);
2318                 for (head = &_ii_group_top; *head;
2319                     head = &((*head)->lst_next)) {
2320                         if ((hash == (*head)->lst_hash) &&
2321                             strncmp((*head)->lst_name, uparms.shadow_vol,
2322                             DSW_NAMELEN) == 0)
2323                                 break;
2324                 }
2325 
2326                 if (!*head) {
2327                         mutex_exit(&_ii_group_mutex);
2328                         return (spcs_s_ocopyoutf(&kstatus, uparms.status,
2329                             DSW_EGNOTFOUND));
2330                 }
2331 
2332                 /* clear any overflow vol usage counts */
2333                 for (np = (*head)->lst_start; np; np = np->lst_next) {
2334                         if (np->lst_ip->bi_overflow) {
2335                                 np->lst_ip->bi_overflow->ii_detachcnt = 0;
2336                         }
2337                 }
2338 
2339                 /* now increment */
2340                 for (np = (*head)->lst_start; np; np = np->lst_next) {
2341                         if (np->lst_ip->bi_overflow) {
2342                                 ++np->lst_ip->bi_overflow->ii_detachcnt;
2343                         }
2344                 }
2345 
2346                 /* finally, disable all group members */
2347                 rerr = 0;
2348                 xnp = &(*head)->lst_start;
2349                 while (*xnp) {
2350                         op = (*xnp)->lst_ip->bi_overflow;
2351                         if (op) {
2352                                 reclaim = (op->ii_drefcnt == op->ii_detachcnt?
2353                                     NO_RECLAIM : RECLAIM);
2354                                 --op->ii_detachcnt;
2355                         }
2356 
2357                         /* clear out the group pointer */
2358                         (*xnp)->lst_ip->bi_group = NULL;
2359 
2360                         rc = _ii_perform_disable((*xnp)->lst_ip->bi_keyname,
2361                             &kstatus, reclaim);
2362                         if (rc) {
2363                                 /* restore group name */
2364                                 (*xnp)->lst_ip->bi_group = (*head)->lst_name;
2365 
2366                                 /* restore detachcnt */
2367                                 if (op) {
2368                                         ++op->ii_detachcnt;
2369                                 }
2370 
2371                                 /* don't delete branch */
2372                                 ++rerr;
2373                                 spcs_s_add(kstatus, rc);
2374 
2375                                 /* move forward in linked list */
2376                                 xnp = &(*xnp)->lst_next;
2377                         } else {
2378                                 oldp = (*xnp);
2379                                 *xnp = (*xnp)->lst_next;
2380                                 kmem_free(oldp, sizeof (_ii_lstinfo_t));
2381                         }
2382                 }
2383                 if (rerr) {
2384                         mutex_exit(&_ii_group_mutex);
2385                         return (spcs_s_ocopyoutf(&kstatus, uparms.status,
2386                             DSW_EDISABLE));
2387                 }
2388                 /* no errors, all sets disabled, OK to free list head */
2389                 oldhead = *head;
2390                 *head = (*head)->lst_next;
2391                 kmem_free(oldhead, sizeof (_ii_lsthead_t));
2392                 mutex_exit(&_ii_group_mutex);
2393         } else {
2394                 /* only a single set is being disabled */
2395                 rc = _ii_perform_disable(uparms.shadow_vol, &kstatus, -1);
2396                 if (rc)
2397                         return (spcs_s_ocopyoutf(&kstatus, uparms.status, rc));
2398         }
2399 
2400         spcs_s_kfree(kstatus);
2401 
2402         return (0);
2403 }
2404 
2405 
2406 /*
2407  * _ii_stat
2408  *      Get state of the shadow.
2409  *
2410  * Calling/Exit State:
2411  *      Returns 0 on success, otherwise an error code is returned
2412  *      and any additional error information is copied out to the user.
2413  *      The size variable in the dsw_stat_t is set to the FBA size
2414  *      of the volume, the stat variable is set to the state, and
2415  *      the structure is copied out.
2416  */
2417 /*ARGSUSED*/
2418 int
2419 _ii_stat(intptr_t arg, int ilp32, int *rvp)
2420 {
2421         dsw_stat_t ustat;
2422         dsw_stat32_t ustat32;
2423         _ii_info_t *ip;
2424         spcs_s_info_t kstatus;
2425         char *group, *cluster;
2426 
2427         if (ilp32) {
2428                 if (copyin((void *)arg, &ustat32, sizeof (ustat32)) < 0)
2429                         return (EFAULT);
2430                 II_TAIL_COPY(ustat, ustat32, shadow_vol, dsw_stat_t);
2431                 ustat.status = (spcs_s_info_t)ustat32.status;
2432         } else if (copyin((void *)arg, &ustat, sizeof (ustat)) < 0)
2433                 return (EFAULT);
2434 
2435         kstatus = spcs_s_kcreate();
2436         if (kstatus == NULL)
2437                 return (ENOMEM);
2438 
2439         if (!ustat.shadow_vol[0])
2440                 return (spcs_s_ocopyoutf(&kstatus, ustat.status, DSW_EEMPTY));
2441 
2442         mutex_enter(&_ii_info_mutex);
2443         ip = _ii_find_set(ustat.shadow_vol);
2444         mutex_exit(&_ii_info_mutex);
2445         if (ip == NULL)
2446                 return (spcs_s_ocopyoutf(&kstatus, ustat.status,
2447                     DSW_ENOTFOUND));
2448 
2449         ustat.stat = ip->bi_flags;
2450         ustat.size = ip->bi_size;
2451         ustat.mtime = ip->bi_mtime;
2452 
2453         if (ilp32)
2454                 bzero(ustat32.overflow_vol, DSW_NAMELEN);
2455         else
2456                 bzero(ustat.overflow_vol, DSW_NAMELEN);
2457         if (ip->bi_overflow) {
2458                 (void) strncpy(ilp32 ? ustat32.overflow_vol :
2459                     ustat.overflow_vol, ip->bi_overflow->ii_volname,
2460                     DSW_NAMELEN);
2461         }
2462 
2463         ustat.shdsize = ip->bi_shdchks;
2464         if ((ip->bi_flags) & DSW_TREEMAP) {
2465                 ustat.shdused = ip->bi_shdchkused;
2466         } else {
2467                 ustat.shdused = 0;
2468         }
2469 
2470         /* copy over group and cluster associations */
2471         group = ilp32? ustat32.group_name : ustat.group_name;
2472         cluster = ilp32? ustat32.cluster_tag : ustat.cluster_tag;
2473         bzero(group, DSW_NAMELEN);
2474         bzero(cluster, DSW_NAMELEN);
2475         if (ip->bi_group)
2476                 (void) strncpy(group, ip->bi_group, DSW_NAMELEN);
2477         if (ip->bi_cluster)
2478                 (void) strncpy(cluster, ip->bi_cluster, DSW_NAMELEN);
2479 
2480         _ii_ioctl_done(ip);
2481         mutex_exit(&ip->bi_mutex);
2482 
2483         spcs_s_kfree(kstatus);
2484         if (ilp32) {
2485                 ustat32.stat = ustat.stat;
2486                 ustat32.size = ustat.size;
2487                 ustat32.shdsize = ustat.shdsize;
2488                 ustat32.shdused = ustat.shdused;
2489                 ustat32.mtime = ustat.mtime;
2490                 if (copyout(&ustat32, (void *)arg, sizeof (ustat32)))
2491                         return (EFAULT);
2492         } else if (copyout(&ustat, (void *)arg, sizeof (ustat)))
2493                 return (EFAULT);
2494 
2495         return (0);
2496 }
2497 
2498 
2499 /*
2500  * _ii_list
2501  *      List what shadow sets are currently configured.
2502  *
2503  * Calling/Exit State:
2504  *      Returns 0 on success, otherwise an error code is returned
2505  *      and any additional error information is copied out to the user.
2506  */
2507 /*ARGSUSED*/
2508 int
2509 _ii_list(intptr_t arg, int ilp32, int *rvp)
2510 {
2511         dsw_list_t ulist;
2512         dsw_list32_t ulist32;
2513         _ii_info_t *ip;
2514         dsw_config_t cf, *cfp;
2515         dsw_config32_t cf32, *cf32p;
2516         int rc;
2517         int used;
2518         spcs_s_info_t kstatus;
2519 
2520         if (ilp32) {
2521                 if (copyin((void *)arg, &ulist32, sizeof (ulist32)) < 0)
2522                         return (EFAULT);
2523                 II_TAIL_COPY(ulist, ulist32, list_size, dsw_list_t);
2524                 ulist.status = (spcs_s_info_t)ulist32.status;
2525         } else if (copyin((void *)arg, &ulist, sizeof (ulist)) < 0)
2526                 return (EFAULT);
2527 
2528         kstatus = spcs_s_kcreate();
2529         if (kstatus == NULL)
2530                 return (ENOMEM);
2531 
2532         cf32p = (dsw_config32_t *)(unsigned long)ulist32.list;
2533         cfp = ulist.list;
2534         ulist.list_used = 0;
2535         mutex_enter(&_ii_info_mutex);
2536         ip = _ii_info_top;
2537 
2538         DTRACE_PROBE1(_ii_list_count, int, ulist.list_size);
2539 
2540         for (rc = used = 0; used < ulist.list_size && ip; ip = ip->bi_next) {
2541 
2542                 if (ip->bi_disabled)
2543                         continue;
2544 
2545                 mutex_enter(&ip->bi_mutex);
2546                 ip->bi_ioctl++;
2547                 if (ilp32) {
2548                         bzero(&cf32, sizeof (cf32));
2549                         cf32.flag = ip->bi_flags;
2550                         (void) strncpy(cf32.master_vol,
2551                             ii_pathname(ip->bi_mstfd), DSW_NAMELEN);
2552                         (void) strncpy(cf32.shadow_vol,
2553                             ip->bi_keyname, DSW_NAMELEN);
2554                         (void) strncpy(cf32.bitmap_vol, (ip->bi_bmpfd)
2555                             ? ii_pathname(ip->bi_bmpfd)
2556                             : "<offline_bitmap>", DSW_NAMELEN);
2557                         if (copyout(&cf32, (void *)cf32p, sizeof (cf32)))
2558                                 rc = EFAULT;
2559                         cf32p++;
2560                 } else {
2561                         bzero(&cf, sizeof (cf));
2562                         cf.flag = ip->bi_flags;
2563                         (void) strncpy(cf.master_vol,
2564                             ii_pathname(ip->bi_mstfd), DSW_NAMELEN);
2565                         (void) strncpy(cf.shadow_vol,
2566                             ip->bi_keyname, DSW_NAMELEN);
2567                         (void) strncpy(cf.bitmap_vol, (ip->bi_bmpfd)
2568                             ? ii_pathname(ip->bi_bmpfd)
2569                             : "<offline_bitmap>", DSW_NAMELEN);
2570                         if (copyout(&cf, (void *)cfp, sizeof (cf)))
2571                                 rc = EFAULT;
2572                         cfp++;
2573                 }
2574                 _ii_ioctl_done(ip);
2575                 mutex_exit(&ip->bi_mutex);
2576                 used++;
2577         }
2578         mutex_exit(&_ii_info_mutex);
2579 
2580         spcs_s_kfree(kstatus);
2581         if (rc)
2582                 return (rc);
2583 
2584         ulist.list_used = used;
2585         if (ilp32) {
2586                 ulist32.list_used = ulist.list_used;
2587                 if (copyout(&ulist32, (void *)arg, sizeof (ulist32)))
2588                         return (EFAULT);
2589         } else if (copyout(&ulist, (void *)arg, sizeof (ulist)))
2590                 return (EFAULT);
2591 
2592         return (0);
2593 }
2594 
2595 /*
2596  * _ii_listlen
2597  *      Counts the number of items the DSWIOC_LIST and DSWIOC_OLIST
2598  *      ioctl calls would return.
2599  *
2600  * Calling/Exit State:
2601  *      Returns 0 on success, otherwise an error code is returned.
2602  *      Result is returned as successful ioctl value.
2603  */
2604 /*ARGSUSED*/
2605 int
2606 _ii_listlen(int cmd, int ilp32, int *rvp)
2607 {
2608         _ii_info_t *ip;
2609         _ii_overflow_t *op;
2610         int count = 0;
2611 
2612         switch (cmd) {
2613 
2614         case DSWIOC_LISTLEN:
2615                 mutex_enter(&_ii_info_mutex);
2616                 for (ip = _ii_info_top; ip; ip = ip->bi_next) {
2617                         if (ip->bi_disabled == 0) {
2618                                 count++;
2619                         }
2620                 }
2621                 mutex_exit(&_ii_info_mutex);
2622                 break;
2623         case DSWIOC_OLISTLEN:
2624                 mutex_enter(&_ii_overflow_mutex);
2625                 for (op = _ii_overflow_top; op; op = op->ii_next)
2626                         count++;
2627                 mutex_exit(&_ii_overflow_mutex);
2628                 break;
2629         default:
2630                 return (EINVAL);
2631         }
2632         *rvp = count;
2633 
2634         return (0);
2635 }
2636 
2637 /*
2638  * _ii_report_bmp
2639  *
2640  *      Report to the user daemon that the bitmap has gone bad
2641  */
2642 static int
2643 _ii_report_bmp(_ii_info_t *ip)
2644 {
2645         int rc;
2646         struct nskernd *nsk;
2647 
2648         nsk = kmem_zalloc(sizeof (*nsk), KM_SLEEP);
2649         if (!nsk) {
2650                 return (ENOMEM);
2651         }
2652         nsk->command = NSKERND_IIBITMAP;
2653         nsk->data1 = (int64_t)(ip->bi_flags | DSW_BMPOFFLINE);
2654         (void) strncpy(nsk->char1, ip->bi_keyname,
2655             min(DSW_NAMELEN, NSC_MAXPATH));
2656 
2657         rc = nskernd_get(nsk);
2658         if (rc == 0) {
2659                 rc = (int)nsk->data1;
2660         }
2661         if (rc == 0) {
2662                 DTRACE_PROBE(_ii_report_bmp_end);
2663         } else {
2664                 DTRACE_PROBE1(_ii_report_bmp_end_2, int, rc);
2665         }
2666         kmem_free(nsk, sizeof (*nsk));
2667         return (rc);
2668 }
2669 
2670 /*
2671  * _ii_offline
2672  *      Set volume offline flag(s) for a shadow.
2673  *
2674  * Calling/Exit State:
2675  *      Returns 0 on success, otherwise an error code is returned
2676  *      and any additional error information is copied out to the user.
2677  */
2678 /*ARGSUSED*/
2679 int
2680 _ii_offline(intptr_t arg, int ilp32, int *rvp)
2681 {
2682         dsw_ioctl_t uparms;
2683         dsw_ioctl32_t uparms32;
2684         _ii_info_t *ip;
2685         int rc;
2686         spcs_s_info_t kstatus;
2687 
2688         if (ilp32) {
2689                 if (copyin((void *)arg, &uparms32, sizeof (uparms32)) < 0)
2690                         return (EFAULT);
2691                 II_TAIL_COPY(uparms, uparms32, shadow_vol, dsw_ioctl_t);
2692                 uparms.status = (spcs_s_info_t)uparms32.status;
2693         } else if (copyin((void *)arg, &uparms, sizeof (uparms)) < 0)
2694                 return (EFAULT);
2695 
2696         kstatus = spcs_s_kcreate();
2697         if (kstatus == NULL)
2698                 return (ENOMEM);
2699 
2700         if (!uparms.shadow_vol[0])
2701                 return (spcs_s_ocopyoutf(&kstatus, uparms.status, DSW_EEMPTY));
2702 
2703         mutex_enter(&_ii_info_mutex);
2704         ip = _ii_find_set(uparms.shadow_vol);
2705         mutex_exit(&_ii_info_mutex);
2706         if (ip == NULL)
2707                 return (spcs_s_ocopyoutf(&kstatus, uparms.status,
2708                     DSW_ENOTFOUND));
2709 
2710         if ((rc = _ii_rsrv_devs(ip, BMP, II_INTERNAL)) != 0) {
2711                 _ii_ioctl_done(ip);
2712                 mutex_exit(&ip->bi_mutex);
2713                 spcs_s_add(kstatus, rc);
2714                 return (spcs_s_ocopyoutf(&kstatus, uparms.status,
2715                     DSW_ERSRVFAIL));
2716         }
2717 
2718         mutex_exit(&ip->bi_mutex);
2719         _ii_error(ip, uparms.flags & DSW_OFFLINE);
2720         mutex_enter(&ip->bi_mutex);
2721         _ii_ioctl_done(ip);
2722         mutex_exit(&ip->bi_mutex);
2723 
2724         _ii_rlse_devs(ip, BMP);
2725 
2726         spcs_s_kfree(kstatus);
2727 
2728         return (0);
2729 }
2730 
2731 
2732 /*
2733  * _ii_wait
2734  *      Wait for a copy to complete.
2735  *
2736  * Calling/Exit State:
2737  *      Returns 0 if the copy completed, otherwise error code.
2738  *
2739  */
2740 /*ARGSUSED*/
2741 int
2742 _ii_wait(intptr_t arg, int ilp32, int *rvp)
2743 {
2744         dsw_ioctl_t uparms;
2745         dsw_ioctl32_t uparms32;
2746         _ii_info_t *ip;
2747         int rc = 0;
2748         spcs_s_info_t kstatus;
2749 
2750         if (ilp32) {
2751                 if (copyin((void *)arg, &uparms32, sizeof (uparms32)) < 0)
2752                         return (EFAULT);
2753                 II_TAIL_COPY(uparms, uparms32, shadow_vol, dsw_ioctl_t);
2754                 uparms.status = (spcs_s_info_t)uparms32.status;
2755                 uparms.pid = uparms32.pid;
2756         } else if (copyin((void *)arg, &uparms, sizeof (uparms)) < 0)
2757                 return (EFAULT);
2758 
2759         kstatus = spcs_s_kcreate();
2760         if (kstatus == NULL)
2761                 return (ENOMEM);
2762 
2763         if (!uparms.shadow_vol[0])
2764                 return (spcs_s_ocopyoutf(&kstatus, uparms.status, DSW_EEMPTY));
2765 
2766         mutex_enter(&_ii_info_mutex);
2767         ip = _ii_find_set(uparms.shadow_vol);
2768         mutex_exit(&_ii_info_mutex);
2769         if (ip == NULL)
2770                 return (spcs_s_ocopyoutf(&kstatus, uparms.status,
2771                     DSW_ENOTFOUND));
2772 
2773         while (ip->bi_flags & DSW_COPYINGP) {
2774                 if (cv_wait_sig(&ip->bi_copydonecv, &ip->bi_mutex) == 0) {
2775                         /* Awoken by a signal */
2776                         rc = EINTR;
2777                         break;
2778                 }
2779         }
2780 
2781         /* Is this an attempt to unlock the copy/update PID? */
2782         if (uparms.flags & CV_LOCK_PID) {
2783                 if (ip->bi_locked_pid == 0) {
2784                         rc = DSW_ENOTLOCKED;
2785                 } else if (uparms.pid == -1) {
2786                         cmn_err(CE_WARN, "!ii: Copy/Update PID %d, cleared",
2787                             ip->bi_locked_pid);
2788                         ip->bi_locked_pid = 0;
2789                 } else if (uparms.pid != ip->bi_locked_pid) {
2790                         rc = DSW_EINUSE;
2791                 } else {
2792                         ip->bi_locked_pid = 0;
2793                 }
2794         }
2795 
2796         _ii_ioctl_done(ip);
2797         mutex_exit(&ip->bi_mutex);
2798 
2799         return (spcs_s_ocopyoutf(&kstatus, uparms.status, rc));
2800 }
2801 
2802 
2803 static int
2804 _ii_reset_mstvol(_ii_info_t *ip)
2805 {
2806         _ii_info_t *xip;
2807 
2808         if (!NSHADOWS(ip))
2809                 return (DSW_COPYINGS | DSW_COPYINGP);
2810 
2811         /* check for siblings updating master */
2812         for (xip = ip->bi_head; xip; xip = xip->bi_sibling) {
2813                 if (xip == ip)
2814                         continue;
2815                 /* check if master is okay */
2816                 if ((xip->bi_flags & DSW_MSTOFFLINE) == 0) {
2817                         return (0);
2818                 }
2819         }
2820 
2821         return (DSW_COPYINGS | DSW_COPYINGP);
2822 }
2823 
2824 /*
2825  * _ii_reset
2826  *      Reset offlined underlying volumes
2827  *
2828  * Calling/Exit State:
2829  *      Returns 0 on success, otherwise an error code is returned
2830  *      and any additional error information is copied out to the user.
2831  */
2832 /*ARGSUSED*/
2833 int
2834 _ii_reset(intptr_t arg, int ilp32, int *rvp)
2835 {
2836         dsw_ioctl_t uparms;
2837         dsw_ioctl32_t uparms32;
2838         _ii_info_t *ip;
2839         nsc_buf_t *tmp = NULL;
2840         int rc;
2841         int flags;
2842         ii_header_t *bm_header;
2843         spcs_s_info_t kstatus;
2844         int rtype;
2845 
2846         if (ilp32) {
2847                 if (copyin((void *)arg, &uparms32, sizeof (uparms32)) < 0)
2848                         return (EFAULT);
2849                 II_TAIL_COPY(uparms, uparms32, shadow_vol, dsw_ioctl_t);
2850                 uparms.status = (spcs_s_info_t)uparms32.status;
2851         } else if (copyin((void *)arg, &uparms, sizeof (uparms)) < 0)
2852                 return (EFAULT);
2853 
2854         kstatus = spcs_s_kcreate();
2855         if (kstatus == NULL)
2856                 return (ENOMEM);
2857 
2858         if (!uparms.shadow_vol[0])
2859                 return (spcs_s_ocopyoutf(&kstatus, uparms.status, DSW_EEMPTY));
2860 
2861         mutex_enter(&_ii_info_mutex);
2862         ip = _ii_find_set(uparms.shadow_vol);
2863         mutex_exit(&_ii_info_mutex);
2864         if (ip == NULL)
2865                 return (spcs_s_ocopyoutf(&kstatus, uparms.status,
2866                     DSW_ENOTFOUND));
2867 
2868         mutex_exit(&ip->bi_mutex);
2869 
2870         /* Figure out what to do according to what was flagged as  */
2871 
2872         if ((ip->bi_flags & DSW_OFFLINE) == 0) {
2873                 /* Nothing offline, so no op */
2874                 mutex_enter(&ip->bi_mutex);
2875                 _ii_ioctl_done(ip);
2876                 mutex_exit(&ip->bi_mutex);
2877                 spcs_s_kfree(kstatus);
2878                 return (0);
2879         }
2880 
2881         if (!ip->bi_bmpfd) {
2882                 /* No bitmap fd, can't do anything */
2883                 mutex_enter(&ip->bi_mutex);
2884                 _ii_ioctl_done(ip);
2885                 mutex_exit(&ip->bi_mutex);
2886                 spcs_s_kfree(kstatus);
2887                 return (DSW_EHDRBMP);
2888         }
2889 
2890         rtype = MSTR|SHDR|BMP;
2891         if ((rc = _ii_rsrv_devs(ip, rtype, II_INTERNAL)) != 0) {
2892                 mutex_enter(&ip->bi_mutex);
2893                 _ii_ioctl_done(ip);
2894                 mutex_exit(&ip->bi_mutex);
2895                 spcs_s_add(kstatus, rc);
2896                 return (spcs_s_ocopyoutf(&kstatus, uparms.status,
2897                     DSW_ERSRVFAIL));
2898         }
2899 
2900         /*
2901          * Cannot use _ii_bm_header_get as it will fail if DSW_BMPOFFLINE
2902          */
2903         II_READ_START(ip, bitmap);
2904         rc = nsc_alloc_buf(ip->bi_bmpfd, 0, FBA_LEN(sizeof (ii_header_t)),
2905             NSC_RDWRBUF, &tmp);
2906         II_READ_END(ip, bitmap, rc, FBA_LEN(sizeof (ii_header_t)));
2907         if (!II_SUCCESS(rc)) {
2908                 _ii_rlse_devs(ip, rtype);
2909                 mutex_enter(&ip->bi_mutex);
2910                 _ii_ioctl_done(ip);
2911                 mutex_exit(&ip->bi_mutex);
2912                 if (tmp)
2913                         (void) nsc_free_buf(tmp);
2914                 _ii_error(ip, DSW_BMPOFFLINE);
2915                 spcs_s_add(kstatus, rc);
2916                 return (spcs_s_ocopyoutf(&kstatus, uparms.status, DSW_EHDRBMP));
2917         }
2918 
2919         bm_header = (ii_header_t *)(tmp)->sb_vec[0].sv_addr;
2920         if (bm_header == NULL) {
2921                 _ii_rlse_devs(ip, rtype);
2922                 mutex_enter(&ip->bi_mutex);
2923                 _ii_ioctl_done(ip);
2924                 mutex_exit(&ip->bi_mutex);
2925                 if (tmp)
2926                         (void) nsc_free_buf(tmp);
2927                 return (spcs_s_ocopyoutf(&kstatus, uparms.status, DSW_EHDRBMP));
2928         }
2929 
2930         flags = ip->bi_flags & ~DSW_COPY_FLAGS;
2931         if ((flags & (DSW_SHDIMPORT|DSW_SHDEXPORT)) == 0) {
2932                 if (((flags & DSW_SHDOFFLINE) == 0) &&
2933                     ((flags & DSW_MSTOFFLINE) == DSW_MSTOFFLINE)) {
2934                         /* Shadow was OK but master was offline */
2935                         flags |= _ii_reset_mstvol(ip);
2936                 } else if ((flags & DSW_SHDOFFLINE) == DSW_SHDOFFLINE) {
2937                         /* Shadow was offline, don't care what the master was */
2938                         flags |= (DSW_COPYINGM | DSW_COPYINGP);
2939                 }
2940         }
2941         if (ip->bi_flags & DSW_VOVERFLOW) {
2942                 ip->bi_flags &= ~DSW_VOVERFLOW;
2943                 ip->bi_flags |= DSW_FRECLAIM;
2944         }
2945         flags &= ~(DSW_OFFLINE | DSW_CFGOFFLINE | DSW_VOVERFLOW | DSW_OVERFLOW);
2946         if ((ip->bi_flags & DSW_BMPOFFLINE) == DSW_BMPOFFLINE) {
2947                 /* free any overflow allocation */
2948                 ii_overflow_free(ip, INIT_OVR);
2949                 /* Bitmap now OK, so set up new bitmap header */
2950                 (void) strncpy(bm_header->master_vol, ii_pathname(ip->bi_mstfd),
2951                     DSW_NAMELEN);
2952                 (void) strncpy(bm_header->shadow_vol, ii_pathname(ip->bi_shdfd),
2953                     DSW_NAMELEN);
2954                 (void) strncpy(bm_header->bitmap_vol, ii_pathname(ip->bi_bmpfd),
2955                     DSW_NAMELEN);
2956                 if (ip->bi_cluster) {
2957                         (void) strncpy(bm_header->clstr_name, ip->bi_cluster,
2958                             DSW_NAMELEN);
2959                 }
2960                 if (ip->bi_group) {
2961                         (void) strncpy(bm_header->group_name, ip->bi_group,
2962                             DSW_NAMELEN);
2963                 }
2964                 bm_header->ii_type = (flags & DSW_GOLDEN) ?
2965                     DSW_GOLDEN_TYPE : DSW_QUICK_TYPE;
2966                 bm_header->ii_magic = DSW_DIRTY;
2967                 bm_header->ii_version = II_HEADER_VERSION;
2968                 bm_header->ii_shdfba = DSW_SHD_BM_OFFSET;
2969                 bm_header->ii_copyfba = DSW_COPY_BM_OFFSET;
2970                 bm_header->ii_throttle_delay = ip->bi_throttle_delay;
2971                 bm_header->ii_throttle_unit = ip->bi_throttle_unit;
2972                 ip->bi_shdfba = bm_header->ii_shdfba;
2973                 ip->bi_copyfba = bm_header->ii_copyfba;
2974         } else if ((ip->bi_flags & DSW_SHDOFFLINE) == DSW_SHDOFFLINE) {
2975                 /* bitmap didn't go offline, but shadow did */
2976                 if (ip->bi_overflow) {
2977                         ii_overflow_free(ip, RECLAIM);
2978                 }
2979         }
2980         _ii_lock_chunk(ip, II_NULLCHUNK);
2981         mutex_enter(&ip->bi_mutex);
2982         II_FLAG_ASSIGN(flags, ip);
2983 
2984         mutex_exit(&ip->bi_mutex);
2985         rc = ii_fill_copy_bmp(ip);
2986         if (rc == 0)
2987                 rc = II_ZEROBM(ip);
2988         if (rc == 0) {
2989                 if ((ip->bi_flags&(DSW_GOLDEN)) == 0) {
2990                         /* just clear bitmaps for dependent copy */
2991                         if (ip->bi_flags & DSW_TREEMAP) {
2992                                 bm_header->ii_state = ip->bi_flags;
2993                                 mutex_enter(&ip->bi_mutex);
2994                                 rc = _ii_bm_header_put(bm_header, ip, tmp);
2995                                 mutex_exit(&ip->bi_mutex);
2996                                 tmp = NULL;
2997                                 if (rc == 0) {
2998                                         rc = ii_tinit(ip);
2999                                         if (rc == 0) {
3000                                                 mutex_enter(&ip->bi_mutex);
3001                                                 bm_header =
3002                                                     _ii_bm_header_get(ip, &tmp);
3003                                                 mutex_exit(&ip->bi_mutex);
3004                                         }
3005                                 }
3006                         }
3007 
3008                         if (rc == 0)
3009                                 II_FLAG_CLRX(DSW_COPY_FLAGS, ip);
3010                         /*
3011                          * if copy flags were set, another process may be
3012                          * waiting
3013                          */
3014                         if (rc == 0 && (flags & DSW_COPYINGP))
3015                                 cv_broadcast(&ip->bi_copydonecv);
3016 
3017                         if (rc == 0)
3018                                 rc = II_COPYBM(ip);
3019                 }
3020         }
3021         _ii_unlock_chunk(ip, II_NULLCHUNK);
3022         if (rc) {
3023                 if (tmp)
3024                         _ii_bm_header_free(bm_header, ip, tmp);
3025                 mutex_enter(&ip->bi_mutex);
3026                 _ii_ioctl_done(ip);
3027                 mutex_exit(&ip->bi_mutex);
3028                 _ii_rlse_devs(ip, rtype);
3029                 spcs_s_add(kstatus, rc);
3030                 return (spcs_s_ocopyoutf(&kstatus, uparms.status, DSW_EHDRBMP));
3031         }
3032         bm_header->ii_state = ip->bi_flags;
3033         mutex_enter(&ip->bi_mutex);
3034         rc = _ii_bm_header_put(bm_header, ip, tmp);
3035         if (!II_SUCCESS(rc)) {
3036                 _ii_ioctl_done(ip);
3037                 mutex_exit(&ip->bi_mutex);
3038                 _ii_rlse_devs(ip, rtype);
3039                 spcs_s_add(kstatus, rc);
3040                 return (spcs_s_ocopyoutf(&kstatus, uparms.status, DSW_EHDRBMP));
3041         }
3042 
3043         /* check with RDC */
3044         if (ii_update_denied(ip, kstatus, (ip->bi_flags & DSW_COPYINGS) ?
3045             CV_SHD2MST : 0, 1)) {
3046                 _ii_ioctl_done(ip);
3047                 mutex_exit(&ip->bi_mutex);
3048                 _ii_rlse_devs(ip, rtype);
3049                 return (spcs_s_ocopyoutf(&kstatus, uparms.status, rc));
3050         }
3051 
3052         /* don't perform copy for dependent shadows */
3053         if ((ip->bi_flags&(DSW_GOLDEN)) == 0) {
3054                 _ii_ioctl_done(ip);
3055                 mutex_exit(&ip->bi_mutex);
3056                 _ii_rlse_devs(ip, rtype);
3057                 return (spcs_s_ocopyoutf(&kstatus, uparms.status, rc));
3058         }
3059 
3060         mutex_exit(&ip->bi_mutex);
3061         /* _ii_copyvol calls _ii_ioctl_done() */
3062         if (ip->bi_flags & DSW_COPYINGS)
3063                 rc = _ii_copyvol(ip, CV_SHD2MST, rtype, kstatus, 1);
3064         else if (ip->bi_flags & DSW_COPYINGM)
3065                 rc = _ii_copyvol(ip, 0, rtype, kstatus, 1);
3066         else {
3067                 mutex_enter(&ip->bi_mutex);
3068                 _ii_ioctl_done(ip);
3069                 mutex_exit(&ip->bi_mutex);
3070         }
3071 
3072         _ii_rlse_devs(ip, rtype);
3073 
3074         return (spcs_s_ocopyoutf(&kstatus, uparms.status, rc));
3075 }
3076 
3077 
3078 /*
3079  * _ii_version
3080  *      Get version of the InstantImage module.
3081  *
3082  * Calling/Exit State:
3083  *      Returns 0 on success, otherwise EFAULT is returned.
3084  *      The major and minor revisions are copied out to the user if
3085  *      successful.
3086  */
3087 /*ARGSUSED*/
3088 int
3089 _ii_version(intptr_t arg, int ilp32, int *rvp)
3090 {
3091         dsw_version_t uversion;
3092         dsw_version32_t uversion32;
3093 
3094         if (ilp32) {
3095                 if (copyin((void *)arg, &uversion32, sizeof (uversion32)) < 0)
3096                         return (EFAULT);
3097 
3098                 uversion32.major = dsw_major_rev;
3099                 uversion32.minor = dsw_minor_rev;
3100                 uversion32.micro = dsw_micro_rev;
3101                 uversion32.baseline = dsw_baseline_rev;
3102 
3103                 if (copyout(&uversion32, (void *)arg, sizeof (uversion32)))
3104                         return (EFAULT);
3105         } else {
3106                 if (copyin((void *)arg, &uversion, sizeof (uversion)) < 0)
3107                         return (EFAULT);
3108 
3109                 uversion.major = dsw_major_rev;
3110                 uversion.minor = dsw_minor_rev;
3111                 uversion.micro = dsw_micro_rev;
3112                 uversion.baseline = dsw_baseline_rev;
3113 
3114                 if (copyout(&uversion, (void *)arg, sizeof (uversion)))
3115                         return (EFAULT);
3116         }
3117 
3118         return (0);
3119 }
3120 
3121 /*
3122  * _ii_copyparm
3123  *      Get and set copy parameters.
3124  *
3125  * Calling/Exit State:
3126  *      Returns 0 on success, otherwise EFAULT is returned.
3127  *      The previous values are returned to the user.
3128  */
3129 /*ARGSUSED*/
3130 int
3131 _ii_copyparm(intptr_t arg, int ilp32, int *rvp)
3132 {
3133         dsw_copyp_t copyp;
3134         dsw_copyp32_t copyp32;
3135         spcs_s_info_t kstatus;
3136         _ii_info_t *ip;
3137         int rc = 0;
3138         int tmp;
3139 
3140         if (ilp32) {
3141                 if (copyin((void *)arg, &copyp32, sizeof (copyp32)) < 0)
3142                         return (EFAULT);
3143                 II_TAIL_COPY(copyp, copyp32, shadow_vol, dsw_copyp_t);
3144                 copyp.status = (spcs_s_info_t)copyp32.status;
3145         } else if (copyin((void *)arg, &copyp, sizeof (copyp)) < 0)
3146                         return (EFAULT);
3147 
3148         kstatus = spcs_s_kcreate();
3149         if (kstatus == NULL)
3150                 return (ENOMEM);
3151 
3152         if (!copyp.shadow_vol[0])
3153                 return (spcs_s_ocopyoutf(&kstatus, copyp.status, DSW_EEMPTY));
3154 
3155         mutex_enter(&_ii_info_mutex);
3156         ip = _ii_find_set(copyp.shadow_vol);
3157         mutex_exit(&_ii_info_mutex);
3158         if (ip == NULL)
3159                 return (spcs_s_ocopyoutf(&kstatus, copyp.status,
3160                     DSW_ENOTFOUND));
3161 
3162         tmp = ip->bi_throttle_delay;
3163         if (copyp.copy_delay != -1) {
3164                 if (copyp.copy_delay >= MIN_THROTTLE_DELAY &&
3165                     copyp.copy_delay <= MAX_THROTTLE_DELAY)
3166                         ip->bi_throttle_delay = copyp.copy_delay;
3167                 else {
3168                         cmn_err(CE_WARN, "!ii: delay out of range %d",
3169                             copyp.copy_delay);
3170                         rc = EINVAL;
3171                 }
3172         }
3173         copyp.copy_delay = tmp;
3174 
3175         tmp = ip->bi_throttle_unit;
3176         if (copyp.copy_unit != -1) {
3177                 if (copyp.copy_unit >= MIN_THROTTLE_UNIT &&
3178                     copyp.copy_unit <= MAX_THROTTLE_UNIT) {
3179                         if (rc != EINVAL)
3180                                 ip->bi_throttle_unit = copyp.copy_unit;
3181                 } else {
3182                         cmn_err(CE_WARN, "!ii: unit out of range %d",
3183                             copyp.copy_unit);
3184                         if (rc != EINVAL) {
3185                                 rc = EINVAL;
3186                                 ip->bi_throttle_delay = copyp.copy_delay;
3187                         }
3188                 }
3189         }
3190         copyp.copy_unit = tmp;
3191 
3192         _ii_ioctl_done(ip);
3193         mutex_exit(&ip->bi_mutex);
3194 
3195         if (ilp32) {
3196                 copyp32.copy_delay = copyp.copy_delay;
3197                 copyp32.copy_unit = copyp.copy_unit;
3198                 if (copyout(&copyp32, (void *)arg, sizeof (copyp32)) < 0)
3199                         return (EFAULT);
3200         } else if (copyout(&copyp, (void *)arg, sizeof (copyp)))
3201                         return (EFAULT);
3202 
3203         return (spcs_s_ocopyoutf(&kstatus, copyp.status, rc));
3204 }
3205 
3206 
3207 /*
3208  * _ii_suspend_vol
3209  *      suspend an individual InstantImage group
3210  *
3211  * Calling/Exit State:
3212  *      Returns 0 on success, nonzero otherwise
3213  */
3214 
3215 int
3216 _ii_suspend_vol(_ii_info_t *ip)
3217 {
3218         _ii_info_t **xip;
3219         int copy_flag;
3220         int rc;
3221         nsc_buf_t *tmp = NULL;
3222         ii_header_t *bm_header;
3223 
3224         copy_flag = ip->bi_flags & DSW_COPY_FLAGS;
3225 
3226         _ii_stopvol(ip);
3227         ASSERT(total_ref(ip) == 0);
3228 
3229         if ((rc = _ii_rsrv_devs(ip, BMP, II_INTERNAL)) != 0)
3230                 return (rc);
3231 
3232         /* this rw_enter forces us to drain all active IO */
3233         rw_enter(&ip->bi_linkrw, RW_WRITER);
3234         rw_exit(&ip->bi_linkrw);
3235 
3236         mutex_enter(&_ii_info_mutex);
3237         for (xip = &_ii_info_top; *xip; xip = &(*xip)->bi_next) {
3238                 if (ip == *xip)
3239                         break;
3240         }
3241         *xip = ip->bi_next;
3242         mutex_exit(&_ii_info_mutex);
3243 
3244         rc = II_SAVE_BMP(ip, 1);
3245         mutex_enter(&ip->bi_mutex);
3246         if (rc == 0)
3247                 bm_header = _ii_bm_header_get(ip, &tmp);
3248         if (rc == 0 && bm_header) {
3249                 bm_header->ii_magic = DSW_CLEAN;
3250                 bm_header->ii_state |= copy_flag;
3251                 bm_header->ii_throttle_delay = ip->bi_throttle_delay;
3252                 bm_header->ii_throttle_unit = ip->bi_throttle_unit;
3253                 /* copy over the mtime */
3254                 bm_header->ii_mtime = ip->bi_mtime;
3255                 /* write it to disk */
3256                 rc = _ii_bm_header_put(bm_header, ip, tmp);
3257         }
3258         --iigkstat.num_sets.value.ul;
3259         mutex_exit(&ip->bi_mutex);
3260 
3261         ii_overflow_free(ip, NO_RECLAIM);
3262         _ii_rlse_devs(ip, BMP);
3263 
3264         ii_sibling_free(ip);
3265 
3266         return (rc);
3267 }
3268 
3269 /*
3270  * _ii_suspend_cluster
3271  *      Cluster resource group is switching over to another node, so
3272  *      all shadowed volumes in that group are suspended.
3273  *
3274  * Returns 0 on success, or ESRCH if the name of the cluster resource
3275  * group couldn't be found.
3276  */
3277 int
3278 _ii_suspend_cluster(char *shadow_vol)
3279 {
3280         int found, last;
3281         uint64_t hash;
3282         _ii_info_t *ip;
3283         _ii_lsthead_t **cp, *xcp;
3284         _ii_lstinfo_t **np, *xnp;
3285 
3286         /* find appropriate cluster list */
3287         mutex_enter(&_ii_cluster_mutex);
3288         hash = nsc_strhash(shadow_vol);
3289         for (cp = &_ii_cluster_top; *cp; cp = &((*cp)->lst_next)) {
3290                 if ((hash == (*cp)->lst_hash) && strncmp(shadow_vol,
3291                     (*cp)->lst_name, DSW_NAMELEN) == 0)
3292                         break;
3293         }
3294 
3295         if (!*cp) {
3296                 mutex_exit(&_ii_cluster_mutex);
3297                 return (DSW_ECNOTFOUND);
3298         }
3299 
3300         found = 1;
3301         last = 0;
3302         while (found && !last) {
3303                 found = 0;
3304 
3305                 mutex_enter(&_ii_info_mutex);
3306                 for (np = &(*cp)->lst_start; *np; np = &((*np)->lst_next)) {
3307                         ip = (*np)->lst_ip;
3308 
3309                         if (ip->bi_disabled)
3310                                 continue;
3311 
3312                         found++;
3313 
3314                         ip->bi_disabled = 1;
3315                         if (NSHADOWS(ip) && (ip->bi_master == ip)) {
3316                                 ip->bi_flags &= (~DSW_COPYING);
3317                                 ip->bi_state |= DSW_MULTIMST;
3318                         }
3319                         mutex_exit(&_ii_info_mutex);
3320 
3321                         xnp = *np;
3322                         *np = (*np)->lst_next;
3323                         kmem_free(xnp, sizeof (_ii_lstinfo_t));
3324                         ip->bi_cluster = NULL;
3325 
3326                         (void) _ii_suspend_vol(ip);
3327                         break;
3328                 }
3329                 if (found == 0)
3330                         mutex_exit(&_ii_info_mutex);
3331                 else if (!(*cp)->lst_start) {
3332                         xcp = *cp;
3333                         *cp = (*cp)->lst_next;
3334                         kmem_free(xcp, sizeof (_ii_lsthead_t));
3335                         last = 1;
3336                 }
3337         }
3338         mutex_exit(&_ii_cluster_mutex);
3339 
3340         return (0);
3341 }
3342 
3343 /*
3344  * _ii_shutdown
3345  *      System is shutting down, so all shadowed volumes are suspended.
3346  *
3347  *      This always succeeds, so always returns 0.
3348  */
3349 
3350 /* ARGSUSED */
3351 
3352 int
3353 _ii_shutdown(intptr_t arg, int *rvp)
3354 {
3355         _ii_info_t **xip, *ip;
3356         int found;
3357 
3358         *rvp = 0;
3359 
3360         _ii_shutting_down = 1;
3361 
3362         /* Go through the list until only disabled entries are found */
3363 
3364         found = 1;
3365         while (found) {
3366                 found = 0;
3367 
3368                 mutex_enter(&_ii_info_mutex);
3369                 for (xip = &_ii_info_top; *xip; xip = &(*xip)->bi_next) {
3370                         ip = *xip;
3371                         if (ip->bi_disabled) {
3372                                 /* Also covers not fully configured yet */
3373                                 continue;
3374                         }
3375                         found++;
3376 
3377                         ip->bi_disabled = 1;
3378                         mutex_exit(&_ii_info_mutex);
3379 
3380                         (void) _ii_suspend_vol(ip);
3381 
3382                         break;
3383                 }
3384                 if (found == 0)
3385                         mutex_exit(&_ii_info_mutex);
3386         }
3387 
3388         _ii_shutting_down = 0;
3389 
3390         return (0);
3391 }
3392 
3393 /*
3394  * _ii_suspend
3395  *      Suspend an InstantImage, saving its state to allow a subsequent resume.
3396  *
3397  * Calling/Exit State:
3398  *      Returns 0 if the pair was suspended. Otherwise an error code
3399  *      is returned and any additional error information is copied
3400  *      out to the user.
3401  */
3402 
3403 /* ARGSUSED */
3404 
3405 int
3406 _ii_suspend(intptr_t arg, int ilp32, int *rvp)
3407 {
3408         dsw_ioctl_t uparms;
3409         dsw_ioctl32_t uparms32;
3410         _ii_info_t *ip;
3411         int rc;
3412         spcs_s_info_t kstatus;
3413 
3414         *rvp = 0;
3415 
3416         if (ilp32) {
3417                 if (copyin((void *)arg, &uparms32, sizeof (uparms32)) < 0)
3418                         return (EFAULT);
3419                 II_TAIL_COPY(uparms, uparms32, shadow_vol, dsw_ioctl_t);
3420                 uparms.status = (spcs_s_info_t)uparms32.status;
3421         } else if (copyin((void *)arg, &uparms, sizeof (uparms)) < 0)
3422                 return (EFAULT);
3423 
3424         kstatus = spcs_s_kcreate();
3425         if (kstatus == NULL)
3426                 return (ENOMEM);
3427 
3428         if (!uparms.shadow_vol[0])
3429                 return (spcs_s_ocopyoutf(&kstatus, uparms.status, DSW_EEMPTY));
3430 
3431         if ((uparms.flags & CV_IS_CLUSTER) != 0) {
3432                 rc = _ii_suspend_cluster(uparms.shadow_vol);
3433         } else {
3434                 mutex_enter(&_ii_info_mutex);
3435                 ip = _ii_find_set(uparms.shadow_vol);
3436                 if (ip == NULL) {
3437                         mutex_exit(&_ii_info_mutex);
3438                         return (spcs_s_ocopyoutf(&kstatus, uparms.status,
3439                             DSW_ENOTFOUND));
3440                 }
3441 
3442                 ip->bi_disabled = 1;
3443                 if (NSHADOWS(ip) && (ip->bi_master == ip)) {
3444                         ip->bi_flags &= (~DSW_COPYING);
3445                         ip->bi_state |= DSW_MULTIMST;
3446                 }
3447                 mutex_exit(&_ii_info_mutex);
3448 
3449                 _ii_ioctl_done(ip);
3450                 mutex_exit(&ip->bi_mutex);
3451 
3452                 rc = _ii_suspend_vol(ip);
3453         }
3454 
3455         return (spcs_s_ocopyoutf(&kstatus, uparms.status, rc));
3456 }
3457 
3458 
3459 /*
3460  * _ii_abort
3461  *      Stop any copying process for shadow.
3462  *
3463  * Calling/Exit State:
3464  *      Returns 0 if the abort succeeded. Otherwise an error code
3465  *      is returned and any additional error information is copied
3466  *      out to the user.
3467  */
3468 
3469 /* ARGSUSED */
3470 
3471 int
3472 _ii_abort(intptr_t arg, int ilp32, int *rvp)
3473 {
3474         dsw_ioctl_t uabort;
3475         dsw_ioctl32_t uabort32;
3476         _ii_info_t *ip;
3477         int rc;
3478         spcs_s_info_t kstatus;
3479 
3480         if (ilp32) {
3481                 if (copyin((void *)arg, &uabort32, sizeof (uabort32)) < 0)
3482                         return (EFAULT);
3483                 II_TAIL_COPY(uabort, uabort32, shadow_vol, dsw_ioctl_t);
3484                 uabort.status = (spcs_s_info_t)uabort32.status;
3485         } else if (copyin((void *)arg, &uabort, sizeof (uabort)) < 0)
3486                 return (EFAULT);
3487 
3488         kstatus = spcs_s_kcreate();
3489         if (kstatus == NULL)
3490                 return (ENOMEM);
3491 
3492         if (!uabort.shadow_vol[0])
3493                 return (spcs_s_ocopyoutf(&kstatus, uabort.status, DSW_EEMPTY));
3494 
3495         mutex_enter(&_ii_info_mutex);
3496         ip = _ii_find_set(uabort.shadow_vol);
3497         mutex_exit(&_ii_info_mutex);
3498         if (ip == NULL)
3499                 return (spcs_s_ocopyoutf(&kstatus, uabort.status,
3500                     DSW_ENOTFOUND));
3501 
3502         mutex_exit(&ip->bi_mutex);
3503 
3504         rc = _ii_stopcopy(ip);
3505 
3506         mutex_enter(&ip->bi_mutex);
3507         _ii_ioctl_done(ip);
3508         mutex_exit(&ip->bi_mutex);
3509 
3510         return (spcs_s_ocopyoutf(&kstatus, uabort.status, rc));
3511 }
3512 
3513 
3514 /*
3515  * _ii_segment
3516  *      Copy out II pair bitmaps (cpy, shd, idx) in segments
3517  *
3518  * Calling/Exit State:
3519  *      Returns 0 if the operation succeeded. Otherwise an error code
3520  *      is returned and any additional error information is copied
3521  *      out to the user.
3522  *
3523  */
3524 int
3525 _ii_segment(intptr_t arg, int ilp32, int *rvp)
3526 {
3527         dsw_segment_t usegment;
3528         dsw_segment32_t usegment32;
3529         _ii_info_t *ip;
3530         int rc, size;
3531         spcs_s_info_t kstatus;
3532         int32_t bi_idxfba;
3533 
3534         *rvp = 0;
3535 
3536         if (ilp32) {
3537                 if (copyin((void *)arg, &usegment32, sizeof (usegment32)))
3538                         return (EFAULT);
3539                 usegment.status = (spcs_s_info_t)usegment32.status;
3540                 bcopy(usegment32.shadow_vol, usegment.shadow_vol, DSW_NAMELEN);
3541                 usegment.seg_number = (unsigned)usegment32.seg_number;
3542                 usegment.shd_bitmap =
3543                     (unsigned char   *)(unsigned long)usegment32.shd_bitmap;
3544                 usegment.shd_size = usegment32.shd_size;
3545                 usegment.cpy_bitmap =
3546                     (unsigned char   *)(unsigned long)usegment32.cpy_bitmap;
3547                 usegment.cpy_size = usegment32.cpy_size;
3548                 usegment.idx_bitmap =
3549                     (unsigned char   *)(unsigned long)usegment32.idx_bitmap;
3550                 usegment.idx_size = usegment32.idx_size;
3551         } else if (copyin((void *)arg, &usegment, sizeof (usegment)))
3552                 return (EFAULT);
3553 
3554         kstatus = spcs_s_kcreate();
3555         if (kstatus == NULL)
3556                 return (ENOMEM);
3557 
3558         if (usegment.shadow_vol[0]) {
3559                 mutex_enter(&_ii_info_mutex);
3560                 ip = _ii_find_set(usegment.shadow_vol);
3561                 mutex_exit(&_ii_info_mutex);
3562                 if (ip == NULL)
3563                         return (spcs_s_ocopyoutf(&kstatus, usegment.status,
3564                             DSW_ENOTFOUND));
3565         } else
3566                 return (spcs_s_ocopyoutf(&kstatus, usegment.status,
3567                     DSW_EEMPTY));
3568 
3569         mutex_exit(&ip->bi_mutex);
3570 
3571         size = ((((ip->bi_size + (DSW_SIZE-1))
3572             / DSW_SIZE) + (DSW_BITS-1))) / DSW_BITS;
3573         bi_idxfba = ip->bi_copyfba + (ip->bi_copyfba - ip->bi_shdfba);
3574         if (((nsc_size_t)usegment.seg_number > DSW_BM_FBA_LEN(ip->bi_size)) ||
3575             (usegment.shd_size > size) ||
3576             (usegment.cpy_size > size) ||
3577             (!(ip->bi_flags & DSW_GOLDEN) && (usegment.idx_size > size*32))) {
3578                 _ii_ioctl_done(ip);
3579                 return (spcs_s_ocopyoutf(&kstatus, usegment.status,
3580                     DSW_EMISMATCH));
3581         }
3582 
3583         if ((rc = _ii_rsrv_devs(ip, BMP, II_INTERNAL)) != 0) {
3584                 mutex_enter(&ip->bi_mutex);
3585                 _ii_ioctl_done(ip);
3586                 mutex_exit(&ip->bi_mutex);
3587                 spcs_s_add(kstatus, rc);
3588                 return (spcs_s_ocopyoutf(&kstatus, usegment.status,
3589                     DSW_ERSRVFAIL));
3590         }
3591 
3592         if (usegment.shd_bitmap && usegment.shd_size > 0)
3593                 rc = II_CO_BMP(ip, ip->bi_shdfba+usegment.seg_number,
3594                     usegment.shd_bitmap, usegment.shd_size);
3595         if (rc == 0 && usegment.cpy_bitmap && usegment.cpy_size > 0)
3596                 rc = II_CO_BMP(ip, ip->bi_copyfba+usegment.seg_number,
3597                     usegment.cpy_bitmap, usegment.cpy_size);
3598         if (!(ip->bi_flags & DSW_GOLDEN)) {
3599                 if (rc == 0 && usegment.idx_bitmap && usegment.idx_size > 0)
3600                         rc = II_CO_BMP(ip, bi_idxfba+usegment.seg_number*32,
3601                             usegment.idx_bitmap, usegment.idx_size);
3602         }
3603 
3604         _ii_rlse_devs(ip, BMP);
3605         mutex_enter(&ip->bi_mutex);
3606         _ii_ioctl_done(ip);
3607         mutex_exit(&ip->bi_mutex);
3608         if (rc) {
3609                 spcs_s_add(kstatus, rc);
3610                 return (spcs_s_ocopyoutf(&kstatus, usegment.status, DSW_EIO));
3611         }
3612 
3613         spcs_s_kfree(kstatus);
3614         return (0);
3615 }
3616 
3617 
3618 /*
3619  * _ii_bitmap
3620  *      Copy out II pair bitmaps to user program
3621  *
3622  * Calling/Exit State:
3623  *      Returns 0 if the operation succeeded. Otherwise an error code
3624  *      is returned and any additional error information is copied
3625  *      out to the user.
3626  */
3627 
3628 int
3629 _ii_bitmap(intptr_t arg, int ilp32, int *rvp)
3630 {
3631         dsw_bitmap_t ubitmap;
3632         dsw_bitmap32_t ubitmap32;
3633         _ii_info_t *ip;
3634         int rc;
3635         spcs_s_info_t kstatus;
3636 
3637         *rvp = 0;
3638 
3639         if (ilp32) {
3640                 if (copyin((void *)arg, &ubitmap32, sizeof (ubitmap32)))
3641                         return (EFAULT);
3642                 ubitmap.status = (spcs_s_info_t)ubitmap32.status;
3643                 bcopy(ubitmap32.shadow_vol, ubitmap.shadow_vol, DSW_NAMELEN);
3644                 ubitmap.shd_bitmap =
3645                     (unsigned char   *)(unsigned long)ubitmap32.shd_bitmap;
3646                 ubitmap.shd_size = ubitmap32.shd_size;
3647                 ubitmap.copy_bitmap =
3648                     (unsigned char   *)(unsigned long)ubitmap32.copy_bitmap;
3649                 ubitmap.copy_size = ubitmap32.copy_size;
3650         } else if (copyin((void *)arg, &ubitmap, sizeof (ubitmap)))
3651                 return (EFAULT);
3652 
3653         kstatus = spcs_s_kcreate();
3654         if (kstatus == NULL)
3655                 return (ENOMEM);
3656 
3657         if (!ubitmap.shadow_vol[0])
3658                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status, DSW_EEMPTY));
3659 
3660         mutex_enter(&_ii_info_mutex);
3661         ip = _ii_find_set(ubitmap.shadow_vol);
3662         mutex_exit(&_ii_info_mutex);
3663         if (ip == NULL)
3664                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status,
3665                     DSW_ENOTFOUND));
3666 
3667         mutex_exit(&ip->bi_mutex);
3668 
3669         if ((rc = _ii_rsrv_devs(ip, BMP, II_INTERNAL)) != 0) {
3670                 mutex_enter(&ip->bi_mutex);
3671                 _ii_ioctl_done(ip);
3672                 mutex_exit(&ip->bi_mutex);
3673                 spcs_s_add(kstatus, rc);
3674                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status,
3675                     DSW_ERSRVFAIL));
3676         }
3677 
3678         if (ubitmap.shd_bitmap && ubitmap.shd_size > 0)
3679                 rc = II_CO_BMP(ip, ip->bi_shdfba, ubitmap.shd_bitmap,
3680                     ubitmap.shd_size);
3681         if (rc == 0 && ubitmap.copy_bitmap && ubitmap.copy_size > 0)
3682                 rc = II_CO_BMP(ip, ip->bi_copyfba, ubitmap.copy_bitmap,
3683                     ubitmap.copy_size);
3684         _ii_rlse_devs(ip, BMP);
3685         mutex_enter(&ip->bi_mutex);
3686         _ii_ioctl_done(ip);
3687         mutex_exit(&ip->bi_mutex);
3688         if (rc) {
3689                 spcs_s_add(kstatus, rc);
3690                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status, DSW_EIO));
3691         }
3692 
3693         spcs_s_kfree(kstatus);
3694 
3695         return (0);
3696 }
3697 
3698 /*
3699  * _ii_export
3700  *      Exports the shadow volume
3701  *
3702  * Calling/Exit State:
3703  *      Returns 0 if the shadow was exported. Otherwise an error code
3704  *      is returned and any additional error information is copied
3705  *      out to the user.
3706  *
3707  * Description:
3708  */
3709 
3710 int
3711 _ii_export(intptr_t arg, int ilp32, int *rvp)
3712 {
3713         dsw_ioctl_t uparms;
3714         dsw_ioctl32_t uparms32;
3715         _ii_info_t *ip;
3716         nsc_fd_t *fd;
3717         int rc = 0;
3718         spcs_s_info_t kstatus;
3719 
3720         *rvp = 0;
3721 
3722         if (ilp32) {
3723                 if (copyin((void *)arg, &uparms32, sizeof (uparms32)) < 0)
3724                         return (EFAULT);
3725                 II_TAIL_COPY(uparms, uparms32, shadow_vol, dsw_ioctl_t);
3726                 uparms.status = (spcs_s_info_t)uparms32.status;
3727         } else if (copyin((void *)arg, &uparms, sizeof (uparms)) < 0)
3728                 return (EFAULT);
3729 
3730         kstatus = spcs_s_kcreate();
3731         if (kstatus == NULL)
3732                 return (ENOMEM);
3733 
3734         if (!uparms.shadow_vol[0])
3735                 return (spcs_s_ocopyoutf(&kstatus, uparms.status, DSW_EEMPTY));
3736 
3737         mutex_enter(&_ii_info_mutex);
3738         ip = _ii_find_set(uparms.shadow_vol);
3739         mutex_exit(&_ii_info_mutex);
3740         if (ip == NULL)
3741                 return (spcs_s_ocopyoutf(&kstatus, uparms.status,
3742                     DSW_ENOTFOUND));
3743 
3744         if ((ip->bi_flags & DSW_GOLDEN) == 0 ||
3745             ((ip->bi_flags & (DSW_COPYING|DSW_SHDEXPORT|DSW_SHDIMPORT)) != 0)) {
3746                 /*
3747                  * Cannot export a dependent copy or while still copying or
3748                  * the shadow is already in an exported state
3749                  */
3750                 rc = ip->bi_flags & (DSW_SHDEXPORT|DSW_SHDIMPORT)
3751                     ? DSW_EALREADY : DSW_EDEPENDENCY;
3752                 _ii_ioctl_done(ip);
3753                 mutex_exit(&ip->bi_mutex);
3754                 return (spcs_s_ocopyoutf(&kstatus, uparms.status, rc));
3755         }
3756         if ((rc = _ii_rsrv_devs(ip, BMP, II_INTERNAL)) != 0) {
3757                 _ii_ioctl_done(ip);
3758                 mutex_exit(&ip->bi_mutex);
3759                 spcs_s_add(kstatus, rc);
3760                 return (spcs_s_ocopyoutf(&kstatus, uparms.status,
3761                     DSW_ERSRVFAIL));
3762         }
3763         II_FLAG_SET(DSW_SHDEXPORT, ip);
3764 
3765         mutex_exit(&ip->bi_mutex);
3766 
3767         /* this rw_enter forces us to drain all active IO */
3768         rw_enter(&ip->bi_linkrw, RW_WRITER);
3769         rw_exit(&ip->bi_linkrw);
3770 
3771         mutex_enter(&ip->bi_mutex);
3772 
3773         _ii_rlse_devs(ip, BMP);
3774 
3775         /* Shut shadow volume. */
3776         if (ip->bi_shdfd) {
3777                 if (ip->bi_shdrsrv) {
3778                         nsc_release(ip->bi_shdfd);
3779                         ip->bi_shdrsrv = NULL;
3780                 }
3781                 fd = ip->bi_shdfd;
3782                 ip->bi_shdfd = NULL;
3783                 mutex_exit(&ip->bi_mutex);
3784                 (void) nsc_close(fd);
3785                 mutex_enter(&ip->bi_mutex);
3786         }
3787 
3788         if (ip->bi_shdrfd) {
3789                 if (ip->bi_shdrrsrv) {
3790                         nsc_release(ip->bi_shdrfd);
3791                         ip->bi_shdrrsrv = NULL;
3792                 }
3793                 fd = ip->bi_shdrfd;
3794                 ip->bi_shdrfd = NULL;
3795                 mutex_exit(&ip->bi_mutex);
3796                 (void) nsc_close(fd);
3797                 mutex_enter(&ip->bi_mutex);
3798         }
3799         _ii_ioctl_done(ip);
3800         mutex_exit(&ip->bi_mutex);
3801 
3802         (void) _ii_reserve_begin(ip);
3803         if (ip->bi_shd_tok) {
3804                 (void) _ii_unregister_path(ip->bi_shd_tok, 0, "shadow");
3805                 ip->bi_shd_tok = NULL;
3806         }
3807 
3808         if (ip->bi_shdr_tok) {
3809                 (void) _ii_unregister_path(ip->bi_shdr_tok, 0,
3810                     "raw shadow");
3811                 ip->bi_shdr_tok = NULL;
3812         }
3813         _ii_reserve_end(ip);
3814 
3815         spcs_s_kfree(kstatus);
3816 
3817         return (0);
3818 }
3819 
3820 /*
3821  * _ii_join
3822  *      Rejoins the shadow volume
3823  *
3824  * Calling/Exit State:
3825  *      Returns 0 if the shadow was exported. Otherwise an error code
3826  *      is returned and any additional error information is copied
3827  *      out to the user.
3828  *
3829  * Description:
3830  */
3831 
3832 int
3833 _ii_join(intptr_t arg, int ilp32, int *rvp)
3834 {
3835         dsw_bitmap_t ubitmap;
3836         dsw_bitmap32_t ubitmap32;
3837         _ii_info_t *ip;
3838         uint64_t bm_size;
3839         int rc = 0;
3840         int rtype = 0;
3841         spcs_s_info_t kstatus;
3842 
3843         *rvp = 0;
3844 
3845         if (ilp32) {
3846                 if (copyin((void *)arg, &ubitmap32, sizeof (ubitmap32)) < 0)
3847                         return (EFAULT);
3848                 II_TAIL_COPY(ubitmap, ubitmap32, shadow_vol, dsw_bitmap_t);
3849                 ubitmap.status = (spcs_s_info_t)ubitmap32.status;
3850                 ubitmap.shd_bitmap =
3851                     (unsigned char   *)(unsigned long)ubitmap32.shd_bitmap;
3852                 ubitmap.shd_size = ubitmap32.shd_size;
3853         } else if (copyin((void *)arg, &ubitmap, sizeof (ubitmap)) < 0)
3854                 return (EFAULT);
3855 
3856         kstatus = spcs_s_kcreate();
3857         if (kstatus == NULL)
3858                 return (ENOMEM);
3859 
3860         if (!ubitmap.shadow_vol[0])
3861                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status, DSW_EEMPTY));
3862 
3863         mutex_enter(&_ii_info_mutex);
3864         ip = _ii_find_set(ubitmap.shadow_vol);
3865         mutex_exit(&_ii_info_mutex);
3866         if (ip == NULL)
3867                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status,
3868                     DSW_ENOTFOUND));
3869 
3870         /*
3871          * Check that group has shadow exported.
3872          */
3873         if ((ip->bi_flags & DSW_SHDEXPORT) == 0) {
3874                 /*
3875                  * Cannot join if the shadow isn't exported.
3876                  */
3877                 _ii_ioctl_done(ip);
3878                 mutex_exit(&ip->bi_mutex);
3879                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status,
3880                     DSW_ENOTEXPORTED));
3881         }
3882         /* check bitmap is at least large enough for master volume size */
3883         bm_size = FBA_SIZE(DSW_BM_FBA_LEN(ip->bi_size));
3884         if (ubitmap.shd_size < bm_size) {
3885                 /* bitmap is to small */
3886                 _ii_ioctl_done(ip);
3887                 mutex_exit(&ip->bi_mutex);
3888                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status,
3889                     DSW_EINVALBMP));
3890         }
3891         /* read in bitmap and or with differences bitmap */
3892         rtype = BMP;
3893         if ((rc = _ii_rsrv_devs(ip, rtype, II_INTERNAL)) != 0) {
3894                 _ii_ioctl_done(ip);
3895                 mutex_exit(&ip->bi_mutex);
3896                 spcs_s_add(kstatus, rc);
3897                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status,
3898                     DSW_ERSRVFAIL));
3899         }
3900         rc = II_CI_BMP(ip, ip->bi_shdfba, ubitmap.shd_bitmap,
3901             ubitmap.shd_size);
3902         /* open up shadow */
3903         if ((rc = ii_open_shadow(ip, ip->bi_keyname)) != 0) {
3904                 _ii_ioctl_done(ip);
3905                 mutex_exit(&ip->bi_mutex);
3906                 spcs_s_add(kstatus, rc);
3907                 _ii_rlse_devs(ip, rtype);
3908                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status, DSW_EOPEN));
3909         }
3910         ii_register_shd(ip);
3911         if (!rc)
3912                 II_FLAG_CLR(DSW_SHDEXPORT, ip);
3913         _ii_ioctl_done(ip);
3914         mutex_exit(&ip->bi_mutex);
3915         _ii_rlse_devs(ip, rtype);
3916 
3917         if (rc) {
3918                 spcs_s_add(kstatus, rc);
3919                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status, DSW_EIO));
3920         }
3921 
3922         spcs_s_kfree(kstatus);
3923 
3924         return (0);
3925 }
3926 
3927 
3928 /*
3929  * _ii_ocreate
3930  *      Configures a volume suitable for use as an overflow volume.
3931  *
3932  * Calling/Exit State:
3933  *      Returns 0 if the volume was configured successfully. Otherwise
3934  *       an error code is returned and any additional error information
3935  *      is copied out to the user.
3936  *
3937  * Description:
3938  */
3939 
3940 int
3941 _ii_ocreate(intptr_t arg, int ilp32, int *rvp)
3942 {
3943         dsw_ioctl_t uioctl;
3944         dsw_ioctl32_t uioctl32;
3945         _ii_overflow_t  ov;
3946         _ii_overflow_t  *op = &ov;
3947         int rc = 0;
3948         nsc_fd_t        *fd;
3949         nsc_iodev_t     *iodev;
3950         nsc_size_t vol_size;
3951         char *overflow_vol;
3952         spcs_s_info_t kstatus;
3953 
3954         *rvp = 0;
3955 
3956         if (ilp32) {
3957                 if (copyin((void *)arg, &uioctl32, sizeof (uioctl32)) < 0)
3958                         return (EFAULT);
3959                 II_TAIL_COPY(uioctl, uioctl32, shadow_vol, dsw_ioctl_t);
3960                 uioctl.status = (spcs_s_info_t)uioctl32.status;
3961         } else if (copyin((void *)arg, &uioctl, sizeof (uioctl)) < 0)
3962                 return (EFAULT);
3963 
3964         overflow_vol = uioctl.shadow_vol;
3965         kstatus = spcs_s_kcreate();
3966         if (kstatus == NULL)
3967                 return (ENOMEM);
3968 
3969         if (!overflow_vol[0])
3970                 return (spcs_s_ocopyoutf(&kstatus, uioctl.status, DSW_EEMPTY));
3971 
3972         if (ii_volume(overflow_vol, 0) != NONE)
3973                 return (spcs_s_ocopyoutf(&kstatus, uioctl.status, DSW_EINUSE));
3974 
3975         fd = nsc_open(overflow_vol,
3976             NSC_IIR_ID|NSC_FILE|NSC_RDWR, NULL, (blind_t)&(iodev), &rc);
3977         if (!fd)
3978                 fd = nsc_open(uioctl.shadow_vol,
3979                     NSC_IIR_ID|NSC_DEVICE|NSC_RDWR, NULL,
3980                     (blind_t)&(iodev), &rc);
3981         if (fd == NULL) {
3982                 spcs_s_add(kstatus, rc);
3983                 return (spcs_s_ocopyoutf(&kstatus, uioctl.status, DSW_EIO));
3984         }
3985         if ((rc = nsc_reserve(fd, 0)) != 0) {
3986                 spcs_s_add(kstatus, rc);
3987                 (void) nsc_close(fd);
3988                 return (spcs_s_ocopyoutf(&kstatus, uioctl.status,
3989                     DSW_ERSRVFAIL));
3990         }
3991         /* setup magic number etc; */
3992         rc = nsc_partsize(fd, &vol_size);
3993         if (rc) {
3994                 spcs_s_add(kstatus, rc);
3995                 (void) nsc_close(fd);
3996                 return (spcs_s_ocopyoutf(&kstatus, uioctl.status, DSW_EIO));
3997         }
3998         op->ii_hmagic = II_OMAGIC;
3999                 /* take 1 off as chunk 0 contains header */
4000         op->ii_nchunks = (vol_size / DSW_SIZE) -1;
4001         op->ii_drefcnt = 0;
4002         op->ii_used = 1;                     /* we have used the header */
4003         op->ii_unused = op->ii_nchunks - op->ii_used;
4004         op->ii_freehead = II_NULLNODE;
4005         op->ii_hversion = OV_HEADER_VERSION;
4006         op->ii_flags = 0;
4007         op->ii_urefcnt = 0;
4008         (void) strncpy(op->ii_volname, uioctl.shadow_vol, DSW_NAMELEN);
4009         rc = _ii_nsc_io(0, KS_NA, fd, NSC_WRBUF, II_OHEADER_FBA,
4010             (unsigned char *)&op->ii_do, sizeof (op->ii_do));
4011         (void) nsc_release(fd);
4012         (void) nsc_close(fd);
4013         if (rc) {
4014                 spcs_s_add(kstatus, rc);
4015                 return (spcs_s_ocopyoutf(&kstatus, uioctl.status, DSW_EIO));
4016         }
4017 
4018         spcs_s_kfree(kstatus);
4019 
4020         return (0);
4021 }
4022 
4023 
4024 /*
4025  * _ii_oattach
4026  *      Attaches the volume in the "bitmap_vol" field as an overflow volume.
4027  *
4028  * Calling/Exit State:
4029  *      Returns 0 if the volume was attached. Fails if the shadow group
4030  *      is of the wrong type (eg independent) or already has an overflow
4031  *      volume attached.
4032  *
4033  * Description:
4034  */
4035 
4036 int
4037 _ii_oattach(intptr_t arg, int ilp32, int *rvp)
4038 {
4039         dsw_config_t uconfig;
4040         dsw_config32_t uconfig32;
4041         _ii_info_t *ip;
4042         int rc = 0;
4043         int rtype = 0;
4044         ii_header_t *bm_header;
4045         nsc_buf_t *tmp = NULL;
4046         spcs_s_info_t kstatus;
4047 
4048         *rvp = 0;
4049 
4050         if (ilp32) {
4051                 if (copyin((void *)arg, &uconfig32, sizeof (uconfig32)) < 0)
4052                         return (EFAULT);
4053                 II_TAIL_COPY(uconfig, uconfig32, shadow_vol, dsw_config_t);
4054                 uconfig.status = (spcs_s_info_t)uconfig32.status;
4055         } else if (copyin((void *)arg, &uconfig, sizeof (uconfig)) < 0)
4056                 return (EFAULT);
4057 
4058         kstatus = spcs_s_kcreate();
4059         if (kstatus == NULL)
4060                 return (ENOMEM);
4061 
4062         if (!uconfig.shadow_vol[0])
4063                 return (spcs_s_ocopyoutf(&kstatus, uconfig.status, DSW_EEMPTY));
4064 
4065         switch (ii_volume(uconfig.bitmap_vol, 0)) {
4066         case NONE:
4067         case OVR:
4068                 break;
4069         default:
4070                 return (spcs_s_ocopyoutf(&kstatus, uconfig.status, DSW_EINUSE));
4071         }
4072         mutex_enter(&_ii_info_mutex);
4073         ip = _ii_find_set(uconfig.shadow_vol);
4074         mutex_exit(&_ii_info_mutex);
4075         if (ip == NULL)
4076                 return (spcs_s_ocopyoutf(&kstatus, uconfig.status,
4077                     DSW_ENOTFOUND));
4078 
4079         /* check shadow doesn't already have an overflow volume */
4080         if (ip->bi_overflow) {
4081                 _ii_ioctl_done(ip);
4082                 mutex_exit(&ip->bi_mutex);
4083                 return (spcs_s_ocopyoutf(&kstatus, uconfig.status,
4084                     DSW_EALREADY));
4085         }
4086         /* check shadow is mapped so can have an overflow */
4087         if ((ip->bi_flags&DSW_TREEMAP) == 0) {
4088                 _ii_ioctl_done(ip);
4089                 mutex_exit(&ip->bi_mutex);
4090                 return (spcs_s_ocopyoutf(&kstatus, uconfig.status,
4091                     DSW_EWRONGTYPE));
4092         }
4093         rtype = BMP;
4094         if ((rc = _ii_rsrv_devs(ip, rtype, II_INTERNAL)) != 0) {
4095                 _ii_ioctl_done(ip);
4096                 mutex_exit(&ip->bi_mutex);
4097                 spcs_s_add(kstatus, rc);
4098                 return (spcs_s_ocopyoutf(&kstatus, uconfig.status,
4099                     DSW_ERSRVFAIL));
4100         }
4101         /* attach volume */
4102         if ((rc = ii_overflow_attach(ip, uconfig.bitmap_vol, 1)) != 0) {
4103                 _ii_ioctl_done(ip);
4104                 mutex_exit(&ip->bi_mutex);
4105                 _ii_rlse_devs(ip, rtype);
4106                 return (spcs_s_ocopyoutf(&kstatus, uconfig.status, rc));
4107         }
4108 
4109         /* re-write header so shadow can be restarted with overflow volume */
4110 
4111         bm_header = _ii_bm_header_get(ip, &tmp);
4112         if (bm_header == NULL) {
4113                 /* detach volume */
4114                 ii_overflow_free(ip, RECLAIM);
4115                 _ii_ioctl_done(ip);
4116                 mutex_exit(&ip->bi_mutex);
4117                 _ii_rlse_devs(ip, rtype);
4118                 return (spcs_s_ocopyoutf(&kstatus, uconfig.status,
4119                     DSW_EHDRBMP));
4120         }
4121         (void) strncpy(bm_header->overflow_vol, uconfig.bitmap_vol,
4122             DSW_NAMELEN);
4123         (void) _ii_bm_header_put(bm_header, ip, tmp);
4124         _ii_rlse_devs(ip, rtype);
4125         _ii_ioctl_done(ip);
4126         mutex_exit(&ip->bi_mutex);
4127 
4128         spcs_s_kfree(kstatus);
4129 
4130         return (0);
4131 }
4132 
4133 
4134 /*
4135  * _ii_odetach
4136  *      Breaks the link with the overflow volume.
4137  *
4138  * Calling/Exit State:
4139  *      Returns 0 if the overflow volume was detached. Otherwise an error code
4140  *      is returned and any additional error information is copied
4141  *      out to the user.
4142  *
4143  * Description:
4144  */
4145 
4146 int
4147 _ii_odetach(intptr_t arg, int ilp32, int *rvp)
4148 {
4149         dsw_bitmap_t ubitmap;
4150         dsw_bitmap32_t ubitmap32;
4151         _ii_info_t *ip;
4152         int rc = 0;
4153         int rtype = 0;
4154         ii_header_t *bm_header;
4155         nsc_buf_t *tmp = NULL;
4156         spcs_s_info_t kstatus;
4157 
4158         *rvp = 0;
4159 
4160         if (ilp32) {
4161                 if (copyin((void *)arg, &ubitmap32, sizeof (ubitmap32)) < 0)
4162                         return (EFAULT);
4163                 II_TAIL_COPY(ubitmap, ubitmap32, shadow_vol, dsw_bitmap_t);
4164                 ubitmap.status = (spcs_s_info_t)ubitmap32.status;
4165         } else if (copyin((void *)arg, &ubitmap, sizeof (ubitmap)) < 0)
4166                 return (EFAULT);
4167 
4168         kstatus = spcs_s_kcreate();
4169         if (kstatus == NULL)
4170                 return (ENOMEM);
4171 
4172         if (!ubitmap.shadow_vol[0])
4173                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status, DSW_EEMPTY));
4174 
4175         mutex_enter(&_ii_info_mutex);
4176         ip = _ii_find_set(ubitmap.shadow_vol);
4177         mutex_exit(&_ii_info_mutex);
4178         if (ip == NULL)
4179                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status,
4180                     DSW_ENOTFOUND));
4181 
4182         if ((ip->bi_flags&DSW_VOVERFLOW) != 0) {
4183                 _ii_ioctl_done(ip);
4184                 mutex_exit(&ip->bi_mutex);
4185                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status,
4186                     DSW_EODEPENDENCY));
4187         }
4188         rtype = BMP;
4189         if ((rc = _ii_rsrv_devs(ip, rtype, II_INTERNAL)) != 0) {
4190                 _ii_ioctl_done(ip);
4191                 mutex_exit(&ip->bi_mutex);
4192                 spcs_s_add(kstatus, rc);
4193                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status,
4194                     DSW_ERSRVFAIL));
4195         }
4196         ii_overflow_free(ip, RECLAIM);
4197         /* re-write header to break link with overflow volume */
4198 
4199         bm_header = _ii_bm_header_get(ip, &tmp);
4200         if (bm_header == NULL) {
4201                 _ii_rlse_devs(ip, rtype);
4202                 _ii_ioctl_done(ip);
4203                 mutex_exit(&ip->bi_mutex);
4204                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status,
4205                     DSW_EHDRBMP));
4206         }
4207         bzero(bm_header->overflow_vol, DSW_NAMELEN);
4208         (void) _ii_bm_header_put(bm_header, ip, tmp);
4209 
4210         _ii_rlse_devs(ip, rtype);
4211         _ii_ioctl_done(ip);
4212 
4213         mutex_exit(&ip->bi_mutex);
4214         if (rc) {
4215                 spcs_s_add(kstatus, rc);
4216                 return (spcs_s_ocopyoutf(&kstatus, ubitmap.status, DSW_EIO));
4217         }
4218 
4219         spcs_s_kfree(kstatus);
4220 
4221         --iigkstat.assoc_over.value.ul;
4222 
4223         return (0);
4224 }
4225 
4226 
4227 /*
4228  * _ii_gc_list
4229  *      Returns a list of all lists, or all entries in a list
4230  *
4231  */
4232 int
4233 _ii_gc_list(intptr_t arg, int ilp32, int *rvp, kmutex_t *mutex,
4234     _ii_lsthead_t *lst)
4235 {
4236         dsw_aioctl_t ulist;
4237         dsw_aioctl32_t ulist32;
4238         size_t name_offset;
4239         int i;
4240         spcs_s_info_t kstatus;
4241         char *carg = (char *)arg;
4242         uint64_t hash;
4243         _ii_lsthead_t *cp;
4244         _ii_lstinfo_t *np;
4245 
4246         *rvp = 0;
4247         name_offset = offsetof(dsw_aioctl_t, shadow_vol[0]);
4248         if (ilp32) {
4249                 if (copyin((void *) arg, &ulist32, sizeof (ulist32)) < 0)
4250                         return (EFAULT);
4251                 II_TAIL_COPY(ulist, ulist32, flags, dsw_aioctl_t);
4252                 ulist.status = (spcs_s_info_t)ulist32.status;
4253                 name_offset = offsetof(dsw_aioctl32_t, shadow_vol[0]);
4254         } else if (copyin((void *) arg, &ulist, sizeof (ulist)) < 0)
4255                 return (EFAULT);
4256 
4257         kstatus = spcs_s_kcreate();
4258         if (kstatus == NULL)
4259                 return (ENOMEM);
4260 
4261         mutex_enter(mutex);
4262         if (ulist.shadow_vol[ 0 ] != 0) {
4263                 /* search for specific list */
4264                 hash = nsc_strhash(ulist.shadow_vol);
4265                 for (cp = lst; cp; cp = cp->lst_next) {
4266                         if ((hash == cp->lst_hash) && strncmp(ulist.shadow_vol,
4267                             cp->lst_name, DSW_NAMELEN) == 0) {
4268                                 break;
4269                         }
4270                 }
4271                 if (cp) {
4272                         for (i = 0, np = cp->lst_start; i < ulist.count && np;
4273                             np = np->lst_next, carg += DSW_NAMELEN, i++) {
4274                                 if (copyout(np->lst_ip->bi_keyname,
4275                                     carg + name_offset, DSW_NAMELEN)) {
4276                                         mutex_exit(mutex);
4277                                         return (spcs_s_ocopyoutf(&kstatus,
4278                                             ulist.status, EFAULT));
4279                                 }
4280                         }
4281                 } else {
4282                         i = 0;
4283                 }
4284         } else {
4285                 /* return full list */
4286                 for (i = 0, cp = lst; i < ulist.count && cp;
4287                     carg += DSW_NAMELEN, i++, cp = cp->lst_next) {
4288                         if (copyout(cp->lst_name, carg + name_offset,
4289                             DSW_NAMELEN)) {
4290                                 mutex_exit(mutex);
4291                                 return (spcs_s_ocopyoutf(&kstatus, ulist.status,
4292                                     EFAULT));
4293                         }
4294                 }
4295         }
4296         mutex_exit(mutex);
4297         ulist32.count = ulist.count = i;
4298 
4299         if (ilp32) {
4300                 if (copyout(&ulist32, (void *) arg, name_offset))
4301                         return (EFAULT);
4302         } else {
4303                 if (copyout(&ulist, (void*) arg, name_offset))
4304                         return (EFAULT);
4305         }
4306 
4307         return (spcs_s_ocopyoutf(&kstatus, ulist.status, 0));
4308 }
4309 
4310 /*
4311  * _ii_olist
4312  *      Breaks the link with the overflow volume.
4313  *
4314  * Calling/Exit State:
4315  *      Returns 0 if the overflow volume was detached. Otherwise an error code
4316  *      is returned and any additional error information is copied
4317  *      out to the user.
4318  *
4319  * Description:
4320  */
4321 
4322 int
4323 _ii_olist(intptr_t arg, int ilp32, int *rvp)
4324 {
4325         dsw_aioctl_t ulist;
4326         dsw_aioctl32_t ulist32;
4327         _ii_overflow_t *op;
4328         size_t name_offset;
4329         int rc = 0;
4330         int i;
4331         char *carg = (char *)arg;
4332         spcs_s_info_t kstatus;
4333 
4334         *rvp = 0;
4335 
4336         name_offset = offsetof(dsw_aioctl_t, shadow_vol[0]);
4337         if (ilp32) {
4338                 if (copyin((void *)arg, &ulist32, sizeof (ulist32)) < 0)
4339                         return (EFAULT);
4340                 II_TAIL_COPY(ulist, ulist32, flags, dsw_aioctl_t);
4341                 ulist.status = (spcs_s_info_t)ulist32.status;
4342                 name_offset = offsetof(dsw_aioctl32_t, shadow_vol[0]);
4343         } else if (copyin((void *)arg, &ulist, sizeof (ulist)) < 0)
4344                 return (EFAULT);
4345 
4346         kstatus = spcs_s_kcreate();
4347         if (kstatus == NULL)
4348                 return (ENOMEM);
4349 
4350         i = 0;
4351 
4352         mutex_enter(&_ii_overflow_mutex);
4353         for (op = _ii_overflow_top; i < ulist.count && op;
4354             carg += DSW_NAMELEN) {
4355                 if (copyout(op->ii_volname, carg+name_offset, DSW_NAMELEN)) {
4356                         mutex_exit(&_ii_overflow_mutex);
4357                         return (spcs_s_ocopyoutf(&kstatus, ulist.status,
4358                             EFAULT));
4359                 }
4360                 i++;
4361                 op = op->ii_next;
4362         }
4363         mutex_exit(&_ii_overflow_mutex);
4364         ulist32.count = ulist.count = i;
4365         /* return count of items listed to user */
4366         if (ilp32) {
4367                 if (copyout(&ulist32, (void *)arg, name_offset))
4368                         return (EFAULT);
4369         } else {
4370                 if (copyout(&ulist, (void *)arg, name_offset))
4371                         return (EFAULT);
4372         }
4373 
4374         return (spcs_s_ocopyoutf(&kstatus, ulist.status, rc));
4375 }
4376 
4377 /*
4378  * _ii_ostat
4379  *      Breaks the link with the overflow volume.
4380  *
4381  * Calling/Exit State:
4382  *      Returns 0 if the overflow volume was detached. Otherwise an error code
4383  *      is returned and any additional error information is copied
4384  *      out to the user.
4385  *
4386  * Description:
4387  */
4388 
4389 int
4390 _ii_ostat(intptr_t arg, int ilp32, int *rvp, int is_iost_2)
4391 {
4392         dsw_ostat_t ustat;
4393         dsw_ostat32_t ustat32;
4394         _ii_overflow_t *op;
4395         spcs_s_info_t kstatus;
4396 
4397         *rvp = 0;
4398 
4399         if (ilp32) {
4400                 if (copyin((void *)arg, &ustat32, sizeof (ustat32)) < 0)
4401                         return (EFAULT);
4402                 II_TAIL_COPY(ustat, ustat32, overflow_vol, dsw_ostat_t);
4403                 ustat.status = (spcs_s_info_t)ustat32.status;
4404         } else if (copyin((void *)arg, &ustat, sizeof (ustat)) < 0)
4405                 return (EFAULT);
4406 
4407         kstatus = spcs_s_kcreate();
4408         if (kstatus == NULL)
4409                 return (ENOMEM);
4410         if (!ustat.overflow_vol[0])
4411                 return (spcs_s_ocopyoutf(&kstatus, ustat.status, DSW_EEMPTY));
4412 
4413         op = _ii_find_overflow(ustat.overflow_vol);
4414         if (op == NULL)
4415                 return (spcs_s_ocopyoutf(&kstatus, ustat.status,
4416                     DSW_ENOTFOUND));
4417 
4418         ustat.nchunks = op->ii_nchunks;
4419         ustat.used = op->ii_used;
4420         ustat.unused = op->ii_unused;
4421         ustat.drefcnt = op->ii_drefcnt;
4422         ustat.crefcnt = op->ii_crefcnt;
4423         if (is_iost_2) {
4424                 ustat.hversion = op->ii_hversion;
4425                 ustat.flags = op->ii_flags;
4426                 ustat.hmagic = op->ii_hmagic;
4427         }
4428 
4429         spcs_s_kfree(kstatus);
4430         if (ilp32) {
4431                 ustat32.nchunks = ustat.nchunks;
4432                 ustat32.used = ustat.used;
4433                 ustat32.unused = ustat.unused;
4434                 ustat32.drefcnt = ustat.drefcnt;
4435                 ustat32.crefcnt = ustat.crefcnt;
4436                 if (is_iost_2) {
4437                         ustat32.hversion = ustat.hversion;
4438                         ustat32.flags = ustat.flags;
4439                         ustat32.hmagic = ustat.hmagic;
4440                 }
4441                 if (copyout(&ustat32, (void *)arg, sizeof (ustat32)))
4442                         return (EFAULT);
4443         } else {
4444                 if (copyout(&ustat, (void *)arg, sizeof (ustat)))
4445                         return (EFAULT);
4446         }
4447         return (0);
4448 }
4449 
4450 /*
4451  * _ii_move_grp()
4452  *      Move a set from one group to another, possibly creating the new
4453  *      group.
4454  */
4455 
4456 int
4457 _ii_move_grp(intptr_t arg, int ilp32, int *rvp)
4458 {
4459         dsw_movegrp_t umove;
4460         dsw_movegrp32_t umove32;
4461         spcs_s_info_t kstatus;
4462         _ii_info_t *ip;
4463         int rc = 0;
4464         nsc_buf_t *tmp;
4465         ii_header_t *bm_header;
4466 
4467         *rvp = 0;
4468 
4469         if (ilp32) {
4470                 if (copyin((void *)arg, &umove32, sizeof (umove32)) < 0)
4471                         return (EFAULT);
4472                 II_TAIL_COPY(umove, umove32, shadow_vol, dsw_movegrp_t);
4473                 umove.status = (spcs_s_info_t)umove32.status;
4474         } else if (copyin((void *)arg, &umove, sizeof (umove)) < 0)
4475                 return (EFAULT);
4476 
4477         kstatus = spcs_s_kcreate();
4478         if (kstatus == NULL)
4479                 return (ENOMEM);
4480 
4481         if (!umove.shadow_vol[0])
4482                 return (spcs_s_ocopyoutf(&kstatus, umove.status, DSW_EEMPTY));
4483 
4484         mutex_enter(&_ii_info_mutex);
4485         ip = _ii_find_set(umove.shadow_vol);
4486         mutex_exit(&_ii_info_mutex);
4487 
4488         if (!ip)
4489                 return (spcs_s_ocopyoutf(&kstatus, umove.status,
4490                     DSW_ENOTFOUND));
4491 
4492         if (!umove.new_group[0]) {
4493                 /* are we clearing the group association? */
4494                 if (ip->bi_group) {
4495                         DTRACE_PROBE2(_ii_move_grp1, char *, ip->bi_keyname,
4496                             char *, ip->bi_group);
4497                         rc = II_UNLINK_GROUP(ip);
4498                 }
4499         } else if (!ip->bi_group) {
4500                 rc = II_LINK_GROUP(ip, umove.new_group);
4501                 DTRACE_PROBE2(_ii_move_grp2, char *, ip->bi_keyname,
4502                     char *, ip->bi_group);
4503         } else {
4504                 /* remove it from one group and add it to the other */
4505                 DTRACE_PROBE3(_ii_move_grp, char *, ip->bi_keyname,
4506                     char *, ip->bi_group, char *, umove.new_group);
4507                 rc = II_UNLINK_GROUP(ip);
4508                 if (!rc)
4509                         rc = II_LINK_GROUP(ip, umove.new_group);
4510         }
4511 
4512         /* ** BEGIN UPDATE BITMAP HEADER ** */
4513         if ((rc = _ii_rsrv_devs(ip, BMP, II_INTERNAL)) != 0) {
4514                 _ii_ioctl_done(ip);
4515                 mutex_exit(&ip->bi_mutex);
4516                 spcs_s_add(kstatus, rc);
4517                 return (spcs_s_ocopyoutf(&kstatus, umove.status,
4518                     DSW_ERSRVFAIL));
4519         }
4520         bm_header = _ii_bm_header_get(ip, &tmp);
4521         if (bm_header) {
4522                 (void) strncpy(bm_header->group_name, umove.new_group,
4523                     DSW_NAMELEN);
4524                 (void) _ii_bm_header_put(bm_header, ip, tmp);
4525         }
4526         _ii_rlse_devs(ip, BMP);
4527         /* ** END UPDATE BITMAP HEADER ** */
4528 
4529         _ii_ioctl_done(ip);
4530         mutex_exit(&ip->bi_mutex);
4531 
4532         return (spcs_s_ocopyoutf(&kstatus, umove.status, rc));
4533 }
4534 
4535 /*
4536  * _ii_change_tag()
4537  *      Move a set from one group to another, possibly creating the new
4538  *      group.
4539  */
4540 
4541 int
4542 _ii_change_tag(intptr_t arg, int ilp32, int *rvp)
4543 {
4544         dsw_movegrp_t umove;
4545         dsw_movegrp32_t umove32;
4546         spcs_s_info_t kstatus;
4547         _ii_info_t *ip;
4548         int rc = 0;
4549         nsc_buf_t *tmp;
4550         ii_header_t *bm_header;
4551 
4552         *rvp = 0;
4553 
4554         if (ilp32) {
4555                 if (copyin((void *)arg, &umove32, sizeof (umove32)) < 0)
4556                         return (EFAULT);
4557                 II_TAIL_COPY(umove, umove32, shadow_vol, dsw_movegrp_t);
4558                 umove.status = (spcs_s_info_t)umove32.status;
4559         } else if (copyin((void *)arg, &umove, sizeof (umove)) < 0)
4560                 return (EFAULT);
4561 
4562         kstatus = spcs_s_kcreate();
4563         if (kstatus == NULL)
4564                 return (ENOMEM);
4565 
4566         if (!umove.shadow_vol[0])
4567                 return (spcs_s_ocopyoutf(&kstatus, umove.status, DSW_EEMPTY));
4568 
4569         mutex_enter(&_ii_info_mutex);
4570         ip = _ii_find_set(umove.shadow_vol);
4571         mutex_exit(&_ii_info_mutex);
4572 
4573         if (!ip)
4574                 return (spcs_s_ocopyoutf(&kstatus, umove.status,
4575                     DSW_ENOTFOUND));
4576 
4577         if (!umove.new_group[0]) {
4578                 /* are we clearing the group association? */
4579                 if (ip->bi_cluster) {
4580                         DTRACE_PROBE2(_ii_change_tag, char *, ip->bi_keyname,
4581                             char *, ip->bi_cluster);
4582                         rc = II_UNLINK_CLUSTER(ip);
4583                 }
4584         } else if (!ip->bi_cluster) {
4585                 /* are we adding it to a group for the first time? */
4586                 rc = II_LINK_CLUSTER(ip, umove.new_group);
4587                 DTRACE_PROBE2(_ii_change_tag, char *, ip->bi_keyname,
4588                     char *, ip->bi_cluster);
4589         } else {
4590                 /* remove it from one group and add it to the other */
4591                 DTRACE_PROBE3(_ii_change_tag_2, char *, ip->bi_keyname,
4592                     char *, ip->bi_cluster, char *, umove.new_group);
4593                 rc = II_UNLINK_CLUSTER(ip);
4594                 if (!rc)
4595                         rc = II_LINK_CLUSTER(ip, umove.new_group);
4596         }
4597 
4598         /* ** BEGIN UPDATE BITMAP HEADER ** */
4599         if ((rc = _ii_rsrv_devs(ip, BMP, II_INTERNAL)) != 0) {
4600                 _ii_ioctl_done(ip);
4601                 mutex_exit(&ip->bi_mutex);
4602                 spcs_s_add(kstatus, rc);
4603                 return (spcs_s_ocopyoutf(&kstatus, umove.status,
4604                     DSW_ERSRVFAIL));
4605         }
4606         bm_header = _ii_bm_header_get(ip, &tmp);
4607         if (bm_header) {
4608                 (void) strncpy(bm_header->clstr_name, umove.new_group,
4609                     DSW_NAMELEN);
4610                 (void) _ii_bm_header_put(bm_header, ip, tmp);
4611         }
4612         _ii_rlse_devs(ip, BMP);
4613         /* ** END UPDATE BITMAP HEADER ** */
4614 
4615         _ii_ioctl_done(ip);
4616         mutex_exit(&ip->bi_mutex);
4617 
4618         return (spcs_s_ocopyoutf(&kstatus, umove.status, rc));
4619 }
4620 
4621 
4622 /*
4623  * _ii_spcs_s_ocopyoutf()
4624  * Wrapper for spcs_s_ocopyoutf() used by _ii_chk_copy() which permits
4625  * the spcs_s_info_t argument to be NULL. _ii_chk_copy() requires this
4626  * functionality as it is sometimes called by _ii_control_copy() which
4627  * has no user context to copy any errors into. At all other times a NULL
4628  * spcs_s_info_t argument would indicate a bug in the calling function.
4629  */
4630 
4631 static int
4632 _ii_spcs_s_ocopyoutf(spcs_s_info_t *kstatusp, spcs_s_info_t ustatus, int err)
4633 {
4634         if (ustatus)
4635                 return (spcs_s_ocopyoutf(kstatusp, ustatus, err));
4636         spcs_s_kfree(*kstatusp);
4637         return (err);
4638 }
4639 
4640 static int
4641 _ii_chk_copy(_ii_info_t *ip, int flags, spcs_s_info_t *kstatusp, pid_t pid,
4642     spcs_s_info_t ustatus)
4643 {
4644         _ii_info_t *xip;
4645         int rc;
4646         int rtype;
4647 
4648         if ((ip->bi_flags & DSW_COPYINGP) != 0) {
4649                 _ii_ioctl_done(ip);
4650                 mutex_exit(&ip->bi_mutex);
4651                 return (_ii_spcs_s_ocopyoutf(kstatusp, ustatus, DSW_ECOPYING));
4652         }
4653 
4654         if (ip->bi_flags & DSW_OFFLINE) {
4655                 _ii_ioctl_done(ip);
4656                 mutex_exit(&ip->bi_mutex);
4657                 return (_ii_spcs_s_ocopyoutf(kstatusp, ustatus, DSW_EOFFLINE));
4658         }
4659 
4660         if ((ip->bi_flags & (DSW_SHDIMPORT|DSW_SHDEXPORT)) != 0) {
4661                 _ii_ioctl_done(ip);
4662                 mutex_exit(&ip->bi_mutex);
4663                 return (_ii_spcs_s_ocopyoutf(kstatusp, ustatus,
4664                     DSW_EISEXPORTED));
4665         }
4666 
4667         if ((flags & CV_SHD2MST) == CV_SHD2MST) {
4668                 if ((ip->bi_flags & DSW_COPYINGM) != 0) {
4669                                 _ii_ioctl_done(ip);
4670                                 mutex_exit(&ip->bi_mutex);
4671                                 return (_ii_spcs_s_ocopyoutf(kstatusp, ustatus,
4672                                     DSW_ECOPYING));
4673                 }
4674                 /* check if any sibling shadow is copying towards this master */
4675                 for (xip = ip->bi_head; xip; xip = xip->bi_sibling) {
4676                         if (ip != xip && (xip->bi_flags & DSW_COPYINGS) != 0) {
4677                                 _ii_ioctl_done(ip);
4678                                 mutex_exit(&ip->bi_mutex);
4679                                 return (_ii_spcs_s_ocopyoutf(kstatusp, ustatus,
4680                                     DSW_ECOPYING));
4681                         }
4682                 }
4683         }
4684 
4685         if (((flags & CV_SHD2MST) == 0) &&
4686             ((ip->bi_flags & DSW_COPYINGS) != 0)) {
4687                 _ii_ioctl_done(ip);
4688                 mutex_exit(&ip->bi_mutex);
4689                 return (_ii_spcs_s_ocopyoutf(kstatusp, ustatus, DSW_ECOPYING));
4690         }
4691 
4692         if (ip->bi_flags & DSW_TREEMAP) {
4693                 if ((ip->bi_flags & DSW_OVERFLOW) && (flags & CV_SHD2MST)) {
4694                         _ii_ioctl_done(ip);
4695                         mutex_exit(&ip->bi_mutex);
4696                         return (_ii_spcs_s_ocopyoutf(kstatusp, ustatus,
4697                             DSW_EINCOMPLETE));
4698                 }
4699         }
4700 
4701         /* Assure that no other PID owns this copy/update */
4702         if (ip->bi_locked_pid == 0) {
4703                 if (flags & CV_LOCK_PID)
4704                         ip->bi_locked_pid = pid;
4705         } else if (ip->bi_locked_pid != pid) {
4706                 _ii_ioctl_done(ip);
4707                 mutex_exit(&ip->bi_mutex);
4708                 return (spcs_s_ocopyoutf(kstatusp, ustatus, DSW_EINUSE));
4709         }
4710 
4711         mutex_exit(&ip->bi_mutex);
4712 
4713         rtype = MSTR|SHDR|BMP;
4714         if ((rc = _ii_rsrv_devs(ip, rtype, II_INTERNAL)) != 0) {
4715                 mutex_enter(&ip->bi_mutex);
4716                 _ii_ioctl_done(ip);
4717                 mutex_exit(&ip->bi_mutex);
4718                 spcs_s_add(*kstatusp, rc);
4719                 return (_ii_spcs_s_ocopyoutf(kstatusp, ustatus,
4720                     DSW_ERSRVFAIL));
4721         }
4722 
4723         if (ii_update_denied(ip, *kstatusp, flags & CV_SHD2MST, 0)) {
4724                 mutex_enter(&ip->bi_mutex);
4725                 _ii_ioctl_done(ip);
4726                 mutex_exit(&ip->bi_mutex);
4727                 _ii_rlse_devs(ip, rtype);
4728                 return (_ii_spcs_s_ocopyoutf(kstatusp, ustatus,
4729                     DSW_EOPACKAGE));
4730         }
4731 
4732         return (0);
4733 }
4734 
4735 static int
4736 _ii_do_copy(_ii_info_t *ip, int flags, spcs_s_info_t kstatus, int waitflag)
4737 {
4738         int rc = 0;
4739         int rtype = MSTR|SHDR|BMP;
4740         _ii_overflow_t *op;
4741         int quick_update = 0;
4742 
4743         waitflag = (waitflag != 0);
4744         /*
4745          * a copy of a tree-mapped device must be downgraded to
4746          * an update.
4747          */
4748         if (ip->bi_flags & DSW_TREEMAP)
4749                 flags |= CV_BMP_ONLY;
4750 
4751         /*
4752          * If we want to update the dependent shadow we only need to zero
4753          * the shadow bitmap.
4754          */
4755 
4756         if (((ip->bi_flags & DSW_GOLDEN) == 0) &&
4757             (flags & (CV_BMP_ONLY|CV_SHD2MST)) == CV_BMP_ONLY) {
4758 
4759                 DTRACE_PROBE(DEPENDENT);
4760 
4761                 /* assign updating time */
4762                 ip->bi_mtime = ddi_get_time();
4763 
4764                 if (ip->bi_flags & DSW_TREEMAP) {
4765                         DTRACE_PROBE(COMPACT_DEPENDENT);
4766 
4767                         if (ip->bi_overflow &&
4768                             (ip->bi_overflow->ii_flags & IIO_VOL_UPDATE) == 0) {
4769                                 /* attempt to do a quick update */
4770                                 quick_update = 1;
4771                                 ip->bi_overflow->ii_flags |= IIO_VOL_UPDATE;
4772                                 ip->bi_overflow->ii_detachcnt = 1;
4773                         }
4774 
4775                         rc = ii_tinit(ip);
4776 
4777                         if (quick_update && ip->bi_overflow) {
4778                                 /* clean up */
4779                                 ip->bi_overflow->ii_flags &= ~(IIO_VOL_UPDATE);
4780                                 ip->bi_overflow->ii_detachcnt = 0;
4781                         }
4782                 }
4783 
4784                 if (rc == 0)
4785                         rc = II_ZEROBM(ip);     /* update copy of shadow */
4786                 if (((op = ip->bi_overflow) != NULL) &&
4787                     (op->ii_hversion >= 1) && (op->ii_hmagic == II_OMAGIC)) {
4788                         mutex_enter(&_ii_overflow_mutex);
4789                         if (ip->bi_flags & DSW_OVRHDRDRTY) {
4790                                 mutex_enter(&ip->bi_mutex);
4791                                 ip->bi_flags &= ~DSW_OVRHDRDRTY;
4792                                 mutex_exit(&ip->bi_mutex);
4793                                 ASSERT(op->ii_urefcnt > 0);
4794                                 op->ii_urefcnt--;
4795                         }
4796                         if (op->ii_urefcnt == 0) {
4797                                 op->ii_flags &= ~IIO_CNTR_INVLD;
4798                                 op->ii_unused = op->ii_nchunks - 1;
4799                         }
4800                         mutex_exit(&_ii_overflow_mutex);
4801                 }
4802                 mutex_enter(&ip->bi_mutex);
4803                 II_FLAG_CLR(DSW_OVERFLOW, ip);
4804                 mutex_exit(&ip->bi_mutex);
4805 
4806                 _ii_unlock_chunk(ip, II_NULLCHUNK);
4807                 mutex_enter(&ip->bi_mutex);
4808                 _ii_ioctl_done(ip);
4809                 mutex_exit(&ip->bi_mutex);
4810                 _ii_rlse_devs(ip, rtype);
4811                 if (rc) {
4812                         spcs_s_add(kstatus, rc);
4813                         return (DSW_EIO);
4814                 } else {
4815                         DTRACE_PROBE(_ii_do_copy_end);
4816                         return (0);
4817                 }
4818         }
4819 
4820         /*
4821          * need to perform an actual copy.
4822          */
4823 
4824         /*
4825          * Perform bitmap copy if asked or from dependent shadow to master.
4826          */
4827         if ((flags & CV_BMP_ONLY) ||
4828             ((flags & CV_SHD2MST) &&
4829             ((ip->bi_flags & DSW_GOLDEN) == 0))) {
4830                 DTRACE_PROBE(INDEPENDENT_fast);
4831                 rc = II_ORBM(ip);               /* save shadow bits for copy */
4832         } else {
4833                 DTRACE_PROBE(INDEPENDENT_slow);
4834                 rc = ii_fill_copy_bmp(ip); /* set bits for independent copy */
4835         }
4836         if (rc == 0)
4837                 rc = II_ZEROBM(ip);
4838         _ii_unlock_chunk(ip, II_NULLCHUNK);
4839         if (rc == 0) {
4840                 mutex_enter(&ip->bi_mutex);
4841                 if (ip->bi_flags & (DSW_COPYINGP | DSW_SHDEXPORT)) {
4842                         rc = (ip->bi_flags & DSW_COPYINGP)
4843                             ? DSW_ECOPYING : DSW_EISEXPORTED;
4844 
4845                         _ii_ioctl_done(ip);
4846                         mutex_exit(&ip->bi_mutex);
4847                         _ii_rlse_devs(ip, rtype);
4848                         return (rc);
4849                 }
4850 
4851                 /* assign copying time */
4852                 ip->bi_mtime = ddi_get_time();
4853 
4854                 if (flags & CV_SHD2MST)
4855                         II_FLAG_SET(DSW_COPYINGS | DSW_COPYINGP, ip);
4856                 else
4857                         II_FLAG_SET(DSW_COPYINGM | DSW_COPYINGP, ip);
4858                 mutex_exit(&ip->bi_mutex);
4859                 rc = _ii_copyvol(ip, (flags & CV_SHD2MST),
4860                     rtype, kstatus, waitflag);
4861         } else {
4862                 mutex_enter(&ip->bi_mutex);
4863                 _ii_ioctl_done(ip);
4864                 mutex_exit(&ip->bi_mutex);
4865         }
4866 
4867         if (waitflag)
4868                 _ii_rlse_devs(ip, rtype);
4869 
4870         return (rc);
4871 }
4872 
4873 /*
4874  * _ii_copy
4875  *      Copy or update (take snapshot) II volume.
4876  *
4877  * Calling/Exit State:
4878  *      Returns 0 if the operation succeeded. Otherwise an error code
4879  *      is returned and any additional error information is copied
4880  *      out to the user.
4881  */
4882 
4883 int
4884 _ii_copy(intptr_t arg, int ilp32, int *rvp)
4885 {
4886         dsw_ioctl_t ucopy;
4887         dsw_ioctl32_t ucopy32;
4888         _ii_info_t *ip;
4889         int rc = 0;
4890         spcs_s_info_t kstatus;
4891 
4892         *rvp = 0;
4893 
4894         if (ilp32) {
4895                 if (copyin((void *)arg, &ucopy32, sizeof (ucopy32)) < 0)
4896                         return (EFAULT);
4897                 II_TAIL_COPY(ucopy, ucopy32, shadow_vol, dsw_ioctl_t);
4898                 ucopy.status = (spcs_s_info_t)ucopy32.status;
4899         } else if (copyin((void *)arg, &ucopy, sizeof (ucopy)) < 0)
4900                 return (EFAULT);
4901 
4902         kstatus = spcs_s_kcreate();
4903         if (kstatus == NULL)
4904                 return (ENOMEM);
4905 
4906         if (!ucopy.shadow_vol[0])
4907                 return (spcs_s_ocopyoutf(&kstatus, ucopy.status, DSW_EEMPTY));
4908 
4909         mutex_enter(&_ii_info_mutex);
4910         ip = _ii_find_set(ucopy.shadow_vol);
4911         mutex_exit(&_ii_info_mutex);
4912         if (ip == NULL)
4913                 return (spcs_s_ocopyoutf(&kstatus, ucopy.status,
4914                     DSW_ENOTFOUND));
4915 
4916         /* Check that the copy/update makes sense */
4917         if ((rc = _ii_chk_copy(ip, ucopy.flags, &kstatus, ucopy.pid,
4918             ucopy.status)) == 0) {
4919                 /* perform the copy */
4920                 _ii_lock_chunk(ip, II_NULLCHUNK);
4921                 /* _ii_do_copy() calls _ii_ioctl_done() */
4922                 rc = _ii_do_copy(ip, ucopy.flags, kstatus, 1);
4923                 return (spcs_s_ocopyoutf(&kstatus, ucopy.status, rc));
4924         }
4925 
4926         return (rc);
4927 }
4928 
4929 /*
4930  * _ii_mass_copy
4931  * Copies/updates the sets pointed to in the ipa array.
4932  *
4933  * Calling/Exit State:
4934  * Returns 0 if the operations was successful.  Otherwise an
4935  * error code.
4936  */
4937 int
4938 _ii_mass_copy(_ii_info_t **ipa, dsw_aioctl_t *ucopy, int wait)
4939 {
4940         int i;
4941         int rc = 0;
4942         int failed;
4943         int rtype = MSTR|SHDR|BMP;
4944         _ii_info_t *ip;
4945         spcs_s_info_t kstatus;
4946 
4947         kstatus = spcs_s_kcreate();
4948         if (kstatus == NULL)
4949                 return (ENOMEM);
4950 
4951         /* Check copy validitity */
4952         for (i = 0; i < ucopy->count; i++) {
4953                 ip = ipa[i];
4954 
4955                 rc = _ii_chk_copy(ip, ucopy->flags, &kstatus, ucopy->pid,
4956                     ucopy->status);
4957 
4958                 if (rc) {
4959                         /* Clean up the mess */
4960 
4961                         DTRACE_PROBE1(_ii_mass_copy_end1, int, rc);
4962 
4963                         /*
4964                          * The array ipa now looks like:
4965                          *    0..(i-1): needs mutex_enter/ioctl_done/mutex_exit
4966                          *    i: needs nothing (_ii_chk_copy does cleanup)
4967                          *    (i+1)..n: needs just ioctl_done/mutex_exit
4968                          */
4969 
4970                         failed = i;
4971 
4972                         for (i = 0; i < failed; i++) {
4973                                 mutex_enter(&(ipa[i]->bi_mutex));
4974                                 _ii_ioctl_done(ipa[i]);
4975                                 mutex_exit(&(ipa[i]->bi_mutex));
4976                                 _ii_rlse_devs(ipa[i], rtype);
4977                         }
4978 
4979                         /* skip 'failed', start with failed + 1 */
4980 
4981                         for (i = failed + 1; i < ucopy->count; i++) {
4982                                 _ii_ioctl_done(ipa[i]);
4983                                 mutex_exit(&(ipa[i]->bi_mutex));
4984                         }
4985 
4986                         return (rc);
4987                 }
4988         }
4989 
4990         /* Check for duplicate shadows in same II group */
4991         if (ucopy->flags & CV_SHD2MST) {
4992                 /* Reset the state of all masters */
4993                 for (i = 0; i < ucopy->count; i++) {
4994                         ip = ipa[i];
4995                         ip->bi_master->bi_state &= ~DSW_MSTTARGET;
4996                 }
4997 
4998                 for (i = 0; i < ucopy->count; i++) {
4999                         ip = ipa[i];
5000                         /*
5001                          * Check the state of the master.  If DSW_MSTTARGET is
5002                          * set, it's because this master is attached to another
5003                          * shadow within this set.
5004                          */
5005                         if (ip->bi_master->bi_state & DSW_MSTTARGET) {
5006                                 rc = EINVAL;
5007                                 break;
5008                         }
5009 
5010                         /*
5011                          * Set the DSW_MSTTARGET bit on the master associated
5012                          * with this shadow.  This will allow us to detect
5013                          * multiple shadows pointing to this master within
5014                          * this loop.
5015                          */
5016                         ip->bi_master->bi_state |= DSW_MSTTARGET;
5017                 }
5018         }
5019 
5020         /* Handle error */
5021         if (rc) {
5022                 DTRACE_PROBE1(_ii_mass_copy_end2, int, rc);
5023                 for (i = 0; i < ucopy->count; i++) {
5024                         ip = ipa[i];
5025 
5026                         _ii_rlse_devs(ip, rtype);
5027 
5028                         mutex_enter(&ip->bi_mutex);
5029                         _ii_ioctl_done(ip);
5030                         mutex_exit(&ip->bi_mutex);
5031                 }
5032 
5033                 return (spcs_s_ocopyoutf(&kstatus, ucopy->status, rc));
5034         }
5035 
5036         /* Lock bitmaps & prepare counts */
5037         for (i = 0; i < ucopy->count; i++) {
5038                 ip = ipa[i];
5039                 _ii_lock_chunk(ip, II_NULLCHUNK);
5040                 if (ip->bi_overflow) {
5041                         ip->bi_overflow->ii_detachcnt = 0;
5042                 }
5043         }
5044 
5045         /* determine which volumes we're dealing with */
5046         for (i = 0; i < ucopy->count; i++) {
5047                 ip = ipa[i];
5048                 if (ip->bi_overflow) {
5049                         ip->bi_overflow->ii_flags |= IIO_VOL_UPDATE;
5050                         if ((ucopy->flags & (CV_BMP_ONLY|CV_SHD2MST)) ==
5051                             CV_BMP_ONLY) {
5052                                 ++ip->bi_overflow->ii_detachcnt;
5053                         }
5054                 }
5055         }
5056 
5057         /* Perform copy */
5058         for (i = 0; i < ucopy->count; i++) {
5059                 ip = ipa[i];
5060                 rc = _ii_do_copy(ip, ucopy->flags, kstatus, wait);
5061                 /* Hum... what to do if one of these fails? */
5062         }
5063 
5064         /* clear out flags so as to prevent any accidental reuse */
5065         for (i = 0; i < ucopy->count; i++) {
5066                 ip = ipa[i];
5067                 if (ip->bi_overflow)
5068                         ip->bi_overflow->ii_flags &= ~(IIO_VOL_UPDATE);
5069         }
5070 
5071         /*
5072          * We can only clean up the kstatus structure if there are
5073          * no waiters.  If someone's waiting for the information,
5074          * _ii_copyvolp() uses spcs_s_add to write to kstatus.  Panic
5075          * would ensue if we freed it up now.
5076          */
5077         if (!wait)
5078                 rc = spcs_s_ocopyoutf(&kstatus, ucopy->status, rc);
5079 
5080         return (rc);
5081 }
5082 
5083 /*
5084  * _ii_list_copy
5085  * Retrieve a list from a character array and use _ii_mass_copy to
5086  * initiate a copy/update operation on all of the specified sets.
5087  *
5088  * Calling/Exit State:
5089  * Returns 0 if the operations was successful.  Otherwise an
5090  * error code.
5091  */
5092 int
5093 _ii_list_copy(char *list, dsw_aioctl_t *ucopy, int wait)
5094 {
5095         int i;
5096         int rc = 0;
5097         char *name;
5098         _ii_info_t *ip;
5099         _ii_info_t **ipa;
5100 
5101         ipa = kmem_zalloc(sizeof (_ii_info_t *) * ucopy->count, KM_SLEEP);
5102 
5103         /* Reserve devices */
5104         name = list;
5105         mutex_enter(&_ii_info_mutex);
5106         for (i = 0; i < ucopy->count; i++, name += DSW_NAMELEN) {
5107                 ip = _ii_find_set(name);
5108 
5109                 if (ip == NULL) {
5110                         rc = DSW_ENOTFOUND;
5111                         break;
5112                 }
5113 
5114                 ipa[i] = ip;
5115         }
5116 
5117         if (rc != 0) {
5118                 /* Failed to find all sets, release those we do have */
5119                 while (i-- > 0) {
5120                         ip = ipa[i];
5121                         mutex_enter(&ip->bi_mutex);
5122                         _ii_ioctl_done(ip);
5123                         mutex_exit(&ip->bi_mutex);
5124                 }
5125         } else {
5126                 /* Begin copy operation */
5127                 rc = _ii_mass_copy(ipa, ucopy, wait);
5128         }
5129 
5130         mutex_exit(&_ii_info_mutex);
5131 
5132         kmem_free(ipa, sizeof (_ii_info_t *) * ucopy->count);
5133 
5134         return (rc);
5135 }
5136 
5137 /*
5138  * _ii_group_copy
5139  * Retrieve list of sets in a group and use _ii_mass_copy to initiate
5140  * a copy/update of all of them.
5141  *
5142  * Calling/Exit State:
5143  * Returns 0 if the operations was successful.  Otherwise an
5144  * error code.
5145  */
5146 int
5147 _ii_group_copy(char *name, dsw_aioctl_t *ucopy, int wait)
5148 {
5149         int             i;
5150         int             rc;
5151         uint64_t        hash;
5152         _ii_info_t      **ipa;
5153         _ii_lsthead_t   *head;
5154         _ii_lstinfo_t   *np;
5155 
5156         /* find group */
5157         hash = nsc_strhash(name);
5158 
5159         mutex_enter(&_ii_group_mutex);
5160 
5161         for (head = _ii_group_top; head; head = head->lst_next) {
5162                 if (hash == head->lst_hash && strncmp(head->lst_name,
5163                     name, DSW_NAMELEN) == 0)
5164                         break;
5165         }
5166 
5167         if (!head) {
5168                 mutex_exit(&_ii_group_mutex);
5169                 DTRACE_PROBE(_ii_group_copy);
5170                 return (DSW_EGNOTFOUND);
5171         }
5172 
5173         /* Count entries */
5174         for (ucopy->count = 0, np = head->lst_start; np; np = np->lst_next)
5175                 ++ucopy->count;
5176 
5177         if (ucopy->count == 0) {
5178                 mutex_exit(&_ii_group_mutex);
5179                 return (DSW_EGNOTFOUND);
5180         }
5181 
5182         ipa = kmem_zalloc(sizeof (_ii_info_t *) * ucopy->count, KM_SLEEP);
5183         if (ipa == NULL) {
5184                 mutex_exit(&_ii_group_mutex);
5185                 return (ENOMEM);
5186         }
5187 
5188         /* Create list */
5189         mutex_enter(&_ii_info_mutex);
5190         np = head->lst_start;
5191         for (i = 0; i < ucopy->count; i++) {
5192                 ASSERT(np != 0);
5193 
5194                 ipa[i] = np->lst_ip;
5195 
5196                 mutex_enter(&ipa[i]->bi_mutex);
5197                 ipa[i]->bi_ioctl++;
5198 
5199                 np = np->lst_next;
5200         }
5201 
5202         /* Begin copy operation */
5203         rc = _ii_mass_copy(ipa, ucopy, wait);
5204 
5205         mutex_exit(&_ii_info_mutex);
5206         mutex_exit(&_ii_group_mutex);
5207 
5208         kmem_free(ipa, sizeof (_ii_info_t *) * ucopy->count);
5209 
5210         return (rc);
5211 }
5212 
5213 /*
5214  * _ii_acopy
5215  *      Copy or update (take snapshot) II multiple volumes.
5216  *
5217  * Calling/Exit State:
5218  *      Returns 0 if the operation succeeded. Otherwise an error code
5219  *      is returned and any additional error information is copied
5220  *      out to the user.
5221  */
5222 int
5223 _ii_acopy(intptr_t arg, int ilp32, int *rvp)
5224 {
5225         int rc;
5226         size_t name_offset;
5227         char *list;
5228         char *nptr;
5229         char name[DSW_NAMELEN];
5230         dsw_aioctl_t ucopy;
5231         dsw_aioctl32_t ucopy32;
5232         spcs_s_info_t kstatus;
5233 
5234         *rvp = 0;
5235 
5236         name_offset = offsetof(dsw_aioctl_t, shadow_vol[0]);
5237 
5238         if (ilp32) {
5239                 if (copyin((void *)arg, &ucopy32, sizeof (ucopy32)) < 0)
5240                         return (EFAULT);
5241                 II_TAIL_COPY(ucopy, ucopy32, flags, dsw_ioctl_t);
5242                 ucopy.status = (spcs_s_info_t)ucopy32.status;
5243                 name_offset = offsetof(dsw_aioctl32_t, shadow_vol[0]);
5244         } else if (copyin((void *)arg, &ucopy, sizeof (ucopy)) < 0)
5245                 return (EFAULT);
5246 
5247         kstatus = spcs_s_kcreate();
5248 
5249         if (kstatus == NULL)
5250                 return (ENOMEM);
5251 
5252         nptr = (char *)arg + name_offset;
5253         rc = 0;
5254 
5255         if (ucopy.flags & CV_IS_GROUP) {
5256                 if (copyin(nptr, name, DSW_NAMELEN) < 0)
5257                         return (spcs_s_ocopyoutf(&kstatus, ucopy.status,
5258                             EFAULT));
5259 
5260                 /* kstatus information is handled within _ii_group_copy */
5261                 rc = _ii_group_copy(name, &ucopy, 0);
5262         } else if (ucopy.count > 0) {
5263                 list = kmem_alloc(DSW_NAMELEN * ucopy.count, KM_SLEEP);
5264 
5265                 if (list == NULL)
5266                         return (spcs_s_ocopyoutf(&kstatus, ucopy.status,
5267                             ENOMEM));
5268 
5269                 if (copyin(nptr, list, DSW_NAMELEN * ucopy.count) < 0)
5270                         return (spcs_s_ocopyoutf(&kstatus, ucopy.status,
5271                             EFAULT));
5272 
5273                 rc = _ii_list_copy(list, &ucopy, 0);
5274                 kmem_free(list, DSW_NAMELEN * ucopy.count);
5275         }
5276 
5277         return (spcs_s_ocopyoutf(&kstatus, ucopy.status, rc));
5278 }
5279 
5280 /*
5281  * _ii_bitsset
5282  *      Copy out II pair bitmaps to user program
5283  *
5284  * Calling/Exit State:
5285  *      Returns 0 if the operation succeeded. Otherwise an error code
5286  *      is returned and any additional error information is copied
5287  *      out to the user.
5288  */
5289 int
5290 _ii_bitsset(intptr_t arg, int ilp32, int cmd, int *rvp)
5291 {
5292         dsw_bitsset_t ubitsset;
5293         dsw_bitsset32_t ubitsset32;
5294         nsc_size_t nbitsset;
5295         _ii_info_t *ip;
5296         int rc;
5297         spcs_s_info_t kstatus;
5298         int bitmap_size;
5299 
5300         *rvp = 0;
5301 
5302         if (ilp32) {
5303                 if (copyin((void *)arg, &ubitsset32, sizeof (ubitsset32)))
5304                         return (EFAULT);
5305                 ubitsset.status = (spcs_s_info_t)ubitsset32.status;
5306                 bcopy(ubitsset32.shadow_vol, ubitsset.shadow_vol, DSW_NAMELEN);
5307         } else if (copyin((void *)arg, &ubitsset, sizeof (ubitsset)))
5308                 return (EFAULT);
5309 
5310         kstatus = spcs_s_kcreate();
5311         if (kstatus == NULL)
5312                 return (ENOMEM);
5313 
5314         if (!ubitsset.shadow_vol[0])
5315                 return (spcs_s_ocopyoutf(&kstatus, ubitsset.status,
5316                     DSW_EEMPTY));
5317 
5318         mutex_enter(&_ii_info_mutex);
5319         ip = _ii_find_set(ubitsset.shadow_vol);
5320         mutex_exit(&_ii_info_mutex);
5321         if (ip == NULL)
5322                 return (spcs_s_ocopyoutf(&kstatus, ubitsset.status,
5323                     DSW_ENOTFOUND));
5324 
5325         mutex_exit(&ip->bi_mutex);
5326 
5327         if ((rc = _ii_rsrv_devs(ip, BMP, II_INTERNAL)) != 0) {
5328                 mutex_enter(&ip->bi_mutex);
5329                 _ii_ioctl_done(ip);
5330                 mutex_exit(&ip->bi_mutex);
5331                 spcs_s_add(kstatus, rc);
5332                 return (spcs_s_ocopyoutf(&kstatus, ubitsset.status,
5333                     DSW_ERSRVFAIL));
5334         }
5335 
5336         ubitsset.tot_size = ip->bi_size / DSW_SIZE;
5337         if ((ip->bi_size % DSW_SIZE) != 0)
5338                 ++ubitsset.tot_size;
5339         bitmap_size = (ubitsset.tot_size + 7) / 8;
5340         if (cmd == DSWIOC_SBITSSET)
5341                 rc = II_CNT_BITS(ip, ip->bi_shdfba, &nbitsset, bitmap_size);
5342         else
5343                 rc = II_CNT_BITS(ip, ip->bi_copyfba, &nbitsset, bitmap_size);
5344         ubitsset.tot_set = nbitsset;
5345         _ii_rlse_devs(ip, BMP);
5346         mutex_enter(&ip->bi_mutex);
5347         _ii_ioctl_done(ip);
5348         mutex_exit(&ip->bi_mutex);
5349         if (rc) {
5350                 spcs_s_add(kstatus, rc);
5351                 return (spcs_s_ocopyoutf(&kstatus, ubitsset.status, DSW_EIO));
5352         }
5353 
5354         spcs_s_kfree(kstatus);
5355         /* return the fetched names to the user */
5356         if (ilp32) {
5357                 ubitsset32.status = (spcs_s_info32_t)ubitsset.status;
5358                 ubitsset32.tot_size = ubitsset.tot_size;
5359                 ubitsset32.tot_set = ubitsset.tot_set;
5360                 rc = copyout(&ubitsset32, (void *)arg, sizeof (ubitsset32));
5361         } else {
5362                 rc = copyout(&ubitsset, (void *)arg, sizeof (ubitsset));
5363         }
5364 
5365         return (rc);
5366 }
5367 
5368 /*
5369  * _ii_stopvol
5370  *      Stop any copying process for shadow, and stop shadowing
5371  *
5372  */
5373 
5374 static void
5375 _ii_stopvol(_ii_info_t *ip)
5376 {
5377         nsc_path_t *mst_tok;
5378         nsc_path_t *mstr_tok;
5379         nsc_path_t *shd_tok;
5380         nsc_path_t *shdr_tok;
5381         nsc_path_t *bmp_tok;
5382         int rc;
5383 
5384         while (_ii_stopcopy(ip) == EINTR)
5385                 ;
5386 
5387         DTRACE_PROBE(_ii_stopvol);
5388 
5389         mutex_enter(&ip->bi_mutex);
5390         mst_tok = ip->bi_mst_tok;
5391         mstr_tok = ip->bi_mstr_tok;
5392         shd_tok = ip->bi_shd_tok;
5393         shdr_tok = ip->bi_shdr_tok;
5394         bmp_tok = ip->bi_bmp_tok;
5395         ip->bi_shd_tok = 0;
5396         ip->bi_shdr_tok = 0;
5397         if (!NSHADOWS(ip)) {
5398                 ip->bi_mst_tok = 0;
5399                 ip->bi_mstr_tok = 0;
5400         }
5401         ip->bi_bmp_tok = 0;
5402 
5403         /* Wait for any _ii_open() calls to complete */
5404 
5405         while (ip->bi_ioctl) {
5406                 ip->bi_state |= DSW_IOCTL;
5407                 cv_wait(&ip->bi_ioctlcv, &ip->bi_mutex);
5408         }
5409         mutex_exit(&ip->bi_mutex);
5410 
5411         rc = _ii_reserve_begin(ip);
5412         if (rc) {
5413                 cmn_err(CE_WARN, "!_ii_stopvol: _ii_reserve_begin %d", rc);
5414         }
5415         if (!NSHADOWS(ip)) {
5416                 if (mst_tok) {
5417                         rc = _ii_unregister_path(mst_tok, NSC_PCATCH,
5418                             "master");
5419                         if (rc)
5420                                 cmn_err(CE_WARN, "!ii: unregister master %d",
5421                                     rc);
5422                 }
5423 
5424                 if (mstr_tok) {
5425                         rc = _ii_unregister_path(mstr_tok, NSC_PCATCH,
5426                             "raw master");
5427                         if (rc)
5428                                 cmn_err(CE_WARN, "!ii: unregister raw "
5429                                     "master %d", rc);
5430                 }
5431         }
5432 
5433         if (shd_tok) {
5434                 rc = _ii_unregister_path(shd_tok, NSC_PCATCH, "shadow");
5435                 if (rc)
5436                         cmn_err(CE_WARN, "!ii: unregister shadow %d", rc);
5437         }
5438 
5439         if (shdr_tok) {
5440                 rc = _ii_unregister_path(shdr_tok, NSC_PCATCH, "raw shadow");
5441                 if (rc)
5442                         cmn_err(CE_WARN, "!ii: unregister raw shadow %d", rc);
5443         }
5444 
5445         if (bmp_tok) {
5446                 rc = _ii_unregister_path(bmp_tok, NSC_PCATCH, "bitmap");
5447                 if (rc)
5448                         cmn_err(CE_WARN, "!ii: unregister bitmap %d", rc);
5449         }
5450         _ii_reserve_end(ip);
5451 
5452         /* Wait for all necessary _ii_close() calls to complete */
5453         mutex_enter(&ip->bi_mutex);
5454 
5455         while (total_ref(ip) != 0) {
5456                 ip->bi_state |= DSW_CLOSING;
5457                 cv_wait(&ip->bi_closingcv, &ip->bi_mutex);
5458         }
5459         if (!NSHADOWS(ip)) {
5460                 nsc_set_owner(ip->bi_mstfd, NULL);
5461                 nsc_set_owner(ip->bi_mstrfd, NULL);
5462         }
5463         nsc_set_owner(ip->bi_shdfd, NULL);
5464         nsc_set_owner(ip->bi_shdrfd, NULL);
5465         mutex_exit(&ip->bi_mutex);
5466 
5467 }
5468 
5469 
5470 /*
5471  * _ii_ioctl_done
5472  *      If this is the last one to complete, wakeup all processes waiting
5473  *      for ioctls to complete
5474  *
5475  */
5476 
5477 static void
5478 _ii_ioctl_done(_ii_info_t *ip)
5479 {
5480         ASSERT(ip->bi_ioctl > 0);
5481         ip->bi_ioctl--;
5482         if (ip->bi_ioctl == 0 && (ip->bi_state & DSW_IOCTL)) {
5483                 ip->bi_state &= ~DSW_IOCTL;
5484                 cv_broadcast(&ip->bi_ioctlcv);
5485         }
5486 
5487 }
5488 
5489 /*
5490  * _ii_find_vol
5491  *      Search the configured shadows list for the supplied volume.
5492  *      If found, flag an ioctl in progress and return the locked _ii_info_t.
5493  *
5494  *      The caller must check to see if the bi_disable flag is set and
5495  *      treat it appropriately.
5496  *
5497  * ASSUMPTION:
5498  *      _ii_info_mutex must be locked prior to calling this function
5499  *
5500  */
5501 
5502 static _ii_info_t *
5503 _ii_find_vol(char *volume, int vol)
5504 {
5505         _ii_info_t **xip, *ip;
5506 
5507         for (xip = &_ii_info_top; *xip; xip = &(*xip)->bi_next) {
5508                 if ((*xip)->bi_disabled)
5509                         continue;
5510                 if (strcmp(volume, vol == MST ? ii_pathname((*xip)->bi_mstfd) :
5511                     (*xip)->bi_keyname) == 0) {
5512                         break;
5513                 }
5514         }
5515 
5516         if (!*xip) {
5517                 DTRACE_PROBE(VolNotFound);
5518                 return (NULL);
5519         }
5520 
5521         ip = *xip;
5522         if (!ip->bi_shd_tok && ((ip->bi_flags & DSW_SHDEXPORT) == 0)) {
5523                 /* Not fully configured until bi_shd_tok is set */
5524                 DTRACE_PROBE(SetNotConfiged);
5525                 return (NULL);
5526 
5527         }
5528         mutex_enter(&ip->bi_mutex);
5529         ip->bi_ioctl++;
5530 
5531         return (ip);
5532 }
5533 
5534 static _ii_info_t *
5535 _ii_find_set(char *volume)
5536 {
5537         return (_ii_find_vol(volume, SHD));
5538 }
5539 
5540 /*
5541  * _ii_find_overflow
5542  *      Search the configured shadows list for the supplied overflow volume.
5543  *
5544  */
5545 
5546 static _ii_overflow_t *
5547 _ii_find_overflow(char *volume)
5548 {
5549         _ii_overflow_t **xop, *op;
5550 
5551         mutex_enter(&_ii_overflow_mutex);
5552 
5553         DTRACE_PROBE(_ii_find_overflowmutex);
5554 
5555         for (xop = &_ii_overflow_top; *xop; xop = &(*xop)->ii_next) {
5556                 if (strcmp(volume, (*xop)->ii_volname) == 0) {
5557                         break;
5558                 }
5559         }
5560 
5561         if (!*xop) {
5562                 mutex_exit(&_ii_overflow_mutex);
5563                 return (NULL);
5564         }
5565 
5566         op = *xop;
5567         mutex_exit(&_ii_overflow_mutex);
5568 
5569         return (op);
5570 }
5571 
5572 /*
5573  * _ii_bm_header_get
5574  *      Fetch the bitmap volume header
5575  *
5576  */
5577 
5578 ii_header_t *
5579 _ii_bm_header_get(_ii_info_t *ip, nsc_buf_t **tmp)
5580 {
5581         ii_header_t *hdr;
5582         nsc_off_t read_fba;
5583         int rc;
5584 
5585         ASSERT(ip->bi_bmprsrv);              /* assert bitmap is reserved */
5586         ASSERT(MUTEX_HELD(&ip->bi_mutex));
5587 
5588         if ((ip->bi_flags & DSW_BMPOFFLINE) != 0)
5589                 return (NULL);
5590 
5591         *tmp = NULL;
5592         read_fba = 0;
5593 
5594         II_READ_START(ip, bitmap);
5595         rc = nsc_alloc_buf(ip->bi_bmpfd, read_fba,
5596             FBA_LEN(sizeof (ii_header_t)), NSC_RDWRBUF, tmp);
5597         II_READ_END(ip, bitmap, rc, FBA_LEN(sizeof (ii_header_t)));
5598         if (!II_SUCCESS(rc)) {
5599                 if (ii_debug > 2)
5600                         cmn_err(CE_WARN, "!ii: nsc_alloc_buf returned 0x%x",
5601                             rc);
5602                 if (*tmp)
5603                         (void) nsc_free_buf(*tmp);
5604                 *tmp = NULL;
5605                 mutex_exit(&ip->bi_mutex);
5606                 _ii_error(ip, DSW_BMPOFFLINE);
5607                 mutex_enter(&ip->bi_mutex);
5608                 return (NULL);
5609         }
5610 
5611         hdr = (ii_header_t *)(*tmp)->sb_vec[0].sv_addr;
5612 
5613         return (hdr);
5614 }
5615 
5616 
5617 /*
5618  * _ii_bm_header_free
5619  *      Free the bitmap volume header
5620  *
5621  */
5622 
5623 /* ARGSUSED */
5624 
5625 void
5626 _ii_bm_header_free(ii_header_t *hdr, _ii_info_t *ip, nsc_buf_t *tmp)
5627 {
5628         (void) nsc_free_buf(tmp);
5629 
5630 }
5631 
5632 /*
5633  * _ii_bm_header_put
5634  *      Write out the modified bitmap volume header and free it
5635  *
5636  */
5637 
5638 /* ARGSUSED */
5639 
5640 int
5641 _ii_bm_header_put(ii_header_t *hdr, _ii_info_t *ip, nsc_buf_t *tmp)
5642 {
5643         nsc_off_t write_fba;
5644         int rc;
5645 
5646         ASSERT(MUTEX_HELD(&ip->bi_mutex));
5647 
5648         write_fba = 0;
5649 
5650         II_NSC_WRITE(ip, bitmap, rc, tmp, write_fba,
5651             FBA_LEN(sizeof (ii_header_t)), 0);
5652 
5653         (void) nsc_free_buf(tmp);
5654         if (!II_SUCCESS(rc)) {
5655                 mutex_exit(&ip->bi_mutex);
5656                 _ii_error(ip, DSW_BMPOFFLINE);
5657                 mutex_enter(&ip->bi_mutex);
5658                 DTRACE_PROBE(_ii_bm_header_put);
5659                 return (rc);
5660         } else {
5661                 DTRACE_PROBE(_ii_bm_header_put_end);
5662                 return (0);
5663         }
5664 }
5665 
5666 /*
5667  * _ii_flag_op
5668  *      Clear or set a flag in bi_flags and dsw_state.
5669  *      This relies on the ownership of the header block's nsc_buf
5670  *      for locking.
5671  *
5672  */
5673 
5674 void
5675 _ii_flag_op(and, or, ip, update)
5676 int     and, or;
5677 _ii_info_t *ip;
5678 int update;
5679 {
5680         ii_header_t *bm_header;
5681         nsc_buf_t *tmp;
5682 
5683         ip->bi_flags &= and;
5684         ip->bi_flags |= or;
5685 
5686         if (update == TRUE) {
5687 
5688                 /*
5689                  * No point trying to access bitmap header if it's offline
5690                  * or has been disassociated from set via DSW_HANGING
5691                  */
5692                 if ((ip->bi_flags & (DSW_BMPOFFLINE|DSW_HANGING)) == 0) {
5693                         bm_header = _ii_bm_header_get(ip, &tmp);
5694                         if (bm_header == NULL) {
5695                                 if (tmp)
5696                                         (void) nsc_free_buf(tmp);
5697                                 DTRACE_PROBE(_ii_flag_op_end);
5698                                 return;
5699                         }
5700                         bm_header->ii_state &= and;
5701                         bm_header->ii_state |= or;
5702                         /* copy over the mtime */
5703                         bm_header->ii_mtime = ip->bi_mtime;
5704                         (void) _ii_bm_header_put(bm_header, ip, tmp);
5705                 }
5706         }
5707 
5708 }
5709 
5710 /*
5711  * _ii_nsc_io
5712  *      Perform read or write on an underlying nsc device
5713  * fd           - nsc file descriptor
5714  * flag         - nsc io direction and characteristics flag
5715  * fba_pos      - offset from beginning of device in FBAs
5716  * io_addr      - pointer to data buffer
5717  * io_len       - length of io in bytes
5718  */
5719 
5720 int
5721 _ii_nsc_io(_ii_info_t *ip, int ks, nsc_fd_t *fd, int flag, nsc_off_t fba_pos,
5722     unsigned char *io_addr, nsc_size_t io_len)
5723 {
5724         nsc_buf_t *tmp = NULL;
5725         nsc_vec_t *vecp;
5726         uchar_t *vaddr;
5727         size_t  copy_len;
5728         int64_t vlen;
5729         int     rc;
5730         nsc_size_t      fba_req, fba_len;
5731         nsc_size_t      maxfbas = 0;
5732         nsc_size_t      tocopy;
5733         unsigned char *toaddr;
5734 
5735         rc = nsc_maxfbas(fd, 0, &maxfbas);
5736         if (!II_SUCCESS(rc)) {
5737 #ifdef DEBUG
5738                 cmn_err(CE_WARN, "!_ii_nsc_io: maxfbas failed (%d)", rc);
5739 #endif
5740                 maxfbas = DSW_CBLK_FBA;
5741         }
5742 
5743         toaddr = io_addr;
5744         fba_req = FBA_LEN(io_len);
5745 
5746 #ifdef DEBUG_SPLIT_IO
5747         cmn_err(CE_NOTE, "!_ii_nsc_io: maxfbas = %08x", maxfbas);
5748         cmn_err(CE_NOTE, "!_ii_nsc_io: toaddr=%08x, io_len=%08x, fba_req=%08x",
5749             toaddr, io_len, fba_req);
5750 #endif
5751 
5752 loop:
5753         tmp = NULL;
5754         fba_len = min(fba_req, maxfbas);
5755         tocopy = min(io_len, FBA_SIZE(fba_len));
5756 
5757         DTRACE_PROBE2(_ii_nsc_io_buffer, nsc_off_t, fba_pos,
5758             nsc_size_t, fba_len);
5759 
5760 #ifdef DEBUG_SPLIT_IO
5761         cmn_err(CE_NOTE, "!_ii_nsc_io: fba_pos=%08x, fba_len=%08x",
5762             fba_pos, fba_len);
5763 #endif
5764 
5765 #ifndef DISABLE_KSTATS
5766         if (flag & NSC_READ) {
5767                 switch (ks) {
5768                 case KS_MST:
5769                         II_READ_START(ip, master);
5770                         break;
5771                 case KS_SHD:
5772                         II_READ_START(ip, shadow);
5773                         break;
5774                 case KS_BMP:
5775                         II_READ_START(ip, bitmap);
5776                         break;
5777                 case KS_OVR:
5778                         II_READ_START(ip, overflow);
5779                         break;
5780                 default:
5781                         cmn_err(CE_WARN, "!Invalid kstats type %d", ks);
5782                         break;
5783                 }
5784         }
5785 #endif
5786 
5787         rc = nsc_alloc_buf(fd, fba_pos, fba_len, flag, &tmp);
5788 
5789 #ifndef DISABLE_KSTATS
5790         if (flag & NSC_READ) {
5791                 switch (ks) {
5792                 case KS_MST:
5793                         II_READ_END(ip, master, rc, fba_len);
5794                         break;
5795                 case KS_SHD:
5796                         II_READ_END(ip, shadow, rc, fba_len);
5797                         break;
5798                 case KS_BMP:
5799                         II_READ_END(ip, bitmap, rc, fba_len);
5800                         break;
5801                 case KS_OVR:
5802                         II_READ_END(ip, overflow, rc, fba_len);
5803                         break;
5804                 }
5805         }
5806 #endif
5807 
5808         if (!II_SUCCESS(rc)) {
5809                 if (tmp) {
5810                         (void) nsc_free_buf(tmp);
5811                 }
5812 
5813                 return (EIO);
5814         }
5815 
5816         if ((flag & (NSC_WRITE|NSC_READ)) == NSC_WRITE &&
5817             (FBA_OFF(io_len) != 0)) {
5818                 /*
5819                  * Not overwriting all of the last FBA, so read in the
5820                  * old contents now before we overwrite it with the new
5821                  * data.
5822                  */
5823 #ifdef DEBUG_SPLIT_IO
5824                 cmn_err(CE_NOTE, "!_ii_nsc_io: Read-B4-Write %08x",
5825                     fba_pos+FBA_NUM(io_len));
5826 #endif
5827 
5828 #ifdef DISABLE_KSTATS
5829                 rc = nsc_read(tmp, fba_pos+FBA_NUM(io_len), 1, 0);
5830 #else
5831                 switch (ks) {
5832                 case KS_MST:
5833                         II_NSC_READ(ip, master, rc, tmp,
5834                             fba_pos+FBA_NUM(io_len), 1, 0);
5835                         break;
5836                 case KS_SHD:
5837                         II_NSC_READ(ip, shadow, rc, tmp,
5838                             fba_pos+FBA_NUM(io_len), 1, 0);
5839                         break;
5840                 case KS_BMP:
5841                         II_NSC_READ(ip, bitmap, rc, tmp,
5842                             fba_pos+FBA_NUM(io_len), 1, 0);
5843                         break;
5844                 case KS_OVR:
5845                         II_NSC_READ(ip, overflow, rc, tmp,
5846                             fba_pos+FBA_NUM(io_len), 1, 0);
5847                         break;
5848                 case KS_NA:
5849                         rc = nsc_read(tmp, fba_pos+FBA_NUM(io_len), 1, 0);
5850                         break;
5851                 default:
5852                         cmn_err(CE_WARN, "!Invalid kstats type %d", ks);
5853                         rc = nsc_read(tmp, fba_pos+FBA_NUM(io_len), 1, 0);
5854                         break;
5855                 }
5856 #endif
5857                 if (!II_SUCCESS(rc)) {
5858                         (void) nsc_free_buf(tmp);
5859                         return (EIO);
5860                 }
5861         }
5862 
5863         vecp = tmp->sb_vec;
5864         vlen = vecp->sv_len;
5865         vaddr = vecp->sv_addr;
5866 
5867         while (tocopy > 0) {
5868                 if (vecp->sv_addr == 0 || vecp->sv_len == 0) {
5869 #ifdef DEBUG
5870                         cmn_err(CE_WARN, "!_ii_nsc_io: ran off end of handle");
5871 #endif
5872                         break;
5873                 }
5874 
5875                 copy_len = (size_t)min(vlen, tocopy);
5876 
5877                 DTRACE_PROBE1(_ii_nsc_io_bcopy, size_t, copy_len);
5878 
5879                 if (flag & NSC_WRITE)
5880                         bcopy(io_addr, vaddr, copy_len);
5881                 else
5882                         bcopy(vaddr, io_addr, copy_len);
5883 
5884                 toaddr += copy_len;
5885                 tocopy -= copy_len;
5886                 io_addr += copy_len;
5887                 io_len -= copy_len;
5888                 vaddr += copy_len;
5889                 vlen -= copy_len;
5890 
5891                 if (vlen <= 0) {
5892                         vecp++;
5893                         vaddr = vecp->sv_addr;
5894                         vlen = vecp->sv_len;
5895                 }
5896         }
5897 
5898         if (flag & NSC_WRITE) {
5899 #ifdef DISABLE_KSTATS
5900                 rc = nsc_write(tmp, tmp->sb_pos, tmp->sb_len, 0);
5901 #else
5902                 switch (ks) {
5903                 case KS_MST:
5904                         II_NSC_WRITE(ip, master, rc, tmp, tmp->sb_pos,
5905                             tmp->sb_len, 0);
5906                         break;
5907                 case KS_SHD:
5908                         II_NSC_WRITE(ip, shadow, rc, tmp, tmp->sb_pos,
5909                             tmp->sb_len, 0);
5910                         break;
5911                 case KS_BMP:
5912                         II_NSC_WRITE(ip, bitmap, rc, tmp, tmp->sb_pos,
5913                             tmp->sb_len, 0);
5914                         break;
5915                 case KS_OVR:
5916                         II_NSC_WRITE(ip, overflow, rc, tmp, tmp->sb_pos,
5917                             tmp->sb_len, 0);
5918                         break;
5919                 case KS_NA:
5920                         rc = nsc_write(tmp, tmp->sb_pos, tmp->sb_len, 0);
5921                         break;
5922                 default:
5923                         cmn_err(CE_WARN, "!Invalid kstats type %d", ks);
5924                         rc = nsc_write(tmp, tmp->sb_pos, tmp->sb_len, 0);
5925                         break;
5926                 }
5927 #endif
5928                 if (!II_SUCCESS(rc)) {
5929                         (void) nsc_free_buf(tmp);
5930                         return (rc);
5931                 }
5932         }
5933 
5934         (void) nsc_free_buf(tmp);
5935 
5936         fba_pos += fba_len;
5937         fba_req -= fba_len;
5938         if (fba_req > 0)
5939                 goto loop;
5940 
5941         return (0);
5942 }
5943 
5944 
5945 /*
5946  * ii_overflow_attach
5947  */
5948 static int
5949 ii_overflow_attach(_ii_info_t *ip, char *name, int first)
5950 {
5951         _ii_overflow_t *op;
5952         int rc = 0;
5953         int reserved = 0;
5954         int mutex_set = 0;
5955         int II_OLD_OMAGIC = 0x426c7565; /* "Blue" */
5956 
5957         mutex_enter(&_ii_overflow_mutex);
5958         /* search for name in list */
5959         for (op = _ii_overflow_top; op; op = op->ii_next) {
5960                 if (strncmp(op->ii_volname, name, DSW_NAMELEN) == 0)
5961                         break;
5962         }
5963         if (op) {
5964                 ip->bi_overflow = op;
5965                 op->ii_crefcnt++;
5966                 op->ii_drefcnt++;
5967                 if ((op->ii_flags & IIO_CNTR_INVLD) && (op->ii_hversion >= 1)) {
5968                         if (!first)
5969                                 mutex_enter(&ip->bi_mutex);
5970                         ip->bi_flags |= DSW_OVRHDRDRTY;
5971                         if (!first)
5972                                 mutex_exit(&ip->bi_mutex);
5973                         op->ii_urefcnt++;
5974                 }
5975 #ifndef DISABLE_KSTATS
5976                 ip->bi_kstat_io.overflow = op->ii_overflow;
5977                 (void) strlcpy(ip->bi_kstat_io.ovrio, op->ii_ioname,
5978                     KSTAT_DATA_CHAR_LEN);
5979 #endif
5980                 /* write header */
5981                 if (!(rc = nsc_reserve(op->ii_dev->bi_fd, NSC_MULTI))) {
5982                         rc = _ii_nsc_io(ip, KS_OVR, op->ii_dev->bi_fd,
5983                             NSC_WRBUF, II_OHEADER_FBA,
5984                             (unsigned char *)&op->ii_do, sizeof (op->ii_do));
5985                         (void) nsc_release(op->ii_dev->bi_fd);
5986                         ++iigkstat.assoc_over.value.ul;
5987                 }
5988                 mutex_exit(&_ii_overflow_mutex);
5989                 return (rc);
5990         }
5991         if ((op = kmem_zalloc(sizeof (*op), KM_SLEEP)) == NULL) {
5992                 mutex_exit(&_ii_overflow_mutex);
5993                 return (ENOMEM);
5994         }
5995         if ((op->ii_dev = kmem_zalloc(sizeof (_ii_info_dev_t), KM_SLEEP))
5996             == NULL) {
5997                 kmem_free(op, sizeof (*op));
5998                 mutex_exit(&_ii_overflow_mutex);
5999                 return (ENOMEM);
6000         }
6001 #ifndef DISABLE_KSTATS
6002         if ((op->ii_overflow = _ii_overflow_kstat_create(ip, op))) {
6003                 ip->bi_kstat_io.overflow = op->ii_overflow;
6004                 (void) strlcpy(op->ii_ioname, ip->bi_kstat_io.ovrio,
6005                     KSTAT_DATA_CHAR_LEN);
6006         } else {
6007                 goto fail;
6008         }
6009 #endif
6010         /* open overflow volume */
6011         op->ii_dev->bi_fd = nsc_open(name, NSC_IIR_ID|NSC_FILE|NSC_RDWR, NULL,
6012             (blind_t)&(op->ii_dev->bi_iodev), &rc);
6013         if (!op->ii_dev->bi_fd)
6014                 op->ii_dev->bi_fd = nsc_open(name,
6015                     NSC_IIR_ID|NSC_DEVICE|NSC_RDWR, NULL,
6016                     (blind_t)&(op->ii_dev->bi_iodev), &rc);
6017         if (op->ii_dev->bi_fd == NULL) {
6018                 goto fail;
6019         }
6020         if ((rc = nsc_reserve(op->ii_dev->bi_fd, 0)) != 0)
6021                 goto fail;
6022         reserved = 1;
6023         /* register path */
6024         op->ii_dev->bi_tok = _ii_register_path(name, NSC_DEVICE,
6025             _ii_ior);
6026         if (!op->ii_dev->bi_tok) {
6027                 goto fail;
6028         }
6029         /* read header */
6030         rc = _ii_nsc_io(ip, KS_OVR, op->ii_dev->bi_fd, NSC_RDBUF,
6031             II_OHEADER_FBA, (unsigned char *)&op->ii_do, sizeof (op->ii_do));
6032         if (!II_SUCCESS(rc)) {
6033                 _ii_error(ip, DSW_OVROFFLINE);
6034                 goto fail;
6035         }
6036         /* On resume, check for old hmagic */
6037         if (strncmp(op->ii_volname, name, DSW_NAMELEN) ||
6038             ((op->ii_hmagic != II_OLD_OMAGIC) &&
6039             (op->ii_hmagic != II_OMAGIC))) {
6040                 rc = DSW_EOMAGIC;
6041                 goto fail;
6042         }
6043         /* set up counts */
6044         op->ii_crefcnt = 1;
6045         op->ii_drefcnt = 0;
6046         op->ii_urefcnt = 0;
6047         op->ii_hmagic = II_OMAGIC;
6048         if (!first) {
6049                 /* if header version > 0, check if header written */
6050                 if (((op->ii_flags & IIO_HDR_WRTN) == 0) &&
6051                     (op->ii_hversion >= 1)) {
6052                         op->ii_flags |= IIO_CNTR_INVLD;
6053                         mutex_enter(&ip->bi_mutex);
6054                         ip->bi_flags |= DSW_OVRHDRDRTY;
6055                         mutex_exit(&ip->bi_mutex);
6056                         op->ii_urefcnt++;
6057                 }
6058         }
6059         op->ii_flags &= ~IIO_HDR_WRTN;
6060         op->ii_drefcnt++;
6061         /* write header */
6062         rc = _ii_nsc_io(ip, KS_OVR, op->ii_dev->bi_fd, NSC_WRBUF,
6063             II_OHEADER_FBA, (unsigned char *)&op->ii_do, sizeof (op->ii_do));
6064         nsc_release(op->ii_dev->bi_fd);
6065         reserved = 0;
6066         if (!II_SUCCESS(rc)) {
6067                 _ii_error(ip, DSW_OVROFFLINE);
6068                 goto fail;
6069         }
6070 
6071         mutex_init(&op->ii_mutex, NULL, MUTEX_DRIVER, NULL);
6072         mutex_set++;
6073 
6074         /* link onto list */
6075         op->ii_next = _ii_overflow_top;
6076         _ii_overflow_top = op;
6077         ip->bi_overflow = op;
6078 
6079         ++iigkstat.assoc_over.value.ul;
6080         mutex_exit(&_ii_overflow_mutex);
6081 
6082         DTRACE_PROBE(_ii_overflow_attach_end);
6083         return (0);
6084 fail:
6085 #ifndef DISABLE_KSTATS
6086         /* Clean-up kstat stuff */
6087         if (op->ii_overflow) {
6088                 kstat_delete(op->ii_overflow);
6089                 mutex_destroy(&op->ii_kstat_mutex);
6090         }
6091 #endif
6092         /* clean up mutex if we made it that far */
6093         if (mutex_set) {
6094                 mutex_destroy(&op->ii_mutex);
6095         }
6096 
6097         if (op->ii_dev) {
6098                 if (op->ii_dev->bi_tok) {
6099                         (void) _ii_unregister_path(op->ii_dev->bi_tok, 0,
6100                             "overflow");
6101                 }
6102                 if (reserved)
6103                         (void) nsc_release(op->ii_dev->bi_fd);
6104                 if (op->ii_dev->bi_fd)
6105                         (void) nsc_close(op->ii_dev->bi_fd);
6106                 kmem_free(op->ii_dev, sizeof (_ii_info_dev_t));
6107         }
6108         kmem_free(op, sizeof (*op));
6109         mutex_exit(&_ii_overflow_mutex);
6110 
6111         return (rc);
6112 }
6113 
6114 /*
6115  * ii_overflow_free
6116  * Assumes that ip is locked for I/O
6117  */
6118 static void
6119 ii_overflow_free(_ii_info_t *ip, int reclaim)
6120 {
6121         _ii_overflow_t *op, **xp;
6122 
6123         if ((op = ip->bi_overflow) == NULL)
6124                 return;
6125         ip->bi_kstat_io.overflow = NULL;
6126         mutex_enter(&_ii_overflow_mutex);
6127         switch (reclaim) {
6128         case NO_RECLAIM:
6129                 if (--(op->ii_drefcnt) == 0) {
6130                         /* indicate header written */
6131                         op->ii_flags |= IIO_HDR_WRTN;
6132                         /* write out header */
6133                         ASSERT(op->ii_dev->bi_fd);
6134                         (void) nsc_reserve(op->ii_dev->bi_fd, NSC_MULTI);
6135                         (void) _ii_nsc_io(ip, KS_OVR, op->ii_dev->bi_fd,
6136                             NSC_WRBUF, II_OHEADER_FBA,
6137                             (unsigned char *)&op->ii_do,
6138                             sizeof (op->ii_do));
6139                         nsc_release(op->ii_dev->bi_fd);
6140                 }
6141                 break;
6142         case RECLAIM:
6143                 ii_reclaim_overflow(ip);
6144                 /* FALLTHRU */
6145         case INIT_OVR:
6146                 if (--(op->ii_drefcnt) == 0) {
6147                         /* reset to new condition, c.f. _ii_ocreate() */
6148                         op->ii_used = 1;
6149                         op->ii_unused = op->ii_nchunks - op->ii_used;
6150                         op->ii_freehead = II_NULLNODE;
6151                 }
6152 
6153                 /* write out header */
6154                 ASSERT(op->ii_dev->bi_fd);
6155                 (void) nsc_reserve(op->ii_dev->bi_fd, NSC_MULTI);
6156                 (void) _ii_nsc_io(ip, KS_OVR, op->ii_dev->bi_fd, NSC_WRBUF,
6157                     II_OHEADER_FBA, (unsigned char *)&op->ii_do,
6158                     sizeof (op->ii_do));
6159                 nsc_release(op->ii_dev->bi_fd);
6160         }
6161 
6162         if (--(op->ii_crefcnt) == 0) {
6163                 /* Close fd and unlink from active chain; */
6164 
6165                 (void) _ii_unregister_path(op->ii_dev->bi_tok, 0, "overflow");
6166                 (void) nsc_close(op->ii_dev->bi_fd);
6167 
6168                 for (xp = &_ii_overflow_top; *xp && *xp != op;
6169                     xp = &((*xp)->ii_next))
6170                         /* NULL statement */;
6171                 *xp = op->ii_next;
6172 
6173                 if (op->ii_overflow) {
6174                         kstat_delete(op->ii_overflow);
6175                 }
6176 
6177                 /* Clean up ii_overflow_t mutexs */
6178                 mutex_destroy(&op->ii_kstat_mutex);
6179                 mutex_destroy(&op->ii_mutex);
6180 
6181                 if (op->ii_dev)
6182                         kmem_free(op->ii_dev, sizeof (_ii_info_dev_t));
6183                 kmem_free(op, sizeof (*op));
6184         }
6185         ip->bi_overflow = NULL;
6186         --iigkstat.assoc_over.value.ul;
6187         mutex_exit(&_ii_overflow_mutex);
6188 
6189 }
6190 
6191 /*
6192  * ii_sibling_free
6193  *      Free resources and unlink the sibling chains etc.
6194  */
6195 
6196 static void
6197 ii_sibling_free(_ii_info_t *ip)
6198 {
6199         _ii_info_t *hip, *yip;
6200 
6201         if (!ip)
6202                 return;
6203 
6204         if (ip->bi_shdr_tok)
6205                 (void) _ii_unregister_path(ip->bi_shdr_tok, 0, "raw shadow");
6206 
6207         if (ip->bi_shd_tok)
6208                 (void) _ii_unregister_path(ip->bi_shd_tok, 0, "shadow");
6209 
6210         rw_enter(&ip->bi_linkrw, RW_WRITER);
6211 
6212         ip->bi_shd_tok = NULL;
6213         ip->bi_shdr_tok = NULL;
6214 
6215         if (NSHADOWS(ip)) {
6216                 mutex_enter(&_ii_info_mutex);
6217                 if (ip->bi_head == ip) {     /* removing head of list */
6218                         hip = ip->bi_sibling;
6219                         for (yip = hip; yip; yip = yip->bi_sibling)
6220                                 yip->bi_head = hip;
6221 
6222                 } else {                /* removing member of list */
6223                         hip = ip->bi_head;
6224                         for (yip = ip->bi_head; yip; yip = yip->bi_sibling) {
6225                                 if (yip->bi_sibling == ip) {
6226                                         yip->bi_sibling = ip->bi_sibling;
6227                                         break;
6228                                 }
6229                         }
6230                 }
6231                 hip->bi_master->bi_head = hip;
6232                 if (ip->bi_master == ip) {    /* master I/O goes through this */
6233                         mutex_exit(&_ii_info_mutex);
6234                         _ii_info_freeshd(ip);
6235                         rw_exit(&ip->bi_linkrw);
6236                         return;
6237                 }
6238                 mutex_exit(&_ii_info_mutex);
6239         } else {
6240                 if (ip->bi_master != ip)     /* last ref to master side ip */
6241                         _ii_info_free(ip->bi_master);        /* ==A== */
6242         }
6243 
6244         if (ip->bi_master != ip) {   /* info_free ==A== will close these */
6245                 /*
6246                  * Null out any pointers to shared master side resources
6247                  * that should only be freed once when the last reference
6248                  * to this master is freed and calls _ii_info_free().
6249                  */
6250                 ip->bi_mstdev = NULL;
6251                 ip->bi_mstrdev = NULL;
6252                 ip->bi_kstat_io.master = NULL;
6253         }
6254         rw_exit(&ip->bi_linkrw);
6255         _ii_info_free(ip);
6256 
6257 }
6258 
6259 /*
6260  * _ii_info_freeshd
6261  *      Free shadow side resources
6262  *
6263  * Calling/Exit State:
6264  *      No mutexes should be held on entry to this function.
6265  *
6266  * Description:
6267  *      Frees the system resources associated with the shadow
6268  *      access, leaving the master side alone. This allows the
6269  *      original master side to continue in use while there are
6270  *      outstanding references to this _ii_info_t.
6271  */
6272 
6273 static void
6274 _ii_info_freeshd(_ii_info_t *ip)
6275 {
6276         if (!ip)
6277                 return;
6278         if ((ip->bi_flags&DSW_HANGING) == DSW_HANGING)
6279                 return;         /* this work has already been completed */
6280 
6281         II_FLAG_SETX(DSW_HANGING, ip);
6282 
6283         if (ip->bi_cluster)
6284                 (void) II_UNLINK_CLUSTER(ip);
6285         if (ip->bi_group)
6286                 (void) II_UNLINK_GROUP(ip);
6287 
6288         if (ip->bi_shdfd && ip->bi_shdrsrv)
6289                 nsc_release(ip->bi_shdfd);
6290         if (ip->bi_shdrfd && ip->bi_shdrrsrv)
6291                 nsc_release(ip->bi_shdrfd);
6292         if (ip->bi_bmpfd && ip->bi_bmprsrv)
6293                 nsc_release(ip->bi_bmpfd);
6294 
6295         if (ip->bi_bmp_tok)
6296                 (void) _ii_unregister_path(ip->bi_bmp_tok, 0, "bitmap");
6297 
6298         if (ip->bi_shdr_tok)
6299                 (void) _ii_unregister_path(ip->bi_shdr_tok, 0, "raw shadow");
6300 
6301         if (ip->bi_shd_tok)
6302                 (void) _ii_unregister_path(ip->bi_shd_tok, 0, "shadow");
6303         ip->bi_shd_tok = NULL;
6304         ip->bi_shdr_tok = NULL;
6305 
6306         if (ip->bi_shdfd)
6307                 (void) nsc_close(ip->bi_shdfd);
6308 
6309         if (ip->bi_shdrfd)
6310                 (void) nsc_close(ip->bi_shdrfd);
6311 
6312         if (ip->bi_bmpfd)
6313                 (void) nsc_close(ip->bi_bmpfd);
6314 
6315         ip->bi_shdfd = NULL;
6316         ip->bi_shdrfd = NULL;
6317         ip->bi_bmpfd = NULL;
6318 
6319         if (ip->bi_busy)
6320                 kmem_free(ip->bi_busy,
6321                     1 + (ip->bi_size / (DSW_SIZE * DSW_BITS)));
6322         ip->bi_busy = NULL;
6323 
6324         if (ip->bi_kstat_io.shadow) {
6325                 kstat_delete(ip->bi_kstat_io.shadow);
6326                 ip->bi_kstat_io.shadow = NULL;
6327         }
6328         if (ip->bi_kstat_io.bitmap) {
6329                 kstat_delete(ip->bi_kstat_io.bitmap);
6330                 ip->bi_kstat_io.bitmap = NULL;
6331         }
6332         if (ip->bi_kstat) {
6333                 kstat_delete(ip->bi_kstat);
6334                 ip->bi_kstat = NULL;
6335         }
6336 
6337 }
6338 
6339 /*
6340  * _ii_info_free
6341  *      Free resources
6342  *
6343  * Calling/Exit State:
6344  *      No mutexes should be held on entry to this function.
6345  *
6346  * Description:
6347  *      Frees the system resources associated with the specified
6348  *      II information structure.
6349  */
6350 
6351 static void
6352 _ii_info_free(_ii_info_t *ip)
6353 {
6354         _ii_info_t **xip;
6355 
6356         if (!ip)
6357                 return;
6358 
6359         mutex_enter(&_ii_info_mutex);
6360         for (xip = &_ii_mst_top; *xip; xip = &((*xip)->bi_nextmst)) {
6361                 if (ip == *xip) {
6362                         *xip = ip->bi_nextmst;
6363                         break;
6364                 }
6365         }
6366         mutex_exit(&_ii_info_mutex);
6367 
6368         /* this rw_enter forces us to wait until all nsc_buffers are freed */
6369         rw_enter(&ip->bi_linkrw, RW_WRITER);
6370         if (ip->bi_mstdev && ip->bi_mstfd && ip->bi_mstrsrv)
6371                 nsc_release(ip->bi_mstfd);
6372         if (ip->bi_mstrdev && ip->bi_mstrfd && ip->bi_mstrrsrv)
6373                 nsc_release(ip->bi_mstrfd);
6374 
6375         if (ip->bi_mstdev && ip->bi_mst_tok)
6376                 (void) _ii_unregister_path(ip->bi_mst_tok, 0, "master");
6377         if (ip->bi_mstrdev && ip->bi_mstr_tok)
6378                 (void) _ii_unregister_path(ip->bi_mstr_tok, 0, "raw master");
6379 
6380         if (ip->bi_mstdev && ip->bi_mstfd)
6381                 (void) nsc_close(ip->bi_mstfd);
6382         if (ip->bi_mstrdev && ip->bi_mstrfd)
6383                 (void) nsc_close(ip->bi_mstrfd);
6384         rw_exit(&ip->bi_linkrw);
6385 
6386         if (ip->bi_mstdev) {
6387                 nsc_kmem_free(ip->bi_mstdev, sizeof (*ip->bi_mstdev));
6388         }
6389         if (ip->bi_mstrdev) {
6390                 nsc_kmem_free(ip->bi_mstrdev, sizeof (*ip->bi_mstrdev));
6391         }
6392 
6393         if (ip->bi_kstat_io.master) {
6394                 kstat_delete(ip->bi_kstat_io.master);
6395         }
6396         if (ip->bi_kstat_io.shadow) {
6397                 kstat_delete(ip->bi_kstat_io.shadow);
6398                 ip->bi_kstat_io.shadow = 0;
6399         }
6400         if (ip->bi_kstat_io.bitmap) {
6401                 kstat_delete(ip->bi_kstat_io.bitmap);
6402                 ip->bi_kstat_io.bitmap = 0;
6403         }
6404         if (ip->bi_kstat) {
6405                 kstat_delete(ip->bi_kstat);
6406                 ip->bi_kstat = NULL;
6407         }
6408 
6409         /* this rw_enter forces us to wait until all nsc_buffers are freed */
6410         rw_enter(&ip->bi_linkrw, RW_WRITER);
6411         rw_exit(&ip->bi_linkrw);
6412 
6413         mutex_destroy(&ip->bi_mutex);
6414         mutex_destroy(&ip->bi_rsrvmutex);
6415         mutex_destroy(&ip->bi_rlsemutex);
6416         mutex_destroy(&ip->bi_bmpmutex);
6417         mutex_destroy(&ip->bi_chksmutex);
6418         cv_destroy(&ip->bi_copydonecv);
6419         cv_destroy(&ip->bi_reservecv);
6420         cv_destroy(&ip->bi_releasecv);
6421         cv_destroy(&ip->bi_ioctlcv);
6422         cv_destroy(&ip->bi_closingcv);
6423         cv_destroy(&ip->bi_busycv);
6424         rw_destroy(&ip->bi_busyrw);
6425         rw_destroy(&ip->bi_linkrw);
6426 
6427         _ii_info_freeshd(ip);
6428 
6429 #ifdef DEBUG
6430         ip->bi_head = (_ii_info_t *)0xdeadbeef;
6431 #endif
6432 
6433         nsc_kmem_free(ip, sizeof (*ip));
6434 
6435 }
6436 
6437 /*
6438  * _ii_copy_chunks
6439  *      Perform a copy of some chunks
6440  *
6441  * Calling/Exit State:
6442  *      Returns 0 if the data was copied successfully, otherwise
6443  *      error code.
6444  *
6445  * Description:
6446  *      flag is set to CV_SHD2MST if the data is to be copied from the shadow
6447  *      to the master, 0 if it is to be copied from the master to the shadow.
6448  */
6449 
6450 static int
6451 _ii_copy_chunks(_ii_info_t *ip, int flag, chunkid_t chunk_num, int nchunks)
6452 {
6453         int     mst_flag;
6454         int     shd_flag;
6455         int     ovr_flag;
6456         nsc_off_t       pos;
6457         nsc_size_t      len;
6458         int     rc;
6459         nsc_off_t       shd_pos;
6460         chunkid_t       shd_chunk;
6461         nsc_buf_t *mst_tmp = NULL;
6462         nsc_buf_t *shd_tmp = NULL;
6463 
6464         if (ip->bi_flags & DSW_MSTOFFLINE) {
6465                 DTRACE_PROBE(_ii_copy_chunks_end);
6466                 return (EIO);
6467         }
6468 
6469         if (ip->bi_flags & (DSW_SHDOFFLINE|DSW_SHDEXPORT|DSW_SHDIMPORT)) {
6470                 DTRACE_PROBE(_ii_copy_chunks_end);
6471                 return (EIO);
6472         }
6473 
6474         if (flag == CV_SHD2MST) {
6475                 mst_flag = NSC_WRBUF|NSC_WRTHRU;
6476                 shd_flag = NSC_RDBUF;
6477         } else {
6478                 shd_flag = NSC_WRBUF|NSC_WRTHRU;
6479                 mst_flag = NSC_RDBUF;
6480         }
6481 
6482         pos = DSW_CHK2FBA(chunk_num);
6483         len = DSW_SIZE * nchunks;
6484         if (pos + len > ip->bi_size)
6485                 len = ip->bi_size - pos;
6486         if (ip->bi_flags & DSW_TREEMAP) {
6487                 ASSERT(nchunks == 1);
6488                 shd_chunk = ii_tsearch(ip, chunk_num);
6489                 if (shd_chunk == II_NULLNODE) {
6490                         /* shadow is full */
6491                         mutex_enter(&ip->bi_mutex);
6492                         II_FLAG_SET(DSW_OVERFLOW, ip);
6493                         mutex_exit(&ip->bi_mutex);
6494                         DTRACE_PROBE(_ii_copy_chunks_end);
6495                         return (EIO);
6496                 }
6497 
6498                 ovr_flag = II_ISOVERFLOW(shd_chunk);
6499                 shd_pos = DSW_CHK2FBA((ovr_flag) ?
6500                     II_2OVERFLOW(shd_chunk) : shd_chunk);
6501         } else {
6502                 ovr_flag = FALSE;
6503                 shd_chunk = chunk_num;
6504                 shd_pos = pos;
6505         }
6506 
6507         /*
6508          * Always allocate the master side before the shadow to
6509          * avoid deadlocks on the same chunk.
6510          */
6511 
6512         DTRACE_PROBE2(_ii_copy_chunks_alloc, nsc_off_t, pos, nsc_size_t, len);
6513 
6514         II_ALLOC_BUF(ip, master, rc, MSTFD(ip), pos, len, mst_flag, &mst_tmp);
6515         if (!II_SUCCESS(rc)) {
6516                 if (mst_tmp)
6517                         (void) nsc_free_buf(mst_tmp);
6518                 _ii_error(ip, DSW_MSTOFFLINE);
6519                 DTRACE_PROBE(_ii_copy_chunks_end);
6520                 return (rc);
6521         }
6522 
6523         if (ovr_flag) {
6524                 /* use overflow volume */
6525                 (void) nsc_reserve(OVRFD(ip), NSC_MULTI);
6526                 II_ALLOC_BUF(ip, overflow, rc, OVRFD(ip), shd_pos, len,
6527                     shd_flag, &shd_tmp);
6528         } else {
6529                 II_ALLOC_BUF(ip, shadow, rc, SHDFD(ip), shd_pos, len, shd_flag,
6530                     &shd_tmp);
6531         }
6532         if (!II_SUCCESS(rc)) {
6533                 (void) nsc_free_buf(mst_tmp);
6534                 if (shd_tmp)
6535                         (void) nsc_free_buf(shd_tmp);
6536                 if (ovr_flag)
6537                         nsc_release(OVRFD(ip));
6538                 _ii_error(ip, DSW_SHDOFFLINE);
6539                 if (ovr_flag)
6540                         _ii_error(ip, DSW_OVROFFLINE);
6541                 DTRACE_PROBE(_ii_copy_chunks_end);
6542                 return (rc);
6543         }
6544 
6545         /*
6546          * The direction of copy is determined by the mst_flag.
6547          */
6548         DTRACE_PROBE2(_ii_copy_chunks_copy, kstat_named_t, ii_copy_direct,
6549             int, mst_flag);
6550 
6551         if (ii_copy_direct) {
6552                 if (mst_flag & NSC_WRBUF) {
6553                         if (ovr_flag) {
6554                                 II_NSC_COPY_DIRECT(ip, overflow, master, rc,
6555                                     shd_tmp, mst_tmp, shd_pos, pos, len)
6556                         } else {
6557                                 II_NSC_COPY_DIRECT(ip, shadow, master, rc,
6558                                     shd_tmp, mst_tmp, shd_pos, pos, len)
6559                         }
6560                         if (!II_SUCCESS(rc)) {
6561                                 /* A copy has failed - something is wrong */
6562                                 _ii_error(ip, DSW_MSTOFFLINE);
6563                                 _ii_error(ip, DSW_SHDOFFLINE);
6564                                 if (ovr_flag)
6565                                         _ii_error(ip, DSW_OVROFFLINE);
6566                         }
6567                 } else {
6568                         if (ovr_flag) {
6569                                 II_NSC_COPY_DIRECT(ip, master, overflow, rc,
6570                                     mst_tmp, shd_tmp, pos, shd_pos, len);
6571                         } else {
6572                                 II_NSC_COPY_DIRECT(ip, master, shadow, rc,
6573                                     mst_tmp, shd_tmp, pos, shd_pos, len);
6574                         }
6575                         if (!II_SUCCESS(rc)) {
6576                                 /*
6577                                  * A failure has occurred during the above copy.
6578                                  * The macro calls nsc_copy_direct, which will
6579                                  * never return a read failure, only a write
6580                                  * failure. With this assumption, we should
6581                                  * take only the target volume offline.
6582                                  */
6583                                 _ii_error(ip, DSW_SHDOFFLINE);
6584                                 if (ovr_flag)
6585                                         _ii_error(ip, DSW_OVROFFLINE);
6586                         }
6587                 }
6588         } else {
6589                 if (mst_flag & NSC_WRBUF) {
6590                         rc = nsc_copy(shd_tmp, mst_tmp, shd_pos, pos, len);
6591                         if (II_SUCCESS(rc)) {
6592                                 II_NSC_WRITE(ip, master, rc, mst_tmp, pos, len,
6593                                     0);
6594                                 if (!II_SUCCESS(rc))
6595                                         _ii_error(ip, DSW_MSTOFFLINE);
6596                         } else {
6597                                 /* A copy has failed - something is wrong */
6598                                 _ii_error(ip, DSW_MSTOFFLINE);
6599                                 _ii_error(ip, DSW_SHDOFFLINE);
6600                         }
6601                 } else {
6602                         rc = nsc_copy(mst_tmp, shd_tmp, pos, shd_pos, len);
6603                         if (II_SUCCESS(rc)) {
6604                                 if (ovr_flag) {
6605                                         II_NSC_WRITE(ip, overflow, rc, shd_tmp,
6606                                             shd_pos, len, 0);
6607                                 } else {
6608                                         II_NSC_WRITE(ip, shadow, rc, shd_tmp,
6609                                             shd_pos, len, 0);
6610                                 }
6611                                 if (!II_SUCCESS(rc)) {
6612                                         _ii_error(ip, DSW_SHDOFFLINE);
6613                                         if (ovr_flag)
6614                                                 _ii_error(ip, DSW_OVROFFLINE);
6615                                 }
6616                         } else {
6617                                 /* A copy has failed - something is wrong */
6618                                 _ii_error(ip, DSW_MSTOFFLINE);
6619                                 _ii_error(ip, DSW_SHDOFFLINE);
6620                         }
6621                 }
6622         }
6623 
6624         (void) nsc_free_buf(mst_tmp);
6625         (void) nsc_free_buf(shd_tmp);
6626         if (ovr_flag)
6627                 nsc_release(OVRFD(ip));
6628 
6629         DTRACE_PROBE(_ii_copy_chunks);
6630 
6631         if (II_SUCCESS(rc)) {
6632                 (void) II_CLR_COPY_BITS(ip, chunk_num, nchunks);
6633                 rc = 0;
6634         }
6635 
6636         return (rc);
6637 }
6638 
6639 
6640 /*
6641  * _ii_copy_on_write
6642  *
6643  * Calling/Exit State:
6644  *      Returns 0 on success, otherwise error code.
6645  *
6646  * Description:
6647  *      Determines if a copy on write is necessary, and performs it.
6648  *      A copy on write is necessary in the following cases:
6649  *              - No copy is in progress and the shadow bit is clear, which
6650  *                means this is the first write to this track.
6651  *              - A copy is in progress and the copy bit is set, which means
6652  *                that a track copy is required.
6653  *      If a copy to the master is to be done, make a recursive call to this
6654  *      function to do any necessary copy on write on other InstantImage groups
6655  *      that share the same master volume.
6656  */
6657 
6658 static int
6659 _ii_copy_on_write(_ii_info_t *ip, int flag, chunkid_t chunk_num, int nchunks)
6660 {
6661         int rc = 0;
6662         int rtype;
6663         int hanging =  (ip->bi_flags&DSW_HANGING);
6664 
6665         if (hanging ||
6666             (flag & (CV_SIBLING|CV_SHD2MST)) == CV_SHD2MST && NSHADOWS(ip)) {
6667                 _ii_info_t *xip;
6668                 /*
6669                  * Preserve copy of master for all other shadows of this master
6670                  * before writing our data onto the master.
6671                  */
6672 
6673                 /*
6674                  * Avoid deadlock with COW on same chunk of sibling shadow
6675                  * by unlocking this chunk before copying all other sibling
6676                  * chunks.
6677                  */
6678 
6679                 /*
6680                  * Only using a single chunk when copying to master avoids
6681                  * complex code here.
6682                  */
6683 
6684                 ASSERT(nchunks == 1);
6685                 if (!hanging)
6686                         _ii_unlock_chunk(ip, chunk_num);
6687                 for (xip = ip->bi_head; xip; xip = xip->bi_sibling) {
6688                         if (xip == ip)          /* don't copy ourselves again */
6689                                 continue;
6690 
6691                         DTRACE_PROBE(_ii_copy_on_write);
6692 
6693                         rw_enter(&xip->bi_linkrw, RW_READER);
6694                         mutex_enter(&xip->bi_mutex);
6695                         if (xip->bi_disabled) {
6696                                 mutex_exit(&xip->bi_mutex);
6697                                 rw_exit(&xip->bi_linkrw);
6698                                 continue;       /* this set is stopping */
6699                         }
6700                         xip->bi_shdref++;
6701                         mutex_exit(&xip->bi_mutex);
6702                         /* don't waste time asking for MST as ip shares it */
6703                         rtype = SHDR|BMP;
6704                         (void) _ii_rsrv_devs(xip, rtype, II_INTERNAL);
6705                         _ii_lock_chunk(xip, chunk_num);
6706                         rc = _ii_copy_on_write(xip, flag | CV_SIBLING,
6707                             chunk_num, 1);
6708 
6709                         /*
6710                          * See comments in _ii_shadow_write()
6711                          */
6712                         if (rc == 0 ||
6713                             (rc == EIO && (xip->bi_flags&DSW_OVERFLOW) != 0))
6714                                 (void) II_SET_SHD_BIT(xip, chunk_num);
6715 
6716                         _ii_unlock_chunk(xip, chunk_num);
6717                         _ii_rlse_devs(xip, rtype);
6718                         mutex_enter(&xip->bi_mutex);
6719                         xip->bi_shdref--;
6720                         if (xip->bi_state & DSW_CLOSING) {
6721                                 if (total_ref(xip) == 0) {
6722                                         cv_signal(&xip->bi_closingcv);
6723                                 }
6724                         }
6725                         mutex_exit(&xip->bi_mutex);
6726                         rw_exit(&xip->bi_linkrw);
6727                 }
6728                 if (hanging) {
6729                         DTRACE_PROBE(_ii_copy_on_write_end);
6730                         return (0);
6731                 }
6732                 /*
6733                  * Reacquire chunk lock and check that a COW by a sibling
6734                  * has not already copied this chunk.
6735                  */
6736                 _ii_lock_chunk(ip, chunk_num);
6737                 rc = II_TST_SHD_BIT(ip, chunk_num);
6738                 if (rc < 0) {
6739                         DTRACE_PROBE(_ii_copy_on_write_end);
6740                         return (EIO);
6741                 }
6742                 if (rc != 0) {
6743                         DTRACE_PROBE(_ii_copy_on_write_end);
6744                         return (0);
6745                 }
6746         }
6747 
6748         if ((ip->bi_flags & DSW_COPYING) == 0) {
6749                 /* Not copying at all */
6750 
6751                 if ((ip->bi_flags & DSW_GOLDEN) == DSW_GOLDEN) {
6752                         /* No copy-on-write as it is independent */
6753                         DTRACE_PROBE(_ii_copy_on_write_end);
6754                         return (0);
6755                 }
6756 
6757                 /* Dependent, so depends on shadow bit */
6758 
6759                 if ((flag == CV_SHD2MST) &&
6760                     ((ip->bi_flags & DSW_SHDOFFLINE) != 0)) {
6761                         /*
6762                          * Writing master but shadow is offline, so
6763                          * no need to copy on write or set shadow bit
6764                          */
6765                         DTRACE_PROBE(_ii_copy_on_write_end);
6766                         return (0);
6767                 }
6768                 if (ip->bi_flags & DSW_BMPOFFLINE) {
6769                         DTRACE_PROBE(_ii_copy_on_write_end);
6770                         return (EIO);
6771                 }
6772                 rc = II_TST_SHD_BIT(ip, chunk_num);
6773                 if (rc < 0) {
6774                         DTRACE_PROBE(_ii_copy_on_write_end);
6775                         return (EIO);
6776                 }
6777                 if (rc == 0) {
6778                         /* Shadow bit clear, copy master to shadow */
6779                         rc = _ii_copy_chunks(ip, 0, chunk_num, nchunks);
6780                 }
6781         } else {
6782                 /* Copying one way or the other */
6783                 if (ip->bi_flags & DSW_BMPOFFLINE) {
6784                         DTRACE_PROBE(_ii_copy_on_write_end);
6785                         return (EIO);
6786                 }
6787                 rc = II_TST_COPY_BIT(ip, chunk_num);
6788                 if (rc < 0) {
6789                         DTRACE_PROBE(_ii_copy_on_write_end);
6790                         return (EIO);
6791                 }
6792                 if (rc) {
6793                         /* Copy bit set, do a copy */
6794                         if ((ip->bi_flags & DSW_COPYINGS) == 0) {
6795                                 /* Copy master to shadow */
6796                                 rc = _ii_copy_chunks(ip, 0, chunk_num, nchunks);
6797                         } else {
6798                                 /* Copy shadow to master */
6799                                 rc = _ii_copy_chunks(ip, CV_SHD2MST, chunk_num,
6800                                     nchunks);
6801                         }
6802                 }
6803         }
6804         return (rc);
6805 }
6806 
6807 #ifdef  DEBUG
6808 int ii_maxchunks = 0;
6809 #endif
6810 
6811 /*
6812  * _ii_copyvolp()
6813  *      Copy volume process.
6814  *
6815  * Calling/Exit State:
6816  *      Passes 0 back to caller when the copy is complete or has been aborted,
6817  *      otherwise error code.
6818  *
6819  * Description:
6820  *      According to the flag, copy the master to the shadow volume or the
6821  *      shadow to the master volume. Upon return wakeup all processes waiting
6822  *      for this copy.
6823  *
6824  */
6825 
6826 static void
6827 _ii_copyvolp(struct copy_args *ca)
6828 {
6829         chunkid_t       chunk_num;
6830         int     rc = 0;
6831         chunkid_t       max_chunk;
6832         nsc_size_t      nc_max;
6833         int             nc_try, nc_got;
6834         nsc_size_t      mst_max, shd_max;
6835         _ii_info_t *ip;
6836         int     flag;
6837         nsc_size_t      bitmap_size;
6838         nsc_size_t      shadow_set, copy_set;
6839         int     chunkcount = 0;
6840         int     rsrv = 1;
6841         spcs_s_info_t kstatus;
6842 
6843         ip = ca->ip;
6844         flag = ca->flag;
6845         kstatus = ca->kstatus;
6846 
6847         if (ip->bi_disabled) {
6848                 rc = DSW_EABORTED;
6849                 goto skip;
6850         }
6851         max_chunk = ip->bi_size / DSW_SIZE;
6852         if ((ip->bi_size % DSW_SIZE) != 0)
6853                 ++max_chunk;
6854         if ((ip->bi_flags&DSW_TREEMAP))
6855                 nc_max = 1;
6856         else {
6857                 mst_max = shd_max = 0;
6858                 (void) nsc_maxfbas(MSTFD(ip), 0, &mst_max);
6859                 (void) nsc_maxfbas(SHDFD(ip), 0, &shd_max);
6860                 nc_max = (mst_max < shd_max) ? mst_max : shd_max;
6861                 nc_max /= DSW_SIZE;
6862                 ASSERT(nc_max > 0 && nc_max < 1000);
6863         }
6864 #ifdef  DEBUG
6865         if (ii_maxchunks > 0)
6866                 nc_max = ii_maxchunks;
6867 #endif
6868         for (chunk_num = nc_got = 0; /* CSTYLED */; /* CSTYLED */) {
6869                 if ((flag & CV_SHD2MST) && NSHADOWS(ip))
6870                         nc_try = 1;
6871                 else
6872                         nc_try = (int)nc_max;
6873                 chunk_num = II_NEXT_COPY_BIT(ip, chunk_num + nc_got,
6874                     max_chunk, nc_try, &nc_got);
6875 
6876                 if (chunk_num >= max_chunk)  /* loop complete */
6877                         break;
6878                 if (ip->bi_flags & DSW_COPYINGX) {
6879                         /* request to abort copy */
6880                         _ii_unlock_chunks(ip, chunk_num, nc_got);
6881                         rc = DSW_EABORTED;
6882                         break;
6883                 }
6884 
6885                 sema_p(&_ii_concopy_sema);
6886                 rc = _ii_copy_on_write(ip, (flag & CV_SHD2MST), chunk_num,
6887                     nc_got);
6888                 sema_v(&_ii_concopy_sema);
6889                 if (ip->bi_flags & DSW_TREEMAP)
6890                         ii_tdelete(ip, chunk_num);
6891                 _ii_unlock_chunks(ip, chunk_num, nc_got);
6892                 if (!II_SUCCESS(rc)) {
6893                         if (ca->wait)
6894                                 spcs_s_add(kstatus, rc);
6895                         rc = DSW_EIO;
6896                         break;
6897                 }
6898                 if (ip->bi_release ||
6899                     (++chunkcount % ip->bi_throttle_unit) == 0) {
6900                         _ii_rlse_devs(ip, (ca->rtype&(~BMP)));
6901                         rsrv = 0;
6902                         delay(ip->bi_throttle_delay);
6903                         ca->rtype = MSTR|SHDR|(ca->rtype&BMP);
6904                         if ((rc = _ii_rsrv_devs(ip, (ca->rtype&(~BMP)),
6905                             II_INTERNAL)) != 0) {
6906                                 if (ca->wait)
6907                                         spcs_s_add(kstatus, rc);
6908                                 rc = DSW_EIO;
6909                                 break;
6910                         }
6911                         rsrv = 1;
6912                         if (nc_max > 1) {
6913                                 /*
6914                                  * maxfbas could have changed during the
6915                                  * release/reserve, so recalculate the size
6916                                  * of transfer we can do.
6917                                  */
6918                                 (void) nsc_maxfbas(MSTFD(ip), 0, &mst_max);
6919                                 (void) nsc_maxfbas(SHDFD(ip), 0, &shd_max);
6920                                 nc_max = (mst_max < shd_max) ?
6921                                     mst_max : shd_max;
6922                                 nc_max /= DSW_SIZE;
6923                         }
6924                 }
6925         }
6926 skip:
6927         mutex_enter(&ip->bi_mutex);
6928         if (ip->bi_flags & DSW_COPYINGX)
6929                 II_FLAG_CLR(DSW_COPYINGP|DSW_COPYINGX, ip);
6930         else
6931                 II_FLAG_CLR(DSW_COPY_FLAGS, ip);
6932 
6933         if ((ip->bi_flags & DSW_TREEMAP) && (flag & CV_SHD2MST) &&
6934             (ip->bi_flags & DSW_VOVERFLOW)) {
6935                 int rs;
6936                 bitmap_size = ip->bi_size / DSW_SIZE;
6937                 if ((ip->bi_size % DSW_SIZE) != 0)
6938                         ++bitmap_size;
6939                 bitmap_size += 7;
6940                 bitmap_size /= 8;
6941 
6942                 /* Count the number of copy bits set */
6943                 rs = II_CNT_BITS(ip, ip->bi_copyfba, &copy_set, bitmap_size);
6944                 if ((rs == 0) && (copy_set == 0)) {
6945                         /*
6946                          * If we counted successfully and completed the copy
6947                          * see if any writes have forced the set into the
6948                          * overflow
6949                          */
6950                         rs = II_CNT_BITS(ip, ip->bi_shdfba, &shadow_set,
6951                             bitmap_size);
6952                         if ((rs == 0) && (shadow_set <
6953                             (nsc_size_t)ip->bi_shdchks)) {
6954                                 II_FLAG_CLR(DSW_VOVERFLOW, ip);
6955                                 --iigkstat.spilled_over.value.ul;
6956                         }
6957                 }
6958         }
6959 
6960         ca->rc = rc;
6961         cv_broadcast(&ip->bi_copydonecv);
6962         mutex_exit(&ip->bi_mutex);
6963         if (!ca->wait) {
6964                 if (rsrv)
6965                         _ii_rlse_devs(ip, ca->rtype);
6966                 kmem_free(ca, sizeof (*ca));
6967         }
6968 
6969 }
6970 
6971 /*
6972  * _ii_copyvol()
6973  *      Copy a volume.
6974  *
6975  * Calling/Exit State:
6976  *      Returns 0 when the copy is complete or has been aborted,
6977  *      otherwise error code.
6978  *
6979  * Description:
6980  *      According to the flag, copy the master to the shadow volume or the
6981  *      shadow to the master volume. Upon return wakeup all processes waiting
6982  *      for this copy. Uses a separate process (_ii_copyvolp) to allow the
6983  *      caller to be interrupted.
6984  */
6985 
6986 static int
6987 _ii_copyvol(_ii_info_t *ip, int flag, int rtype, spcs_s_info_t kstatus,
6988                                 int wait)
6989 {
6990         struct copy_args *ca;
6991         int rc;
6992 
6993         /*
6994          * start copy in separate process.
6995          */
6996 
6997         ca = (struct copy_args *)kmem_alloc(sizeof (*ca), KM_SLEEP);
6998         ca->ip = ip;
6999         ca->flag = flag;
7000         ca->rtype = rtype;
7001         ca->kstatus = kstatus;
7002         ca->wait = wait;
7003         ca->rc = 0;
7004 
7005         if (rc = nsc_create_process((void (*)(void *))_ii_copyvolp,
7006             (void *)ca, FALSE)) {
7007                 mutex_enter(&ip->bi_mutex);
7008                 _ii_ioctl_done(ip);
7009                 mutex_exit(&ip->bi_mutex);
7010                 cmn_err(CE_NOTE, "!Can't create II copy process");
7011                 kmem_free(ca, sizeof (*ca));
7012                 return (rc);
7013         }
7014         mutex_enter(&ip->bi_mutex);
7015         if (wait == 0) {
7016                 _ii_ioctl_done(ip);
7017                 mutex_exit(&ip->bi_mutex);
7018                 return (0);
7019         }
7020         while (ip->bi_flags & DSW_COPYINGP) {
7021                 (void) cv_wait_sig(&ip->bi_copydonecv, &ip->bi_mutex);
7022         }
7023         _ii_ioctl_done(ip);
7024         mutex_exit(&ip->bi_mutex);
7025         rc = ca->rc;
7026         kmem_free(ca, sizeof (*ca));
7027 
7028         return (rc);
7029 }
7030 
7031 /*
7032  * _ii_stopcopy
7033  *      Stops any copy process on ip.
7034  *
7035  * Calling/Exit State:
7036  *      Returns 0 if the copy was stopped, otherwise error code.
7037  *
7038  * Description:
7039  *      Stop an in-progress copy by setting the DSW_COPYINGX flag, then
7040  *      wait for the copy to complete.
7041  */
7042 
7043 static int
7044 _ii_stopcopy(_ii_info_t *ip)
7045 {
7046         mutex_enter(&ip->bi_mutex);
7047         DTRACE_PROBE1(_ii_stopcopy_flags,
7048             uint_t, ip->bi_flags);
7049 
7050         while (ip->bi_flags & DSW_COPYINGP) {
7051 
7052                 DTRACE_PROBE(_ii_stopcopy);
7053 
7054                 II_FLAG_SET(DSW_COPYINGX, ip);
7055 
7056                 if (cv_wait_sig(&ip->bi_copydonecv, &ip->bi_mutex) == 0) {
7057                         /* Awoken by a signal */
7058                         mutex_exit(&ip->bi_mutex);
7059                         DTRACE_PROBE(_ii_stopcopy);
7060                         return (EINTR);
7061                 }
7062         }
7063 
7064         mutex_exit(&ip->bi_mutex);
7065 
7066         return (0);
7067 }
7068 
7069 /*
7070  * _ii_error
7071  *      Given the error type that occurred, and the current state of the
7072  *      shadowing, set the appropriate error condition(s).
7073  *
7074  */
7075 
7076 void
7077 _ii_error(_ii_info_t *ip, int error_type)
7078 {
7079         int copy_flags;
7080         int golden;
7081         int flags;
7082         int recursive_call = (error_type & DSW_OVERFLOW) != 0;
7083         int offline_bits = DSW_OFFLINE;
7084         _ii_info_t *xip;
7085         int rc;
7086 
7087         error_type &= ~DSW_OVERFLOW;
7088 
7089         mutex_enter(&ip->bi_mutex);
7090         flags = (ip->bi_flags) & offline_bits;
7091         if ((flags ^ error_type) == 0) {
7092                 /* nothing new offline */
7093                 mutex_exit(&ip->bi_mutex);
7094                 return;
7095         }
7096 
7097         if (error_type == DSW_BMPOFFLINE &&
7098             (ip->bi_flags & DSW_BMPOFFLINE) == 0) {
7099                 /* first, let nskerd know */
7100                 rc = _ii_report_bmp(ip);
7101                 if (rc) {
7102                         if (ii_debug > 0) {
7103                                 cmn_err(CE_WARN, "!Unable to mark bitmap bad in"
7104                                     " config DB; rc = %d", rc);
7105                         }
7106                         ip->bi_flags |= DSW_CFGOFFLINE;
7107                 }
7108         }
7109 
7110         flags = ip->bi_flags;
7111         golden = ((flags & DSW_GOLDEN) == DSW_GOLDEN);
7112         copy_flags = flags & DSW_COPYING;
7113 
7114         switch (error_type) {
7115 
7116         case DSW_BMPOFFLINE:
7117                 /* prevent further use of bitmap */
7118                 flags |= DSW_BMPOFFLINE;
7119                 if (ii_debug > 0)
7120                         cmn_err(CE_NOTE, "!ii: Bitmap offline");
7121 
7122                 switch (copy_flags) {
7123 
7124                 case DSW_COPYINGM:
7125                         /* Bitmap offline, copying master to shadow */
7126                         flags |= DSW_SHDOFFLINE;
7127                         if (ii_debug > 0)
7128                                 cmn_err(CE_NOTE, "!ii: Implied shadow offline");
7129                         break;
7130 
7131                 case DSW_COPYINGS:
7132                         /* Bitmap offline, copying shadow to master */
7133                         if (golden) {
7134                                 /* Shadow is still usable */
7135                                 if (ii_debug > 0)
7136                                         cmn_err(CE_NOTE,
7137                                             "!ii: Implied master offline");
7138                                 flags |= DSW_MSTOFFLINE;
7139                         } else {
7140                                 /*
7141                                  * Snapshot restore from shadow to master
7142                                  * is a dumb thing to do anyway. Lose both.
7143                                  */
7144                                 flags |= DSW_SHDOFFLINE | DSW_MSTOFFLINE;
7145                                 if (ii_debug > 0)
7146                                         cmn_err(CE_NOTE,
7147                                             "ii: Implied master and "
7148                                             "shadow offline");
7149                         }
7150                         break;
7151 
7152                 case 0:
7153                         /* Bitmap offline, no copying in progress */
7154                         if (!golden) {
7155                                 if (ii_debug > 0)
7156                                         cmn_err(CE_NOTE,
7157                                             "!ii: Implied shadow offline");
7158                                 flags |= DSW_SHDOFFLINE;
7159                         }
7160                         break;
7161                 }
7162                 break;
7163 
7164         case DSW_OVROFFLINE:
7165                 flags |= DSW_OVROFFLINE;
7166                 ASSERT(ip->bi_overflow);
7167                 if (ii_debug > 0)
7168                         cmn_err(CE_NOTE, "!ii: Overflow offline");
7169                 /* FALLTHRU */
7170         case DSW_SHDOFFLINE:
7171                 flags |= DSW_SHDOFFLINE;
7172                 if (ii_debug > 0)
7173                         cmn_err(CE_NOTE, "!ii: Shadow offline");
7174 
7175                 if (copy_flags == DSW_COPYINGS) {
7176                         /* Shadow offline, copying shadow to master */
7177                         if (ii_debug > 0)
7178                                 cmn_err(CE_NOTE, "!ii: Implied master offline");
7179                         flags |= DSW_MSTOFFLINE;
7180                 }
7181                 break;
7182 
7183         case DSW_MSTOFFLINE:
7184                 flags |= DSW_MSTOFFLINE;
7185                 if (ii_debug > 0)
7186                         cmn_err(CE_NOTE, "!ii: Master offline");
7187 
7188                 switch (copy_flags) {
7189 
7190                 case DSW_COPYINGM:
7191                         /* Master offline, copying master to shadow */
7192                         flags |= DSW_SHDOFFLINE;
7193                         if (ii_debug > 0)
7194                                 cmn_err(CE_NOTE, "!ii: Implied shadow offline");
7195                         break;
7196 
7197                 case DSW_COPYINGS:
7198                         /* Master offline, copying shadow to master */
7199                         if (!golden) {
7200                                 flags |= DSW_SHDOFFLINE;
7201                                 if (ii_debug > 0)
7202                                         cmn_err(CE_NOTE,
7203                                             "!ii: Implied shadow offline");
7204                         }
7205                         break;
7206 
7207                 case 0:
7208                         /* Master offline, no copying in progress */
7209                         if (!golden) {
7210                                 flags |= DSW_SHDOFFLINE;
7211                                 if (ii_debug > 0)
7212                                         cmn_err(CE_NOTE,
7213                                             "!ii: Implied shadow offline");
7214                         }
7215                         break;
7216                 }
7217                 break;
7218 
7219         default:
7220                 break;
7221         }
7222 
7223         II_FLAG_SET(flags, ip);
7224         mutex_exit(&ip->bi_mutex);
7225 
7226         if (!recursive_call &&
7227             NSHADOWS(ip) && (flags&DSW_MSTOFFLINE) == DSW_MSTOFFLINE) {
7228                 /* take master offline for all other sibling shadows */
7229                 for (xip = ip->bi_head; xip; xip = xip->bi_sibling) {
7230                         if (xip == ip)
7231                                 continue;
7232                         if (_ii_rsrv_devs(xip, BMP, II_INTERNAL) != 0)
7233                                 continue;
7234                                         /* overload DSW_OVERFLOW */
7235                         _ii_error(xip, DSW_MSTOFFLINE|DSW_OVERFLOW);
7236                         _ii_rlse_devs(xip, BMP);
7237                 }
7238         }
7239 
7240 }
7241 
7242 
7243 /*
7244  * _ii_lock_chunk
7245  *      Locks access to the specified chunk
7246  *
7247  */
7248 
7249 static void
7250 _ii_lock_chunk(_ii_info_t *ip, chunkid_t chunk)
7251 {
7252         if (chunk == II_NULLCHUNK) {
7253 
7254                 DTRACE_PROBE(_ii_lock_chunk_type);
7255 
7256                 rw_enter(&ip->bi_busyrw, RW_WRITER);
7257 
7258         } else {
7259 
7260                 DTRACE_PROBE(_ii_lock_chunk_type);
7261 
7262                 if (ip->bi_busy == NULL) {
7263                         DTRACE_PROBE(_ii_lock_chunk_end);
7264                         return;
7265                 }
7266 
7267                 rw_enter(&ip->bi_busyrw, RW_READER);
7268                 mutex_enter(&ip->bi_mutex);
7269                 while (DSW_BIT_ISSET(ip->bi_busy[chunk / DSW_BITS],
7270                     chunk % DSW_BITS))
7271                         cv_wait(&ip->bi_busycv, &ip->bi_mutex);
7272                 DSW_BIT_SET(ip->bi_busy[chunk / DSW_BITS], chunk % DSW_BITS);
7273                 mutex_exit(&ip->bi_mutex);
7274         }
7275 
7276 }
7277 
7278 
7279 /*
7280  * _ii_trylock_chunk
7281  *      Tries to lock access to the specified chunk
7282  * Returns non-zero on success.
7283  *
7284  */
7285 
7286 static int
7287 _ii_trylock_chunk(_ii_info_t *ip, chunkid_t chunk)
7288 {
7289         int rc;
7290 
7291         ASSERT(chunk != II_NULLCHUNK);
7292         if (rw_tryenter(&ip->bi_busyrw, RW_READER) == 0) {
7293                 DTRACE_PROBE(_ii_trylock_chunk);
7294                 return (0);
7295         }
7296 
7297         if (ip->bi_busy == NULL) {
7298                 DTRACE_PROBE(_ii_trylock_chunk_end);
7299                 return (0);
7300         }
7301 
7302         mutex_enter(&ip->bi_mutex);
7303         if (DSW_BIT_ISSET(ip->bi_busy[chunk / DSW_BITS], chunk % DSW_BITS)) {
7304                 rw_exit(&ip->bi_busyrw); /* RW_READER */
7305                 rc = 0;
7306         } else {
7307                 DSW_BIT_SET(ip->bi_busy[chunk / DSW_BITS], chunk % DSW_BITS);
7308                 rc = 1;
7309         }
7310         mutex_exit(&ip->bi_mutex);
7311 
7312         return (rc);
7313 }
7314 
7315 /*
7316  * _ii_unlock_chunks
7317  *      Unlocks access to the specified chunks
7318  *
7319  */
7320 
7321 static void
7322 _ii_unlock_chunks(_ii_info_t *ip, chunkid_t  chunk, int n)
7323 {
7324         if (chunk == II_NULLCHUNK) {
7325 
7326                 DTRACE_PROBE(_ii_unlock_chunks);
7327 
7328                 rw_exit(&ip->bi_busyrw); /* RW_WRITER */
7329 
7330         } else {
7331 
7332                 if (ip->bi_busy == NULL) {
7333                         DTRACE_PROBE(_ii_unlock_chunks_end);
7334                         return;
7335                 }
7336                 mutex_enter(&ip->bi_mutex);
7337 
7338                 DTRACE_PROBE(_ii_unlock_chunks);
7339 
7340                 for (; n-- > 0; chunk++) {
7341                         ASSERT(DSW_BIT_ISSET(ip->bi_busy[chunk / DSW_BITS],
7342                             chunk % DSW_BITS));
7343                         DSW_BIT_CLR(ip->bi_busy[chunk / DSW_BITS],
7344                             chunk % DSW_BITS);
7345                         rw_exit(&ip->bi_busyrw); /* RW_READER */
7346                 }
7347                 cv_broadcast(&ip->bi_busycv);
7348                 mutex_exit(&ip->bi_mutex);
7349 
7350         }
7351 }
7352 
7353 /*
7354  * Copyout the bit map.
7355  */
7356 static int
7357 _ii_ab_co_bmp(_ii_info_t *ip, nsc_off_t bm_offset, unsigned char *user_bm,
7358     int user_bm_size)
7359 {
7360         nsc_off_t       last_fba;
7361         nsc_buf_t *tmp;
7362         nsc_vec_t *nsc_vecp;
7363         nsc_off_t       fba_pos;
7364         int     buf_fba_len;
7365         int     buf_byte_len;
7366         size_t  co_len;
7367         int     rc;
7368 
7369         DTRACE_PROBE2(_ii_ab_co_bmp_start, nsc_off_t, bm_offset,
7370             nsc_size_t, user_bm_size);
7371 
7372         if (ip->bi_flags & DSW_BMPOFFLINE)
7373                 return (EIO);
7374 
7375         /* First calculate the size of the shadow and copy bitmaps */
7376         co_len = DSW_BM_FBA_LEN(ip->bi_size);
7377         ASSERT((ip->bi_copyfba - ip->bi_shdfba) == co_len);
7378 
7379         /* Are we in the ranges of the various bitmaps/indexes? */
7380         if (bm_offset < ip->bi_shdfba)
7381                 return (EIO);
7382         else if (bm_offset < (last_fba = ip->bi_shdfba + co_len))
7383                 /*EMPTY*/;
7384         else if (bm_offset < (last_fba = ip->bi_copyfba + co_len))
7385                 /*EMPTY*/;
7386         else if ((ip->bi_flags & DSW_TREEMAP) &&
7387             (bm_offset < (last_fba = last_fba + (co_len * 32))))
7388                 /*EMPTY*/;
7389         else return (EIO);
7390 
7391         /* Are we within the size of the segment being copied? */
7392         if (FBA_LEN(user_bm_size) > last_fba - bm_offset)
7393                 return (EIO);
7394 
7395         for (fba_pos = bm_offset; fba_pos < last_fba && user_bm_size > 0;
7396             fba_pos += DSW_CBLK_FBA) {
7397                 tmp = NULL;
7398                 buf_fba_len = fba_pos + DSW_CBLK_FBA < last_fba ?
7399                     DSW_CBLK_FBA : last_fba - fba_pos;
7400                 II_READ_START(ip, bitmap);
7401                 rc = nsc_alloc_buf(ip->bi_bmpfd, fba_pos, buf_fba_len,
7402                     NSC_RDBUF, &tmp);
7403                 II_READ_END(ip, bitmap, rc, buf_fba_len);
7404                 if (!II_SUCCESS(rc)) {
7405                         if (tmp)
7406                                 (void) nsc_free_buf(tmp);
7407 
7408                         _ii_error(ip, DSW_BMPOFFLINE);
7409                         return (EIO);
7410                 }
7411 
7412                 /* copyout each nsc_vec's worth of data */
7413                 buf_byte_len = FBA_SIZE(buf_fba_len);
7414                 for (nsc_vecp = tmp->sb_vec;
7415                     buf_byte_len > 0 && user_bm_size > 0;
7416                     nsc_vecp++) {
7417                         co_len = (user_bm_size > nsc_vecp->sv_len) ?
7418                             nsc_vecp->sv_len : user_bm_size;
7419                         if (copyout(nsc_vecp->sv_addr, user_bm, co_len)) {
7420                                 (void) nsc_free_buf(tmp);
7421                                 return (EFAULT);
7422                         }
7423                         user_bm += co_len;
7424                         user_bm_size -= co_len;
7425                         buf_byte_len -= co_len;
7426                 }
7427 
7428 
7429                 (void) nsc_free_buf(tmp);
7430         }
7431 
7432         return (0);
7433 }
7434 
7435 /*
7436  * Copyin a bit map and or with differences bitmap.
7437  */
7438 static int
7439 _ii_ab_ci_bmp(_ii_info_t *ip, nsc_off_t bm_offset, unsigned char *user_bm,
7440 int user_bm_size)
7441 {
7442         nsc_off_t       last_fba;
7443         nsc_buf_t *tmp;
7444         nsc_vec_t *nsc_vecp;
7445         nsc_off_t       fba_pos;
7446         int     buf_fba_len;
7447         int     buf_byte_len;
7448         size_t  ci_len;
7449         int     rc;
7450         int     n;
7451         unsigned char *tmp_buf, *tmpp, *tmpq;
7452 
7453         DTRACE_PROBE2(_ii_ab_ci_bmp_start, nsc_off_t, bm_offset,
7454             nsc_size_t, user_bm_size);
7455 
7456         if (ip->bi_flags & DSW_BMPOFFLINE)
7457                 return (EIO);
7458 
7459         tmp_buf = NULL;
7460         last_fba = bm_offset + DSW_BM_FBA_LEN(ip->bi_size);
7461 
7462         for (fba_pos = bm_offset; fba_pos < last_fba && user_bm_size > 0;
7463             fba_pos += DSW_CBLK_FBA) {
7464                 tmp = NULL;
7465                 buf_fba_len = fba_pos + DSW_CBLK_FBA < last_fba ?
7466                     DSW_CBLK_FBA : last_fba - fba_pos;
7467                 II_READ_START(ip, bitmap);
7468                 rc = nsc_alloc_buf(ip->bi_bmpfd, fba_pos, buf_fba_len,
7469                     NSC_RDWRBUF, &tmp);
7470                 II_READ_END(ip, bitmap, rc, buf_fba_len);
7471                 if (!II_SUCCESS(rc)) {
7472                         if (tmp)
7473                                 (void) nsc_free_buf(tmp);
7474 
7475                         _ii_error(ip, DSW_BMPOFFLINE);
7476                         return (EIO);
7477                 }
7478 
7479                 /* copyin each nsc_vec's worth of data */
7480                 buf_byte_len = FBA_SIZE(buf_fba_len);
7481                 for (nsc_vecp = tmp->sb_vec;
7482                     buf_byte_len > 0 && user_bm_size > 0;
7483                     nsc_vecp++) {
7484                         ci_len = (user_bm_size > nsc_vecp->sv_len) ?
7485                             nsc_vecp->sv_len : user_bm_size;
7486                         tmpp = tmp_buf = kmem_alloc(ci_len, KM_SLEEP);
7487                         tmpq = nsc_vecp->sv_addr;
7488                         if (copyin(user_bm, tmpp, ci_len)) {
7489                                 (void) nsc_free_buf(tmp);
7490                                 kmem_free(tmp_buf, ci_len);
7491                                 return (EFAULT);
7492                         }
7493                         for (n = ci_len; n-- > 0; /* CSTYLED */)
7494                                 *tmpq++ |= *tmpp++;
7495                         user_bm += ci_len;
7496                         user_bm_size -= ci_len;
7497                         buf_byte_len -= ci_len;
7498                         kmem_free(tmp_buf, ci_len);
7499                 }
7500 
7501                 II_NSC_WRITE(ip, bitmap, rc, tmp, fba_pos, buf_fba_len, 0);
7502                 if (!II_SUCCESS(rc)) {
7503                         (void) nsc_free_buf(tmp);
7504                         _ii_error(ip, DSW_BMPOFFLINE);
7505                         return (EIO);
7506                 }
7507 
7508                 (void) nsc_free_buf(tmp);
7509         }
7510 
7511         ip->bi_state |= (DSW_CNTSHDBITS|DSW_CNTCPYBITS);
7512 
7513         return (0);
7514 }
7515 
7516 /*
7517  * Completely zero the bit map.
7518  *
7519  *      Returns 0 if no error
7520  *      Returns non-zero if there was an error
7521  */
7522 static int
7523 _ii_ab_zerobm(_ii_info_t *ip)
7524 {
7525         nsc_off_t fba_pos;
7526         int rc;
7527         nsc_size_t len;
7528         nsc_size_t size;
7529         nsc_buf_t *tmp;
7530 
7531         size = DSW_BM_FBA_LEN(ip->bi_size) + ip->bi_shdfba;
7532         for (fba_pos = ip->bi_shdfba; fba_pos < size; fba_pos += DSW_CBLK_FBA) {
7533                 tmp = NULL;
7534                 len = fba_pos + DSW_CBLK_FBA < size ?
7535                     DSW_CBLK_FBA : size - fba_pos;
7536                 II_READ_START(ip, bitmap);
7537                 rc = nsc_alloc_buf(ip->bi_bmpfd, fba_pos, len, NSC_RDWRBUF,
7538                     &tmp);
7539                 II_READ_END(ip, bitmap, rc, len);
7540                 if (!II_SUCCESS(rc)) {
7541                         if (tmp)
7542                                 (void) nsc_free_buf(tmp);
7543 
7544                         _ii_error(ip, DSW_BMPOFFLINE);
7545                         return (rc);
7546                 }
7547 
7548                 rc = nsc_zero(tmp, fba_pos, len, 0);
7549                 if (II_SUCCESS(rc)) {
7550                         II_NSC_WRITE(ip, bitmap, rc, tmp, fba_pos, len, 0);
7551                 }
7552 
7553                 (void) nsc_free_buf(tmp);
7554                 if (!II_SUCCESS(rc)) {
7555                         _ii_error(ip, DSW_BMPOFFLINE);
7556                         return (rc);
7557                 }
7558         }
7559 
7560         ip->bi_state |= (DSW_CNTSHDBITS|DSW_CNTCPYBITS);
7561 
7562         return (0);
7563 }
7564 
7565 
7566 /*
7567  * Copy shadow bitmap to copy bitmap
7568  */
7569 static int
7570 _ii_ab_copybm(_ii_info_t *ip)
7571 {
7572         nsc_off_t copy_fba_pos, shd_fba_pos;
7573         int rc;
7574         nsc_size_t len;
7575         nsc_off_t size;
7576         nsc_buf_t *copy_tmp, *shd_tmp;
7577 
7578         size = DSW_BM_FBA_LEN(ip->bi_size) + ip->bi_shdfba;
7579         copy_fba_pos = ip->bi_copyfba;
7580         for (shd_fba_pos = ip->bi_shdfba; shd_fba_pos < size;
7581             copy_fba_pos += DSW_CBLK_FBA, shd_fba_pos += DSW_CBLK_FBA) {
7582                 shd_tmp = NULL;
7583                 len = shd_fba_pos + DSW_CBLK_FBA < size ?
7584                     DSW_CBLK_FBA : size - shd_fba_pos;
7585                 II_READ_START(ip, bitmap);
7586                 rc = nsc_alloc_buf(ip->bi_bmpfd, shd_fba_pos, len, NSC_RDBUF,
7587                     &shd_tmp);
7588                 II_READ_END(ip, bitmap, rc, len);
7589                 if (!II_SUCCESS(rc)) {
7590                         if (shd_tmp)
7591                                 (void) nsc_free_buf(shd_tmp);
7592 
7593                         _ii_error(ip, DSW_BMPOFFLINE);
7594                         if (ii_debug > 1)
7595                                 cmn_err(CE_NOTE, "!ii: copybm failed 1 rc %d",
7596                                     rc);
7597 
7598                         return (rc);
7599                 }
7600 
7601                 copy_tmp = NULL;
7602                 rc = nsc_alloc_buf(ip->bi_bmpfd, copy_fba_pos, len, NSC_WRBUF,
7603                     &copy_tmp);
7604                 if (!II_SUCCESS(rc)) {
7605                         (void) nsc_free_buf(shd_tmp);
7606                         if (copy_tmp)
7607                                 (void) nsc_free_buf(copy_tmp);
7608 
7609                         _ii_error(ip, DSW_BMPOFFLINE);
7610                         if (ii_debug > 1)
7611                                 cmn_err(CE_NOTE, "!ii: copybm failed 2 rc %d",
7612                                     rc);
7613 
7614                         return (rc);
7615                 }
7616                 rc = nsc_copy(shd_tmp, copy_tmp, shd_fba_pos, copy_fba_pos,
7617                     len);
7618                 if (II_SUCCESS(rc)) {
7619                         II_NSC_WRITE(ip, bitmap, rc, copy_tmp, copy_fba_pos,
7620                             len, 0);
7621                 }
7622 
7623                 (void) nsc_free_buf(shd_tmp);
7624                 (void) nsc_free_buf(copy_tmp);
7625                 if (!II_SUCCESS(rc)) {
7626                         if (ii_debug > 1)
7627                                 cmn_err(CE_NOTE, "!ii: copybm failed 4 rc %d",
7628                                     rc);
7629                         _ii_error(ip, DSW_BMPOFFLINE);
7630                         return (rc);
7631                 }
7632         }
7633 
7634         ip->bi_state |= (DSW_CNTSHDBITS|DSW_CNTCPYBITS);
7635 
7636         return (0);
7637 }
7638 
7639 
7640 /*
7641  * stolen from nsc_copy_h()
7642  */
7643 
7644 static int
7645 _ii_nsc_or(nsc_buf_t *h1, nsc_buf_t *h2, nsc_off_t pos1, nsc_off_t pos2,
7646         nsc_size_t len)
7647 {
7648         unsigned char *a1, *a2;
7649         unsigned char *b1, *b2;
7650         nsc_vec_t *v1, *v2;
7651         int i, sz, l1, l2;
7652 
7653         if (pos1 < h1->sb_pos || pos1 + len > h1->sb_pos + h1->sb_len ||
7654             pos2 < h2->sb_pos || pos2 + len > h2->sb_pos + h2->sb_len)
7655                 return (EINVAL);
7656 
7657         if (!len)
7658                 return (0);
7659 
7660         /* find starting point in "from" vector */
7661 
7662         v1 = h1->sb_vec;
7663         pos1 -= h1->sb_pos;
7664 
7665         for (; pos1 >= FBA_NUM(v1->sv_len); v1++)
7666                 pos1 -= FBA_NUM(v1->sv_len);
7667 
7668         a1 = v1->sv_addr + FBA_SIZE(pos1);
7669         l1 = v1->sv_len - FBA_SIZE(pos1);
7670 
7671         /* find starting point in "to" vector */
7672 
7673         v2 = h2->sb_vec;
7674         pos2 -= h2->sb_pos;
7675 
7676         for (; pos2 >= FBA_NUM(v2->sv_len); v2++)
7677                 pos2 -= FBA_NUM(v2->sv_len);
7678 
7679         a2 = v2->sv_addr + FBA_SIZE(pos2);
7680         l2 = v2->sv_len - FBA_SIZE(pos2);
7681 
7682         /* copy required data */
7683 
7684         len = FBA_SIZE(len);
7685 
7686         while (len) {
7687                 sz = min(l1, l2);
7688                 sz = (int)min((nsc_size_t)sz, len);
7689 
7690                 b1 = a1;
7691                 b2 = a2;
7692                 for (i = sz; i-- > 0; /* CSTYLED */)
7693                         *b2++ |= *b1++;
7694 
7695                 l1 -= sz;
7696                 l2 -= sz;
7697                 a1 += sz;
7698                 a2 += sz;
7699                 len -= sz;
7700 
7701                 if (!l1) {
7702                         a1 = (++v1)->sv_addr;
7703                         l1 = v1->sv_len;
7704                 }
7705                 if (!l2) {
7706                         a2 = (++v2)->sv_addr;
7707                         l2 = v2->sv_len;
7708                 }
7709         }
7710 
7711         return (0);
7712 }
7713 
7714 
7715 /*
7716  * Or the shadow bitmap in to the copy bitmap, clear the
7717  * shadow bitmap.
7718  */
7719 static int
7720 _ii_ab_orbm(_ii_info_t *ip)
7721 {
7722         nsc_off_t copy_fba_pos, shd_fba_pos;
7723         int rc;
7724         nsc_size_t len;
7725         size_t size;
7726         nsc_buf_t *copy_tmp, *shd_tmp;
7727 
7728         if (ip->bi_flags & DSW_BMPOFFLINE)
7729                 return (EIO);
7730 
7731         size = DSW_BM_FBA_LEN(ip->bi_size) + ip->bi_shdfba;
7732         copy_fba_pos = ip->bi_copyfba;
7733         for (shd_fba_pos = ip->bi_shdfba; shd_fba_pos < size;
7734             copy_fba_pos += DSW_CBLK_FBA, shd_fba_pos += DSW_CBLK_FBA) {
7735                 shd_tmp = NULL;
7736                 len = shd_fba_pos + DSW_CBLK_FBA < size ?
7737                     DSW_CBLK_FBA : size - shd_fba_pos;
7738                 II_READ_START(ip, bitmap);
7739                 rc = nsc_alloc_buf(ip->bi_bmpfd, shd_fba_pos, len,
7740                     NSC_RDBUF|NSC_WRBUF, &shd_tmp);
7741                 II_READ_END(ip, bitmap, rc, len);
7742                 if (!II_SUCCESS(rc)) {
7743                         if (shd_tmp)
7744                                 (void) nsc_free_buf(shd_tmp);
7745 
7746                         _ii_error(ip, DSW_BMPOFFLINE);
7747                         return (rc);
7748                 }
7749 
7750                 copy_tmp = NULL;
7751                 II_READ_START(ip, bitmap);
7752                 rc = nsc_alloc_buf(ip->bi_bmpfd, copy_fba_pos, len,
7753                     NSC_RDBUF|NSC_WRBUF, &copy_tmp);
7754                 II_READ_END(ip, bitmap, rc, len);
7755                 if (!II_SUCCESS(rc)) {
7756                         (void) nsc_free_buf(shd_tmp);
7757                         if (copy_tmp)
7758                                 (void) nsc_free_buf(copy_tmp);
7759 
7760                         _ii_error(ip, DSW_BMPOFFLINE);
7761                         return (rc);
7762                 }
7763                 rc = _ii_nsc_or(shd_tmp, copy_tmp, shd_fba_pos, copy_fba_pos,
7764                     len);
7765                 if (II_SUCCESS(rc)) {
7766                         II_NSC_WRITE(ip, bitmap, rc, copy_tmp, copy_fba_pos,
7767                             len, 0);
7768                 }
7769                 if (II_SUCCESS(rc))
7770                         rc = nsc_zero(shd_tmp, shd_fba_pos, len, 0);
7771                 if (II_SUCCESS(rc)) {
7772                         II_NSC_WRITE(ip, bitmap, rc, shd_tmp, shd_fba_pos, len,
7773                             0);
7774                 }
7775 
7776                 (void) nsc_free_buf(shd_tmp);
7777                 (void) nsc_free_buf(copy_tmp);
7778                 if (!II_SUCCESS(rc)) {
7779                         _ii_error(ip, DSW_BMPOFFLINE);
7780                         return (rc);
7781                 }
7782         }
7783 
7784         ip->bi_state |= (DSW_CNTSHDBITS|DSW_CNTCPYBITS);
7785 
7786         return (0);
7787 }
7788 
7789 /*
7790  * _ii_ab_tst_shd_bit
7791  *      Determine if a chunk has been copied to the shadow device
7792  *      Relies on the alloc_buf/free_buf semantics for locking.
7793  *
7794  * Calling/Exit State:
7795  *      Returns 1 if the modified bit has been set for the shadow device,
7796  *      Returns 0 if the modified bit has not been set for the shadow device,
7797  *      Returns -1 if there was an error
7798  */
7799 
7800 static int
7801 _ii_ab_tst_shd_bit(_ii_info_t *ip, chunkid_t chunk)
7802 {
7803         int rc;
7804         nsc_off_t fba;
7805         nsc_buf_t *tmp = NULL;
7806 
7807         if (ip->bi_flags & DSW_BMPOFFLINE)
7808                 return (EIO);
7809 
7810         fba = ip->bi_shdfba + chunk / (FBA_SIZE(1) * DSW_BITS);
7811         chunk %= FBA_SIZE(1) * DSW_BITS;
7812         II_READ_START(ip, bitmap);
7813         rc = nsc_alloc_buf(ip->bi_bmpfd, fba, 1, NSC_RDBUF, &tmp);
7814         II_READ_END(ip, bitmap, rc, 1);
7815         if (!II_SUCCESS(rc)) {
7816                 _ii_error(ip, DSW_BMPOFFLINE);
7817                 if (tmp)
7818                         (void) nsc_free_buf(tmp);
7819                 return (-1);
7820         }
7821         rc = DSW_BIT_ISSET(tmp->sb_vec->sv_addr[chunk/DSW_BITS],
7822             chunk%DSW_BITS);
7823         (void) nsc_free_buf(tmp);
7824 
7825         return (rc);
7826 }
7827 
7828 
7829 /*
7830  * _ii_ab_set_shd_bit
7831  *      Records that a chunk has been copied to the shadow device
7832  *
7833  *      Returns non-zero if an error is encountered
7834  *      Returns 0 if no error
7835  */
7836 
7837 static int
7838 _ii_ab_set_shd_bit(_ii_info_t *ip, chunkid_t chunk)
7839 {
7840         int rc;
7841         nsc_off_t fba;
7842         nsc_buf_t *tmp = NULL;
7843 
7844         if (ip->bi_flags & DSW_BMPOFFLINE)
7845                 return (EIO);
7846 
7847         fba = ip->bi_shdfba + chunk / (FBA_SIZE(1) * DSW_BITS);
7848         chunk %= FBA_SIZE(1) * DSW_BITS;
7849         II_READ_START(ip, bitmap);
7850         rc = nsc_alloc_buf(ip->bi_bmpfd, fba, 1, NSC_RDBUF|NSC_WRBUF, &tmp);
7851         II_READ_END(ip, bitmap, rc, 1);
7852         if (!II_SUCCESS(rc)) {
7853                 _ii_error(ip, DSW_BMPOFFLINE);
7854                 if (tmp)
7855                         (void) nsc_free_buf(tmp);
7856                 return (rc);
7857         }
7858         if (DSW_BIT_ISSET(tmp->sb_vec->sv_addr[chunk/DSW_BITS],
7859             chunk%DSW_BITS) == 0) {
7860                 DSW_BIT_SET(tmp->sb_vec->sv_addr[chunk/DSW_BITS],
7861                     chunk%DSW_BITS);
7862                 II_NSC_WRITE(ip, bitmap, rc, tmp, fba, 1, 0);
7863                 if ((ip->bi_state & DSW_CNTSHDBITS) == 0)
7864                         ip->bi_shdbits++;
7865         }
7866         (void) nsc_free_buf(tmp);
7867         if (!II_SUCCESS(rc)) {
7868                 _ii_error(ip, DSW_BMPOFFLINE);
7869                 return (rc);
7870         }
7871 
7872         return (0);
7873 }
7874 
7875 
7876 /*
7877  * _ii_ab_tst_copy_bit
7878  *      Determine if a chunk needs to be copied during updates.
7879  *
7880  * Calling/Exit State:
7881  *      Returns 1 if the copy bit for the chunk is set
7882  *      Returns 0 if the copy bit for the chunk is not set
7883  *      Returns -1 if an error is encountered
7884  */
7885 
7886 static int
7887 _ii_ab_tst_copy_bit(_ii_info_t *ip, chunkid_t chunk)
7888 {
7889         int rc;
7890         nsc_off_t fba;
7891         nsc_buf_t *tmp = NULL;
7892 
7893         if (ip->bi_flags & DSW_BMPOFFLINE)
7894                 return (-1);
7895 
7896         fba = ip->bi_copyfba + chunk / (FBA_SIZE(1) * DSW_BITS);
7897         chunk %= FBA_SIZE(1) * DSW_BITS;
7898         II_READ_START(ip, bitmap);
7899         rc = nsc_alloc_buf(ip->bi_bmpfd, fba, 1, NSC_RDBUF, &tmp);
7900         II_READ_END(ip, bitmap, rc, 1);
7901         if (!II_SUCCESS(rc)) {
7902                 if (tmp)
7903                         (void) nsc_free_buf(tmp);
7904                 _ii_error(ip, DSW_BMPOFFLINE);
7905                 return (-1);
7906         }
7907         rc = DSW_BIT_ISSET(tmp->sb_vec->sv_addr[chunk/DSW_BITS],
7908             chunk%DSW_BITS);
7909         (void) nsc_free_buf(tmp);
7910 
7911         return (rc);
7912 }
7913 
7914 
7915 /*
7916  * _ii_ab_set_copy_bit
7917  *      Records that a chunk has been copied to the shadow device
7918  *
7919  *      Returns non-zero if an error is encountered
7920  *      Returns 0 if no error
7921  */
7922 
7923 static int
7924 _ii_ab_set_copy_bit(_ii_info_t *ip, chunkid_t chunk)
7925 {
7926         int rc;
7927         nsc_off_t fba;
7928         nsc_buf_t *tmp = NULL;
7929 
7930         if (ip->bi_flags & DSW_BMPOFFLINE)
7931                 return (EIO);
7932 
7933         fba = ip->bi_copyfba + chunk / (FBA_SIZE(1) * DSW_BITS);
7934         chunk %= FBA_SIZE(1) * DSW_BITS;
7935         II_READ_START(ip, bitmap);
7936         rc = nsc_alloc_buf(ip->bi_bmpfd, fba, 1, NSC_RDBUF|NSC_WRBUF, &tmp);
7937         II_READ_END(ip, bitmap, rc, 1);
7938         if (!II_SUCCESS(rc)) {
7939                 if (tmp)
7940                         (void) nsc_free_buf(tmp);
7941                 _ii_error(ip, DSW_BMPOFFLINE);
7942                 return (rc);
7943         }
7944         if (DSW_BIT_ISSET(tmp->sb_vec->sv_addr[chunk/DSW_BITS],
7945             chunk%DSW_BITS) == 0) {
7946                 DSW_BIT_SET(tmp->sb_vec->sv_addr[chunk/DSW_BITS],
7947                     chunk%DSW_BITS);
7948                 if ((ip->bi_state & DSW_CNTCPYBITS) == 0)
7949                         ip->bi_copybits++;
7950 
7951                 II_NSC_WRITE(ip, bitmap, rc, tmp, fba, 1, 0);
7952         }
7953         (void) nsc_free_buf(tmp);
7954         if (!II_SUCCESS(rc)) {
7955                 _ii_error(ip, DSW_BMPOFFLINE);
7956                 return (rc);
7957         }
7958 
7959         return (0);
7960 }
7961 
7962 
7963 /*
7964  * _ii_ab_clr_copy_bits
7965  *      Records that a chunk has been cleared on the shadow device, this
7966  *      function assumes that the bits to clear are all in the same fba,
7967  *      as is the case when they were generated by _ii_ab_next_copy_bit().
7968  *
7969  *      Returns non-zero if an error is encountered
7970  *      Returns 0 if no error
7971  */
7972 
7973 static int
7974 _ii_ab_clr_copy_bits(_ii_info_t *ip, chunkid_t chunk, int nchunks)
7975 {
7976         int rc;
7977         nsc_off_t fba;
7978         nsc_buf_t *tmp = NULL;
7979 
7980         if (ip->bi_flags & DSW_BMPOFFLINE)
7981                 return (EIO);
7982 
7983         fba = ip->bi_copyfba + chunk / (FBA_SIZE(1) * DSW_BITS);
7984         chunk %= FBA_SIZE(1) * DSW_BITS;
7985         II_READ_START(ip, bitmap);
7986         rc = nsc_alloc_buf(ip->bi_bmpfd, fba, 1, NSC_RDBUF|NSC_WRBUF, &tmp);
7987         II_READ_END(ip, bitmap, rc, 1);
7988         if (!II_SUCCESS(rc)) {
7989                 if (tmp)
7990                         (void) nsc_free_buf(tmp);
7991                 _ii_error(ip, DSW_BMPOFFLINE);
7992                 return (rc);
7993         }
7994         for (; nchunks-- > 0; chunk++) {
7995                 DSW_BIT_CLR(tmp->sb_vec->sv_addr[chunk/DSW_BITS],
7996                     chunk%DSW_BITS);
7997                 if (ip->bi_copybits > 0)
7998                         ip->bi_copybits--;
7999         }
8000 
8001         II_NSC_WRITE(ip, bitmap, rc, tmp, fba, 1, 0);
8002         (void) nsc_free_buf(tmp);
8003         if (!II_SUCCESS(rc)) {
8004                 _ii_error(ip, DSW_BMPOFFLINE);
8005                 return (rc);
8006         }
8007 
8008         return (0);
8009 }
8010 
8011 /*
8012  * _ii_ab_fill_copy_bmp
8013  *      Fills the copy bitmap with 1's.
8014  *
8015  *      Returns non-zero if an error is encountered
8016  *      Returns 0 if no error
8017  */
8018 
8019 static int
8020 _ii_ab_fill_copy_bmp(_ii_info_t *ip)
8021 {
8022         int rc;
8023         nsc_off_t fba;
8024         nsc_buf_t *tmp;
8025         unsigned char *p;
8026         int i, j;
8027 
8028         if (ip->bi_flags & DSW_BMPOFFLINE)
8029                 return (EIO);
8030 
8031         fba = ip->bi_copyfba;
8032         for (i = DSW_BM_FBA_LEN(ip->bi_size); i-- > 0; fba++) {
8033                 tmp = NULL;
8034                 rc = nsc_alloc_buf(ip->bi_bmpfd, fba, 1, NSC_WRBUF, &tmp);
8035                 if (!II_SUCCESS(rc)) {
8036                         if (tmp)
8037                                 (void) nsc_free_buf(tmp);
8038                         _ii_error(ip, DSW_BMPOFFLINE);
8039                         return (rc);
8040                 }
8041                 p = (unsigned char *)tmp->sb_vec->sv_addr;
8042                 for (j = FBA_SIZE(1); j-- > 0; p++)
8043                         *p = (unsigned char)0xff;
8044                 II_NSC_WRITE(ip, bitmap, rc, tmp, fba, 1, 0);
8045                 if (!II_SUCCESS(rc)) {
8046                         _ii_error(ip, DSW_BMPOFFLINE);
8047                         (void) nsc_free_buf(tmp);
8048                         return (rc);
8049                 }
8050                 (void) nsc_free_buf(tmp);
8051         }
8052 
8053         ip->bi_state |= (DSW_CNTSHDBITS|DSW_CNTCPYBITS);
8054 
8055         return (0);
8056 }
8057 
8058 /*
8059  * _ii_ab_load_bmp
8060  *      Load bitmap from persistent storage.
8061  */
8062 
8063 static int
8064 _ii_ab_load_bmp(_ii_info_t *ip, int flag)
8065 /* ARGSUSED */
8066 {
8067         if (ip->bi_flags & DSW_BMPOFFLINE)
8068                 return (EIO);
8069 
8070         ip->bi_state |= (DSW_CNTSHDBITS|DSW_CNTCPYBITS);
8071 
8072         return (0);
8073 }
8074 
8075 /*
8076  * _ii_ab_next_copy_bit
8077  *      Find next set copy bit.
8078  *
8079  * Returns the next bits set in the copy bitmap, with the corresponding chunks
8080  * locked. Used to avoid having to reread the same bit map block as each bit
8081  * is tested.
8082  */
8083 
8084 static chunkid_t
8085 _ii_ab_next_copy_bit(_ii_info_t *ip, chunkid_t startchunk, chunkid_t maxchunk,
8086         int wanted, int *got)
8087 {
8088         chunkid_t rc;
8089         nsc_off_t fba;
8090         chunkid_t chunk;
8091         int bits_per_fba = FBA_SIZE(1) * DSW_BITS;
8092         int high;
8093         chunkid_t nextchunk;
8094         nsc_buf_t *tmp = NULL;
8095 
8096         *got = 0;
8097 again:
8098         if (ip->bi_flags & DSW_BMPOFFLINE)
8099                 return (maxchunk + 1);
8100 
8101         while (startchunk < maxchunk) {
8102                 tmp = NULL;
8103                 fba = ip->bi_copyfba + startchunk / bits_per_fba;
8104                 chunk = startchunk % bits_per_fba;
8105                 II_READ_START(ip, bitmap);
8106                 rc = nsc_alloc_buf(ip->bi_bmpfd, fba, 1, NSC_RDBUF, &tmp);
8107                 II_READ_END(ip, bitmap, rc, 1);
8108                 if (!II_SUCCESS(rc)) {
8109                         if (tmp)
8110                                 (void) nsc_free_buf(tmp);
8111                         _ii_error(ip, DSW_BMPOFFLINE);
8112                         return (maxchunk + 1);
8113                 }
8114                 high = startchunk + bits_per_fba - startchunk%bits_per_fba;
8115                 if (high > maxchunk)
8116                         high = maxchunk;
8117                 for (; startchunk < high; chunk++, startchunk++) {
8118                         if (DSW_BIT_ISSET(tmp->sb_vec->sv_addr[chunk/DSW_BITS],
8119                             chunk%DSW_BITS)) {
8120                                 /*
8121                                  * trylock won't sleep so can use while
8122                                  * holding the buf.
8123                                  */
8124                                 if (!_ii_trylock_chunk(ip, startchunk)) {
8125                                         (void) nsc_free_buf(tmp);
8126                                         _ii_lock_chunk(ip, startchunk);
8127                                         if (_ii_ab_tst_copy_bit(ip, startchunk)
8128                                             != 1) {
8129                                                 /*
8130                                                  * another process copied this
8131                                                  * chunk while we were acquiring
8132                                                  * the chunk lock.
8133                                                  */
8134                                                 _ii_unlock_chunk(ip,
8135                                                     startchunk);
8136                                                 DTRACE_PROBE(
8137                                                     _ii_ab_next_copy_bit_again);
8138                                                 goto again;
8139                                         }
8140                                         *got = 1;
8141                                         DTRACE_PROBE(_ii_ab_next_copy_bit_end);
8142                                         return (startchunk);
8143                                 }
8144                                 *got = 1;
8145                                 nextchunk = startchunk + 1;
8146                                 chunk++;
8147                                 for (; --wanted > 0 && nextchunk < high;
8148                                     nextchunk++, chunk++) {
8149                                         if (!DSW_BIT_ISSET(tmp->sb_vec->sv_addr
8150                                             [chunk/DSW_BITS], chunk%DSW_BITS)) {
8151                                                 break;  /* end of bit run */
8152                                         }
8153                                         if (_ii_trylock_chunk(ip, nextchunk))
8154                                                 (*got)++;
8155                                         else
8156                                                 break;
8157                                 }
8158                                 (void) nsc_free_buf(tmp);
8159                                 DTRACE_PROBE(_ii_ab_next_copy_bit);
8160                                 return (startchunk);
8161                         }
8162                 }
8163                 (void) nsc_free_buf(tmp);
8164         }
8165 
8166         return (maxchunk + 1);
8167 }
8168 
8169 /*
8170  * _ii_ab_save_bmp
8171  *      Save bitmap to persistent storage.
8172  */
8173 
8174 static int
8175 _ii_ab_save_bmp(_ii_info_t *ip, int flag)
8176 /* ARGSUSED */
8177 {
8178         if (ip->bi_flags & DSW_BMPOFFLINE)
8179                 return (EIO);
8180 
8181         return (0);
8182 }
8183 
8184 /*
8185  * _ii_ab_change_bmp
8186  *      copy change bitmap to memory
8187  */
8188 
8189 static int
8190 _ii_ab_change_bmp(_ii_info_t *ip, unsigned char *ptr)
8191 /* ARGSUSED */
8192 {
8193         int     bm_size;
8194         int     i, j, fba;
8195         int     rc;
8196         unsigned char *p;
8197         nsc_buf_t *tmp = NULL;
8198 
8199         if (ip->bi_flags & DSW_BMPOFFLINE)
8200                 return (EIO);
8201         bm_size = FBA_SIZE(DSW_BM_FBA_LEN(ip->bi_size));
8202 
8203         rc = _ii_nsc_io(ip, KS_BMP, ip->bi_bmpfd, NSC_RDBUF, ip->bi_shdfba,
8204             ptr, bm_size);
8205         if (!II_SUCCESS(rc)) {
8206                 _ii_error(ip, DSW_BMPOFFLINE);
8207                 return (rc);
8208         }
8209 
8210         fba = ip->bi_copyfba;
8211         for (i = DSW_BM_FBA_LEN(ip->bi_size); i-- > 0; fba++) {
8212                 tmp = NULL;
8213                 II_READ_START(ip, bitmap);
8214                 rc = nsc_alloc_buf(ip->bi_bmpfd, fba, 1, NSC_RDBUF, &tmp);
8215                 II_READ_END(ip, bitmap, rc, 1);
8216                 if (!II_SUCCESS(rc)) {
8217                         if (tmp)
8218                                 (void) nsc_free_buf(tmp);
8219                         _ii_error(ip, DSW_BMPOFFLINE);
8220                         return (rc);
8221                 }
8222                 p = (unsigned char *)tmp->sb_vec->sv_addr;
8223                 for (j = FBA_SIZE(1); j-- > 0; p++)
8224                         *ptr |= *p;
8225                 (void) nsc_free_buf(tmp);
8226         }
8227 
8228         return (0);
8229 }
8230 
8231 /*
8232  * Count bits set in the bit map.
8233  */
8234 static int
8235 _ii_ab_cnt_bits(_ii_info_t *ip, nsc_off_t bm_offset, nsc_size_t *counter,
8236 int bm_size)
8237 {
8238         nsc_size_t      last_fba;
8239         nsc_buf_t *tmp;
8240         nsc_vec_t *sd_vecp;
8241         nsc_off_t       fba_pos;
8242         int     buf_fba_len;
8243         int     buf_byte_len;
8244         int     co_len;
8245         int     i;
8246         unsigned int j, k;
8247         unsigned char *cp;
8248         int     rc;
8249 
8250         *counter = 0;
8251         if (ip->bi_flags & DSW_BMPOFFLINE)
8252                 return (EIO);
8253 
8254         last_fba = bm_offset + DSW_BM_FBA_LEN(ip->bi_size);
8255 
8256         for (fba_pos = bm_offset; fba_pos < last_fba && bm_size > 0;
8257             fba_pos += DSW_CBLK_FBA) {
8258                 tmp = NULL;
8259                 buf_fba_len = fba_pos + DSW_CBLK_FBA < last_fba ?
8260                     DSW_CBLK_FBA : last_fba - fba_pos;
8261                 II_READ_START(ip, bitmap);
8262                 rc = nsc_alloc_buf(ip->bi_bmpfd, fba_pos, buf_fba_len,
8263                     NSC_RDBUF, &tmp);
8264                 II_READ_END(ip, bitmap, rc, 1);
8265                 if (!II_SUCCESS(rc)) {
8266                         if (tmp)
8267                                 (void) nsc_free_buf(tmp);
8268 
8269                         _ii_error(ip, DSW_BMPOFFLINE);
8270                         return (EIO);
8271                 }
8272 
8273                 /* count each sd_vec's worth of data */
8274                 buf_byte_len = FBA_SIZE(buf_fba_len);
8275                 for (sd_vecp = tmp->sb_vec;
8276                     buf_byte_len > 0 && bm_size > 0;
8277                     sd_vecp++) {
8278                         co_len = (bm_size > sd_vecp->sv_len) ?
8279                             sd_vecp->sv_len : bm_size;
8280                         cp = sd_vecp->sv_addr;
8281                         for (i = k = 0; i < co_len; i++)
8282                                 for (j = (unsigned)*cp++; j; j &= j - 1)
8283                                         k++;
8284                         *counter += k;
8285                         bm_size -= co_len;
8286                         buf_byte_len -= co_len;
8287                 }
8288 
8289 
8290                 (void) nsc_free_buf(tmp);
8291         }
8292 
8293         return (0);
8294 }
8295 
8296 /*
8297  * OR the bitmaps as part of a join operation
8298  */
8299 static int
8300 _ii_ab_join_bmp(_ii_info_t *dest_ip, _ii_info_t *src_ip)
8301 {
8302         int rc;
8303         nsc_size_t len;
8304         nsc_size_t size;
8305         nsc_buf_t *dest_tmp, *src_tmp;
8306         nsc_off_t src_fba_pos;
8307 
8308         if ((src_ip->bi_flags & DSW_BMPOFFLINE) ||
8309             (dest_ip->bi_flags & DSW_BMPOFFLINE))
8310                 return (EIO);
8311 
8312         size = DSW_BM_FBA_LEN(src_ip->bi_size) + src_ip->bi_shdfba;
8313         for (src_fba_pos = src_ip->bi_shdfba; src_fba_pos < size;
8314             src_fba_pos += DSW_CBLK_FBA) {
8315                 src_tmp = NULL;
8316                 len = src_fba_pos + DSW_CBLK_FBA < size ?
8317                     DSW_CBLK_FBA : size - src_fba_pos;
8318                 II_READ_START(src_ip, bitmap);
8319                 rc = nsc_alloc_buf(src_ip->bi_bmpfd, src_fba_pos, len,
8320                     NSC_RDWRBUF, &src_tmp);
8321                 II_READ_END(src_ip, bitmap, rc, len);
8322                 if (!II_SUCCESS(rc)) {
8323                         if (src_tmp)
8324                                 (void) nsc_free_buf(src_tmp);
8325 
8326                         _ii_error(src_ip, DSW_BMPOFFLINE);
8327                         return (rc);
8328                 }
8329 
8330                 dest_tmp = NULL;
8331                 II_READ_START(dest_ip, bitmap);
8332                 rc = nsc_alloc_buf(dest_ip->bi_bmpfd, src_fba_pos, len,
8333                     NSC_RDWRBUF, &dest_tmp);
8334                 II_READ_END(dest_ip, bitmap, rc, len);
8335                 if (!II_SUCCESS(rc)) {
8336                         (void) nsc_free_buf(src_tmp);
8337                         if (dest_tmp)
8338                                 (void) nsc_free_buf(dest_tmp);
8339 
8340                         _ii_error(dest_ip, DSW_BMPOFFLINE);
8341                         return (rc);
8342                 }
8343                 rc = _ii_nsc_or(src_tmp, dest_tmp, src_fba_pos, src_fba_pos,
8344                     len);
8345                 if (II_SUCCESS(rc)) {
8346                         II_NSC_WRITE(dest_ip, bitmap, rc, dest_tmp,
8347                             src_fba_pos, len, 0);
8348                 }
8349 
8350                 (void) nsc_free_buf(src_tmp);
8351                 (void) nsc_free_buf(dest_tmp);
8352                 if (!II_SUCCESS(rc)) {
8353                         _ii_error(dest_ip, DSW_BMPOFFLINE);
8354                         return (rc);
8355                 }
8356         }
8357 
8358         dest_ip->bi_state |= (DSW_CNTSHDBITS|DSW_CNTCPYBITS);
8359 
8360         return (0);
8361 
8362 }
8363 
8364 static _ii_bmp_ops_t alloc_buf_bmp = {
8365         _ii_ab_co_bmp,
8366         _ii_ab_ci_bmp,
8367         _ii_ab_zerobm,
8368         _ii_ab_copybm,
8369         _ii_ab_orbm,
8370         _ii_ab_tst_shd_bit,
8371         _ii_ab_set_shd_bit,
8372         _ii_ab_tst_copy_bit,
8373         _ii_ab_set_copy_bit,
8374         _ii_ab_clr_copy_bits,
8375         _ii_ab_next_copy_bit,
8376         _ii_ab_fill_copy_bmp,
8377         _ii_ab_load_bmp,
8378         _ii_ab_save_bmp,
8379         _ii_ab_change_bmp,
8380         _ii_ab_cnt_bits,
8381         _ii_ab_join_bmp
8382 };
8383 
8384 
8385 /*
8386  * Copyout the bit map.
8387  */
8388 static int
8389 _ii_km_co_bmp(_ii_info_t *ip, nsc_off_t bm_offset, unsigned char *user_bm,
8390     int user_bm_size)
8391 {
8392         int     start_offset;
8393         int     bm_size;
8394         size_t  co_len;
8395         nsc_off_t       last_fba;
8396 
8397         /* First calculate the size of the shadow and copy bitmaps */
8398         co_len = DSW_BM_FBA_LEN(ip->bi_size);
8399         ASSERT((ip->bi_copyfba - ip->bi_shdfba) == co_len);
8400 
8401         /* Are we in the ranges of the various bitmaps/indexes? */
8402         if (bm_offset < ip->bi_shdfba)
8403                 return (EIO);
8404         else if (bm_offset < (last_fba = ip->bi_shdfba + co_len))
8405                 /*EMPTY*/;
8406         else if (bm_offset < (last_fba = ip->bi_copyfba + co_len))
8407                 /*EMPTY*/;
8408         else if ((ip->bi_flags & DSW_TREEMAP) &&
8409             (bm_offset < (last_fba = last_fba + (co_len * 32))))
8410                 /*EMPTY*/;
8411         else return (EIO);
8412 
8413         if (FBA_LEN(user_bm_size) > last_fba - bm_offset)
8414                 return (EIO);
8415 
8416         start_offset = FBA_SIZE(bm_offset);
8417         bm_size = FBA_SIZE(last_fba);
8418 
8419         co_len = (user_bm_size > bm_size) ? bm_size : user_bm_size;
8420         if (copyout(ip->bi_bitmap + start_offset, user_bm, co_len))
8421                 return (EFAULT);
8422 
8423         return (0);
8424 }
8425 
8426 /*
8427  * Copyin a bit map and or with differences bitmap.
8428  */
8429 static int
8430 _ii_km_ci_bmp(_ii_info_t *ip, nsc_off_t bm_offset, unsigned char *user_bm,
8431     int user_bm_size)
8432 {
8433         unsigned char *tmp_buf;
8434         unsigned char *dest;
8435         unsigned char *p;
8436         size_t  tmp_size;
8437         int     n;
8438         int     start_offset;
8439         int     bm_size;
8440         size_t  ci_len;
8441         int     rc = 0;
8442 
8443         start_offset = FBA_SIZE(bm_offset);
8444         bm_size = FBA_SIZE(DSW_BM_FBA_LEN(ip->bi_size));
8445 
8446         tmp_buf = NULL;
8447         tmp_size = FBA_SIZE(1);
8448 
8449         tmp_buf = kmem_alloc(tmp_size, KM_SLEEP);
8450         start_offset = FBA_SIZE(bm_offset);
8451         dest = ip->bi_bitmap + start_offset;
8452         bm_size = FBA_SIZE(DSW_BM_FBA_LEN(ip->bi_size));
8453 
8454         ci_len = (user_bm_size > bm_size) ? bm_size : user_bm_size;
8455         while (ci_len > 0) {
8456                 n = (tmp_size > ci_len) ? ci_len : tmp_size;
8457                 if (copyin(user_bm, tmp_buf, n)) {
8458                         rc = EFAULT;
8459                         break;
8460                 }
8461                 user_bm += n;
8462                 for (p = tmp_buf; n--> 0; ci_len--)
8463                         *dest++ |= *p++;
8464         }
8465         if (tmp_buf)
8466                 kmem_free(tmp_buf, tmp_size);
8467 
8468         ip->bi_state |= (DSW_CNTSHDBITS|DSW_CNTCPYBITS);
8469 
8470         return (rc);
8471 }
8472 
8473 /*
8474  * Completely zero the bit map.
8475  */
8476 static int
8477 _ii_km_zerobm(_ii_info_t *ip)
8478 {
8479         int start_offset = FBA_SIZE(ip->bi_shdfba);
8480         int len;
8481 
8482         len = FBA_SIZE(ip->bi_copyfba - ip->bi_shdfba);
8483         mutex_enter(&ip->bi_bmpmutex);
8484         bzero(ip->bi_bitmap+start_offset, len);
8485         mutex_exit(&ip->bi_bmpmutex);
8486 
8487         ip->bi_state |= (DSW_CNTSHDBITS|DSW_CNTCPYBITS);
8488 
8489         return (0);
8490 }
8491 
8492 
8493 /*
8494  * Copy shadow bitmap to copy bitmap
8495  */
8496 static int
8497 _ii_km_copybm(_ii_info_t *ip)
8498 {
8499         int copy_offset, shd_offset;
8500         int len;
8501 
8502         len = FBA_SIZE(ip->bi_copyfba - ip->bi_shdfba);
8503         shd_offset = FBA_SIZE(ip->bi_shdfba);
8504         copy_offset = FBA_SIZE(ip->bi_copyfba);
8505         mutex_enter(&ip->bi_bmpmutex);
8506         bcopy(ip->bi_bitmap+shd_offset, ip->bi_bitmap+copy_offset, len);
8507         mutex_exit(&ip->bi_bmpmutex);
8508 
8509         ip->bi_state |= (DSW_CNTSHDBITS|DSW_CNTCPYBITS);
8510 
8511         return (0);
8512 }
8513 
8514 
8515 /*
8516  * Or the shadow bitmap in to the copy bitmap, clear the
8517  * shadow bitmap.
8518  */
8519 static int
8520 _ii_km_orbm(_ii_info_t *ip)
8521 {
8522         unsigned char *copy, *shd;
8523         int copy_offset, shd_offset;
8524         int len;
8525 
8526         len = FBA_SIZE(ip->bi_copyfba - ip->bi_shdfba);
8527         shd_offset = FBA_SIZE(ip->bi_shdfba);
8528         copy_offset = FBA_SIZE(ip->bi_copyfba);
8529         shd = ip->bi_bitmap + shd_offset;
8530         copy = ip->bi_bitmap + copy_offset;
8531 
8532         mutex_enter(&ip->bi_bmpmutex);
8533         while (len-- > 0)
8534                 *copy++ |= *shd++;
8535         mutex_exit(&ip->bi_bmpmutex);
8536 
8537         ip->bi_state |= (DSW_CNTSHDBITS|DSW_CNTCPYBITS);
8538 
8539         return (0);
8540 }
8541 
8542 /*
8543  * _ii_km_tst_shd_bit
8544  *      Determine if a chunk has been copied to the shadow device
8545  *
8546  * Calling/Exit State:
8547  *      Returns 1 if the modified bit has been set for the shadow device,
8548  *      otherwise returns 0.
8549  */
8550 
8551 static int
8552 _ii_km_tst_shd_bit(_ii_info_t *ip, chunkid_t chunk)
8553 {
8554         unsigned char *bmp;
8555         int bmp_offset;
8556         int rc;
8557 
8558         bmp_offset = FBA_SIZE(ip->bi_shdfba);
8559         bmp = ip->bi_bitmap + bmp_offset;
8560 
8561         mutex_enter(&ip->bi_bmpmutex);
8562         rc = DSW_BIT_ISSET(bmp[chunk/DSW_BITS], chunk%DSW_BITS);
8563         mutex_exit(&ip->bi_bmpmutex);
8564 
8565         return (rc);
8566 }
8567 
8568 
8569 /*
8570  * _ii_km_set_shd_bit
8571  *      Records that a chunk has been copied to the shadow device
8572  */
8573 
8574 static int
8575 _ii_km_set_shd_bit(_ii_info_t *ip, chunkid_t chunk)
8576 {
8577         unsigned char *bmp;
8578         int bmp_offset;
8579 
8580         bmp_offset = FBA_SIZE(ip->bi_shdfba);
8581         bmp = ip->bi_bitmap + bmp_offset;
8582 
8583         mutex_enter(&ip->bi_bmpmutex);
8584         if (DSW_BIT_ISSET(bmp[chunk/DSW_BITS], chunk%DSW_BITS) == 0) {
8585                 DSW_BIT_SET(bmp[chunk/DSW_BITS], chunk%DSW_BITS);
8586                 if ((ip->bi_state & DSW_CNTSHDBITS) == 0)
8587                         ip->bi_shdbits++;
8588         }
8589         mutex_exit(&ip->bi_bmpmutex);
8590 
8591         return (0);
8592 }
8593 
8594 /*
8595  * _ii_km_tst_copy_bit
8596  *      Determine if a chunk needs to be copied during updates.
8597  *
8598  * Calling/Exit State:
8599  *      Returns 1 if the copy bit for the chunk is set,
8600  *      otherwise returns 0
8601  */
8602 
8603 static int
8604 _ii_km_tst_copy_bit(_ii_info_t *ip, chunkid_t chunk)
8605 {
8606         unsigned char *bmp;
8607         int bmp_offset;
8608         int rc;
8609 
8610         bmp_offset = FBA_SIZE(ip->bi_copyfba);
8611         bmp = ip->bi_bitmap + bmp_offset;
8612 
8613         mutex_enter(&ip->bi_bmpmutex);
8614         rc = DSW_BIT_ISSET(bmp[chunk/DSW_BITS], chunk%DSW_BITS);
8615         mutex_exit(&ip->bi_bmpmutex);
8616 
8617         return (rc);
8618 }
8619 
8620 
8621 /*
8622  * _ii_km_set_copy_bit
8623  *      Records that a chunk has been copied to the shadow device
8624  */
8625 
8626 static int
8627 _ii_km_set_copy_bit(_ii_info_t *ip, chunkid_t chunk)
8628 {
8629         unsigned char *bmp;
8630         int bmp_offset;
8631 
8632         bmp_offset = FBA_SIZE(ip->bi_copyfba);
8633         bmp = ip->bi_bitmap + bmp_offset;
8634 
8635         mutex_enter(&ip->bi_bmpmutex);
8636         if (DSW_BIT_ISSET(bmp[chunk/DSW_BITS], chunk%DSW_BITS) == 0) {
8637                 DSW_BIT_SET(bmp[chunk/DSW_BITS], chunk%DSW_BITS);
8638                 if ((ip->bi_state & DSW_CNTCPYBITS) == 0)
8639                         ip->bi_copybits++;
8640         }
8641         mutex_exit(&ip->bi_bmpmutex);
8642 
8643         return (0);
8644 }
8645 
8646 
8647 /*
8648  * _ii_km_clr_copy_bits
8649  *      Records that a chunk has been cleared on the shadow device
8650  */
8651 
8652 static int
8653 _ii_km_clr_copy_bits(_ii_info_t *ip, chunkid_t chunk, int nchunks)
8654 {
8655         unsigned char *bmp;
8656         int bmp_offset;
8657 
8658         bmp_offset = FBA_SIZE(ip->bi_copyfba);
8659         bmp = ip->bi_bitmap + bmp_offset;
8660 
8661         mutex_enter(&ip->bi_bmpmutex);
8662         for (; nchunks-- > 0; chunk++) {
8663                 DSW_BIT_CLR(bmp[chunk/DSW_BITS], chunk%DSW_BITS);
8664                 if (ip->bi_copybits > 0)
8665                         ip->bi_copybits--;
8666         }
8667         mutex_exit(&ip->bi_bmpmutex);
8668 
8669         return (0);
8670 }
8671 
8672 /*
8673  * _ii_km_fill_copy_bmp
8674  *      Fills the copy bitmap with 1's.
8675  */
8676 
8677 static int
8678 _ii_km_fill_copy_bmp(_ii_info_t *ip)
8679 {
8680         int len;
8681         unsigned char *bmp;
8682         int bmp_offset;
8683 
8684         bmp_offset = FBA_SIZE(ip->bi_copyfba);
8685         bmp = ip->bi_bitmap + bmp_offset;
8686 
8687         len = FBA_SIZE(ip->bi_copyfba - ip->bi_shdfba);
8688 
8689         mutex_enter(&ip->bi_bmpmutex);
8690         while (len-- > 0)
8691                 *bmp++ = (unsigned char)0xff;
8692         mutex_exit(&ip->bi_bmpmutex);
8693 
8694         ip->bi_state |= (DSW_CNTSHDBITS|DSW_CNTCPYBITS);
8695 
8696         return (0);
8697 }
8698 
8699 /*
8700  * _ii_km_load_bmp
8701  *      Load bitmap from persistent storage.
8702  */
8703 
8704 static int
8705 _ii_km_load_bmp(_ii_info_t *ip, int flag)
8706 {
8707         nsc_off_t bmp_offset;
8708         nsc_size_t bitmap_size;
8709         int rc;
8710 
8711         if (ip->bi_flags & DSW_BMPOFFLINE)
8712                 return (EIO);
8713 
8714         if (ip->bi_bitmap == NULL) {
8715                 bitmap_size = FBA_SIZE(2 * (ip->bi_copyfba - ip->bi_shdfba) +
8716                     ip->bi_shdfba);
8717                 ip->bi_bitmap = nsc_kmem_zalloc(bitmap_size, KM_SLEEP,
8718                     _ii_local_mem);
8719         }
8720         if (flag)
8721                 return (0);             /* just create an empty bitmap */
8722         bmp_offset = FBA_SIZE(ip->bi_shdfba);
8723         rc = _ii_nsc_io(ip, KS_BMP, ip->bi_bmpfd, NSC_RDBUF, ip->bi_shdfba,
8724             ip->bi_bitmap + bmp_offset,
8725             2 * FBA_SIZE(ip->bi_copyfba - ip->bi_shdfba));
8726         if (!II_SUCCESS(rc))
8727                 _ii_error(ip, DSW_BMPOFFLINE);
8728 
8729         ip->bi_state |= (DSW_CNTSHDBITS|DSW_CNTCPYBITS);
8730 
8731         return (rc);
8732 }
8733 
8734 /*
8735  * _ii_km_save_bmp
8736  *      Save bitmap to persistent storage.
8737  */
8738 
8739 static int
8740 _ii_km_save_bmp(_ii_info_t *ip, int flag)
8741 {
8742         int bmp_offset;
8743         int bitmap_size;
8744         int rc;
8745 
8746         bmp_offset = FBA_SIZE(ip->bi_shdfba);
8747         if (ip->bi_flags & DSW_BMPOFFLINE)
8748                 rc = EIO;
8749         else {
8750                 rc = _ii_nsc_io(ip, KS_BMP, ip->bi_bmpfd, NSC_WRBUF,
8751                     ip->bi_shdfba, ip->bi_bitmap + bmp_offset,
8752                     2 * FBA_SIZE(ip->bi_copyfba - ip->bi_shdfba));
8753                 if (!II_SUCCESS(rc))
8754                         _ii_error(ip, DSW_BMPOFFLINE);
8755         }
8756 
8757         if (flag && ip->bi_bitmap) {         /* dispose of bitmap memory */
8758                 bitmap_size = FBA_SIZE(2 * (ip->bi_copyfba - ip->bi_shdfba) +
8759                     ip->bi_shdfba);
8760                 nsc_kmem_free(ip->bi_bitmap, bitmap_size);
8761                 ip->bi_bitmap = NULL;
8762         }
8763 
8764         return (rc);
8765 }
8766 
8767 /*
8768  * _ii_km_next_copy_bit
8769  *      Find next set copy bit.
8770  *
8771  * Returns the next bits set in the copy bitmap, with the corresponding chunks
8772  * locked. Used to cut down on the number of times the bmpmutex is acquired.
8773  */
8774 
8775 static chunkid_t
8776 _ii_km_next_copy_bit(_ii_info_t *ip, chunkid_t chunk, chunkid_t maxchunk,
8777         int want, int *got)
8778 {
8779         unsigned char *bmp;
8780         int bmp_offset;
8781         int nextchunk;
8782 
8783         *got = 0;
8784         bmp_offset = FBA_SIZE(ip->bi_copyfba);
8785         bmp = ip->bi_bitmap + bmp_offset;
8786 
8787         mutex_enter(&ip->bi_bmpmutex);
8788         for (; chunk < maxchunk; chunk++) {
8789                 if (DSW_BIT_ISSET(bmp[chunk/DSW_BITS], chunk%DSW_BITS)) {
8790                         /*
8791                          * trylock won't sleep so can use while
8792                          * holding bi_bmpmutex.
8793                          */
8794                         if (!_ii_trylock_chunk(ip, chunk)) {
8795                                 mutex_exit(&ip->bi_bmpmutex);
8796                                 _ii_lock_chunk(ip, chunk);
8797                                 *got = 1;
8798 
8799                                 DTRACE_PROBE(_ii_km_next_copy_bit);
8800 
8801                                 return (chunk);
8802                         }
8803                         *got = 1;
8804                         for (nextchunk = chunk + 1;
8805                             *got < want && nextchunk < maxchunk; nextchunk++) {
8806                                 if (!DSW_BIT_ISSET(bmp[nextchunk/DSW_BITS],
8807                                     nextchunk%DSW_BITS))
8808                                         break;
8809                                 if (_ii_trylock_chunk(ip, nextchunk))
8810                                         (*got)++;
8811                                 else
8812                                         break;
8813                         }
8814                         mutex_exit(&ip->bi_bmpmutex);
8815 
8816                         DTRACE_PROBE(_ii_km_next_copy_bit);
8817                         return (chunk);
8818                 }
8819         }
8820         mutex_exit(&ip->bi_bmpmutex);
8821 
8822         return (maxchunk + 1);
8823 }
8824 
8825 /*
8826  * _ii_km_change_bmp
8827  *      copy change bitmap to memory
8828  */
8829 
8830 static int
8831 _ii_km_change_bmp(_ii_info_t *ip, unsigned char *ptr)
8832 /* ARGSUSED */
8833 {
8834         int     start_offset;
8835         int     bm_size;
8836         unsigned char *q;
8837 
8838         bm_size = FBA_SIZE(DSW_BM_FBA_LEN(ip->bi_size));
8839 
8840         start_offset = FBA_SIZE(ip->bi_shdfba);
8841         bcopy(ip->bi_bitmap + start_offset, ptr, bm_size);
8842 
8843         start_offset = FBA_SIZE(ip->bi_copyfba);
8844         q = ip->bi_bitmap + start_offset;
8845         while (bm_size-- > 0)
8846                 *ptr |= *q;
8847 
8848         return (0);
8849 }
8850 
8851 /*
8852  * Count bits set in the bit map.
8853  */
8854 static int
8855 _ii_km_cnt_bits(_ii_info_t *ip, nsc_off_t bm_offset, nsc_size_t *counter,
8856     int bm_size)
8857 {
8858         int     start_offset;
8859         int     i;
8860         nsc_size_t j, k;
8861         unsigned char *cp;
8862 
8863         start_offset = FBA_SIZE(bm_offset);
8864 
8865         cp = ip->bi_bitmap + start_offset;
8866         for (i = k = 0; i < bm_size; i++)
8867                 for (j = (unsigned)*cp++; j; j &= j - 1)
8868                         k++;
8869         *counter = k;
8870 
8871         return (0);
8872 }
8873 
8874 /*
8875  * Or the shadow bitmap in to the copy bitmap, clear the
8876  * shadow bitmap.
8877  */
8878 static int
8879 _ii_km_join_bmp(_ii_info_t *dest_ip, _ii_info_t *src_ip)
8880 {
8881         uchar_t *dest, *src;
8882         nsc_size_t bm_size;
8883 
8884         dest = dest_ip->bi_bitmap + FBA_SIZE(dest_ip->bi_shdfba);
8885         src = src_ip->bi_bitmap + FBA_SIZE(src_ip->bi_shdfba);
8886         bm_size = FBA_SIZE(DSW_BM_FBA_LEN(dest_ip->bi_size));
8887 
8888         while (bm_size-- > 0)
8889                 *dest++ |= *src++;
8890 
8891         dest_ip->bi_state |= (DSW_CNTSHDBITS|DSW_CNTCPYBITS);
8892 
8893         return (0);
8894 }
8895 
8896 static _ii_bmp_ops_t kmem_buf_bmp = {
8897         _ii_km_co_bmp,
8898         _ii_km_ci_bmp,
8899         _ii_km_zerobm,
8900         _ii_km_copybm,
8901         _ii_km_orbm,
8902         _ii_km_tst_shd_bit,
8903         _ii_km_set_shd_bit,
8904         _ii_km_tst_copy_bit,
8905         _ii_km_set_copy_bit,
8906         _ii_km_clr_copy_bits,
8907         _ii_km_next_copy_bit,
8908         _ii_km_fill_copy_bmp,
8909         _ii_km_load_bmp,
8910         _ii_km_save_bmp,
8911         _ii_km_change_bmp,
8912         _ii_km_cnt_bits,
8913         _ii_km_join_bmp
8914 };
8915 
8916 
8917 static int
8918 ii_read_volume(_ii_info_t *ip, int mst_src, nsc_buf_t *srcbuf,
8919         nsc_buf_t *dstbuf, chunkid_t chunk_num, nsc_off_t fba, nsc_size_t len)
8920 {
8921         int rc;
8922         nsc_buf_t *tmp;
8923         nsc_off_t mapped_fba;
8924         chunkid_t mapped_chunk;
8925         int overflow;
8926 
8927         if (mst_src || (ip->bi_flags&DSW_TREEMAP) == 0) {
8928                 /* simple read with optional copy */
8929                 if (mst_src) {
8930                         II_NSC_READ(ip, master, rc, srcbuf, fba, len, 0);
8931                 } else {
8932                         II_NSC_READ(ip, shadow, rc, srcbuf, fba, len, 0);
8933                 }
8934                 if (dstbuf && II_SUCCESS(rc)) {
8935                         rc = nsc_copy(srcbuf, dstbuf, fba, fba, len);
8936                 }
8937 
8938                 return (rc);
8939         }
8940         /* read from mapped shadow into final buffer */
8941         mapped_chunk = ii_tsearch(ip, chunk_num);
8942         if (mapped_chunk == II_NULLNODE)
8943                 return (EIO);
8944         overflow = II_ISOVERFLOW(mapped_chunk);
8945         if (overflow)
8946                 mapped_chunk = II_2OVERFLOW(mapped_chunk);
8947         /* convert chunk number from tsearch into final fba */
8948         mapped_fba = DSW_CHK2FBA(mapped_chunk) + (fba % DSW_SIZE);
8949         tmp = NULL;
8950         if (overflow) {
8951                 (void) nsc_reserve(OVRFD(ip), NSC_MULTI);
8952                 II_READ_START(ip, overflow);
8953                 rc = nsc_alloc_buf(OVRFD(ip), mapped_fba, len, NSC_RDBUF, &tmp);
8954                 II_READ_END(ip, overflow, rc, len);
8955         } else {
8956                 II_READ_START(ip, shadow);
8957                 rc = nsc_alloc_buf(SHDFD(ip), mapped_fba, len, NSC_RDBUF, &tmp);
8958                 II_READ_END(ip, shadow, rc, len);
8959         }
8960         if (II_SUCCESS(rc)) {
8961                 if (dstbuf == NULL)
8962                         dstbuf = srcbuf;
8963                 rc = nsc_copy(tmp, dstbuf, mapped_fba, fba, len);
8964                 (void) nsc_free_buf(tmp);
8965         }
8966         if (overflow)
8967                 nsc_release(OVRFD(ip));
8968 
8969         return (rc);
8970 }
8971 
8972 /*
8973  * _ii_fill_buf
8974  *      Read data from the required device
8975  *
8976  * Calling/Exit State:
8977  *      Returns 0 if the data was read successfully, otherwise
8978  *      error code.
8979  *
8980  * Description:
8981  *      Reads the data from fba_pos for length fba_len from the
8982  *      required device. This data may be a mix of data from the master
8983  *      device and the shadow device, depending on the state of the
8984  *      bitmaps.
8985  */
8986 
8987 static int
8988 _ii_fill_buf(ii_fd_t *bfd, nsc_off_t fba_pos, nsc_size_t fba_len, int flag,
8989     nsc_buf_t **handle, nsc_buf_t **handle2)
8990 {
8991         _ii_info_t *ip = bfd->ii_info;
8992         _ii_info_t *xip;
8993         int second_shd = 0;
8994         nsc_off_t temp_fba;
8995         nsc_size_t temp_len;
8996         nsc_size_t bmp_len;
8997         chunkid_t chunk_num;
8998         int rc;
8999         int fill_from_pair;
9000         int rtype = SHDR|BMP;
9001         nsc_buf_t *second_buf = NULL;
9002 
9003         if (flag&NSC_RDAHEAD)
9004                 return (NSC_DONE);
9005 
9006         chunk_num = fba_pos / DSW_SIZE;
9007         temp_fba = fba_pos;
9008         temp_len = fba_len;
9009 
9010         /*
9011          * If the master is being updated from a shadow we need to fill from
9012          * the correct shadow volume.
9013          */
9014         if (NSHADOWS(ip) && bfd->ii_shd == 0) {
9015                 for (xip = ip->bi_head; xip; xip = xip->bi_sibling) {
9016                         if (xip == ip)
9017                                 continue;
9018                         if (xip->bi_flags &DSW_COPYINGS) {
9019                                 second_shd = 1;
9020                                 ip = xip;
9021                                 if ((rc = _ii_rsrv_devs(ip, rtype,
9022                                     II_INTERNAL)) != 0)
9023                                         return (EIO);
9024                                 rc = nsc_alloc_buf(SHDFD(ip), fba_pos, fba_len,
9025                                     (flag&NSC_RDAHEAD)|NSC_MIXED, &second_buf);
9026                                 if (!II_SUCCESS(rc)) {
9027                                         rc = EIO;
9028                                         goto out;
9029                                 }
9030                                 handle2 = &second_buf;
9031                                 break;
9032                         }
9033                 }
9034         }
9035 
9036         while (temp_len > 0) {
9037                 if ((temp_fba + temp_len) > DSW_CHK2FBA(chunk_num + 1)) {
9038                         bmp_len = DSW_CHK2FBA(chunk_num + 1) - temp_fba;
9039                         temp_len -= bmp_len;
9040                 } else {
9041                         bmp_len = temp_len;
9042                         temp_len = 0;
9043                 }
9044 
9045                 fill_from_pair = 0;
9046 
9047                 if ((ip->bi_flags & DSW_COPYINGM) == DSW_COPYINGM) {
9048                         rc = II_TST_COPY_BIT(ip, chunk_num);
9049                         /* Treat a failed bitmap volume as a clear bit */
9050                         if (rc > 0) {
9051                                 /* Copy bit set */
9052                                 if (bfd->ii_shd) {
9053                                         if (*handle2)
9054                                                 fill_from_pair = 1;
9055                                         else {
9056                                                 rc = EIO;
9057                                                 goto out;
9058                                         }
9059                                 }
9060                         }
9061                 }
9062                 if ((ip->bi_flags & DSW_COPYINGS) == DSW_COPYINGS) {
9063                         rc = II_TST_COPY_BIT(ip, chunk_num);
9064                         /* Treat a failed bitmap volume as a clear bit */
9065                         if (rc > 0) {
9066                                 /* Copy bit set */
9067                                 if (bfd->ii_shd == 0) {
9068                                         if (*handle2 ||
9069                                             (ip->bi_flags&DSW_TREEMAP))
9070                                                 fill_from_pair = 1;
9071                                         else {
9072                                                 rc = EIO;
9073                                                 goto out;
9074                                         }
9075                                 }
9076                         }
9077                 }
9078                 if (((ip->bi_flags & DSW_GOLDEN) == 0) && bfd->ii_shd) {
9079                         /* Dependent shadow read */
9080 
9081                         rc = II_TST_SHD_BIT(ip, chunk_num);
9082                         if (rc < 0) {
9083                                 rc = EIO;
9084                                 goto out;
9085                         }
9086                         if (rc == 0) {
9087                                 /* Shadow bit clear */
9088                                 if (*handle2)
9089                                         fill_from_pair = 1;
9090                                 else {
9091                                         rc = EIO;
9092                                         goto out;
9093                                 }
9094                         }
9095                 }
9096 
9097                 if (fill_from_pair) {
9098                         /* it matters now */
9099                         if (ip->bi_flags & (DSW_MSTOFFLINE | DSW_SHDOFFLINE)) {
9100                                 rc = EIO;
9101                                 goto out;
9102                         }
9103                         if (*handle2 == NULL &&
9104                             (ip->bi_flags&DSW_TREEMAP) == 0) {
9105                                 rc = EIO;
9106                                 goto out;
9107                         }
9108                         rc = ii_read_volume(ip, bfd->ii_shd,
9109                             *handle2, *handle, chunk_num, temp_fba, bmp_len);
9110                         if (!II_SUCCESS(rc)) {
9111                                 _ii_error(ip, DSW_MSTOFFLINE);
9112                                 _ii_error(ip, DSW_SHDOFFLINE);
9113                                 goto out;
9114                         }
9115                 } else {
9116                         if (bfd->ii_shd && (ip->bi_flags & DSW_SHDOFFLINE)) {
9117                                 rc = EIO;
9118                                 goto out;
9119                         }
9120                         if ((bfd->ii_shd == 0) &&
9121                             (ip->bi_flags & DSW_MSTOFFLINE)) {
9122                                 rc = EIO;
9123                                 goto out;
9124                         }
9125                         rc = ii_read_volume(ip, !(bfd->ii_shd), *handle, NULL,
9126                             chunk_num, temp_fba, bmp_len);
9127                         if (!II_SUCCESS(rc)) {
9128                                 if (bfd->ii_shd)
9129                                         _ii_error(ip, DSW_SHDOFFLINE);
9130                                 else
9131                                         _ii_error(ip, DSW_MSTOFFLINE);
9132                                 goto out;
9133                         }
9134                 }
9135 
9136                 temp_fba += bmp_len;
9137                 chunk_num++;
9138         }
9139 
9140         rc = 0;
9141 out:
9142         if (second_buf)
9143                 (void) nsc_free_buf(second_buf);
9144         if (second_shd)
9145                 _ii_rlse_devs(ip, rtype);
9146 
9147         return (rc);
9148 }
9149 
9150 
9151 /*
9152  * _ii_shadow_write
9153  *      Perform any copy on write required by a write buffer request
9154  *
9155  * Calling/Exit State:
9156  *      Returns 0 on success, otherwise error code.
9157  *
9158  */
9159 
9160 static int
9161 _ii_shadow_write(ii_fd_t *bfd, nsc_off_t pos, nsc_size_t len)
9162 {
9163         _ii_info_t *ip = bfd->ii_info;
9164         chunkid_t       chunk_num;
9165         int     rc;
9166         int     flag;
9167         int hanging;
9168 
9169         DTRACE_PROBE2(_ii_shadow_write_start, nsc_off_t, pos, nsc_size_t, len);
9170 
9171         /* fail immediately if config DB is unavailable */
9172         if ((ip->bi_flags & DSW_CFGOFFLINE) == DSW_CFGOFFLINE) {
9173                 return (EIO);
9174         }
9175 
9176         chunk_num = pos / DSW_SIZE;
9177 
9178         if (bfd->ii_shd)
9179                 flag = 0;               /* To shadow */
9180         else
9181                 flag = CV_SHD2MST;      /* To master */
9182 
9183         mutex_enter(&ip->bi_mutex);
9184         ip->bi_shdref++;
9185         mutex_exit(&ip->bi_mutex);
9186         hanging = (ip->bi_flags&DSW_HANGING) != 0;
9187 
9188         for (; (chunk_num >= 0) &&
9189             DSW_CHK2FBA(chunk_num) < (pos + len); chunk_num++) {
9190 
9191                 if (!hanging)
9192                         _ii_lock_chunk(ip, chunk_num);
9193                 rc = _ii_copy_on_write(ip, flag, chunk_num, 1);
9194 
9195                 /*
9196                  * Set the shadow bit when a small shadow has overflowed so
9197                  * that ii_read_volume can return an error if an attempt is
9198                  * made to read that chunk.
9199                  */
9200                 if (!hanging) {
9201                         if (rc == 0 ||
9202                             (rc == EIO && (ip->bi_flags&DSW_OVERFLOW) != 0))
9203                                 (void) II_SET_SHD_BIT(ip, chunk_num);
9204                         _ii_unlock_chunk(ip, chunk_num);
9205                 }
9206         }
9207 
9208         mutex_enter(&ip->bi_mutex);
9209         ip->bi_shdref--;
9210         if (ip->bi_state & DSW_CLOSING) {
9211                 if (total_ref(ip) == 0) {
9212                         cv_signal(&ip->bi_closingcv);
9213                 }
9214         }
9215         mutex_exit(&ip->bi_mutex);
9216 
9217         /* did the bitmap fail during this process? */
9218         return (ip->bi_flags & DSW_CFGOFFLINE? EIO : 0);
9219 }
9220 
9221 /*
9222  * _ii_alloc_buf
9223  *      Allocate a buffer of data
9224  *
9225  * Calling/Exit State:
9226  *      Returns 0 for success, < 0 for async I/O, > 0 is an error code.
9227  *
9228  * Description:
9229  *      For a write buffer, calls dsw_shadow_write to perform any necessary
9230  *      copy on write operations, then allocates the real buffers from the
9231  *      underlying devices.
9232  *      For a read buffer, allocates the real buffers from the underlying
9233  *      devices, then calls _ii_fill_buf to fill the required buffer.
9234  *      For a buffer that is neither read nor write, just allocate the
9235  *      buffers so that a _ii_fill_buf can be done later by _ii_read.
9236  */
9237 
9238 static int
9239 _ii_alloc_buf(ii_fd_t *bfd, nsc_off_t pos, nsc_size_t len, int flag,
9240     ii_buf_t **ptr)
9241 {
9242         _ii_info_t *ip = bfd->ii_info;
9243         ii_buf_t *h;
9244         int     raw = II_RAW(bfd);
9245         int rc = 0;
9246         int ioflag;
9247         int fbuf = 0, fbuf2 = 0, abuf = 0;
9248         int rw_ent = 0;
9249 
9250         if (bfd->ii_bmp) {
9251                 DTRACE_PROBE(_ii_alloc_buf_end);
9252                 /* any I/O to the bitmap device is barred */
9253                 return (EIO);
9254         }
9255 
9256         if (len == 0) {
9257                 DTRACE_PROBE(_ii_alloc_buf_end);
9258                 return (EINVAL);
9259         }
9260 
9261         /* Bounds checking */
9262         if (pos + len > ip->bi_size) {
9263                 if (ii_debug > 1)
9264                         cmn_err(CE_NOTE,
9265                             "!ii: Attempt to access beyond end of ii volume");
9266                 DTRACE_PROBE(_ii_alloc_buf_end);
9267                 return (EIO);
9268         }
9269 
9270         h = *ptr;
9271         if (h == NULL) {
9272                 h = (ii_buf_t *)_ii_alloc_handle(NULL, NULL, NULL, bfd);
9273                 if (h == NULL) {
9274                         DTRACE_PROBE(_ii_alloc_buf_end);
9275                         return (ENOMEM);
9276                 }
9277         }
9278 
9279         /*
9280          * Temporary nsc_reserve of bitmap and other device.
9281          * This device has already been reserved by the preceding _ii_attach.
9282          * Corresponding nsc_release is in _ii_free_buf.
9283          */
9284 
9285         h->ii_rsrv = BMP | (raw ? (bfd->ii_shd ? MSTR : SHDR)
9286             : (bfd->ii_shd ? MST : SHD));
9287 
9288         if (!bfd->ii_shd)
9289                 ip = ip->bi_master;
9290 
9291         rw_enter(&ip->bi_linkrw, RW_READER);
9292         rw_ent = 1;
9293         if (ip->bi_shdfd == NULL || (ip->bi_flags & DSW_SHDEXPORT) ==
9294             DSW_SHDEXPORT)
9295                 h->ii_rsrv &= ~(SHD|SHDR);
9296         if ((rc = _ii_rsrv_devs(ip, h->ii_rsrv, II_EXTERNAL)) != 0) {
9297                 rw_exit(&ip->bi_linkrw);
9298                 rw_ent = 0;
9299                 h->ii_rsrv = NULL;
9300                 goto error;
9301         }
9302 
9303         if (flag & NSC_WRBUF) {
9304                 rc = _ii_shadow_write(bfd, pos, len);
9305                 if (!II_SUCCESS(rc))
9306                         goto error;
9307         }
9308 
9309         if (!(flag & NSC_RDAHEAD))
9310                 ioflag = flag & ~(NSC_RDBUF);
9311         else
9312                 ioflag = flag;
9313 
9314         if (bfd->ii_shd) {
9315                 /*
9316                  * SHADOW
9317                  */
9318 
9319                 if (ip->bi_flags & DSW_SHDEXPORT) {
9320                         rc = EIO;
9321                         goto error;
9322                 }
9323                 /*
9324                  * The master device buffer has to be allocated first
9325                  * so that deadlocks are avoided.
9326                  */
9327                 DTRACE_PROBE(AllocBufFor_SHADOW);
9328 
9329                 if ((ip->bi_flags & (DSW_MSTOFFLINE|DSW_SHDIMPORT)) == 0) {
9330                         rc = nsc_alloc_buf(MSTFD(ip), pos, len,
9331                             (flag&NSC_RDAHEAD)|NSC_MIXED, &h->ii_bufp2);
9332                         if (!II_SUCCESS(rc)) {
9333                                 if (ii_debug > 2)
9334                                         cmn_err(CE_WARN, "!ii: "
9335                                             "Join/write-S race detected\n");
9336                                 if (h->ii_bufp2)
9337                                         (void) nsc_free_buf(h->ii_bufp2);
9338                                 h->ii_bufp2 = NULL;
9339                                 /*
9340                                  * Carry on as this will not matter if
9341                                  * _ii_fill_buf is not called, or if
9342                                  * it is called but doesn't need to read this
9343                                  * volume.
9344                                  */
9345                                 rc = 0;
9346                         }
9347                         fbuf2 = 1;
9348                 }
9349 
9350                 if (ip->bi_flags & DSW_SHDOFFLINE) {
9351                         rc = EIO;
9352                         goto error;
9353                 }
9354                 if ((ip->bi_flags)&DSW_TREEMAP) {
9355                         rc = nsc_alloc_abuf(pos, len, 0, &h->ii_abufp);
9356                         if (!II_SUCCESS(rc)) {
9357                                 _ii_error(ip, DSW_SHDOFFLINE);
9358                                 goto error;
9359                         }
9360                         abuf = 1;
9361                 } else {
9362                         II_ALLOC_BUF(ip, shadow, rc, SHDFD(ip), pos, len,
9363                             ioflag, &h->ii_bufp);        /* do not read yet */
9364                         if (!II_SUCCESS(rc)) {
9365                                 _ii_error(ip, DSW_SHDOFFLINE);
9366                                 goto error;
9367                         }
9368                         fbuf = 1;
9369                 }
9370         } else {
9371                 /*
9372                  * MASTER
9373                  */
9374 
9375                 /*
9376                  * The master device buffer has to be allocated first
9377                  * so that deadlocks are avoided.
9378                  */
9379 
9380                 if (ip->bi_flags & (DSW_MSTOFFLINE|DSW_SHDIMPORT)) {
9381                         rc = EIO;
9382                         goto error;
9383                 }
9384 
9385                 DTRACE_PROBE(AllocBufFor_MASTER);
9386 
9387                 II_ALLOC_BUF(ip, master, rc, MSTFD(ip), pos, len, ioflag,
9388                     &h->ii_bufp);                /* do not read yet */
9389                 if (!II_SUCCESS(rc)) {
9390                         _ii_error(ip, DSW_MSTOFFLINE);
9391                         goto error;
9392                 }
9393                 fbuf = 1;
9394 
9395                 /*
9396                  * If shadow FD and (dependent set OR copying) and
9397                  * not (compact dependent && shadow offline && shadow exported)
9398                  */
9399                 if ((ip->bi_shdfd) &&
9400                     ((ip->bi_flags & DSW_COPYINGP) ||
9401                     (!(ip->bi_flags & DSW_GOLDEN))) &&
9402                     (!(ip->bi_flags &
9403                     (DSW_TREEMAP|DSW_SHDOFFLINE|DSW_SHDEXPORT)))) {
9404                         rc = nsc_alloc_buf(SHDFD(ip), pos, len,
9405                             (flag&NSC_RDAHEAD)|NSC_MIXED, &h->ii_bufp2);
9406                         if (!II_SUCCESS(rc)) {
9407                                 if (ii_debug > 2)
9408                                         cmn_err(CE_WARN, "!ii: "
9409                                             "Join/write-M race detected\n");
9410                                 if (h->ii_bufp2)
9411                                         (void) nsc_free_buf(h->ii_bufp2);
9412                                 h->ii_bufp2 = NULL;
9413                                 /*
9414                                  * Carry on as this will not matter if
9415                                  * _ii_fill_buf is not called, or if
9416                                  * it is called but doesn't need to read this
9417                                  * volume.
9418                                  */
9419                                 rc = 0;
9420                         }
9421                         fbuf2 = 1;
9422                 }
9423         }
9424 
9425         if (flag & NSC_RDBUF)
9426                 rc = _ii_fill_buf(bfd, pos, len, flag,
9427                     h->ii_abufp ? &h->ii_abufp : &h->ii_bufp, &h->ii_bufp2);
9428 
9429 error:
9430         if (II_SUCCESS(rc)) {
9431                 h->ii_bufh.sb_vec = h->ii_abufp ? h->ii_abufp->sb_vec :
9432                     h->ii_bufp->sb_vec;
9433                 h->ii_bufh.sb_error = 0;
9434                 h->ii_bufh.sb_flag |= flag;
9435                 h->ii_bufh.sb_pos = pos;
9436                 h->ii_bufh.sb_len = len;
9437         } else {
9438                 h->ii_bufh.sb_error = rc;
9439                 if (h->ii_bufp2 && fbuf2) {
9440                         (void) nsc_free_buf(h->ii_bufp2);
9441                         h->ii_bufp2 = NULL;
9442                 }
9443                 if (h->ii_bufp && fbuf) {
9444                         (void) nsc_free_buf(h->ii_bufp);
9445                         h->ii_bufp = NULL;
9446                 }
9447                 if (h->ii_abufp && abuf) {
9448                         (void) nsc_free_buf(h->ii_abufp);
9449                         h->ii_abufp = NULL;
9450                 }
9451 
9452                 if (h->ii_rsrv) {
9453                         /*
9454                          * Release temporary reserve - reserved above.
9455                          */
9456                         _ii_rlse_devs(ip, h->ii_rsrv);
9457                         h->ii_rsrv = NULL;
9458                 }
9459                 if (rw_ent)
9460                         rw_exit(&ip->bi_linkrw);
9461         }
9462 
9463         return (rc);
9464 }
9465 
9466 
9467 /*
9468  * _ii_free_buf
9469  */
9470 
9471 static int
9472 _ii_free_buf(ii_buf_t *h)
9473 {
9474         ii_fd_t *bfd;
9475         int rsrv;
9476         int rc;
9477 
9478         if (h->ii_abufp == NULL) {
9479                 rc = nsc_free_buf(h->ii_bufp);
9480         } else {
9481                 rc = nsc_free_buf(h->ii_abufp);
9482                 h->ii_abufp = NULL;
9483         }
9484         if (!II_SUCCESS(rc))
9485                 return (rc);
9486         if (h->ii_bufp2) {
9487                 rc = nsc_free_buf(h->ii_bufp2);
9488                 h->ii_bufp2 = NULL;
9489                 if (!II_SUCCESS(rc))
9490                         return (rc);
9491         }
9492 
9493         bfd = h->ii_fd;
9494         rsrv = h->ii_rsrv;
9495 
9496         if ((h->ii_bufh.sb_flag & NSC_HALLOCATED) == 0) {
9497                 rc = _ii_free_handle(h, h->ii_fd);
9498                 if (!II_SUCCESS(rc))
9499                         return (rc);
9500         } else {
9501                 h->ii_bufh.sb_flag = NSC_HALLOCATED;
9502                 h->ii_bufh.sb_vec = NULL;
9503                 h->ii_bufh.sb_error = 0;
9504                 h->ii_bufh.sb_pos = 0;
9505                 h->ii_bufh.sb_len = 0;
9506                 h->ii_rsrv = NULL;
9507         }
9508 
9509         /*
9510          * Release temporary reserve - reserved in _ii_alloc_buf.
9511          */
9512 
9513         if (rsrv)
9514                 _ii_rlse_devs(bfd->ii_info, rsrv);
9515         rw_exit(&bfd->ii_info->bi_linkrw);
9516 
9517         return (0);
9518 }
9519 
9520 
9521 /*
9522  * _ii_open
9523  *      Open a device
9524  *
9525  * Calling/Exit State:
9526  *      Returns a token to identify the shadow device.
9527  *
9528  * Description:
9529  *      Performs the housekeeping operations associated with an upper layer
9530  *      of the nsc stack opening a shadowed device.
9531  */
9532 
9533 /* ARGSUSED */
9534 
9535 static int
9536 _ii_open(char *path, int flag, blind_t *cdp, nsc_iodev_t *iodev)
9537 {
9538         _ii_info_t *ip;
9539         _ii_overflow_t *op;
9540         ii_fd_t *bfd;
9541         int is_mst = 0;
9542         int is_shd = 0;
9543         int raw = (flag & NSC_CACHE) == 0;
9544 
9545         bfd = nsc_kmem_zalloc(sizeof (*bfd), KM_SLEEP, _ii_local_mem);
9546         if (!bfd)
9547                 return (ENOMEM);
9548 
9549         DTRACE_PROBE1(_ii_open_mutex,
9550             ii_fd_t *, bfd);
9551 
9552         mutex_enter(&_ii_info_mutex);
9553 
9554         for (ip = _ii_info_top; ip; ip = ip->bi_next) {
9555                 if (strcmp(path, ii_pathname(ip->bi_mstfd)) == 0) {
9556                         is_mst = 1;
9557                         break;
9558                 } else if (strcmp(path, ip->bi_keyname) == 0) {
9559                         is_shd = 1;
9560                         break;
9561                 } else if (strcmp(path, ii_pathname(ip->bi_bmpfd)) == 0)
9562                         break;
9563         }
9564 
9565         if (is_mst)
9566                 ip = ip->bi_master;
9567 
9568         if (ip && ip->bi_disabled && !(ip->bi_state & DSW_MULTIMST)) {
9569                 DTRACE_PROBE(_ii_open_Disabled);
9570                 mutex_exit(&_ii_info_mutex);
9571                 return (EINTR);
9572         }
9573 
9574         if (!ip) {
9575                 /* maybe it's an overflow */
9576                 mutex_exit(&_ii_info_mutex);
9577                 mutex_enter(&_ii_overflow_mutex);
9578                 for (op = _ii_overflow_top; op; op = op->ii_next) {
9579                         if (strcmp(path, op->ii_volname) == 0)
9580                                 break;
9581                 }
9582                 mutex_exit(&_ii_overflow_mutex);
9583 
9584                 if (!op) {
9585                         nsc_kmem_free(bfd, sizeof (*bfd));
9586                         DTRACE_PROBE(_ii_open_end_EINVAL);
9587                         return (EINVAL);
9588                 }
9589                 bfd->ii_ovr = 1;
9590                 bfd->ii_oflags = flag;
9591                 bfd->ii_optr = op;
9592                 *cdp = (blind_t)bfd;
9593 
9594                 DTRACE_PROBE(_ii_open_end_overflow);
9595                 return (0);
9596         }
9597         mutex_enter(&ip->bi_mutex);
9598         ip->bi_ioctl++;
9599         mutex_exit(&_ii_info_mutex);
9600 
9601         if (is_mst) {
9602                 if (raw) {
9603                         ip->bi_mstr_iodev = NULL;    /* set in attach */
9604                         ip->bi_mstrref++;
9605                 } else {
9606                         ip->bi_mst_iodev = NULL;     /* set in attach */
9607                         ip->bi_mstref++;
9608                 }
9609                 ip->bi_master->bi_iifd = bfd;
9610         } else if (is_shd) {
9611                 if (raw) {
9612                         ip->bi_shdr_iodev = NULL;    /* set in attach */
9613                         ip->bi_shdrref++;
9614                 } else {
9615                         ip->bi_shd_iodev = NULL;     /* set in attach */
9616                         ip->bi_shdref++;
9617                 }
9618                 bfd->ii_shd = 1;
9619         } else {
9620                 ip->bi_bmpref++;
9621                 ip->bi_bmp_iodev = NULL;     /* set in attach */
9622                 bfd->ii_bmp = 1;
9623         }
9624 
9625         _ii_ioctl_done(ip);
9626         mutex_exit(&ip->bi_mutex);
9627 
9628         bfd->ii_info = ip;
9629         bfd->ii_oflags = flag;
9630 
9631         *cdp = (blind_t)bfd;
9632 
9633         return (0);
9634 }
9635 
9636 static int
9637 _ii_openc(char *path, int flag, blind_t *cdp, nsc_iodev_t *iodev)
9638 {
9639         return (_ii_open(path, NSC_CACHE|flag, cdp, iodev));
9640 }
9641 
9642 static int
9643 _ii_openr(char *path, int flag, blind_t *cdp, nsc_iodev_t *iodev)
9644 {
9645         return (_ii_open(path, NSC_DEVICE|flag, cdp, iodev));
9646 }
9647 
9648 
9649 /*
9650  * _ii_close
9651  *      Close a device
9652  *
9653  * Calling/Exit State:
9654  *      Always succeeds - returns 0
9655  *
9656  * Description:
9657  *      Performs the housekeeping operations associated with an upper layer
9658  *      of the nsc stack closing a shadowed device.
9659  */
9660 
9661 static int
9662 _ii_close(bfd)
9663 ii_fd_t *bfd;
9664 {
9665         _ii_info_t *ip = bfd->ii_info;
9666         _ii_info_dev_t *dip;
9667         int raw;
9668 
9669         if (!ip) {
9670                 ASSERT(bfd->ii_ovr);
9671                 return (0);
9672         }
9673 
9674         raw = II_RAW(bfd);
9675 
9676         mutex_enter(&ip->bi_mutex);
9677 
9678         if (bfd->ii_shd && raw) {
9679                 dip = &ip->bi_shdrdev;
9680         } else if (bfd->ii_shd) {
9681                 dip = &ip->bi_shddev;
9682         } else if (bfd->ii_bmp) {
9683                 dip = &ip->bi_bmpdev;
9684         } else if (raw) {
9685                 dip = ip->bi_mstrdev;
9686         } else {
9687                 dip = ip->bi_mstdev;
9688         }
9689 
9690         if (dip) {
9691                 dip->bi_ref--;
9692                 if (dip->bi_ref == 0)
9693                         dip->bi_iodev = NULL;
9694         }
9695 
9696         if (ip->bi_state & DSW_CLOSING) {
9697                 if (total_ref(ip) == 0) {
9698                         cv_signal(&ip->bi_closingcv);
9699                 }
9700         } else if ((ip->bi_flags & DSW_HANGING) &&
9701             (ip->bi_head->bi_state & DSW_CLOSING))
9702                 cv_signal(&ip->bi_head->bi_closingcv);
9703 
9704         if (!(bfd->ii_shd || bfd->ii_bmp))        /* is master device */
9705                 ip->bi_master->bi_iifd = NULL;
9706         mutex_exit(&ip->bi_mutex);
9707 
9708         nsc_kmem_free(bfd, sizeof (*bfd));
9709 
9710         return (0);
9711 }
9712 
9713 /*
9714  * _ii_alloc_handle
9715  *      Allocate a handle
9716  *
9717  */
9718 
9719 static nsc_buf_t *
9720 _ii_alloc_handle(void (*d_cb)(), void (*r_cb)(), void (*w_cb)(), ii_fd_t *bfd)
9721 {
9722         ii_buf_t *h;
9723 
9724         if (REMOTE_VOL(bfd->ii_shd, bfd->ii_info))
9725                 return (NULL);
9726 
9727         h = kmem_alloc(sizeof (*h), KM_SLEEP);
9728         if (!h)
9729                 return (NULL);
9730 
9731         h->ii_abufp = NULL;
9732         h->ii_bufp = nsc_alloc_handle(II_FD(bfd), d_cb, r_cb, w_cb);
9733         if (!h->ii_bufp) {
9734                 kmem_free(h, sizeof (*h));
9735                 return (NULL);
9736         }
9737         h->ii_bufp2 = NULL;
9738         h->ii_bufh.sb_flag = NSC_HALLOCATED;
9739         h->ii_fd = bfd;
9740         h->ii_rsrv = NULL;
9741 
9742         return ((nsc_buf_t *)h);
9743 }
9744 
9745 
9746 /*
9747  * _ii_free_handle
9748  *      Free a handle
9749  *
9750  */
9751 
9752 static int       /*ARGSUSED*/
9753 _ii_free_handle(ii_buf_t *h, ii_fd_t *bfd)
9754 {
9755         int rc;
9756 
9757         if (h->ii_abufp)
9758                 (void) nsc_free_buf(h->ii_abufp);
9759         rc = nsc_free_handle(h->ii_bufp);
9760         if (!II_SUCCESS(rc)) {
9761                 return (rc);
9762         }
9763 
9764         kmem_free(h, sizeof (ii_buf_t));
9765 
9766         return (0);
9767 }
9768 
9769 
9770 /*
9771  * _ii_attach
9772  *      Attach
9773  *
9774  * Calling/Exit State:
9775  *      Returns 0 for success, errno on failure.
9776  *
9777  * Description:
9778  */
9779 
9780 static int
9781 _ii_attach(ii_fd_t *bfd, nsc_iodev_t *iodev)
9782 {
9783         _ii_info_t *ip;
9784         int dev;
9785         int raw;
9786         int rc;
9787         _ii_info_dev_t *infop;
9788 
9789         raw  = II_RAW(bfd);
9790 
9791         DTRACE_PROBE2(_ii_attach_info,
9792             char *, bfd->ii_shd? "shadow" : "master",
9793             int, raw);
9794 
9795         if (bfd->ii_ovr)
9796                 return (EINVAL);
9797 
9798         ip = bfd->ii_info;
9799         if (ip == NULL)
9800                 return (EINVAL);
9801 
9802         mutex_enter(&ip->bi_mutex);
9803         if (bfd->ii_bmp) {
9804                 infop = &ip->bi_bmpdev;
9805         } else if (bfd->ii_shd) {
9806                 if (raw) {
9807                         infop = &ip->bi_shdrdev;
9808                 } else {
9809                         infop = &ip->bi_shddev;
9810                 }
9811         } else if (!bfd->ii_ovr) {
9812                 if (raw) {
9813                         infop = ip->bi_mstrdev;
9814                 } else {
9815                         infop = ip->bi_mstdev;
9816                 }
9817         }
9818 
9819         if (iodev) {
9820                 infop->bi_iodev = iodev;
9821                 nsc_set_owner(infop->bi_fd, infop->bi_iodev);
9822         }
9823         mutex_exit(&ip->bi_mutex);
9824 
9825         if (bfd->ii_bmp)
9826                 return (EINVAL);
9827 
9828         if (raw)
9829                 dev = bfd->ii_shd ? SHDR : MSTR;
9830         else
9831                 dev = bfd->ii_shd ? SHD : MST;
9832 
9833         rc = _ii_rsrv_devs(ip, dev, II_EXTERNAL);
9834 
9835         return (rc);
9836 }
9837 
9838 
9839 /*
9840  * _ii_detach
9841  *      Detach
9842  *
9843  * Calling/Exit State:
9844  *      Returns 0 for success, always succeeds
9845  *
9846  * Description:
9847  */
9848 
9849 static int
9850 _ii_detach(bfd)
9851 ii_fd_t *bfd;
9852 {
9853         int dev;
9854         int raw;
9855 
9856         raw = II_RAW(bfd);
9857 
9858         DTRACE_PROBE2(_ii_detach_info,
9859             char *, bfd->ii_shd? "shadow" : "master",
9860             int, raw);
9861 
9862         if (bfd->ii_bmp)
9863                 return (0);
9864 
9865         ASSERT(bfd->ii_info);
9866         dev = bfd->ii_shd ? (raw ? SHDR : SHD) : (raw ? MSTR : MST);
9867         _ii_rlse_devs(bfd->ii_info, dev);
9868 
9869         return (0);
9870 }
9871 
9872 /*
9873  * _ii_get_pinned
9874  *
9875  */
9876 
9877 static int
9878 _ii_get_pinned(ii_fd_t *bfd)
9879 {
9880         int rc;
9881 
9882         if (REMOTE_VOL(bfd->ii_shd, bfd->ii_info))
9883                 return (EIO);
9884 
9885         rc = nsc_get_pinned(II_FD(bfd));
9886 
9887         return (rc);
9888 }
9889 
9890 /*
9891  * _ii_discard_pinned
9892  *
9893  */
9894 
9895 static int
9896 _ii_discard_pinned(ii_fd_t *bfd, nsc_off_t pos, nsc_size_t len)
9897 {
9898         int rc;
9899 
9900         if (REMOTE_VOL(bfd->ii_shd, bfd->ii_info))
9901                 return (EIO);
9902         rc = nsc_discard_pinned(II_FD(bfd), pos, len);
9903 
9904         return (rc);
9905 }
9906 
9907 /*
9908  * _ii_partsize
9909  *
9910  */
9911 
9912 static int
9913 _ii_partsize(ii_fd_t *bfd, nsc_size_t *ptr)
9914 {
9915         /* Always return saved size */
9916         *ptr = bfd->ii_info->bi_size;
9917         return (0);
9918 }
9919 
9920 /*
9921  * _ii_maxfbas
9922  *
9923  */
9924 
9925 static int
9926 _ii_maxfbas(ii_fd_t *bfd, int flag, nsc_size_t *ptr)
9927 {
9928         int rc;
9929         int rs;
9930         int dev;
9931         _ii_info_t *ip;
9932 
9933         ip = bfd->ii_info;
9934         if (REMOTE_VOL(bfd->ii_shd, ip))
9935                 return (EIO);
9936 
9937         dev =  ((ip->bi_flags)&DSW_SHDIMPORT) ? SHDR : MSTR;
9938 
9939         DTRACE_PROBE1(_ii_maxfbas_info,
9940             char *, dev == SHDR? "shadow" : "master");
9941 
9942         rs = _ii_rsrv_devs(ip, dev, II_INTERNAL);
9943         rc = nsc_maxfbas((dev == MSTR) ? MSTFD(ip) : SHDFD(ip), flag, ptr);
9944 
9945         if (rs == 0)
9946                 _ii_rlse_devs(ip, dev);
9947 
9948         return (rc);
9949 }
9950 
9951 /*
9952  * ii_get_group_list
9953  */
9954 _ii_info_t **
9955 ii_get_group_list(char *group, int *count)
9956 {
9957         int i;
9958         int nip;
9959         uint64_t   hash;
9960         _ii_info_t **ipa;
9961         _ii_lsthead_t *head;
9962         _ii_lstinfo_t *np;
9963 
9964         hash = nsc_strhash(group);
9965 
9966         for (head = _ii_group_top; head; head = head->lst_next) {
9967                 if (hash == head->lst_hash && strncmp(head->lst_name,
9968                     group, DSW_NAMELEN) == 0)
9969                         break;
9970         }
9971 
9972         if (!head) {
9973                 return (NULL);
9974         }
9975 
9976         /* Count entries */
9977         for (nip = 0, np = head->lst_start; np; np = np->lst_next)
9978                 ++nip;
9979 
9980         ASSERT(nip > 0);
9981 
9982         ipa = kmem_zalloc(sizeof (_ii_info_t *) * nip, KM_SLEEP);
9983 
9984         np = head->lst_start;
9985 
9986         for (i = 0; i < nip; i++) {
9987                 ASSERT(np != 0);
9988 
9989                 ipa[i] = np->lst_ip;
9990                 np = np->lst_next;
9991         }
9992 
9993         *count = nip;
9994         return (ipa);
9995 }
9996 
9997 /*
9998  * _ii_pinned
9999  *
10000  */
10001 
10002 static void
10003 _ii_pinned(_ii_info_dev_t *dip, nsc_off_t pos, nsc_size_t len)
10004 {
10005         DTRACE_PROBE3(_ii_pinned_start, nsc_iodev_t, dip->bi_iodev,
10006             nsc_off_t, pos, nsc_size_t, len);
10007 
10008         nsc_pinned_data(dip->bi_iodev, pos, len);
10009 
10010 }
10011 
10012 /*
10013  * _ii_unpinned
10014  *
10015  */
10016 
10017 static void
10018 _ii_unpinned(_ii_info_dev_t *dip, nsc_off_t pos, nsc_size_t len)
10019 {
10020         nsc_unpinned_data(dip->bi_iodev, pos, len);
10021 
10022 }
10023 
10024 
10025 /*
10026  * _ii_read
10027  */
10028 
10029 static int
10030 _ii_read(ii_buf_t *h, nsc_off_t pos, nsc_size_t len, int flag)
10031 {
10032         int rc;
10033         void *sb_vec;
10034         nsc_vec_t **src;
10035 
10036         if (REMOTE_VOL(h->ii_fd->ii_shd, h->ii_fd->ii_info))
10037                 rc = EIO;
10038         else {
10039                 src =  h->ii_abufp? &h->ii_abufp->sb_vec : &h->ii_bufp->sb_vec;
10040                 sb_vec = *src;
10041                 *src = h->ii_bufh.sb_vec;
10042                 rc = _ii_fill_buf(h->ii_fd, pos, len, flag,
10043                     h->ii_abufp ? &h->ii_abufp : &h->ii_bufp, &h->ii_bufp2);
10044                 *src = sb_vec;
10045         }
10046         if (!II_SUCCESS(rc))
10047                 h->ii_bufh.sb_error = rc;
10048 
10049         return (rc);
10050 }
10051 
10052 
10053 /*
10054  * _ii_write
10055  */
10056 
10057 static int
10058 _ii_write(ii_buf_t *h, nsc_off_t pos, nsc_size_t len, int flag)
10059 {
10060         int rc;
10061         ii_fd_t *bfd = h->ii_fd;
10062         _ii_info_t *ip = bfd->ii_info;
10063         chunkid_t       chunk_num;
10064         nsc_size_t      copy_len;
10065         nsc_off_t       mapped_fba;
10066         chunkid_t       mapped_chunk;
10067         int     overflow;
10068         nsc_buf_t *tmp;
10069         void    *sb_vec;
10070 
10071         if (REMOTE_VOL(h->ii_fd->ii_shd, h->ii_fd->ii_info))
10072                 rc = EIO;
10073         else if ((ip->bi_flags&DSW_TREEMAP) == 0 || !bfd->ii_shd) {
10074                 sb_vec = h->ii_bufp->sb_vec;
10075                 h->ii_bufp->sb_vec = h->ii_bufh.sb_vec;
10076                 if (bfd->ii_shd) {
10077                         II_NSC_WRITE(ip, shadow, rc, h->ii_bufp, pos, len,
10078                             flag);
10079                 } else {
10080                         II_NSC_WRITE(ip, master, rc, h->ii_bufp, pos, len,
10081                             flag);
10082                 }
10083                 h->ii_bufp->sb_vec = sb_vec;
10084         } else {
10085                 /* write of mapped shadow buffer */
10086                 rc = 0;
10087                 chunk_num = pos / DSW_SIZE;
10088                 while (len > 0 && II_SUCCESS(rc)) {
10089                         /*
10090                          * don't need to test bitmaps as allocating the
10091                          * write buffer will c-o-write the chunk.
10092                          */
10093                         mapped_chunk = ii_tsearch(ip, chunk_num);
10094                         if (mapped_chunk == II_NULLNODE) {
10095                                 rc = EIO;
10096                                 break;
10097                         }
10098                         overflow = II_ISOVERFLOW(mapped_chunk);
10099                         if (overflow)
10100                                 mapped_chunk = II_2OVERFLOW(mapped_chunk);
10101                         mapped_fba = DSW_CHK2FBA(mapped_chunk) +
10102                             (pos % DSW_SIZE);
10103                         copy_len = DSW_SIZE - (pos % DSW_SIZE);
10104                         if (copy_len > len)
10105                                 copy_len = len;
10106                         tmp = NULL;
10107                         if (overflow) {
10108                                 (void) nsc_reserve(OVRFD(ip), NSC_MULTI);
10109                                 rc = nsc_alloc_buf(OVRFD(ip), mapped_fba,
10110                                     copy_len, NSC_WRBUF, &tmp);
10111                         } else
10112                                 rc = nsc_alloc_buf(SHDFD(ip), mapped_fba,
10113                                     copy_len, NSC_WRBUF, &tmp);
10114                         sb_vec = h->ii_abufp->sb_vec;
10115                         h->ii_abufp->sb_vec = h->ii_bufh.sb_vec;
10116                         if (II_SUCCESS(rc)) {
10117                                 rc = nsc_copy(h->ii_abufp, tmp, pos,
10118                                     mapped_fba, copy_len);
10119                         }
10120                         if (overflow) {
10121                                 II_NSC_WRITE(ip, overflow, rc, tmp, mapped_fba,
10122                                     copy_len, flag);
10123                         } else {
10124                                 II_NSC_WRITE(ip, shadow, rc, tmp, mapped_fba,
10125                                     copy_len, flag);
10126                         }
10127                         h->ii_abufp->sb_vec = sb_vec;
10128                         (void) nsc_free_buf(tmp);
10129                         if (overflow)
10130                                 nsc_release(OVRFD(ip));
10131                         /* move on to next chunk */
10132                         pos += copy_len;
10133                         len -= copy_len;
10134                         chunk_num++;
10135                 }
10136         }
10137         if (!II_SUCCESS(rc))
10138                 h->ii_bufh.sb_error = rc;
10139 
10140         return (rc);
10141 }
10142 
10143 
10144 /*
10145  * _ii_zero
10146  */
10147 
10148 static int
10149 _ii_zero(ii_buf_t *h, nsc_off_t pos, nsc_size_t len, int flag)
10150 {
10151         int rc;
10152         void *sb_vec;
10153 
10154         sb_vec = h->ii_bufp->sb_vec;
10155         h->ii_bufp->sb_vec = h->ii_bufh.sb_vec;
10156         rc = nsc_zero(h->ii_bufp, pos, len, flag);
10157         h->ii_bufp->sb_vec = sb_vec;
10158         if (!II_SUCCESS(rc))
10159                 h->ii_bufh.sb_error = rc;
10160 
10161         return (rc);
10162 }
10163 
10164 
10165 /*
10166  * _ii_uncommit
10167  */
10168 
10169 static int
10170 _ii_uncommit(ii_buf_t *h, nsc_off_t pos, nsc_size_t len, int flag)
10171 {
10172         int rc;
10173         void *sb_vec;
10174 
10175         sb_vec = h->ii_bufp->sb_vec;
10176         h->ii_bufp->sb_vec = h->ii_bufh.sb_vec;
10177         rc = nsc_uncommit(h->ii_bufp, pos, len, flag);
10178         h->ii_bufp->sb_vec = sb_vec;
10179         if (!II_SUCCESS(rc))
10180                 h->ii_bufh.sb_error = rc;
10181 
10182         return (rc);
10183 }
10184 
10185 
10186 /*
10187  * _ii_trksize
10188  */
10189 
10190 static int
10191 _ii_trksize(ii_fd_t *bfd, int trksize)
10192 {
10193         int rc;
10194 
10195         rc = nsc_set_trksize(II_FD(bfd), trksize);
10196 
10197         return (rc);
10198 }
10199 
10200 /*
10201  * _ii_register_path
10202  */
10203 
10204 static nsc_path_t *
10205 _ii_register_path(char *path, int type, nsc_io_t *io)
10206 {
10207         nsc_path_t *tok;
10208 
10209         tok = nsc_register_path(path, type, io);
10210 
10211         return (tok);
10212 }
10213 
10214 /*
10215  * _ii_unregister_path
10216  */
10217 /*ARGSUSED*/
10218 static int
10219 _ii_unregister_path(nsc_path_t *sp, int flag, char *type)
10220 {
10221         int rc;
10222 
10223         rc = nsc_unregister_path(sp, flag);
10224 
10225         return (rc);
10226 }
10227 
10228 int
10229 _ii_ll_add(_ii_info_t *ip, kmutex_t *mutex, _ii_lsthead_t **lst, char *name,
10230     char **key)
10231 {
10232         _ii_lsthead_t **head;
10233         _ii_lstinfo_t *node;
10234         uint64_t hash;
10235 
10236         ASSERT(key && !*key);
10237         ASSERT(ip && mutex && lst && name);
10238 
10239         node = kmem_zalloc(sizeof (_ii_lstinfo_t), KM_SLEEP);
10240         if (!node) {
10241                 cmn_err(CE_WARN, "!ii: _ii_ll_add: ENOMEM");
10242                 DTRACE_PROBE(_ii_ll_add_end_ENOMEM);
10243                 return (ENOMEM);
10244         }
10245         node->lst_ip = ip;
10246 
10247         /* find out where we should insert it */
10248         hash = nsc_strhash(name);
10249 
10250         mutex_enter(mutex);
10251         for (head = lst; *head; head = &((*head)->lst_next)) {
10252                 if (((*head)->lst_hash == hash) &&
10253                     strncmp(name, (*head)->lst_name, DSW_NAMELEN) == 0) {
10254                         node->lst_next = (*head)->lst_start;
10255                         (*head)->lst_start = node;
10256                         break;
10257                 }
10258         }
10259 
10260         if (!*head) {
10261                 /* create a new entry */
10262                 *head = kmem_zalloc(sizeof (_ii_lsthead_t), KM_SLEEP);
10263                 if (!*head) {
10264                         /* bother */
10265                         cmn_err(CE_WARN, "!ii: _ii_ll_add: ENOMEM");
10266                         kmem_free(node, sizeof (_ii_lstinfo_t));
10267                         DTRACE_PROBE(_ii_ll_add_end_2);
10268                         return (ENOMEM);
10269                 }
10270                 (*head)->lst_hash = hash;
10271                 (void) strncpy((*head)->lst_name, name, DSW_NAMELEN);
10272                 (*head)->lst_start = node;
10273         }
10274         mutex_exit(mutex);
10275 
10276         *key = (*head)->lst_name;
10277 
10278         return (0);
10279 }
10280 
10281 int
10282 _ii_ll_remove(_ii_info_t *ip, kmutex_t *mutex, _ii_lsthead_t **lst, char **key)
10283 {
10284         _ii_lsthead_t **head, *oldhead = 0;
10285         _ii_lstinfo_t **node, *oldnode = 0;
10286         uint64_t hash;
10287         int found;
10288 
10289         ASSERT(key && *key);
10290         ASSERT(ip && lst);
10291 
10292         hash = nsc_strhash(*key);
10293 
10294         mutex_enter(mutex);
10295         for (head = lst; *head; head = &((*head)->lst_next)) {
10296                 if (((*head)->lst_hash == hash) &&
10297                     strncmp(*key, (*head)->lst_name, DSW_NAMELEN) == 0)
10298                         break;
10299         }
10300         if (!*head) {
10301                 /* no such link (!) */
10302                 mutex_exit(mutex);
10303                 return (0);
10304         }
10305 
10306         found = 0;
10307         for (node = &(*head)->lst_start; *node; node = &((*node)->lst_next)) {
10308                 if (ip == (*node)->lst_ip) {
10309                         oldnode = *node;
10310                         *node = (*node)->lst_next;
10311                         kmem_free(oldnode, sizeof (_ii_lstinfo_t));
10312                         found = 1;
10313                         break;
10314                 }
10315         }
10316 
10317         ASSERT(found);
10318 
10319         if (!found) {
10320                 mutex_exit(mutex);
10321                 return (0);
10322         }
10323 
10324         /* did we just delete the last set in this resource group? */
10325         if (!(*head)->lst_start) {
10326                 oldhead = *head;
10327                 *head = (*head)->lst_next;
10328                 kmem_free(oldhead, sizeof (_ii_lsthead_t));
10329         }
10330         mutex_exit(mutex);
10331 
10332         *key = NULL;
10333 
10334         return (0);
10335 }
10336 
10337 static nsc_def_t _ii_fd_def[] = {
10338         { "Pinned",     (uintptr_t)_ii_pinned,          0 },
10339         { "Unpinned",   (uintptr_t)_ii_unpinned,        0 },
10340         { NULL,         (uintptr_t)NULL,                0 }
10341 };
10342 
10343 
10344 static nsc_def_t _ii_io_def[] = {
10345         { "Open",       (uintptr_t)_ii_openc,           0 },
10346         { "Close",      (uintptr_t)_ii_close,           0 },
10347         { "Attach",     (uintptr_t)_ii_attach,          0 },
10348         { "Detach",     (uintptr_t)_ii_detach,          0 },
10349         { "AllocHandle", (uintptr_t)_ii_alloc_handle,   0 },
10350         { "FreeHandle", (uintptr_t)_ii_free_handle,     0 },
10351         { "AllocBuf",   (uintptr_t)_ii_alloc_buf,       0 },
10352         { "FreeBuf",    (uintptr_t)_ii_free_buf,        0 },
10353         { "GetPinned",  (uintptr_t)_ii_get_pinned,      0 },
10354         { "Discard",    (uintptr_t)_ii_discard_pinned,  0 },
10355         { "PartSize",   (uintptr_t)_ii_partsize,        0 },
10356         { "MaxFbas",    (uintptr_t)_ii_maxfbas,         0 },
10357         { "Read",       (uintptr_t)_ii_read,            0 },
10358         { "Write",      (uintptr_t)_ii_write,           0 },
10359         { "Zero",       (uintptr_t)_ii_zero,            0 },
10360         { "Uncommit",   (uintptr_t)_ii_uncommit,        0 },
10361         { "TrackSize",  (uintptr_t)_ii_trksize,         0 },
10362         { "Provide",    (uintptr_t)NULL,                0 },
10363         { NULL,         (uintptr_t)NULL,                0 }
10364 };
10365 
10366 static nsc_def_t _ii_ior_def[] = {
10367         { "Open",       (uintptr_t)_ii_openr,           0 },
10368         { "Close",      (uintptr_t)_ii_close,           0 },
10369         { "Attach",     (uintptr_t)_ii_attach,          0 },
10370         { "Detach",     (uintptr_t)_ii_detach,          0 },
10371         { "AllocHandle", (uintptr_t)_ii_alloc_handle,   0 },
10372         { "FreeHandle", (uintptr_t)_ii_free_handle,     0 },
10373         { "AllocBuf",   (uintptr_t)_ii_alloc_buf,       0 },
10374         { "FreeBuf",    (uintptr_t)_ii_free_buf,        0 },
10375         { "GetPinned",  (uintptr_t)_ii_get_pinned,      0 },
10376         { "Discard",    (uintptr_t)_ii_discard_pinned,  0 },
10377         { "PartSize",   (uintptr_t)_ii_partsize,        0 },
10378         { "MaxFbas",    (uintptr_t)_ii_maxfbas,         0 },
10379         { "Read",       (uintptr_t)_ii_read,            0 },
10380         { "Write",      (uintptr_t)_ii_write,           0 },
10381         { "Zero",       (uintptr_t)_ii_zero,            0 },
10382         { "Uncommit",   (uintptr_t)_ii_uncommit,        0 },
10383         { "TrackSize",  (uintptr_t)_ii_trksize,         0 },
10384         { "Provide",    (uintptr_t)NULL,                0 },
10385         { NULL,         (uintptr_t)NULL,                0 }
10386 };