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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  23  *
  24  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 #include <sys/conf.h>
  28 #include <sys/file.h>
  29 #include <sys/ddi.h>
  30 #include <sys/sunddi.h>
  31 #include <sys/modctl.h>
  32 #include <sys/scsi/scsi.h>
  33 #include <sys/scsi/impl/scsi_reset_notify.h>
  34 #include <sys/disp.h>
  35 #include <sys/byteorder.h>
  36 #include <sys/pathname.h>
  37 #include <sys/atomic.h>
  38 #include <sys/nvpair.h>
  39 #include <sys/fs/zfs.h>
  40 #include <sys/sdt.h>
  41 #include <sys/dkio.h>
  42 #include <sys/zfs_ioctl.h>
  43 
  44 #include <sys/stmf.h>
  45 #include <sys/lpif.h>
  46 #include <sys/stmf_ioctl.h>
  47 #include <sys/stmf_sbd_ioctl.h>
  48 
  49 #include "stmf_sbd.h"
  50 #include "sbd_impl.h"
  51 
  52 #define SBD_IS_ZVOL(zvol)       (strncmp("/dev/zvol", zvol, 9))
  53 
  54 extern sbd_status_t sbd_pgr_meta_init(sbd_lu_t *sl);
  55 extern sbd_status_t sbd_pgr_meta_load(sbd_lu_t *sl);
  56 extern void sbd_pgr_reset(sbd_lu_t *sl);
  57 
  58 static int sbd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
  59     void **result);
  60 static int sbd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
  61 static int sbd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
  62 static int sbd_open(dev_t *devp, int flag, int otype, cred_t *credp);
  63 static int sbd_close(dev_t dev, int flag, int otype, cred_t *credp);
  64 static int stmf_sbd_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
  65     cred_t *credp, int *rval);
  66 void sbd_lp_cb(stmf_lu_provider_t *lp, int cmd, void *arg, uint32_t flags);
  67 stmf_status_t sbd_proxy_reg_lu(uint8_t *luid, void *proxy_reg_arg,
  68     uint32_t proxy_reg_arg_len);
  69 stmf_status_t sbd_proxy_dereg_lu(uint8_t *luid, void *proxy_reg_arg,
  70     uint32_t proxy_reg_arg_len);
  71 stmf_status_t sbd_proxy_msg(uint8_t *luid, void *proxy_arg,
  72     uint32_t proxy_arg_len, uint32_t type);
  73 int sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz,
  74     uint32_t *err_ret);
  75 int sbd_create_standby_lu(sbd_create_standby_lu_t *slu, uint32_t *err_ret);
  76 int sbd_set_lu_standby(sbd_set_lu_standby_t *stlu, uint32_t *err_ret);
  77 int sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret,
  78     int no_register, sbd_lu_t **slr);
  79 int sbd_import_active_lu(sbd_import_lu_t *ilu, sbd_lu_t *sl, uint32_t *err_ret);
  80 int sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret);
  81 int sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret);
  82 int sbd_set_global_props(sbd_global_props_t *mlu, int struct_sz,
  83     uint32_t *err_ret);
  84 int sbd_get_global_props(sbd_global_props_t *oslp, uint32_t oslp_sz,
  85     uint32_t *err_ret);
  86 int sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
  87     sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret);
  88 static int sbd_get_unmap_props(sbd_unmap_props_t *sup, sbd_unmap_props_t *osup,
  89     uint32_t *err_ret);
  90 sbd_status_t sbd_create_zfs_meta_object(sbd_lu_t *sl);
  91 sbd_status_t sbd_open_zfs_meta(sbd_lu_t *sl);
  92 sbd_status_t sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
  93     uint64_t off);
  94 sbd_status_t sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
  95     uint64_t off);
  96 sbd_status_t sbd_update_zfs_prop(sbd_lu_t *sl);
  97 int sbd_is_zvol(char *path);
  98 int sbd_zvolget(char *zvol_name, char **comstarprop);
  99 int sbd_zvolset(char *zvol_name, char *comstarprop);
 100 char sbd_ctoi(char c);
 101 void sbd_close_lu(sbd_lu_t *sl);
 102 static nvlist_t *sbd_zvol_get_props(char *zvol_name);
 103 static int sbd_zvol_set_props(char *zvol_name, nvlist_t *nv);
 104 
 105 static ldi_ident_t      sbd_zfs_ident;
 106 static stmf_lu_provider_t *sbd_lp;
 107 static sbd_lu_t         *sbd_lu_list = NULL;
 108 static kmutex_t         sbd_lock;
 109 static dev_info_t       *sbd_dip;
 110 static uint32_t         sbd_lu_count = 0;
 111 
 112 /* Global property settings for the logical unit */
 113 char sbd_vendor_id[]    = "SUN     ";
 114 char sbd_product_id[]   = "COMSTAR         ";
 115 char sbd_revision[]     = "1.0 ";
 116 char *sbd_mgmt_url = NULL;
 117 uint16_t sbd_mgmt_url_alloc_size = 0;
 118 krwlock_t sbd_global_prop_lock;
 119 
 120 static char sbd_name[] = "sbd";
 121 
 122 static struct cb_ops sbd_cb_ops = {
 123         sbd_open,                       /* open */
 124         sbd_close,                      /* close */
 125         nodev,                          /* strategy */
 126         nodev,                          /* print */
 127         nodev,                          /* dump */
 128         nodev,                          /* read */
 129         nodev,                          /* write */
 130         stmf_sbd_ioctl,                 /* ioctl */
 131         nodev,                          /* devmap */
 132         nodev,                          /* mmap */
 133         nodev,                          /* segmap */
 134         nochpoll,                       /* chpoll */
 135         ddi_prop_op,                    /* cb_prop_op */
 136         0,                              /* streamtab */
 137         D_NEW | D_MP,                   /* cb_flag */
 138         CB_REV,                         /* rev */
 139         nodev,                          /* aread */
 140         nodev                           /* awrite */
 141 };
 142 
 143 static struct dev_ops sbd_ops = {
 144         DEVO_REV,
 145         0,
 146         sbd_getinfo,
 147         nulldev,                /* identify */
 148         nulldev,                /* probe */
 149         sbd_attach,
 150         sbd_detach,
 151         nodev,                  /* reset */
 152         &sbd_cb_ops,
 153         NULL,                   /* bus_ops */
 154         NULL                    /* power */
 155 };
 156 
 157 #define SBD_NAME        "COMSTAR SBD"
 158 
 159 static struct modldrv modldrv = {
 160         &mod_driverops,
 161         SBD_NAME,
 162         &sbd_ops
 163 };
 164 
 165 static struct modlinkage modlinkage = {
 166         MODREV_1,
 167         &modldrv,
 168         NULL
 169 };
 170 
 171 int
 172 _init(void)
 173 {
 174         int ret;
 175 
 176         ret = mod_install(&modlinkage);
 177         if (ret)
 178                 return (ret);
 179         sbd_lp = (stmf_lu_provider_t *)stmf_alloc(STMF_STRUCT_LU_PROVIDER,
 180             0, 0);
 181         sbd_lp->lp_lpif_rev = LPIF_REV_2;
 182         sbd_lp->lp_instance = 0;
 183         sbd_lp->lp_name = sbd_name;
 184         sbd_lp->lp_cb = sbd_lp_cb;
 185         sbd_lp->lp_alua_support = 1;
 186         sbd_lp->lp_proxy_msg = sbd_proxy_msg;
 187         sbd_zfs_ident = ldi_ident_from_anon();
 188 
 189         if (stmf_register_lu_provider(sbd_lp) != STMF_SUCCESS) {
 190                 (void) mod_remove(&modlinkage);
 191                 stmf_free(sbd_lp);
 192                 return (EINVAL);
 193         }
 194         mutex_init(&sbd_lock, NULL, MUTEX_DRIVER, NULL);
 195         rw_init(&sbd_global_prop_lock, NULL, RW_DRIVER, NULL);
 196         return (0);
 197 }
 198 
 199 int
 200 _fini(void)
 201 {
 202         int ret;
 203 
 204         /*
 205          * If we have registered lus, then make sure they are all offline
 206          * if so then deregister them. This should drop the sbd_lu_count
 207          * to zero.
 208          */
 209         if (sbd_lu_count) {
 210                 sbd_lu_t *slu;
 211 
 212                 /* See if all of them are offline */
 213                 mutex_enter(&sbd_lock);
 214                 for (slu = sbd_lu_list; slu != NULL; slu = slu->sl_next) {
 215                         if ((slu->sl_state != STMF_STATE_OFFLINE) ||
 216                             slu->sl_state_not_acked) {
 217                                 mutex_exit(&sbd_lock);
 218                                 return (EBUSY);
 219                         }
 220                 }
 221                 mutex_exit(&sbd_lock);
 222 
 223 #if 0
 224                 /* ok start deregistering them */
 225                 while (sbd_lu_list) {
 226                         sbd_store_t *sst = sbd_lu_list->sl_sst;
 227                         if (sst->sst_deregister_lu(sst) != STMF_SUCCESS)
 228                                 return (EBUSY);
 229                 }
 230 #endif
 231                 return (EBUSY);
 232         }
 233         if (stmf_deregister_lu_provider(sbd_lp) != STMF_SUCCESS)
 234                 return (EBUSY);
 235         ret = mod_remove(&modlinkage);
 236         if (ret != 0) {
 237                 (void) stmf_register_lu_provider(sbd_lp);
 238                 return (ret);
 239         }
 240         stmf_free(sbd_lp);
 241         mutex_destroy(&sbd_lock);
 242         rw_destroy(&sbd_global_prop_lock);
 243         ldi_ident_release(sbd_zfs_ident);
 244         return (0);
 245 }
 246 
 247 int
 248 _info(struct modinfo *modinfop)
 249 {
 250         return (mod_info(&modlinkage, modinfop));
 251 }
 252 
 253 /* ARGSUSED */
 254 static int
 255 sbd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
 256 {
 257         switch (cmd) {
 258         case DDI_INFO_DEVT2DEVINFO:
 259                 *result = sbd_dip;
 260                 break;
 261         case DDI_INFO_DEVT2INSTANCE:
 262                 *result = (void *)(uintptr_t)ddi_get_instance(sbd_dip);
 263                 break;
 264         default:
 265                 return (DDI_FAILURE);
 266         }
 267 
 268         return (DDI_SUCCESS);
 269 }
 270 
 271 static int
 272 sbd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 273 {
 274         switch (cmd) {
 275         case DDI_ATTACH:
 276                 sbd_dip = dip;
 277 
 278                 if (ddi_create_minor_node(dip, "admin", S_IFCHR, 0,
 279                     DDI_NT_STMF_LP, 0) != DDI_SUCCESS) {
 280                         break;
 281                 }
 282                 ddi_report_dev(dip);
 283                 return (DDI_SUCCESS);
 284         }
 285 
 286         return (DDI_FAILURE);
 287 }
 288 
 289 static int
 290 sbd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 291 {
 292         switch (cmd) {
 293         case DDI_DETACH:
 294                 ddi_remove_minor_node(dip, 0);
 295                 return (DDI_SUCCESS);
 296         }
 297 
 298         return (DDI_FAILURE);
 299 }
 300 
 301 /* ARGSUSED */
 302 static int
 303 sbd_open(dev_t *devp, int flag, int otype, cred_t *credp)
 304 {
 305         if (otype != OTYP_CHR)
 306                 return (EINVAL);
 307         return (0);
 308 }
 309 
 310 /* ARGSUSED */
 311 static int
 312 sbd_close(dev_t dev, int flag, int otype, cred_t *credp)
 313 {
 314         return (0);
 315 }
 316 
 317 /* ARGSUSED */
 318 static int
 319 stmf_sbd_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
 320         cred_t *credp, int *rval)
 321 {
 322         stmf_iocdata_t          *iocd;
 323         void                    *ibuf   = NULL;
 324         void                    *obuf   = NULL;
 325         sbd_lu_t                *nsl;
 326         int                     i;
 327         int                     ret;
 328 
 329         if (drv_priv(credp) != 0) {
 330                 return (EPERM);
 331         }
 332 
 333         ret = stmf_copyin_iocdata(data, mode, &iocd, &ibuf, &obuf);
 334         if (ret)
 335                 return (ret);
 336         iocd->stmf_error = 0;
 337 
 338         switch (cmd) {
 339         case SBD_IOCTL_CREATE_AND_REGISTER_LU:
 340                 if (iocd->stmf_ibuf_size <
 341                     (sizeof (sbd_create_and_reg_lu_t) - 8)) {
 342                         ret = EFAULT;
 343                         break;
 344                 }
 345                 if ((iocd->stmf_obuf_size == 0) ||
 346                     (iocd->stmf_obuf_size > iocd->stmf_ibuf_size)) {
 347                         ret = EINVAL;
 348                         break;
 349                 }
 350                 ret = sbd_create_register_lu((sbd_create_and_reg_lu_t *)
 351                     ibuf, iocd->stmf_ibuf_size, &iocd->stmf_error);
 352                 bcopy(ibuf, obuf, iocd->stmf_obuf_size);
 353                 break;
 354         case SBD_IOCTL_SET_LU_STANDBY:
 355                 if (iocd->stmf_ibuf_size < sizeof (sbd_set_lu_standby_t)) {
 356                         ret = EFAULT;
 357                         break;
 358                 }
 359                 if (iocd->stmf_obuf_size) {
 360                         ret = EINVAL;
 361                         break;
 362                 }
 363                 ret = sbd_set_lu_standby((sbd_set_lu_standby_t *)ibuf,
 364                     &iocd->stmf_error);
 365                 break;
 366         case SBD_IOCTL_IMPORT_LU:
 367                 if (iocd->stmf_ibuf_size <
 368                     (sizeof (sbd_import_lu_t) - 8)) {
 369                         ret = EFAULT;
 370                         break;
 371                 }
 372                 if ((iocd->stmf_obuf_size == 0) ||
 373                     (iocd->stmf_obuf_size > iocd->stmf_ibuf_size)) {
 374                         ret = EINVAL;
 375                         break;
 376                 }
 377                 ret = sbd_import_lu((sbd_import_lu_t *)ibuf,
 378                     iocd->stmf_ibuf_size, &iocd->stmf_error, 0, NULL);
 379                 bcopy(ibuf, obuf, iocd->stmf_obuf_size);
 380                 break;
 381         case SBD_IOCTL_DELETE_LU:
 382                 if (iocd->stmf_ibuf_size < (sizeof (sbd_delete_lu_t) - 8)) {
 383                         ret = EFAULT;
 384                         break;
 385                 }
 386                 if (iocd->stmf_obuf_size) {
 387                         ret = EINVAL;
 388                         break;
 389                 }
 390                 ret = sbd_delete_lu((sbd_delete_lu_t *)ibuf,
 391                     iocd->stmf_ibuf_size, &iocd->stmf_error);
 392                 break;
 393         case SBD_IOCTL_MODIFY_LU:
 394                 if (iocd->stmf_ibuf_size < (sizeof (sbd_modify_lu_t) - 8)) {
 395                         ret = EFAULT;
 396                         break;
 397                 }
 398                 if (iocd->stmf_obuf_size) {
 399                         ret = EINVAL;
 400                         break;
 401                 }
 402                 ret = sbd_modify_lu((sbd_modify_lu_t *)ibuf,
 403                     iocd->stmf_ibuf_size, &iocd->stmf_error);
 404                 break;
 405         case SBD_IOCTL_SET_GLOBAL_LU:
 406                 if (iocd->stmf_ibuf_size < (sizeof (sbd_global_props_t) - 8)) {
 407                         ret = EFAULT;
 408                         break;
 409                 }
 410                 if (iocd->stmf_obuf_size) {
 411                         ret = EINVAL;
 412                         break;
 413                 }
 414                 ret = sbd_set_global_props((sbd_global_props_t *)ibuf,
 415                     iocd->stmf_ibuf_size, &iocd->stmf_error);
 416                 break;
 417         case SBD_IOCTL_GET_GLOBAL_LU:
 418                 if (iocd->stmf_ibuf_size) {
 419                         ret = EINVAL;
 420                         break;
 421                 }
 422                 if (iocd->stmf_obuf_size < sizeof (sbd_global_props_t)) {
 423                         ret = EINVAL;
 424                         break;
 425                 }
 426                 ret = sbd_get_global_props((sbd_global_props_t *)obuf,
 427                     iocd->stmf_obuf_size, &iocd->stmf_error);
 428                 break;
 429         case SBD_IOCTL_GET_LU_PROPS:
 430                 if (iocd->stmf_ibuf_size < (sizeof (sbd_lu_props_t) - 8)) {
 431                         ret = EFAULT;
 432                         break;
 433                 }
 434                 if (iocd->stmf_obuf_size < sizeof (sbd_lu_props_t)) {
 435                         ret = EINVAL;
 436                         break;
 437                 }
 438                 ret = sbd_get_lu_props((sbd_lu_props_t *)ibuf,
 439                     iocd->stmf_ibuf_size, (sbd_lu_props_t *)obuf,
 440                     iocd->stmf_obuf_size, &iocd->stmf_error);
 441                 break;
 442         case SBD_IOCTL_GET_LU_LIST:
 443                 mutex_enter(&sbd_lock);
 444                 iocd->stmf_obuf_max_nentries = sbd_lu_count;
 445                 iocd->stmf_obuf_nentries = min((iocd->stmf_obuf_size >> 4),
 446                     sbd_lu_count);
 447                 for (nsl = sbd_lu_list, i = 0; nsl &&
 448                     (i < iocd->stmf_obuf_nentries); i++, nsl = nsl->sl_next) {
 449                         bcopy(nsl->sl_device_id + 4,
 450                             &(((uint8_t *)obuf)[i << 4]), 16);
 451                 }
 452                 mutex_exit(&sbd_lock);
 453                 ret = 0;
 454                 iocd->stmf_error = 0;
 455                 break;
 456         case SBD_IOCTL_GET_UNMAP_PROPS:
 457                 if (iocd->stmf_ibuf_size < sizeof (sbd_unmap_props_t)) {
 458                         ret = EFAULT;
 459                         break;
 460                 }
 461                 if (iocd->stmf_obuf_size < sizeof (sbd_unmap_props_t)) {
 462                         ret = EINVAL;
 463                         break;
 464                 }
 465                 ret = sbd_get_unmap_props((sbd_unmap_props_t *)ibuf,
 466                     (sbd_unmap_props_t *)obuf, &iocd->stmf_error);
 467                 break;
 468         default:
 469                 ret = ENOTTY;
 470         }
 471 
 472         if (ret == 0) {
 473                 ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
 474         } else if (iocd->stmf_error) {
 475                 (void) stmf_copyout_iocdata(data, mode, iocd, obuf);
 476         }
 477         if (obuf) {
 478                 kmem_free(obuf, iocd->stmf_obuf_size);
 479                 obuf = NULL;
 480         }
 481         if (ibuf) {
 482                 kmem_free(ibuf, iocd->stmf_ibuf_size);
 483                 ibuf = NULL;
 484         }
 485         kmem_free(iocd, sizeof (stmf_iocdata_t));
 486         return (ret);
 487 }
 488 
 489 /* ARGSUSED */
 490 void
 491 sbd_lp_cb(stmf_lu_provider_t *lp, int cmd, void *arg, uint32_t flags)
 492 {
 493         nvpair_t        *np;
 494         char            *s;
 495         sbd_import_lu_t *ilu;
 496         uint32_t        ilu_sz;
 497         uint32_t        struct_sz;
 498         uint32_t        err_ret;
 499         int             iret;
 500 
 501         if ((cmd != STMF_PROVIDER_DATA_UPDATED) || (arg == NULL)) {
 502                 return;
 503         }
 504 
 505         if ((flags & (STMF_PCB_STMF_ONLINING | STMF_PCB_PREG_COMPLETE)) == 0) {
 506                 return;
 507         }
 508 
 509         np = NULL;
 510         ilu_sz = 1024;
 511         ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP);
 512         while ((np = nvlist_next_nvpair((nvlist_t *)arg, np)) != NULL) {
 513                 if (nvpair_type(np) != DATA_TYPE_STRING) {
 514                         continue;
 515                 }
 516                 if (nvpair_value_string(np, &s) != 0) {
 517                         continue;
 518                 }
 519                 struct_sz = max(8, strlen(s) + 1);
 520                 struct_sz += sizeof (sbd_import_lu_t) - 8;
 521                 if (struct_sz > ilu_sz) {
 522                         kmem_free(ilu, ilu_sz);
 523                         ilu_sz = struct_sz + 32;
 524                         ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP);
 525                 }
 526                 ilu->ilu_struct_size = struct_sz;
 527                 (void) strcpy(ilu->ilu_meta_fname, s);
 528                 iret = sbd_import_lu(ilu, struct_sz, &err_ret, 0, NULL);
 529                 if (iret) {
 530                         stmf_trace(0, "sbd_lp_cb: import_lu failed, ret = %d, "
 531                             "err_ret = %d", iret, err_ret);
 532                 } else {
 533                         stmf_trace(0, "Imported the LU %s", nvpair_name(np));
 534                 }
 535         }
 536 
 537         if (ilu) {
 538                 kmem_free(ilu, ilu_sz);
 539                 ilu = NULL;
 540         }
 541 }
 542 
 543 sbd_status_t
 544 sbd_link_lu(sbd_lu_t *sl)
 545 {
 546         sbd_lu_t *nsl;
 547 
 548         mutex_enter(&sbd_lock);
 549         mutex_enter(&sl->sl_lock);
 550         ASSERT(sl->sl_trans_op != SL_OP_NONE);
 551 
 552         if (sl->sl_flags & SL_LINKED) {
 553                 mutex_exit(&sbd_lock);
 554                 mutex_exit(&sl->sl_lock);
 555                 return (SBD_ALREADY);
 556         }
 557         for (nsl = sbd_lu_list; nsl; nsl = nsl->sl_next) {
 558                 if (strcmp(nsl->sl_name, sl->sl_name) == 0)
 559                         break;
 560         }
 561         if (nsl) {
 562                 mutex_exit(&sbd_lock);
 563                 mutex_exit(&sl->sl_lock);
 564                 return (SBD_ALREADY);
 565         }
 566         sl->sl_next = sbd_lu_list;
 567         sbd_lu_list = sl;
 568         sl->sl_flags |= SL_LINKED;
 569         mutex_exit(&sbd_lock);
 570         mutex_exit(&sl->sl_lock);
 571         return (SBD_SUCCESS);
 572 }
 573 
 574 void
 575 sbd_unlink_lu(sbd_lu_t *sl)
 576 {
 577         sbd_lu_t **ppnsl;
 578 
 579         mutex_enter(&sbd_lock);
 580         mutex_enter(&sl->sl_lock);
 581         ASSERT(sl->sl_trans_op != SL_OP_NONE);
 582 
 583         ASSERT(sl->sl_flags & SL_LINKED);
 584         for (ppnsl = &sbd_lu_list; *ppnsl; ppnsl = &((*ppnsl)->sl_next)) {
 585                 if (*ppnsl == sl)
 586                         break;
 587         }
 588         ASSERT(*ppnsl);
 589         *ppnsl = (*ppnsl)->sl_next;
 590         sl->sl_flags &= ~SL_LINKED;
 591         mutex_exit(&sbd_lock);
 592         mutex_exit(&sl->sl_lock);
 593 }
 594 
 595 sbd_status_t
 596 sbd_find_and_lock_lu(uint8_t *guid, uint8_t *meta_name, uint8_t op,
 597     sbd_lu_t **ppsl)
 598 {
 599         sbd_lu_t *sl;
 600         int found = 0;
 601         sbd_status_t sret;
 602 
 603         mutex_enter(&sbd_lock);
 604         for (sl = sbd_lu_list; sl; sl = sl->sl_next) {
 605                 if (guid) {
 606                         found = bcmp(sl->sl_device_id + 4, guid, 16) == 0;
 607                 } else {
 608                         found = strcmp(sl->sl_name, (char *)meta_name) == 0;
 609                 }
 610                 if (found)
 611                         break;
 612         }
 613         if (!found) {
 614                 mutex_exit(&sbd_lock);
 615                 return (SBD_NOT_FOUND);
 616         }
 617         mutex_enter(&sl->sl_lock);
 618         if (sl->sl_trans_op == SL_OP_NONE) {
 619                 sl->sl_trans_op = op;
 620                 *ppsl = sl;
 621                 sret = SBD_SUCCESS;
 622         } else {
 623                 sret = SBD_BUSY;
 624         }
 625         mutex_exit(&sl->sl_lock);
 626         mutex_exit(&sbd_lock);
 627         return (sret);
 628 }
 629 
 630 sbd_status_t
 631 sbd_read_meta(sbd_lu_t *sl, uint64_t offset, uint64_t size, uint8_t *buf)
 632 {
 633         uint64_t        meta_align;
 634         uint64_t        starting_off;
 635         uint64_t        data_off;
 636         uint64_t        ending_off;
 637         uint64_t        io_size;
 638         uint8_t         *io_buf;
 639         vnode_t         *vp;
 640         sbd_status_t    ret;
 641         ssize_t         resid;
 642         int             vret;
 643 
 644         ASSERT(sl->sl_flags & SL_META_OPENED);
 645         if (sl->sl_flags & SL_SHARED_META) {
 646                 meta_align = (((uint64_t)1) << sl->sl_data_blocksize_shift) - 1;
 647                 vp = sl->sl_data_vp;
 648                 ASSERT(vp);
 649         } else {
 650                 meta_align = (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
 651                 if ((sl->sl_flags & SL_ZFS_META) == 0) {
 652                         vp = sl->sl_meta_vp;
 653                         ASSERT(vp);
 654                 }
 655         }
 656         starting_off = offset & ~(meta_align);
 657         data_off = offset & meta_align;
 658         ending_off = (offset + size + meta_align) & (~meta_align);
 659         if (ending_off > sl->sl_meta_size_used) {
 660                 bzero(buf, size);
 661                 if (starting_off >= sl->sl_meta_size_used) {
 662                         return (SBD_SUCCESS);
 663                 }
 664                 ending_off = (sl->sl_meta_size_used + meta_align) &
 665                     (~meta_align);
 666                 if (size > (ending_off - (starting_off + data_off))) {
 667                         size = ending_off - (starting_off + data_off);
 668                 }
 669         }
 670         io_size = ending_off - starting_off;
 671         io_buf = (uint8_t *)kmem_zalloc(io_size, KM_SLEEP);
 672         ASSERT((starting_off + io_size) <= sl->sl_total_meta_size);
 673 
 674         /*
 675          * Don't proceed if the device has been closed
 676          * This can occur on an access state change to standby or
 677          * a delete. The writer lock is acquired before closing the
 678          * lu. If importing, reading the metadata is valid, hence
 679          * the check on SL_OP_IMPORT_LU.
 680          */
 681         rw_enter(&sl->sl_access_state_lock, RW_READER);
 682         if ((sl->sl_flags & SL_MEDIA_LOADED) == 0 &&
 683             sl->sl_trans_op != SL_OP_IMPORT_LU) {
 684                 rw_exit(&sl->sl_access_state_lock);
 685                 ret = SBD_FILEIO_FAILURE;
 686                 goto sbd_read_meta_failure;
 687         }
 688         if (sl->sl_flags & SL_ZFS_META) {
 689                 if ((ret = sbd_read_zfs_meta(sl, io_buf, io_size,
 690                     starting_off)) != SBD_SUCCESS) {
 691                         rw_exit(&sl->sl_access_state_lock);
 692                         goto sbd_read_meta_failure;
 693                 }
 694         } else {
 695                 vret = vn_rdwr(UIO_READ, vp, (caddr_t)io_buf, (ssize_t)io_size,
 696                     (offset_t)starting_off, UIO_SYSSPACE, FRSYNC,
 697                     RLIM64_INFINITY, CRED(), &resid);
 698 
 699                 if (vret || resid) {
 700                         ret = SBD_FILEIO_FAILURE | vret;
 701                         rw_exit(&sl->sl_access_state_lock);
 702                         goto sbd_read_meta_failure;
 703                 }
 704         }
 705         rw_exit(&sl->sl_access_state_lock);
 706 
 707         bcopy(io_buf + data_off, buf, size);
 708         ret = SBD_SUCCESS;
 709 
 710 sbd_read_meta_failure:
 711         kmem_free(io_buf, io_size);
 712         return (ret);
 713 }
 714 
 715 sbd_status_t
 716 sbd_write_meta(sbd_lu_t *sl, uint64_t offset, uint64_t size, uint8_t *buf)
 717 {
 718         uint64_t        meta_align;
 719         uint64_t        starting_off;
 720         uint64_t        data_off;
 721         uint64_t        ending_off;
 722         uint64_t        io_size;
 723         uint8_t         *io_buf;
 724         vnode_t         *vp;
 725         sbd_status_t    ret;
 726         ssize_t         resid;
 727         int             vret;
 728 
 729         ASSERT(sl->sl_flags & SL_META_OPENED);
 730         if (sl->sl_flags & SL_SHARED_META) {
 731                 meta_align = (((uint64_t)1) << sl->sl_data_blocksize_shift) - 1;
 732                 vp = sl->sl_data_vp;
 733                 ASSERT(vp);
 734         } else {
 735                 meta_align = (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
 736                 if ((sl->sl_flags & SL_ZFS_META) == 0) {
 737                         vp = sl->sl_meta_vp;
 738                         ASSERT(vp);
 739                 }
 740         }
 741         starting_off = offset & ~(meta_align);
 742         data_off = offset & meta_align;
 743         ending_off = (offset + size + meta_align) & (~meta_align);
 744         io_size = ending_off - starting_off;
 745         io_buf = (uint8_t *)kmem_zalloc(io_size, KM_SLEEP);
 746         ret = sbd_read_meta(sl, starting_off, io_size, io_buf);
 747         if (ret != SBD_SUCCESS) {
 748                 goto sbd_write_meta_failure;
 749         }
 750         bcopy(buf, io_buf + data_off, size);
 751         /*
 752          * Don't proceed if the device has been closed
 753          * This can occur on an access state change to standby or
 754          * a delete. The writer lock is acquired before closing the
 755          * lu. If importing, reading the metadata is valid, hence
 756          * the check on SL_OP_IMPORT_LU.
 757          */
 758         rw_enter(&sl->sl_access_state_lock, RW_READER);
 759         if ((sl->sl_flags & SL_MEDIA_LOADED) == 0 &&
 760             sl->sl_trans_op != SL_OP_IMPORT_LU) {
 761                 rw_exit(&sl->sl_access_state_lock);
 762                 ret = SBD_FILEIO_FAILURE;
 763                 goto sbd_write_meta_failure;
 764         }
 765         if (sl->sl_flags & SL_ZFS_META) {
 766                 if ((ret = sbd_write_zfs_meta(sl, io_buf, io_size,
 767                     starting_off)) != SBD_SUCCESS) {
 768                         rw_exit(&sl->sl_access_state_lock);
 769                         goto sbd_write_meta_failure;
 770                 }
 771         } else {
 772                 vret = vn_rdwr(UIO_WRITE, vp, (caddr_t)io_buf, (ssize_t)io_size,
 773                     (offset_t)starting_off, UIO_SYSSPACE, FDSYNC,
 774                     RLIM64_INFINITY, CRED(), &resid);
 775 
 776                 if (vret || resid) {
 777                         ret = SBD_FILEIO_FAILURE | vret;
 778                         rw_exit(&sl->sl_access_state_lock);
 779                         goto sbd_write_meta_failure;
 780                 }
 781         }
 782         rw_exit(&sl->sl_access_state_lock);
 783 
 784         ret = SBD_SUCCESS;
 785 
 786 sbd_write_meta_failure:
 787         kmem_free(io_buf, io_size);
 788         return (ret);
 789 }
 790 
 791 uint8_t
 792 sbd_calc_sum(uint8_t *buf, int size)
 793 {
 794         uint8_t s = 0;
 795 
 796         while (size > 0)
 797                 s += buf[--size];
 798 
 799         return (s);
 800 }
 801 
 802 uint8_t
 803 sbd_calc_section_sum(sm_section_hdr_t *sm, uint32_t sz)
 804 {
 805         uint8_t s, o;
 806 
 807         o = sm->sms_chksum;
 808         sm->sms_chksum = 0;
 809         s = sbd_calc_sum((uint8_t *)sm, sz);
 810         sm->sms_chksum = o;
 811 
 812         return (s);
 813 }
 814 
 815 uint32_t
 816 sbd_strlen(char *str, uint32_t maxlen)
 817 {
 818         uint32_t i;
 819 
 820         for (i = 0; i < maxlen; i++) {
 821                 if (str[i] == 0)
 822                         return (i);
 823         }
 824         return (i);
 825 }
 826 
 827 void
 828 sbd_swap_meta_start(sbd_meta_start_t *sm)
 829 {
 830         if (sm->sm_magic == SBD_MAGIC)
 831                 return;
 832         sm->sm_magic         = BSWAP_64(sm->sm_magic);
 833         sm->sm_meta_size     = BSWAP_64(sm->sm_meta_size);
 834         sm->sm_meta_size_used        = BSWAP_64(sm->sm_meta_size_used);
 835         sm->sm_ver_major     = BSWAP_16(sm->sm_ver_major);
 836         sm->sm_ver_minor     = BSWAP_16(sm->sm_ver_minor);
 837         sm->sm_ver_subminor  = BSWAP_16(sm->sm_ver_subminor);
 838 }
 839 
 840 void
 841 sbd_swap_section_hdr(sm_section_hdr_t *sm)
 842 {
 843         if (sm->sms_data_order == SMS_DATA_ORDER)
 844                 return;
 845         sm->sms_offset               = BSWAP_64(sm->sms_offset);
 846         sm->sms_size         = BSWAP_32(sm->sms_size);
 847         sm->sms_id           = BSWAP_16(sm->sms_id);
 848         sm->sms_chksum               += SMS_DATA_ORDER - sm->sms_data_order;
 849         sm->sms_data_order   = SMS_DATA_ORDER;
 850 }
 851 
 852 void
 853 sbd_swap_lu_info_1_0(sbd_lu_info_1_0_t *sli)
 854 {
 855         sbd_swap_section_hdr(&sli->sli_sms_header);
 856         if (sli->sli_data_order == SMS_DATA_ORDER)
 857                 return;
 858         sli->sli_sms_header.sms_chksum       += SMS_DATA_ORDER - sli->sli_data_order;
 859         sli->sli_data_order          = SMS_DATA_ORDER;
 860         sli->sli_total_store_size    = BSWAP_64(sli->sli_total_store_size);
 861         sli->sli_total_meta_size     = BSWAP_64(sli->sli_total_meta_size);
 862         sli->sli_lu_data_offset              = BSWAP_64(sli->sli_lu_data_offset);
 863         sli->sli_lu_data_size                = BSWAP_64(sli->sli_lu_data_size);
 864         sli->sli_flags                       = BSWAP_32(sli->sli_flags);
 865         sli->sli_blocksize           = BSWAP_16(sli->sli_blocksize);
 866 }
 867 
 868 void
 869 sbd_swap_lu_info_1_1(sbd_lu_info_1_1_t *sli)
 870 {
 871         sbd_swap_section_hdr(&sli->sli_sms_header);
 872         if (sli->sli_data_order == SMS_DATA_ORDER)
 873                 return;
 874         sli->sli_sms_header.sms_chksum       += SMS_DATA_ORDER - sli->sli_data_order;
 875         sli->sli_data_order          = SMS_DATA_ORDER;
 876         sli->sli_flags                       = BSWAP_32(sli->sli_flags);
 877         sli->sli_lu_size             = BSWAP_64(sli->sli_lu_size);
 878         sli->sli_meta_fname_offset   = BSWAP_64(sli->sli_meta_fname_offset);
 879         sli->sli_data_fname_offset   = BSWAP_64(sli->sli_data_fname_offset);
 880         sli->sli_serial_offset               = BSWAP_64(sli->sli_serial_offset);
 881         sli->sli_alias_offset                = BSWAP_64(sli->sli_alias_offset);
 882         sli->sli_mgmt_url_offset     = BSWAP_64(sli->sli_mgmt_url_offset);
 883 }
 884 
 885 sbd_status_t
 886 sbd_load_section_hdr(sbd_lu_t *sl, sm_section_hdr_t *sms)
 887 {
 888         sm_section_hdr_t        h;
 889         uint64_t                st;
 890         sbd_status_t            ret;
 891 
 892         for (st = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
 893             st < sl->sl_meta_size_used; st += h.sms_size) {
 894                 if ((ret = sbd_read_meta(sl, st, sizeof (sm_section_hdr_t),
 895                     (uint8_t *)&h)) != SBD_SUCCESS) {
 896                         return (ret);
 897                 }
 898                 if (h.sms_data_order != SMS_DATA_ORDER) {
 899                         sbd_swap_section_hdr(&h);
 900                 }
 901                 if ((h.sms_data_order != SMS_DATA_ORDER) ||
 902                     (h.sms_offset != st) || (h.sms_size < sizeof (h)) ||
 903                     ((st + h.sms_size) > sl->sl_meta_size_used)) {
 904                         return (SBD_META_CORRUPTED);
 905                 }
 906                 if (h.sms_id == sms->sms_id) {
 907                         bcopy(&h, sms, sizeof (h));
 908                         return (SBD_SUCCESS);
 909                 }
 910         }
 911 
 912         return (SBD_NOT_FOUND);
 913 }
 914 
 915 sbd_status_t
 916 sbd_load_meta_start(sbd_lu_t *sl)
 917 {
 918         sbd_meta_start_t *sm;
 919         sbd_status_t ret;
 920 
 921         /* Fake meta params initially */
 922         sl->sl_total_meta_size = (uint64_t)-1;
 923         sl->sl_meta_size_used = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
 924 
 925         sm = kmem_zalloc(sizeof (*sm), KM_SLEEP);
 926         ret = sbd_read_meta(sl, sl->sl_meta_offset, sizeof (*sm),
 927             (uint8_t *)sm);
 928         if (ret != SBD_SUCCESS) {
 929                 goto load_meta_start_failed;
 930         }
 931 
 932         if (sm->sm_magic != SBD_MAGIC) {
 933                 sbd_swap_meta_start(sm);
 934         }
 935 
 936         if ((sm->sm_magic != SBD_MAGIC) || (sbd_calc_sum((uint8_t *)sm,
 937             sizeof (*sm) - 1) != sm->sm_chksum)) {
 938                 ret = SBD_META_CORRUPTED;
 939                 goto load_meta_start_failed;
 940         }
 941 
 942         if (sm->sm_ver_major != SBD_VER_MAJOR) {
 943                 ret = SBD_NOT_SUPPORTED;
 944                 goto load_meta_start_failed;
 945         }
 946 
 947         sl->sl_total_meta_size = sm->sm_meta_size;
 948         sl->sl_meta_size_used = sm->sm_meta_size_used;
 949         ret = SBD_SUCCESS;
 950 
 951 load_meta_start_failed:
 952         kmem_free(sm, sizeof (*sm));
 953         return (ret);
 954 }
 955 
 956 sbd_status_t
 957 sbd_write_meta_start(sbd_lu_t *sl, uint64_t meta_size, uint64_t meta_size_used)
 958 {
 959         sbd_meta_start_t *sm;
 960         sbd_status_t ret;
 961 
 962         sm = (sbd_meta_start_t *)kmem_zalloc(sizeof (sbd_meta_start_t),
 963             KM_SLEEP);
 964 
 965         sm->sm_magic = SBD_MAGIC;
 966         sm->sm_meta_size = meta_size;
 967         sm->sm_meta_size_used = meta_size_used;
 968         sm->sm_ver_major = SBD_VER_MAJOR;
 969         sm->sm_ver_minor = SBD_VER_MINOR;
 970         sm->sm_ver_subminor = SBD_VER_SUBMINOR;
 971         sm->sm_chksum = sbd_calc_sum((uint8_t *)sm, sizeof (*sm) - 1);
 972 
 973         ret = sbd_write_meta(sl, sl->sl_meta_offset, sizeof (*sm),
 974             (uint8_t *)sm);
 975         kmem_free(sm, sizeof (*sm));
 976 
 977         return (ret);
 978 }
 979 
 980 sbd_status_t
 981 sbd_read_meta_section(sbd_lu_t *sl, sm_section_hdr_t **ppsms, uint16_t sms_id)
 982 {
 983         sbd_status_t ret;
 984         sm_section_hdr_t sms;
 985         int alloced = 0;
 986 
 987         mutex_enter(&sl->sl_metadata_lock);
 988         if (((*ppsms) == NULL) || ((*ppsms)->sms_offset == 0)) {
 989                 bzero(&sms, sizeof (sm_section_hdr_t));
 990                 sms.sms_id = sms_id;
 991                 if ((ret = sbd_load_section_hdr(sl, &sms)) != SBD_SUCCESS) {
 992                         mutex_exit(&sl->sl_metadata_lock);
 993                         return (ret);
 994                 } else {
 995                         if ((*ppsms) == NULL) {
 996                                 *ppsms = (sm_section_hdr_t *)kmem_zalloc(
 997                                     sms.sms_size, KM_SLEEP);
 998                                 alloced = 1;
 999                         }
1000                         bcopy(&sms, *ppsms, sizeof (sm_section_hdr_t));
1001                 }
1002         }
1003 
1004         ret = sbd_read_meta(sl, (*ppsms)->sms_offset, (*ppsms)->sms_size,
1005             (uint8_t *)(*ppsms));
1006         if (ret == SBD_SUCCESS) {
1007                 uint8_t s;
1008                 if ((*ppsms)->sms_data_order != SMS_DATA_ORDER)
1009                         sbd_swap_section_hdr(*ppsms);
1010                 if ((*ppsms)->sms_id != SMS_ID_UNUSED) {
1011                         s = sbd_calc_section_sum(*ppsms, (*ppsms)->sms_size);
1012                         if (s != (*ppsms)->sms_chksum)
1013                                 ret = SBD_META_CORRUPTED;
1014                 }
1015         }
1016         mutex_exit(&sl->sl_metadata_lock);
1017 
1018         if ((ret != SBD_SUCCESS) && alloced)
1019                 kmem_free(*ppsms, sms.sms_size);
1020         return (ret);
1021 }
1022 
1023 sbd_status_t
1024 sbd_load_section_hdr_unbuffered(sbd_lu_t *sl, sm_section_hdr_t *sms)
1025 {
1026         sbd_status_t    ret;
1027 
1028         /*
1029          * Bypass buffering and re-read the meta data from permanent storage.
1030          */
1031         if (sl->sl_flags & SL_ZFS_META) {
1032                 if ((ret = sbd_open_zfs_meta(sl)) != SBD_SUCCESS) {
1033                         return (ret);
1034                 }
1035         }
1036         /* Re-get the meta sizes into sl */
1037         if ((ret = sbd_load_meta_start(sl)) != SBD_SUCCESS) {
1038                 return (ret);
1039         }
1040         return (sbd_load_section_hdr(sl, sms));
1041 }
1042 
1043 sbd_status_t
1044 sbd_write_meta_section(sbd_lu_t *sl, sm_section_hdr_t *sms)
1045 {
1046         sm_section_hdr_t t;
1047         uint64_t off, s;
1048         uint64_t unused_start;
1049         sbd_status_t ret;
1050         sbd_status_t write_meta_ret = SBD_SUCCESS;
1051         uint8_t *cb;
1052         int meta_size_changed = 0;
1053         sm_section_hdr_t sms_before_unused = {0};
1054 
1055         mutex_enter(&sl->sl_metadata_lock);
1056 write_meta_section_again:
1057         if (sms->sms_offset) {
1058                 /*
1059                  * If the section already exists and the size is the
1060                  * same as this new data then overwrite in place. If
1061                  * the sizes are different then mark the existing as
1062                  * unused and look for free space.
1063                  */
1064                 ret = sbd_read_meta(sl, sms->sms_offset, sizeof (t),
1065                     (uint8_t *)&t);
1066                 if (ret != SBD_SUCCESS) {
1067                         mutex_exit(&sl->sl_metadata_lock);
1068                         return (ret);
1069                 }
1070                 if (t.sms_data_order != SMS_DATA_ORDER) {
1071                         sbd_swap_section_hdr(&t);
1072                 }
1073                 if (t.sms_id != sms->sms_id) {
1074                         mutex_exit(&sl->sl_metadata_lock);
1075                         return (SBD_INVALID_ARG);
1076                 }
1077                 if (t.sms_size == sms->sms_size) {
1078                         ret = sbd_write_meta(sl, sms->sms_offset,
1079                             sms->sms_size, (uint8_t *)sms);
1080                         mutex_exit(&sl->sl_metadata_lock);
1081                         return (ret);
1082                 }
1083                 sms_before_unused = t;
1084 
1085                 t.sms_id = SMS_ID_UNUSED;
1086                 /*
1087                  * For unused sections we only use chksum of the header. for
1088                  * all other sections, the chksum is for the entire section.
1089                  */
1090                 t.sms_chksum = sbd_calc_section_sum(&t, sizeof (t));
1091                 ret = sbd_write_meta(sl, t.sms_offset, sizeof (t),
1092                     (uint8_t *)&t);
1093                 if (ret != SBD_SUCCESS) {
1094                         mutex_exit(&sl->sl_metadata_lock);
1095                         return (ret);
1096                 }
1097                 sms->sms_offset = 0;
1098         } else {
1099                 /* Section location is unknown, search for it. */
1100                 t.sms_id = sms->sms_id;
1101                 t.sms_data_order = SMS_DATA_ORDER;
1102                 ret = sbd_load_section_hdr(sl, &t);
1103                 if (ret == SBD_SUCCESS) {
1104                         sms->sms_offset = t.sms_offset;
1105                         sms->sms_chksum =
1106                             sbd_calc_section_sum(sms, sms->sms_size);
1107                         goto write_meta_section_again;
1108                 } else if (ret != SBD_NOT_FOUND) {
1109                         mutex_exit(&sl->sl_metadata_lock);
1110                         return (ret);
1111                 }
1112         }
1113 
1114         /*
1115          * At this point we know that section does not already exist.
1116          * Find space large enough to hold the section or grow meta if
1117          * possible.
1118          */
1119         unused_start = 0;
1120         s = 0;  /* size of space found */
1121 
1122         /*
1123          * Search all sections for unused space of sufficient size.
1124          * The first one found is taken. Contiguous unused sections
1125          * will be combined.
1126          */
1127         for (off = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
1128             off < sl->sl_meta_size_used; off += t.sms_size) {
1129                 ret = sbd_read_meta(sl, off, sizeof (t), (uint8_t *)&t);
1130                 if (ret != SBD_SUCCESS) {
1131                         mutex_exit(&sl->sl_metadata_lock);
1132                         return (ret);
1133                 }
1134                 if (t.sms_data_order != SMS_DATA_ORDER)
1135                         sbd_swap_section_hdr(&t);
1136                 if (t.sms_size == 0) {
1137                         mutex_exit(&sl->sl_metadata_lock);
1138                         return (SBD_META_CORRUPTED);
1139                 }
1140                 if (t.sms_id == SMS_ID_UNUSED) {
1141                         if (unused_start == 0)
1142                                 unused_start = off;
1143                         /*
1144                          * Calculate size of the unused space, break out
1145                          * if it satisfies the requirement.
1146                          */
1147                         s = t.sms_size - unused_start + off;
1148                         if ((s == sms->sms_size) || (s >= (sms->sms_size +
1149                             sizeof (t)))) {
1150                                 break;
1151                         } else {
1152                                 s = 0;
1153                         }
1154                 } else {
1155                         unused_start = 0;
1156                 }
1157         }
1158 
1159         off = (unused_start == 0) ? sl->sl_meta_size_used : unused_start;
1160         /*
1161          * If none found, how much room is at the end?
1162          * See if the data can be expanded.
1163          */
1164         if (s == 0) {
1165                 s = sl->sl_total_meta_size - off;
1166                 if (s >= sms->sms_size || !(sl->sl_flags & SL_SHARED_META)) {
1167                         s = sms->sms_size;
1168                         meta_size_changed = 1;
1169                 } else {
1170                         s = 0;
1171                 }
1172         }
1173 
1174         if (s == 0) {
1175                 mutex_exit(&sl->sl_metadata_lock);
1176                 return (SBD_ALLOC_FAILURE);
1177         }
1178 
1179         sms->sms_offset = off;
1180         sms->sms_chksum = sbd_calc_section_sum(sms, sms->sms_size);
1181         /*
1182          * Since we may have to write more than one section (current +
1183          * any unused), use a combined buffer.
1184          */
1185         cb = kmem_zalloc(s, KM_SLEEP);
1186         bcopy(sms, cb, sms->sms_size);
1187         if (s > sms->sms_size) {
1188                 t.sms_offset = off + sms->sms_size;
1189                 t.sms_size = s - sms->sms_size;
1190                 t.sms_id = SMS_ID_UNUSED;
1191                 t.sms_data_order = SMS_DATA_ORDER;
1192                 t.sms_chksum = sbd_calc_section_sum(&t, sizeof (t));
1193                 bcopy(&t, cb + sms->sms_size, sizeof (t));
1194         }
1195         /*
1196          * Two write events & statuses take place. Failure writing the
1197          * meta section takes precedence, can possibly be rolled back,
1198          * & gets reported. Else return status from writing the meta start.
1199          */
1200         ret = SBD_SUCCESS; /* Set a default, it's not always loaded below. */
1201         if (meta_size_changed) {
1202                 uint64_t old_meta_size;
1203                 uint64_t old_sz_used = sl->sl_meta_size_used; /* save a copy */
1204                 old_meta_size = sl->sl_total_meta_size; /* save a copy */
1205 
1206                 write_meta_ret = sbd_write_meta(sl, off, s, cb);
1207                 if (write_meta_ret == SBD_SUCCESS) {
1208                         sl->sl_meta_size_used = off + s;
1209                         if (sl->sl_total_meta_size < sl->sl_meta_size_used) {
1210                                 uint64_t meta_align =
1211                                     (((uint64_t)1) <<
1212                                     sl->sl_meta_blocksize_shift) - 1;
1213                                 sl->sl_total_meta_size =
1214                                     (sl->sl_meta_size_used + meta_align) &
1215                                     (~meta_align);
1216                         }
1217                         ret = sbd_write_meta_start(sl, sl->sl_total_meta_size,
1218                             sl->sl_meta_size_used);
1219                         if (ret != SBD_SUCCESS) {
1220                                 sl->sl_meta_size_used = old_sz_used;
1221                                 sl->sl_total_meta_size = old_meta_size;
1222                         }
1223                 } else {
1224                         sl->sl_meta_size_used = old_sz_used;
1225                         sl->sl_total_meta_size = old_meta_size;
1226                 }
1227         } else {
1228                 write_meta_ret = sbd_write_meta(sl, off, s, cb);
1229         }
1230         if ((write_meta_ret != SBD_SUCCESS) &&
1231             (sms_before_unused.sms_offset != 0)) {
1232                 sm_section_hdr_t new_sms;
1233                 sm_section_hdr_t *unused_sms;
1234                 /*
1235                  * On failure writing the meta section attempt to undo
1236                  * the change to unused.
1237                  * Re-read the meta data from permanent storage.
1238                  * The section id can't exist for undo to be possible.
1239                  * Read what should be the entire old section data and
1240                  * insure the old data's still present by validating
1241                  * against it's old checksum.
1242                  */
1243                 new_sms.sms_id = sms->sms_id;
1244                 new_sms.sms_data_order = SMS_DATA_ORDER;
1245                 if (sbd_load_section_hdr_unbuffered(sl, &new_sms) !=
1246                     SBD_NOT_FOUND) {
1247                         goto done;
1248                 }
1249                 unused_sms = kmem_zalloc(sms_before_unused.sms_size, KM_SLEEP);
1250                 if (sbd_read_meta(sl, sms_before_unused.sms_offset,
1251                     sms_before_unused.sms_size,
1252                     (uint8_t *)unused_sms) != SBD_SUCCESS) {
1253                         goto done;
1254                 }
1255                 if (unused_sms->sms_data_order != SMS_DATA_ORDER) {
1256                         sbd_swap_section_hdr(unused_sms);
1257                 }
1258                 if (unused_sms->sms_id != SMS_ID_UNUSED) {
1259                         goto done;
1260                 }
1261                 if (unused_sms->sms_offset != sms_before_unused.sms_offset) {
1262                         goto done;
1263                 }
1264                 if (unused_sms->sms_size != sms_before_unused.sms_size) {
1265                         goto done;
1266                 }
1267                 unused_sms->sms_id = sms_before_unused.sms_id;
1268                 if (sbd_calc_section_sum(unused_sms,
1269                     sizeof (sm_section_hdr_t)) !=
1270                     sbd_calc_section_sum(&sms_before_unused,
1271                     sizeof (sm_section_hdr_t))) {
1272                         goto done;
1273                 }
1274                 unused_sms->sms_chksum =
1275                     sbd_calc_section_sum(unused_sms, unused_sms->sms_size);
1276                 if (unused_sms->sms_chksum != sms_before_unused.sms_chksum) {
1277                         goto done;
1278                 }
1279                 (void) sbd_write_meta(sl, unused_sms->sms_offset,
1280                     sizeof (sm_section_hdr_t), (uint8_t *)unused_sms);
1281         }
1282 done:
1283         mutex_exit(&sl->sl_metadata_lock);
1284         kmem_free(cb, s);
1285         if (write_meta_ret != SBD_SUCCESS) {
1286                 return (write_meta_ret);
1287         }
1288         return (ret);
1289 }
1290 
1291 sbd_status_t
1292 sbd_write_lu_info(sbd_lu_t *sl)
1293 {
1294         sbd_lu_info_1_1_t *sli;
1295         int s;
1296         uint8_t *p;
1297         char *zvol_name = NULL;
1298         sbd_status_t ret;
1299 
1300         mutex_enter(&sl->sl_lock);
1301 
1302         s = sl->sl_serial_no_size;
1303         if ((sl->sl_flags & (SL_SHARED_META | SL_ZFS_META)) == 0) {
1304                 if (sl->sl_data_filename) {
1305                         s += strlen(sl->sl_data_filename) + 1;
1306                 }
1307         }
1308         if (sl->sl_flags & SL_ZFS_META) {
1309                 zvol_name = sbd_get_zvol_name(sl);
1310                 s += strlen(zvol_name) + 1;
1311         }
1312         if (sl->sl_alias) {
1313                 s += strlen(sl->sl_alias) + 1;
1314         }
1315         if (sl->sl_mgmt_url) {
1316                 s += strlen(sl->sl_mgmt_url) + 1;
1317         }
1318         sli = (sbd_lu_info_1_1_t *)kmem_zalloc(sizeof (*sli) + s, KM_SLEEP);
1319         p = sli->sli_buf;
1320         if ((sl->sl_flags & (SL_SHARED_META | SL_ZFS_META)) == 0) {
1321                 sli->sli_flags |= SLI_SEPARATE_META;
1322                 (void) strcpy((char *)p, sl->sl_data_filename);
1323                 sli->sli_data_fname_offset =
1324                     (uintptr_t)p - (uintptr_t)sli->sli_buf;
1325                 sli->sli_flags |= SLI_DATA_FNAME_VALID;
1326                 p += strlen(sl->sl_data_filename) + 1;
1327         }
1328         if (sl->sl_flags & SL_ZFS_META) {
1329                 (void) strcpy((char *)p, zvol_name);
1330                 sli->sli_meta_fname_offset =
1331                     (uintptr_t)p - (uintptr_t)sli->sli_buf;
1332                 sli->sli_flags |= SLI_META_FNAME_VALID | SLI_ZFS_META;
1333                 p += strlen(zvol_name) + 1;
1334                 kmem_free(zvol_name, strlen(zvol_name) + 1);
1335                 zvol_name = NULL;
1336         }
1337         if (sl->sl_alias) {
1338                 (void) strcpy((char *)p, sl->sl_alias);
1339                 sli->sli_alias_offset =
1340                     (uintptr_t)p - (uintptr_t)sli->sli_buf;
1341                 sli->sli_flags |= SLI_ALIAS_VALID;
1342                 p += strlen(sl->sl_alias) + 1;
1343         }
1344         if (sl->sl_mgmt_url) {
1345                 (void) strcpy((char *)p, sl->sl_mgmt_url);
1346                 sli->sli_mgmt_url_offset =
1347                     (uintptr_t)p - (uintptr_t)sli->sli_buf;
1348                 sli->sli_flags |= SLI_MGMT_URL_VALID;
1349                 p += strlen(sl->sl_mgmt_url) + 1;
1350         }
1351         if (sl->sl_flags & SL_WRITE_PROTECTED) {
1352                 sli->sli_flags |= SLI_WRITE_PROTECTED;
1353         }
1354         if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE) {
1355                 sli->sli_flags |= SLI_WRITEBACK_CACHE_DISABLE;
1356         }
1357         if (sl->sl_flags & SL_VID_VALID) {
1358                 bcopy(sl->sl_vendor_id, sli->sli_vid, 8);
1359                 sli->sli_flags |= SLI_VID_VALID;
1360         }
1361         if (sl->sl_flags & SL_PID_VALID) {
1362                 bcopy(sl->sl_product_id, sli->sli_pid, 16);
1363                 sli->sli_flags |= SLI_PID_VALID;
1364         }
1365         if (sl->sl_flags & SL_REV_VALID) {
1366                 bcopy(sl->sl_revision, sli->sli_rev, 4);
1367                 sli->sli_flags |= SLI_REV_VALID;
1368         }
1369         if (sl->sl_serial_no_size) {
1370                 bcopy(sl->sl_serial_no, p, sl->sl_serial_no_size);
1371                 sli->sli_serial_size = sl->sl_serial_no_size;
1372                 sli->sli_serial_offset =
1373                     (uintptr_t)p - (uintptr_t)sli->sli_buf;
1374                 sli->sli_flags |= SLI_SERIAL_VALID;
1375                 p += sli->sli_serial_size;
1376         }
1377         sli->sli_lu_size = sl->sl_lu_size;
1378         sli->sli_data_blocksize_shift = sl->sl_data_blocksize_shift;
1379         sli->sli_data_order = SMS_DATA_ORDER;
1380         bcopy(sl->sl_device_id, sli->sli_device_id, 20);
1381 
1382         sli->sli_sms_header.sms_size = sizeof (*sli) + s;
1383         sli->sli_sms_header.sms_id = SMS_ID_LU_INFO_1_1;
1384         sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER;
1385 
1386         mutex_exit(&sl->sl_lock);
1387         ret = sbd_write_meta_section(sl, (sm_section_hdr_t *)sli);
1388         kmem_free(sli, sizeof (*sli) + s);
1389         return (ret);
1390 }
1391 
1392 /*
1393  * Will scribble SL_UNMAP_ENABLED into sl_flags if we succeed.
1394  */
1395 static void
1396 do_unmap_setup(sbd_lu_t *sl)
1397 {
1398         char *file = NULL;
1399         nvlist_t *nv = NULL, *nv2 = NULL;
1400         boolean_t already_compressing = B_FALSE;
1401         uint64_t val;
1402 
1403         ASSERT((sl->sl_flags & SL_UNMAP_ENABLED) == 0);
1404 
1405         if ((sl->sl_flags & SL_ZFS_META) == 0)
1406                 return; /* No UNMAP for you. */
1407 
1408         file = sbd_get_zvol_name(sl);
1409         if (file == NULL) {
1410                 cmn_err(CE_WARN, "sbd has zfs meta but no zvol name");
1411                 return; /* No UNMAP for you. */
1412         }
1413         nv = sbd_zvol_get_props(file);
1414         if (nv == NULL) {
1415                 cmn_err(CE_WARN, "unable to get zvol props");
1416                 kmem_free(file, strlen(file) + 1);
1417                 return; /* No UNMAP for you. */
1418         }
1419 
1420         /* See if compression is supported, but turned off on this dataset. */
1421         if (nvlist_lookup_nvlist(nv, "compression", &nv2) == 0 &&
1422             nvlist_lookup_uint64(nv2, ZPROP_VALUE, &val) == 0) {
1423                 already_compressing = (val != ZIO_COMPRESS_OFF);
1424         } else {
1425                 cmn_err(CE_WARN, "prop lookup for compression failed");
1426         }
1427 
1428         /*
1429          * Check refreservation because no refreservation means this is a
1430          * sparse zvol and we can enable SCSI unmap.
1431          */
1432         if (nvlist_lookup_nvlist(nv, "refreservation", &nv2) != 0) {
1433                 cmn_err(CE_WARN, "lookup for refreservation nvlist failed");
1434         } else if (nvlist_lookup_uint64(nv2, ZPROP_VALUE, &val) != 0) {
1435                 cmn_err(CE_WARN, "prop lookup for refreservation failed");
1436         } else if (val == 0) {
1437                 sl->sl_flags |= SL_UNMAP_ENABLED;
1438                 if (!already_compressing) {
1439                         nvlist_free(nv);
1440                         nv = NULL;
1441                         if (nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) != 0 ||
1442                             nvlist_add_uint64(nv, "compression",
1443                             ZIO_COMPRESS_ZLE) != 0 ||
1444                             sbd_zvol_set_props(file, nv)) {
1445                                 cmn_err(CE_WARN, "Setting zle compression "
1446                                     "failed for zvol %s", file);
1447                         }
1448                 }
1449         }
1450 
1451         nvlist_free(nv);
1452         kmem_free(file, strlen(file) + 1);
1453 }
1454 
1455 int
1456 sbd_populate_and_register_lu(sbd_lu_t *sl, uint32_t *err_ret)
1457 {
1458         stmf_lu_t *lu = sl->sl_lu;
1459         stmf_status_t ret;
1460 
1461         do_unmap_setup(sl);
1462 
1463         lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
1464         if (sl->sl_alias) {
1465                 lu->lu_alias = sl->sl_alias;
1466         } else {
1467                 lu->lu_alias = sl->sl_name;
1468         }
1469         if (sl->sl_access_state == SBD_LU_STANDBY) {
1470                 /* call set access state */
1471                 ret = stmf_set_lu_access(lu, STMF_LU_STANDBY);
1472                 if (ret != STMF_SUCCESS) {
1473                         *err_ret = SBD_RET_ACCESS_STATE_FAILED;
1474                         return (EIO);
1475                 }
1476         }
1477         /* set proxy_reg_cb_arg to meta filename */
1478         if (sl->sl_meta_filename) {
1479                 lu->lu_proxy_reg_arg = sl->sl_meta_filename;
1480                 lu->lu_proxy_reg_arg_len = strlen(sl->sl_meta_filename) + 1;
1481         } else {
1482                 lu->lu_proxy_reg_arg = sl->sl_data_filename;
1483                 lu->lu_proxy_reg_arg_len = strlen(sl->sl_data_filename) + 1;
1484         }
1485         lu->lu_lp = sbd_lp;
1486         lu->lu_task_alloc = sbd_task_alloc;
1487         lu->lu_new_task = sbd_new_task;
1488         lu->lu_dbuf_xfer_done = sbd_dbuf_xfer_done;
1489         lu->lu_send_status_done = sbd_send_status_done;
1490         lu->lu_task_free = sbd_task_free;
1491         lu->lu_abort = sbd_abort;
1492         lu->lu_dbuf_free = sbd_dbuf_free;
1493         lu->lu_ctl = sbd_ctl;
1494         lu->lu_info = sbd_info;
1495         sl->sl_state = STMF_STATE_OFFLINE;
1496 
1497         if ((ret = stmf_register_lu(lu)) != STMF_SUCCESS) {
1498                 stmf_trace(0, "Failed to register with framework, ret=%llx",
1499                     ret);
1500                 if (ret == STMF_ALREADY) {
1501                         *err_ret = SBD_RET_GUID_ALREADY_REGISTERED;
1502                 }
1503                 return (EIO);
1504         }
1505 
1506         *err_ret = 0;
1507         return (0);
1508 }
1509 
1510 int
1511 sbd_open_data_file(sbd_lu_t *sl, uint32_t *err_ret, int lu_size_valid,
1512     int vp_valid, int keep_open)
1513 {
1514         int ret;
1515         int flag;
1516         ulong_t nbits;
1517         uint64_t supported_size;
1518         vattr_t vattr;
1519         enum vtype vt;
1520         struct dk_cinfo dki;
1521         int unused;
1522 
1523         mutex_enter(&sl->sl_lock);
1524         if (vp_valid) {
1525                 goto odf_over_open;
1526         }
1527         if (sl->sl_data_filename[0] != '/') {
1528                 *err_ret = SBD_RET_DATA_PATH_NOT_ABSOLUTE;
1529                 mutex_exit(&sl->sl_lock);
1530                 return (EINVAL);
1531         }
1532         if ((ret = lookupname(sl->sl_data_filename, UIO_SYSSPACE, FOLLOW,
1533             NULLVPP, &sl->sl_data_vp)) != 0) {
1534                 *err_ret = SBD_RET_DATA_FILE_LOOKUP_FAILED;
1535                 mutex_exit(&sl->sl_lock);
1536                 return (ret);
1537         }
1538         sl->sl_data_vtype = vt = sl->sl_data_vp->v_type;
1539         VN_RELE(sl->sl_data_vp);
1540         if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
1541                 *err_ret = SBD_RET_WRONG_DATA_FILE_TYPE;
1542                 mutex_exit(&sl->sl_lock);
1543                 return (EINVAL);
1544         }
1545         if (sl->sl_flags & SL_WRITE_PROTECTED) {
1546                 flag = FREAD | FOFFMAX;
1547         } else {
1548                 flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1549         }
1550         if ((ret = vn_open(sl->sl_data_filename, UIO_SYSSPACE, flag, 0,
1551             &sl->sl_data_vp, 0, 0)) != 0) {
1552                 *err_ret = SBD_RET_DATA_FILE_OPEN_FAILED;
1553                 mutex_exit(&sl->sl_lock);
1554                 return (ret);
1555         }
1556 odf_over_open:
1557         vattr.va_mask = AT_SIZE;
1558         if ((ret = VOP_GETATTR(sl->sl_data_vp, &vattr, 0, CRED(), NULL)) != 0) {
1559                 *err_ret = SBD_RET_DATA_FILE_GETATTR_FAILED;
1560                 goto odf_close_data_and_exit;
1561         }
1562         if ((vt != VREG) && (vattr.va_size == 0)) {
1563                 /*
1564                  * Its a zero byte block or char device. This cannot be
1565                  * a raw disk.
1566                  */
1567                 *err_ret = SBD_RET_WRONG_DATA_FILE_TYPE;
1568                 ret = EINVAL;
1569                 goto odf_close_data_and_exit;
1570         }
1571         /* sl_data_readable size includes any metadata. */
1572         sl->sl_data_readable_size = vattr.va_size;
1573 
1574         if (VOP_PATHCONF(sl->sl_data_vp, _PC_FILESIZEBITS, &nbits,
1575             CRED(), NULL) != 0) {
1576                 nbits = 0;
1577         }
1578         /* nbits cannot be greater than 64 */
1579         sl->sl_data_fs_nbits = (uint8_t)nbits;
1580         if (lu_size_valid) {
1581                 sl->sl_total_data_size = sl->sl_lu_size;
1582                 if (sl->sl_flags & SL_SHARED_META) {
1583                         sl->sl_total_data_size += SHARED_META_DATA_SIZE;
1584                 }
1585                 if ((nbits > 0) && (nbits < 64)) {
1586                         /*
1587                          * The expression below is correct only if nbits is
1588                          * positive and less than 64.
1589                          */
1590                         supported_size = (((uint64_t)1) << nbits) - 1;
1591                         if (sl->sl_total_data_size > supported_size) {
1592                                 *err_ret = SBD_RET_SIZE_NOT_SUPPORTED_BY_FS;
1593                                 ret = EINVAL;
1594                                 goto odf_close_data_and_exit;
1595                         }
1596                 }
1597         } else {
1598                 sl->sl_total_data_size = vattr.va_size;
1599                 if (sl->sl_flags & SL_SHARED_META) {
1600                         if (vattr.va_size > SHARED_META_DATA_SIZE) {
1601                                 sl->sl_lu_size = vattr.va_size -
1602                                     SHARED_META_DATA_SIZE;
1603                         } else {
1604                                 *err_ret = SBD_RET_FILE_SIZE_ERROR;
1605                                 ret = EINVAL;
1606                                 goto odf_close_data_and_exit;
1607                         }
1608                 } else {
1609                         sl->sl_lu_size = vattr.va_size;
1610                 }
1611         }
1612         if (sl->sl_lu_size < SBD_MIN_LU_SIZE) {
1613                 *err_ret = SBD_RET_FILE_SIZE_ERROR;
1614                 ret = EINVAL;
1615                 goto odf_close_data_and_exit;
1616         }
1617         if (sl->sl_lu_size &
1618             ((((uint64_t)1) << sl->sl_data_blocksize_shift) - 1)) {
1619                 *err_ret = SBD_RET_FILE_ALIGN_ERROR;
1620                 ret = EINVAL;
1621                 goto odf_close_data_and_exit;
1622         }
1623         /*
1624          * Get the minor device for direct zvol access
1625          */
1626         if (sl->sl_flags & SL_ZFS_META) {
1627                 if ((ret = VOP_IOCTL(sl->sl_data_vp, DKIOCINFO, (intptr_t)&dki,
1628                     FKIOCTL, kcred, &unused, NULL)) != 0) {
1629                         cmn_err(CE_WARN, "ioctl(DKIOCINFO) failed %d", ret);
1630                         /* zvol reserves 0, so this would fail later */
1631                         sl->sl_zvol_minor = 0;
1632                 } else {
1633                         sl->sl_zvol_minor = dki.dki_unit;
1634                         if (sbd_zvol_get_volume_params(sl) == 0)
1635                                 sl->sl_flags |= SL_CALL_ZVOL;
1636                 }
1637         }
1638         sl->sl_flags |= SL_MEDIA_LOADED;
1639         mutex_exit(&sl->sl_lock);
1640         return (0);
1641 
1642 odf_close_data_and_exit:
1643         if (!keep_open) {
1644                 (void) VOP_CLOSE(sl->sl_data_vp, flag, 1, 0, CRED(), NULL);
1645                 VN_RELE(sl->sl_data_vp);
1646         }
1647         mutex_exit(&sl->sl_lock);
1648         return (ret);
1649 }
1650 
1651 void
1652 sbd_close_lu(sbd_lu_t *sl)
1653 {
1654         int flag;
1655 
1656         if (((sl->sl_flags & SL_SHARED_META) == 0) &&
1657             (sl->sl_flags & SL_META_OPENED)) {
1658                 if (sl->sl_flags & SL_ZFS_META) {
1659                         rw_destroy(&sl->sl_zfs_meta_lock);
1660                         if (sl->sl_zfs_meta) {
1661                                 kmem_free(sl->sl_zfs_meta, ZAP_MAXVALUELEN / 2);
1662                                 sl->sl_zfs_meta = NULL;
1663                         }
1664                 } else {
1665                         flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1666                         (void) VOP_CLOSE(sl->sl_meta_vp, flag, 1, 0,
1667                             CRED(), NULL);
1668                         VN_RELE(sl->sl_meta_vp);
1669                 }
1670                 sl->sl_flags &= ~SL_META_OPENED;
1671         }
1672         if (sl->sl_flags & SL_MEDIA_LOADED) {
1673                 if (sl->sl_flags & SL_WRITE_PROTECTED) {
1674                         flag = FREAD | FOFFMAX;
1675                 } else {
1676                         flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1677                 }
1678                 (void) VOP_CLOSE(sl->sl_data_vp, flag, 1, 0, CRED(), NULL);
1679                 VN_RELE(sl->sl_data_vp);
1680                 sl->sl_flags &= ~SL_MEDIA_LOADED;
1681                 if (sl->sl_flags & SL_SHARED_META) {
1682                         sl->sl_flags &= ~SL_META_OPENED;
1683                 }
1684         }
1685 }
1686 
1687 int
1688 sbd_set_lu_standby(sbd_set_lu_standby_t *stlu, uint32_t *err_ret)
1689 {
1690         sbd_lu_t *sl;
1691         sbd_status_t sret;
1692         stmf_status_t stret;
1693         uint8_t old_access_state;
1694 
1695         sret = sbd_find_and_lock_lu(stlu->stlu_guid, NULL,
1696             SL_OP_MODIFY_LU, &sl);
1697         if (sret != SBD_SUCCESS) {
1698                 if (sret == SBD_BUSY) {
1699                         *err_ret = SBD_RET_LU_BUSY;
1700                         return (EBUSY);
1701                 } else if (sret == SBD_NOT_FOUND) {
1702                         *err_ret = SBD_RET_NOT_FOUND;
1703                         return (ENOENT);
1704                 }
1705                 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
1706                 return (EIO);
1707         }
1708 
1709         old_access_state = sl->sl_access_state;
1710         sl->sl_access_state = SBD_LU_TRANSITION_TO_STANDBY;
1711         stret = stmf_set_lu_access((stmf_lu_t *)sl->sl_lu, STMF_LU_STANDBY);
1712         if (stret != STMF_SUCCESS) {
1713                 sl->sl_trans_op = SL_OP_NONE;
1714                 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
1715                 sl->sl_access_state = old_access_state;
1716                 return (EIO);
1717         }
1718 
1719         /*
1720          * acquire the writer lock here to ensure we're not pulling
1721          * the rug from the vn_rdwr to the backing store
1722          */
1723         rw_enter(&sl->sl_access_state_lock, RW_WRITER);
1724         sbd_close_lu(sl);
1725         rw_exit(&sl->sl_access_state_lock);
1726 
1727         sl->sl_trans_op = SL_OP_NONE;
1728         return (0);
1729 }
1730 
1731 int
1732 sbd_close_delete_lu(sbd_lu_t *sl, int ret)
1733 {
1734 
1735         /*
1736          * acquire the writer lock here to ensure we're not pulling
1737          * the rug from the vn_rdwr to the backing store
1738          */
1739         rw_enter(&sl->sl_access_state_lock, RW_WRITER);
1740         sbd_close_lu(sl);
1741         rw_exit(&sl->sl_access_state_lock);
1742 
1743         if (sl->sl_flags & SL_LINKED)
1744                 sbd_unlink_lu(sl);
1745         mutex_destroy(&sl->sl_metadata_lock);
1746         mutex_destroy(&sl->sl_lock);
1747         rw_destroy(&sl->sl_pgr->pgr_lock);
1748         rw_destroy(&sl->sl_access_state_lock);
1749         if (sl->sl_serial_no_alloc_size) {
1750                 kmem_free(sl->sl_serial_no, sl->sl_serial_no_alloc_size);
1751         }
1752         if (sl->sl_data_fname_alloc_size) {
1753                 kmem_free(sl->sl_data_filename, sl->sl_data_fname_alloc_size);
1754         }
1755         if (sl->sl_alias_alloc_size) {
1756                 kmem_free(sl->sl_alias, sl->sl_alias_alloc_size);
1757         }
1758         if (sl->sl_mgmt_url_alloc_size) {
1759                 kmem_free(sl->sl_mgmt_url, sl->sl_mgmt_url_alloc_size);
1760         }
1761         stmf_free(sl->sl_lu);
1762         return (ret);
1763 }
1764 
1765 int
1766 sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz,
1767     uint32_t *err_ret)
1768 {
1769         char *namebuf;
1770         sbd_lu_t *sl;
1771         stmf_lu_t *lu;
1772         sbd_status_t sret;
1773         char *p;
1774         int sz;
1775         int alloc_sz;
1776         int ret = EIO;
1777         int flag;
1778         int wcd = 0;
1779         uint32_t hid = 0;
1780         enum vtype vt;
1781 
1782         sz = struct_sz - sizeof (sbd_create_and_reg_lu_t) + 8 + 1;
1783 
1784         *err_ret = 0;
1785 
1786         /* Lets validate various offsets */
1787         if (((slu->slu_meta_fname_valid) &&
1788             (slu->slu_meta_fname_off >= sz)) ||
1789             (slu->slu_data_fname_off >= sz) ||
1790             ((slu->slu_alias_valid) &&
1791             (slu->slu_alias_off >= sz)) ||
1792             ((slu->slu_mgmt_url_valid) &&
1793             (slu->slu_mgmt_url_off >= sz)) ||
1794             ((slu->slu_serial_valid) &&
1795             ((slu->slu_serial_off + slu->slu_serial_size) >= sz))) {
1796                 return (EINVAL);
1797         }
1798 
1799         namebuf = kmem_zalloc(sz, KM_SLEEP);
1800         bcopy(slu->slu_buf, namebuf, sz - 1);
1801         namebuf[sz - 1] = 0;
1802 
1803         alloc_sz = sizeof (sbd_lu_t) + sizeof (sbd_pgr_t);
1804         if (slu->slu_meta_fname_valid) {
1805                 alloc_sz += strlen(namebuf + slu->slu_meta_fname_off) + 1;
1806         }
1807         alloc_sz += strlen(namebuf + slu->slu_data_fname_off) + 1;
1808         if (slu->slu_alias_valid) {
1809                 alloc_sz += strlen(namebuf + slu->slu_alias_off) + 1;
1810         }
1811         if (slu->slu_mgmt_url_valid) {
1812                 alloc_sz += strlen(namebuf + slu->slu_mgmt_url_off) + 1;
1813         }
1814         if (slu->slu_serial_valid) {
1815                 alloc_sz += slu->slu_serial_size;
1816         }
1817 
1818         lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU, alloc_sz, 0);
1819         if (lu == NULL) {
1820                 kmem_free(namebuf, sz);
1821                 return (ENOMEM);
1822         }
1823         sl = (sbd_lu_t *)lu->lu_provider_private;
1824         bzero(sl, alloc_sz);
1825         sl->sl_lu = lu;
1826         sl->sl_alloc_size = alloc_sz;
1827         sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
1828         rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
1829         mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
1830         mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL);
1831         rw_init(&sl->sl_access_state_lock, NULL, RW_DRIVER, NULL);
1832         p = ((char *)sl) + sizeof (sbd_lu_t) + sizeof (sbd_pgr_t);
1833         sl->sl_data_filename = p;
1834         (void) strcpy(sl->sl_data_filename, namebuf + slu->slu_data_fname_off);
1835         p += strlen(sl->sl_data_filename) + 1;
1836         sl->sl_meta_offset = SBD_META_OFFSET;
1837         sl->sl_access_state = SBD_LU_ACTIVE;
1838         if (slu->slu_meta_fname_valid) {
1839                 sl->sl_alias = sl->sl_name = sl->sl_meta_filename = p;
1840                 (void) strcpy(sl->sl_meta_filename, namebuf +
1841                     slu->slu_meta_fname_off);
1842                 p += strlen(sl->sl_meta_filename) + 1;
1843         } else {
1844                 sl->sl_alias = sl->sl_name = sl->sl_data_filename;
1845                 if (sbd_is_zvol(sl->sl_data_filename)) {
1846                         sl->sl_flags |= SL_ZFS_META;
1847                         sl->sl_meta_offset = 0;
1848                 } else {
1849                         sl->sl_flags |= SL_SHARED_META;
1850                         sl->sl_data_offset = SHARED_META_DATA_SIZE;
1851                         sl->sl_total_meta_size = SHARED_META_DATA_SIZE;
1852                         sl->sl_meta_size_used = 0;
1853                 }
1854         }
1855         if (slu->slu_alias_valid) {
1856                 sl->sl_alias = p;
1857                 (void) strcpy(p, namebuf + slu->slu_alias_off);
1858                 p += strlen(sl->sl_alias) + 1;
1859         }
1860         if (slu->slu_mgmt_url_valid) {
1861                 sl->sl_mgmt_url = p;
1862                 (void) strcpy(p, namebuf + slu->slu_mgmt_url_off);
1863                 p += strlen(sl->sl_mgmt_url) + 1;
1864         }
1865         if (slu->slu_serial_valid) {
1866                 sl->sl_serial_no = (uint8_t *)p;
1867                 bcopy(namebuf + slu->slu_serial_off, sl->sl_serial_no,
1868                     slu->slu_serial_size);
1869                 sl->sl_serial_no_size = slu->slu_serial_size;
1870                 p += slu->slu_serial_size;
1871         }
1872         kmem_free(namebuf, sz);
1873         if (slu->slu_vid_valid) {
1874                 bcopy(slu->slu_vid, sl->sl_vendor_id, 8);
1875                 sl->sl_flags |= SL_VID_VALID;
1876         }
1877         if (slu->slu_pid_valid) {
1878                 bcopy(slu->slu_pid, sl->sl_product_id, 16);
1879                 sl->sl_flags |= SL_PID_VALID;
1880         }
1881         if (slu->slu_rev_valid) {
1882                 bcopy(slu->slu_rev, sl->sl_revision, 4);
1883                 sl->sl_flags |= SL_REV_VALID;
1884         }
1885         if (slu->slu_write_protected) {
1886                 sl->sl_flags |= SL_WRITE_PROTECTED;
1887         }
1888         if (slu->slu_writeback_cache_disable) {
1889                 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
1890                     SL_SAVED_WRITE_CACHE_DISABLE;
1891         }
1892 
1893         if (slu->slu_blksize_valid) {
1894                 if ((slu->slu_blksize & (slu->slu_blksize - 1)) ||
1895                     (slu->slu_blksize > (32 * 1024)) ||
1896                     (slu->slu_blksize == 0)) {
1897                         *err_ret = SBD_RET_INVALID_BLKSIZE;
1898                         ret = EINVAL;
1899                         goto scm_err_out;
1900                 }
1901                 while ((1 << sl->sl_data_blocksize_shift) != slu->slu_blksize) {
1902                         sl->sl_data_blocksize_shift++;
1903                 }
1904         } else {
1905                 sl->sl_data_blocksize_shift = 9;     /* 512 by default */
1906                 slu->slu_blksize = 512;
1907         }
1908 
1909         /* Now lets start creating meta */
1910         sl->sl_trans_op = SL_OP_CREATE_REGISTER_LU;
1911         if (sbd_link_lu(sl) != SBD_SUCCESS) {
1912                 *err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
1913                 ret = EALREADY;
1914                 goto scm_err_out;
1915         }
1916 
1917         /* 1st focus on the data store */
1918         if (slu->slu_lu_size_valid) {
1919                 sl->sl_lu_size = slu->slu_lu_size;
1920         }
1921         ret = sbd_open_data_file(sl, err_ret, slu->slu_lu_size_valid, 0, 0);
1922         slu->slu_ret_filesize_nbits = sl->sl_data_fs_nbits;
1923         slu->slu_lu_size = sl->sl_lu_size;
1924         if (ret) {
1925                 goto scm_err_out;
1926         }
1927 
1928         /*
1929          * set write cache disable on the device
1930          * if it fails, we'll support it using sync/flush
1931          */
1932         if (slu->slu_writeback_cache_disable) {
1933                 (void) sbd_wcd_set(1, sl);
1934                 wcd = 1;
1935         /*
1936          * Attempt to set it to enable, if that fails and it was explicitly set
1937          * return an error, otherwise get the current setting and use that
1938          */
1939         } else {
1940                 sret = sbd_wcd_set(0, sl);
1941                 if (slu->slu_writeback_cache_disable_valid &&
1942                     sret != SBD_SUCCESS) {
1943                         *err_ret = SBD_RET_WRITE_CACHE_SET_FAILED;
1944                         ret = EFAULT;
1945                         goto scm_err_out;
1946                 }
1947                 if (sret != SBD_SUCCESS) {
1948                         sbd_wcd_get(&wcd, sl);
1949                 }
1950         }
1951 
1952         if (wcd) {
1953                 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
1954                     SL_SAVED_WRITE_CACHE_DISABLE;
1955         }
1956 
1957         if (sl->sl_flags & SL_SHARED_META) {
1958                 goto over_meta_open;
1959         }
1960         if (sl->sl_flags & SL_ZFS_META) {
1961                 if (sbd_create_zfs_meta_object(sl) != SBD_SUCCESS) {
1962                         *err_ret = SBD_RET_ZFS_META_CREATE_FAILED;
1963                         ret = ENOMEM;
1964                         goto scm_err_out;
1965                 }
1966                 sl->sl_meta_blocksize_shift = 0;
1967                 goto over_meta_create;
1968         }
1969         if ((ret = lookupname(sl->sl_meta_filename, UIO_SYSSPACE, FOLLOW,
1970             NULLVPP, &sl->sl_meta_vp)) != 0) {
1971                 *err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
1972                 goto scm_err_out;
1973         }
1974         sl->sl_meta_vtype = vt = sl->sl_meta_vp->v_type;
1975         VN_RELE(sl->sl_meta_vp);
1976         if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
1977                 *err_ret = SBD_RET_WRONG_META_FILE_TYPE;
1978                 ret = EINVAL;
1979                 goto scm_err_out;
1980         }
1981         if (vt == VREG) {
1982                 sl->sl_meta_blocksize_shift = 0;
1983         } else {
1984                 sl->sl_meta_blocksize_shift = 9;
1985         }
1986         flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1987         if ((ret = vn_open(sl->sl_meta_filename, UIO_SYSSPACE, flag, 0,
1988             &sl->sl_meta_vp, 0, 0)) != 0) {
1989                 *err_ret = SBD_RET_META_FILE_OPEN_FAILED;
1990                 goto scm_err_out;
1991         }
1992 over_meta_create:
1993         sl->sl_total_meta_size = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
1994         sl->sl_total_meta_size +=
1995             (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
1996         sl->sl_total_meta_size &=
1997             ~((((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1);
1998         sl->sl_meta_size_used = 0;
1999 over_meta_open:
2000         sl->sl_flags |= SL_META_OPENED;
2001 
2002         sl->sl_device_id[3] = 16;
2003         if (slu->slu_guid_valid) {
2004                 sl->sl_device_id[0] = 0xf1;
2005                 sl->sl_device_id[1] = 3;
2006                 sl->sl_device_id[2] = 0;
2007                 bcopy(slu->slu_guid, sl->sl_device_id + 4, 16);
2008         } else {
2009                 if (slu->slu_host_id_valid)
2010                         hid = slu->slu_host_id;
2011                 if (!slu->slu_company_id_valid)
2012                         slu->slu_company_id = COMPANY_ID_SUN;
2013                 if (stmf_scsilib_uniq_lu_id2(slu->slu_company_id, hid,
2014                     (scsi_devid_desc_t *)&sl->sl_device_id[0]) !=
2015                     STMF_SUCCESS) {
2016                         *err_ret = SBD_RET_META_CREATION_FAILED;
2017                         ret = EIO;
2018                         goto scm_err_out;
2019                 }
2020                 bcopy(sl->sl_device_id + 4, slu->slu_guid, 16);
2021         }
2022 
2023         /* Lets create the meta now */
2024         mutex_enter(&sl->sl_metadata_lock);
2025         if (sbd_write_meta_start(sl, sl->sl_total_meta_size,
2026             sizeof (sbd_meta_start_t)) != SBD_SUCCESS) {
2027                 mutex_exit(&sl->sl_metadata_lock);
2028                 *err_ret = SBD_RET_META_CREATION_FAILED;
2029                 ret = EIO;
2030                 goto scm_err_out;
2031         }
2032         mutex_exit(&sl->sl_metadata_lock);
2033         sl->sl_meta_size_used = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
2034 
2035         if (sbd_write_lu_info(sl) != SBD_SUCCESS) {
2036                 *err_ret = SBD_RET_META_CREATION_FAILED;
2037                 ret = EIO;
2038                 goto scm_err_out;
2039         }
2040 
2041         if (sbd_pgr_meta_init(sl) != SBD_SUCCESS) {
2042                 *err_ret = SBD_RET_META_CREATION_FAILED;
2043                 ret = EIO;
2044                 goto scm_err_out;
2045         }
2046 
2047         /*
2048          * Update the zvol separately as this need only be called upon
2049          * completion of the metadata initialization.
2050          */
2051         if (sl->sl_flags & SL_ZFS_META) {
2052                 if (sbd_update_zfs_prop(sl) != SBD_SUCCESS) {
2053                         *err_ret = SBD_RET_META_CREATION_FAILED;
2054                         ret = EIO;
2055                         goto scm_err_out;
2056                 }
2057         }
2058 
2059         ret = sbd_populate_and_register_lu(sl, err_ret);
2060         if (ret) {
2061                 goto scm_err_out;
2062         }
2063 
2064         sl->sl_trans_op = SL_OP_NONE;
2065         atomic_add_32(&sbd_lu_count, 1);
2066         return (0);
2067 
2068 scm_err_out:
2069         return (sbd_close_delete_lu(sl, ret));
2070 }
2071 
2072 stmf_status_t
2073 sbd_proxy_msg(uint8_t *luid, void *proxy_arg, uint32_t proxy_arg_len,
2074     uint32_t type)
2075 {
2076         switch (type) {
2077                 case STMF_MSG_LU_ACTIVE:
2078                         return (sbd_proxy_reg_lu(luid, proxy_arg,
2079                             proxy_arg_len));
2080                 case STMF_MSG_LU_REGISTER:
2081                         return (sbd_proxy_reg_lu(luid, proxy_arg,
2082                             proxy_arg_len));
2083                 case STMF_MSG_LU_DEREGISTER:
2084                         return (sbd_proxy_dereg_lu(luid, proxy_arg,
2085                             proxy_arg_len));
2086                 default:
2087                         return (STMF_INVALID_ARG);
2088         }
2089 }
2090 
2091 
2092 /*
2093  * register a standby logical unit
2094  * proxy_reg_arg contains the meta filename
2095  */
2096 stmf_status_t
2097 sbd_proxy_reg_lu(uint8_t *luid, void *proxy_reg_arg, uint32_t proxy_reg_arg_len)
2098 {
2099         sbd_lu_t *sl;
2100         sbd_status_t sret;
2101         sbd_create_standby_lu_t *stlu;
2102         int alloc_sz;
2103         uint32_t err_ret = 0;
2104         stmf_status_t stret = STMF_SUCCESS;
2105 
2106         if (luid == NULL) {
2107                 return (STMF_INVALID_ARG);
2108         }
2109 
2110         do {
2111                 sret = sbd_find_and_lock_lu(luid, NULL, SL_OP_MODIFY_LU, &sl);
2112         } while (sret == SBD_BUSY);
2113 
2114         if (sret == SBD_NOT_FOUND) {
2115                 alloc_sz = sizeof (*stlu) + proxy_reg_arg_len - 8;
2116                 stlu = (sbd_create_standby_lu_t *)kmem_zalloc(alloc_sz,
2117                     KM_SLEEP);
2118                 bcopy(luid, stlu->stlu_guid, 16);
2119                 if (proxy_reg_arg_len) {
2120                         bcopy(proxy_reg_arg, stlu->stlu_meta_fname,
2121                             proxy_reg_arg_len);
2122                         stlu->stlu_meta_fname_size = proxy_reg_arg_len;
2123                 }
2124                 if (sbd_create_standby_lu(stlu, &err_ret) != 0) {
2125                         cmn_err(CE_WARN,
2126                             "Unable to create standby logical unit for %s",
2127                             stlu->stlu_meta_fname);
2128                         stret = STMF_FAILURE;
2129                 }
2130                 kmem_free(stlu, alloc_sz);
2131                 return (stret);
2132         } else if (sret == SBD_SUCCESS) {
2133                 /*
2134                  * if the lu is already registered, then the lu should now
2135                  * be in standby mode
2136                  */
2137                 sbd_it_data_t *it;
2138                 if (sl->sl_access_state != SBD_LU_STANDBY) {
2139                         mutex_enter(&sl->sl_lock);
2140                         sl->sl_access_state = SBD_LU_STANDBY;
2141                         for (it = sl->sl_it_list; it != NULL;
2142                             it = it->sbd_it_next) {
2143                                 it->sbd_it_ua_conditions |=
2144                                     SBD_UA_ASYMMETRIC_ACCESS_CHANGED;
2145                                 it->sbd_it_flags &=
2146                                     ~SBD_IT_HAS_SCSI2_RESERVATION;
2147                                 sl->sl_flags &= ~SL_LU_HAS_SCSI2_RESERVATION;
2148                         }
2149                         mutex_exit(&sl->sl_lock);
2150                         sbd_pgr_reset(sl);
2151                 }
2152                 sl->sl_trans_op = SL_OP_NONE;
2153         } else {
2154                 cmn_err(CE_WARN, "could not find and lock logical unit");
2155                 stret = STMF_FAILURE;
2156         }
2157 out:
2158         return (stret);
2159 }
2160 
2161 /* ARGSUSED */
2162 stmf_status_t
2163 sbd_proxy_dereg_lu(uint8_t *luid, void *proxy_reg_arg,
2164     uint32_t proxy_reg_arg_len)
2165 {
2166         sbd_delete_lu_t dlu = {0};
2167         uint32_t err_ret;
2168 
2169         if (luid == NULL) {
2170                 cmn_err(CE_WARN, "de-register lu request had null luid");
2171                 return (STMF_INVALID_ARG);
2172         }
2173 
2174         bcopy(luid, &dlu.dlu_guid, 16);
2175 
2176         if (sbd_delete_lu(&dlu, (int)sizeof (dlu), &err_ret) != 0) {
2177                 cmn_err(CE_WARN, "failed to delete de-register lu request");
2178                 return (STMF_FAILURE);
2179         }
2180 
2181         return (STMF_SUCCESS);
2182 }
2183 
2184 int
2185 sbd_create_standby_lu(sbd_create_standby_lu_t *slu, uint32_t *err_ret)
2186 {
2187         sbd_lu_t *sl;
2188         stmf_lu_t *lu;
2189         int ret = EIO;
2190         int alloc_sz;
2191 
2192         alloc_sz = sizeof (sbd_lu_t) + sizeof (sbd_pgr_t) +
2193             slu->stlu_meta_fname_size;
2194         lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU, alloc_sz, 0);
2195         if (lu == NULL) {
2196                 return (ENOMEM);
2197         }
2198         sl = (sbd_lu_t *)lu->lu_provider_private;
2199         bzero(sl, alloc_sz);
2200         sl->sl_lu = lu;
2201         sl->sl_alloc_size = alloc_sz;
2202 
2203         sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
2204         sl->sl_meta_filename = ((char *)sl) + sizeof (sbd_lu_t) +
2205             sizeof (sbd_pgr_t);
2206 
2207         if (slu->stlu_meta_fname_size > 0) {
2208                 (void) strcpy(sl->sl_meta_filename, slu->stlu_meta_fname);
2209         }
2210         sl->sl_name = sl->sl_meta_filename;
2211 
2212         sl->sl_device_id[3] = 16;
2213         sl->sl_device_id[0] = 0xf1;
2214         sl->sl_device_id[1] = 3;
2215         sl->sl_device_id[2] = 0;
2216         bcopy(slu->stlu_guid, sl->sl_device_id + 4, 16);
2217         lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
2218         sl->sl_access_state = SBD_LU_STANDBY;
2219 
2220         rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
2221         mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
2222         mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL);
2223         rw_init(&sl->sl_access_state_lock, NULL, RW_DRIVER, NULL);
2224 
2225         sl->sl_trans_op = SL_OP_CREATE_REGISTER_LU;
2226 
2227         if (sbd_link_lu(sl) != SBD_SUCCESS) {
2228                 *err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
2229                 ret = EALREADY;
2230                 goto scs_err_out;
2231         }
2232 
2233         ret = sbd_populate_and_register_lu(sl, err_ret);
2234         if (ret) {
2235                 goto scs_err_out;
2236         }
2237 
2238         sl->sl_trans_op = SL_OP_NONE;
2239         atomic_add_32(&sbd_lu_count, 1);
2240         return (0);
2241 
2242 scs_err_out:
2243         return (sbd_close_delete_lu(sl, ret));
2244 }
2245 
2246 int
2247 sbd_load_sli_1_0(sbd_lu_t *sl, uint32_t *err_ret)
2248 {
2249         sbd_lu_info_1_0_t *sli = NULL;
2250         sbd_status_t sret;
2251 
2252         sret = sbd_read_meta_section(sl, (sm_section_hdr_t **)&sli,
2253             SMS_ID_LU_INFO_1_0);
2254 
2255         if (sret != SBD_SUCCESS) {
2256                 *err_ret = SBD_RET_NO_META;
2257                 return (EIO);
2258         }
2259         if (sli->sli_data_order != SMS_DATA_ORDER) {
2260                 sbd_swap_lu_info_1_0(sli);
2261                 if (sli->sli_data_order != SMS_DATA_ORDER) {
2262                         kmem_free(sli, sli->sli_sms_header.sms_size);
2263                         *err_ret = SBD_RET_NO_META;
2264                         return (EIO);
2265                 }
2266         }
2267 
2268         sl->sl_flags |= SL_SHARED_META;
2269         sl->sl_data_blocksize_shift = 9;
2270         sl->sl_data_offset = SHARED_META_DATA_SIZE;
2271         sl->sl_lu_size = sli->sli_total_store_size - SHARED_META_DATA_SIZE;
2272         sl->sl_total_data_size = SHARED_META_DATA_SIZE + sl->sl_lu_size;
2273         bcopy(sli->sli_lu_devid, sl->sl_device_id, 20);
2274 
2275         kmem_free(sli, sli->sli_sms_header.sms_size);
2276         return (0);
2277 }
2278 
2279 int
2280 sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret,
2281     int no_register, sbd_lu_t **slr)
2282 {
2283         stmf_lu_t *lu;
2284         sbd_lu_t *sl;
2285         sbd_lu_info_1_1_t *sli = NULL;
2286         int asz;
2287         int ret = 0;
2288         stmf_status_t stret;
2289         int flag;
2290         int wcd = 0;
2291         int data_opened;
2292         uint16_t sli_buf_sz;
2293         uint8_t *sli_buf_copy = NULL;
2294         enum vtype vt;
2295         int standby = 0;
2296         sbd_status_t sret;
2297 
2298         if (no_register && slr == NULL) {
2299                 return (EINVAL);
2300         }
2301         ilu->ilu_meta_fname[struct_sz - sizeof (*ilu) + 8 - 1] = 0;
2302         /*
2303          * check whether logical unit is already registered ALUA
2304          * For a standby logical unit, the meta filename is set. Use
2305          * that to search for an existing logical unit.
2306          */
2307         sret = sbd_find_and_lock_lu(NULL, (uint8_t *)&(ilu->ilu_meta_fname),
2308             SL_OP_IMPORT_LU, &sl);
2309 
2310         if (sret == SBD_SUCCESS) {
2311                 if (sl->sl_access_state != SBD_LU_ACTIVE) {
2312                         no_register = 1;
2313                         standby = 1;
2314                         lu = sl->sl_lu;
2315                         if (sl->sl_alias_alloc_size) {
2316                                 kmem_free(sl->sl_alias,
2317                                     sl->sl_alias_alloc_size);
2318                                 sl->sl_alias_alloc_size = 0;
2319                                 sl->sl_alias = NULL;
2320                                 lu->lu_alias = NULL;
2321                         }
2322                         if (sl->sl_meta_filename == NULL) {
2323                                 sl->sl_meta_filename = sl->sl_data_filename;
2324                         } else if (sl->sl_data_fname_alloc_size) {
2325                                 kmem_free(sl->sl_data_filename,
2326                                     sl->sl_data_fname_alloc_size);
2327                                 sl->sl_data_fname_alloc_size = 0;
2328                         }
2329                         if (sl->sl_serial_no_alloc_size) {
2330                                 kmem_free(sl->sl_serial_no,
2331                                     sl->sl_serial_no_alloc_size);
2332                                 sl->sl_serial_no_alloc_size = 0;
2333                         }
2334                         if (sl->sl_mgmt_url_alloc_size) {
2335                                 kmem_free(sl->sl_mgmt_url,
2336                                     sl->sl_mgmt_url_alloc_size);
2337                                 sl->sl_mgmt_url_alloc_size = 0;
2338                         }
2339                 } else {
2340                         *err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
2341                         bcopy(sl->sl_device_id + 4, ilu->ilu_ret_guid, 16);
2342                         sl->sl_trans_op = SL_OP_NONE;
2343                         return (EALREADY);
2344                 }
2345         } else if (sret == SBD_NOT_FOUND) {
2346                 asz = strlen(ilu->ilu_meta_fname) + 1;
2347 
2348                 lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU,
2349                     sizeof (sbd_lu_t) + sizeof (sbd_pgr_t) + asz, 0);
2350                 if (lu == NULL) {
2351                         return (ENOMEM);
2352                 }
2353                 sl = (sbd_lu_t *)lu->lu_provider_private;
2354                 bzero(sl, sizeof (*sl));
2355                 sl->sl_lu = lu;
2356                 sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
2357                 sl->sl_meta_filename = ((char *)sl) + sizeof (*sl) +
2358                     sizeof (sbd_pgr_t);
2359                 (void) strcpy(sl->sl_meta_filename, ilu->ilu_meta_fname);
2360                 sl->sl_name = sl->sl_meta_filename;
2361                 rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
2362                 rw_init(&sl->sl_access_state_lock, NULL, RW_DRIVER, NULL);
2363                 mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
2364                 mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL);
2365                 sl->sl_trans_op = SL_OP_IMPORT_LU;
2366         } else {
2367                 *err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
2368                 return (EIO);
2369         }
2370 
2371         /* we're only loading the metadata */
2372         if (!no_register) {
2373                 if (sbd_link_lu(sl) != SBD_SUCCESS) {
2374                         *err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
2375                         bcopy(sl->sl_device_id + 4, ilu->ilu_ret_guid, 16);
2376                         ret = EALREADY;
2377                         goto sim_err_out;
2378                 }
2379         }
2380         if ((ret = lookupname(sl->sl_meta_filename, UIO_SYSSPACE, FOLLOW,
2381             NULLVPP, &sl->sl_meta_vp)) != 0) {
2382                 *err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
2383                 goto sim_err_out;
2384         }
2385         if (sbd_is_zvol(sl->sl_meta_filename)) {
2386                 sl->sl_flags |= SL_ZFS_META;
2387                 sl->sl_data_filename = sl->sl_meta_filename;
2388         }
2389         sl->sl_meta_vtype = vt = sl->sl_meta_vp->v_type;
2390         VN_RELE(sl->sl_meta_vp);
2391         if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
2392                 *err_ret = SBD_RET_WRONG_META_FILE_TYPE;
2393                 ret = EINVAL;
2394                 goto sim_err_out;
2395         }
2396         if (sl->sl_flags & SL_ZFS_META) {
2397                 if (sbd_open_zfs_meta(sl) != SBD_SUCCESS) {
2398                         /* let see if metadata is in the 64k block */
2399                         sl->sl_flags &= ~SL_ZFS_META;
2400                 }
2401         }
2402         if (!(sl->sl_flags & SL_ZFS_META)) {
2403                 /* metadata is always writable */
2404                 flag = FREAD | FWRITE | FOFFMAX | FEXCL;
2405                 if ((ret = vn_open(sl->sl_meta_filename, UIO_SYSSPACE, flag, 0,
2406                     &sl->sl_meta_vp, 0, 0)) != 0) {
2407                         *err_ret = SBD_RET_META_FILE_OPEN_FAILED;
2408                         goto sim_err_out;
2409                 }
2410         }
2411         if ((sl->sl_flags & SL_ZFS_META) || (vt == VREG)) {
2412                 sl->sl_meta_blocksize_shift = 0;
2413         } else {
2414                 sl->sl_meta_blocksize_shift = 9;
2415         }
2416         sl->sl_meta_offset = (sl->sl_flags & SL_ZFS_META) ? 0 : SBD_META_OFFSET;
2417         sl->sl_flags |= SL_META_OPENED;
2418 
2419         mutex_enter(&sl->sl_metadata_lock);
2420         sret = sbd_load_meta_start(sl);
2421         mutex_exit(&sl->sl_metadata_lock);
2422         if (sret != SBD_SUCCESS) {
2423                 if (sret == SBD_META_CORRUPTED) {
2424                         *err_ret = SBD_RET_NO_META;
2425                 } else if (sret == SBD_NOT_SUPPORTED) {
2426                         *err_ret = SBD_RET_VERSION_NOT_SUPPORTED;
2427                 } else {
2428                         *err_ret = SBD_RET_NO_META;
2429                 }
2430                 ret = EINVAL;
2431                 goto sim_err_out;
2432         }
2433 
2434         /* Now lets see if we can read the most recent LU info */
2435         sret = sbd_read_meta_section(sl, (sm_section_hdr_t **)&sli,
2436             SMS_ID_LU_INFO_1_1);
2437         if ((sret == SBD_NOT_FOUND) && ((sl->sl_flags & SL_ZFS_META) == 0)) {
2438                 ret = sbd_load_sli_1_0(sl, err_ret);
2439                 if (ret) {
2440                         goto sim_err_out;
2441                 }
2442                 goto sim_sli_loaded;
2443         }
2444         if (sret != SBD_SUCCESS) {
2445                 *err_ret = SBD_RET_NO_META;
2446                 ret = EIO;
2447                 goto sim_err_out;
2448         }
2449         /* load sli 1.1 */
2450         if (sli->sli_data_order != SMS_DATA_ORDER) {
2451                 sbd_swap_lu_info_1_1(sli);
2452                 if (sli->sli_data_order != SMS_DATA_ORDER) {
2453                         *err_ret = SBD_RET_NO_META;
2454                         ret = EIO;
2455                         goto sim_err_out;
2456                 }
2457         }
2458 
2459         sli_buf_sz = sli->sli_sms_header.sms_size -
2460             sizeof (sbd_lu_info_1_1_t) + 8;
2461         sli_buf_copy = kmem_alloc(sli_buf_sz + 1, KM_SLEEP);
2462         bcopy(sli->sli_buf, sli_buf_copy, sli_buf_sz);
2463         sli_buf_copy[sli_buf_sz] = 0;
2464 
2465         /* Make sure all the offsets are within limits */
2466         if (((sli->sli_flags & SLI_META_FNAME_VALID) &&
2467             (sli->sli_meta_fname_offset > sli_buf_sz)) ||
2468             ((sli->sli_flags & SLI_DATA_FNAME_VALID) &&
2469             (sli->sli_data_fname_offset > sli_buf_sz)) ||
2470             ((sli->sli_flags & SLI_MGMT_URL_VALID) &&
2471             (sli->sli_mgmt_url_offset > sli_buf_sz)) ||
2472             ((sli->sli_flags & SLI_SERIAL_VALID) &&
2473             ((sli->sli_serial_offset + sli->sli_serial_size) > sli_buf_sz)) ||
2474             ((sli->sli_flags & SLI_ALIAS_VALID) &&
2475             (sli->sli_alias_offset > sli_buf_sz))) {
2476                 *err_ret = SBD_RET_NO_META;
2477                 ret = EIO;
2478                 goto sim_err_out;
2479         }
2480 
2481         sl->sl_lu_size = sli->sli_lu_size;
2482         sl->sl_data_blocksize_shift = sli->sli_data_blocksize_shift;
2483         bcopy(sli->sli_device_id, sl->sl_device_id, 20);
2484         if (sli->sli_flags & SLI_SERIAL_VALID) {
2485                 sl->sl_serial_no_size = sl->sl_serial_no_alloc_size =
2486                     sli->sli_serial_size;
2487                 sl->sl_serial_no = kmem_zalloc(sli->sli_serial_size, KM_SLEEP);
2488                 bcopy(sli_buf_copy + sli->sli_serial_offset, sl->sl_serial_no,
2489                     sl->sl_serial_no_size);
2490         }
2491         if (sli->sli_flags & SLI_SEPARATE_META) {
2492                 sl->sl_total_data_size = sl->sl_lu_size;
2493                 if (sli->sli_flags & SLI_DATA_FNAME_VALID) {
2494                         sl->sl_data_fname_alloc_size = strlen((char *)
2495                             sli_buf_copy + sli->sli_data_fname_offset) + 1;
2496                         sl->sl_data_filename = kmem_zalloc(
2497                             sl->sl_data_fname_alloc_size, KM_SLEEP);
2498                         (void) strcpy(sl->sl_data_filename,
2499                             (char *)sli_buf_copy + sli->sli_data_fname_offset);
2500                 }
2501         } else {
2502                 if (sl->sl_flags & SL_ZFS_META) {
2503                         sl->sl_total_data_size = sl->sl_lu_size;
2504                         sl->sl_data_offset = 0;
2505                 } else {
2506                         sl->sl_total_data_size =
2507                             sl->sl_lu_size + SHARED_META_DATA_SIZE;
2508                         sl->sl_data_offset = SHARED_META_DATA_SIZE;
2509                         sl->sl_flags |= SL_SHARED_META;
2510                 }
2511         }
2512         if (sli->sli_flags & SLI_ALIAS_VALID) {
2513                 sl->sl_alias_alloc_size = strlen((char *)sli_buf_copy +
2514                     sli->sli_alias_offset) + 1;
2515                 sl->sl_alias = kmem_alloc(sl->sl_alias_alloc_size, KM_SLEEP);
2516                 (void) strcpy(sl->sl_alias, (char *)sli_buf_copy +
2517                     sli->sli_alias_offset);
2518         }
2519         if (sli->sli_flags & SLI_MGMT_URL_VALID) {
2520                 sl->sl_mgmt_url_alloc_size = strlen((char *)sli_buf_copy +
2521                     sli->sli_mgmt_url_offset) + 1;
2522                 sl->sl_mgmt_url = kmem_alloc(sl->sl_mgmt_url_alloc_size,
2523                     KM_SLEEP);
2524                 (void) strcpy(sl->sl_mgmt_url, (char *)sli_buf_copy +
2525                     sli->sli_mgmt_url_offset);
2526         }
2527         if (sli->sli_flags & SLI_WRITE_PROTECTED) {
2528                 sl->sl_flags |= SL_WRITE_PROTECTED;
2529         }
2530         if (sli->sli_flags & SLI_VID_VALID) {
2531                 sl->sl_flags |= SL_VID_VALID;
2532                 bcopy(sli->sli_vid, sl->sl_vendor_id, 8);
2533         }
2534         if (sli->sli_flags & SLI_PID_VALID) {
2535                 sl->sl_flags |= SL_PID_VALID;
2536                 bcopy(sli->sli_pid, sl->sl_product_id, 16);
2537         }
2538         if (sli->sli_flags & SLI_REV_VALID) {
2539                 sl->sl_flags |= SL_REV_VALID;
2540                 bcopy(sli->sli_rev, sl->sl_revision, 4);
2541         }
2542         if (sli->sli_flags & SLI_WRITEBACK_CACHE_DISABLE) {
2543                 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE;
2544         }
2545 sim_sli_loaded:
2546         if ((sl->sl_flags & SL_SHARED_META) == 0) {
2547                 data_opened = 0;
2548         } else {
2549                 data_opened = 1;
2550                 sl->sl_data_filename = sl->sl_meta_filename;
2551                 sl->sl_data_vp = sl->sl_meta_vp;
2552                 sl->sl_data_vtype = sl->sl_meta_vtype;
2553         }
2554 
2555         sret = sbd_pgr_meta_load(sl);
2556         if (sret != SBD_SUCCESS) {
2557                 *err_ret = SBD_RET_NO_META;
2558                 ret = EIO;
2559                 goto sim_err_out;
2560         }
2561 
2562         ret = sbd_open_data_file(sl, err_ret, 1, data_opened, 0);
2563         if (ret) {
2564                 goto sim_err_out;
2565         }
2566 
2567         /*
2568          * set write cache disable on the device
2569          * Note: this shouldn't fail on import unless the cache capabilities
2570          * of the device changed. If that happened, modify will need to
2571          * be used to set the cache flag appropriately after import is done.
2572          */
2573         if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) {
2574                 (void) sbd_wcd_set(1, sl);
2575                 wcd = 1;
2576         /*
2577          * if not explicitly set, attempt to set it to enable, if that fails
2578          * get the current setting and use that
2579          */
2580         } else {
2581                 sret = sbd_wcd_set(0, sl);
2582                 if (sret != SBD_SUCCESS) {
2583                         sbd_wcd_get(&wcd, sl);
2584                 }
2585         }
2586 
2587         if (wcd) {
2588                 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
2589                     SL_SAVED_WRITE_CACHE_DISABLE;
2590         }
2591 
2592         /* we're only loading the metadata */
2593         if (!no_register) {
2594                 ret = sbd_populate_and_register_lu(sl, err_ret);
2595                 if (ret) {
2596                         goto sim_err_out;
2597                 }
2598                 atomic_add_32(&sbd_lu_count, 1);
2599         }
2600 
2601         bcopy(sl->sl_device_id + 4, ilu->ilu_ret_guid, 16);
2602         sl->sl_trans_op = SL_OP_NONE;
2603 
2604         if (sli) {
2605                 kmem_free(sli, sli->sli_sms_header.sms_size);
2606                 sli = NULL;
2607         }
2608         if (sli_buf_copy) {
2609                 kmem_free(sli_buf_copy, sli_buf_sz + 1);
2610                 sli_buf_copy = NULL;
2611         }
2612         if (no_register && !standby) {
2613                 *slr = sl;
2614         }
2615 
2616         /*
2617          * if this was imported from standby, set the access state
2618          * to active.
2619          */
2620         if (standby) {
2621                 sbd_it_data_t *it;
2622                 mutex_enter(&sl->sl_lock);
2623                 sl->sl_access_state = SBD_LU_ACTIVE;
2624                 for (it = sl->sl_it_list; it != NULL;
2625                     it = it->sbd_it_next) {
2626                         it->sbd_it_ua_conditions |=
2627                             SBD_UA_ASYMMETRIC_ACCESS_CHANGED;
2628                         it->sbd_it_ua_conditions |= SBD_UA_POR;
2629                         it->sbd_it_flags |=  SBD_IT_PGR_CHECK_FLAG;
2630                 }
2631                 mutex_exit(&sl->sl_lock);
2632                 /* call set access state */
2633                 stret = stmf_set_lu_access(lu, STMF_LU_ACTIVE);
2634                 if (stret != STMF_SUCCESS) {
2635                         *err_ret = SBD_RET_ACCESS_STATE_FAILED;
2636                         sl->sl_access_state = SBD_LU_STANDBY;
2637                         goto sim_err_out;
2638                 }
2639                 if (sl->sl_alias) {
2640                         lu->lu_alias = sl->sl_alias;
2641                 } else {
2642                         lu->lu_alias = sl->sl_name;
2643                 }
2644         }
2645         sl->sl_access_state = SBD_LU_ACTIVE;
2646         return (0);
2647 
2648 sim_err_out:
2649         if (sli) {
2650                 kmem_free(sli, sli->sli_sms_header.sms_size);
2651                 sli = NULL;
2652         }
2653         if (sli_buf_copy) {
2654                 kmem_free(sli_buf_copy, sli_buf_sz + 1);
2655                 sli_buf_copy = NULL;
2656         }
2657 
2658         if (standby) {
2659                 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
2660                 sl->sl_trans_op = SL_OP_NONE;
2661                 return (EIO);
2662         } else {
2663                 return (sbd_close_delete_lu(sl, ret));
2664         }
2665 }
2666 
2667 int
2668 sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret)
2669 {
2670         sbd_lu_t *sl = NULL;
2671         uint16_t alias_sz;
2672         int ret = 0;
2673         sbd_it_data_t *it;
2674         sbd_status_t sret;
2675         uint64_t old_size;
2676         int modify_unregistered = 0;
2677         int ua = 0;
2678         sbd_import_lu_t *ilu;
2679         stmf_lu_t *lu;
2680         uint32_t ilu_sz;
2681         uint32_t sz;
2682 
2683         sz = struct_sz - sizeof (*mlu) + 8 + 1;
2684 
2685         /* if there is data in the buf, null terminate it */
2686         if (struct_sz > sizeof (*mlu)) {
2687                 mlu->mlu_buf[struct_sz - sizeof (*mlu) + 8 - 1] = 0;
2688         }
2689 
2690         *err_ret = 0;
2691 
2692         /* Lets validate offsets */
2693         if (((mlu->mlu_alias_valid) &&
2694             (mlu->mlu_alias_off >= sz)) ||
2695             ((mlu->mlu_mgmt_url_valid) &&
2696             (mlu->mlu_mgmt_url_off >= sz)) ||
2697             (mlu->mlu_by_fname) &&
2698             (mlu->mlu_fname_off >= sz)) {
2699                 return (EINVAL);
2700         }
2701 
2702         /*
2703          * We'll look for the device but if we don't find it registered,
2704          * we'll still try to modify the unregistered device.
2705          */
2706         if (mlu->mlu_by_guid) {
2707                 sret = sbd_find_and_lock_lu(mlu->mlu_input_guid, NULL,
2708                     SL_OP_MODIFY_LU, &sl);
2709         } else if (mlu->mlu_by_fname) {
2710                 sret = sbd_find_and_lock_lu(NULL,
2711                     (uint8_t *)&(mlu->mlu_buf[mlu->mlu_fname_off]),
2712                     SL_OP_MODIFY_LU, &sl);
2713         } else {
2714                 return (EINVAL);
2715         }
2716 
2717 
2718         if (sret != SBD_SUCCESS) {
2719                 if (sret == SBD_BUSY) {
2720                         *err_ret = SBD_RET_LU_BUSY;
2721                         return (EBUSY);
2722                 } else if (sret != SBD_NOT_FOUND) {
2723                         return (EIO);
2724                 } else if (!mlu->mlu_by_fname) {
2725                         return (EINVAL);
2726                 }
2727                 /* Okay, try to import the device */
2728                 struct_sz = max(8, strlen(&(mlu->mlu_buf[mlu->mlu_fname_off]))
2729                     + 1);
2730                 struct_sz += sizeof (sbd_import_lu_t) - 8;
2731                 ilu_sz = struct_sz;
2732                 ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP);
2733                 ilu->ilu_struct_size = struct_sz;
2734                 (void) strcpy(ilu->ilu_meta_fname,
2735                     &(mlu->mlu_buf[mlu->mlu_fname_off]));
2736                 ret = sbd_import_lu(ilu, struct_sz, err_ret, 1, &sl);
2737                 kmem_free(ilu, ilu_sz);
2738                 if (ret != SBD_SUCCESS) {
2739                         return (ENOENT);
2740                 }
2741                 modify_unregistered = 1;
2742         }
2743 
2744         if (sl->sl_access_state != SBD_LU_ACTIVE) {
2745                 *err_ret = SBD_RET_ACCESS_STATE_FAILED;
2746                 ret = EINVAL;
2747                 goto smm_err_out;
2748         }
2749 
2750         /* check for write cache change */
2751         if (mlu->mlu_writeback_cache_disable_valid) {
2752                 /* set wce on device */
2753                 sret = sbd_wcd_set(mlu->mlu_writeback_cache_disable, sl);
2754                 if (!mlu->mlu_writeback_cache_disable && sret != SBD_SUCCESS) {
2755                         *err_ret = SBD_RET_WRITE_CACHE_SET_FAILED;
2756                         ret = EFAULT;
2757                         goto smm_err_out;
2758                 }
2759                 mutex_enter(&sl->sl_lock);
2760                 if (!mlu->mlu_writeback_cache_disable) {
2761                         if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) {
2762                                 ua = 1;
2763                                 sl->sl_flags &= ~SL_WRITEBACK_CACHE_DISABLE;
2764                                 sl->sl_flags &= ~SL_SAVED_WRITE_CACHE_DISABLE;
2765                         }
2766                 } else {
2767                         if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) == 0) {
2768                                 ua = 1;
2769                                 sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE;
2770                                 sl->sl_flags |= SL_SAVED_WRITE_CACHE_DISABLE;
2771                         }
2772                 }
2773                 for (it = sl->sl_it_list; ua && it != NULL;
2774                     it = it->sbd_it_next) {
2775                         it->sbd_it_ua_conditions |=
2776                             SBD_UA_MODE_PARAMETERS_CHANGED;
2777                 }
2778                 mutex_exit(&sl->sl_lock);
2779         }
2780         ua = 0;
2781 
2782         if (mlu->mlu_alias_valid) {
2783                 alias_sz = strlen((char *)mlu->mlu_buf +
2784                     mlu->mlu_alias_off) + 1;
2785                 /*
2786                  * Use the allocated buffer or alloc a new one.
2787                  * Don't copy into sl_alias if sl_alias_alloc_size is 0
2788                  * otherwise or you'll be writing over the data/metadata
2789                  * filename.
2790                  */
2791                 mutex_enter(&sl->sl_lock);
2792                 if (sl->sl_alias_alloc_size > 0 &&
2793                     sl->sl_alias_alloc_size < alias_sz) {
2794                         kmem_free(sl->sl_alias,
2795                             sl->sl_alias_alloc_size);
2796                         sl->sl_alias_alloc_size = 0;
2797                 }
2798                 if (sl->sl_alias_alloc_size == 0) {
2799                         sl->sl_alias = kmem_alloc(alias_sz, KM_SLEEP);
2800                         sl->sl_alias_alloc_size = alias_sz;
2801                 }
2802                 (void) strcpy(sl->sl_alias, (char *)mlu->mlu_buf +
2803                     mlu->mlu_alias_off);
2804                 lu = sl->sl_lu;
2805                 lu->lu_alias = sl->sl_alias;
2806                 mutex_exit(&sl->sl_lock);
2807         }
2808 
2809         if (mlu->mlu_mgmt_url_valid) {
2810                 uint16_t url_sz;
2811 
2812                 url_sz = strlen((char *)mlu->mlu_buf + mlu->mlu_mgmt_url_off);
2813                 if (url_sz > 0)
2814                         url_sz++;
2815 
2816                 mutex_enter(&sl->sl_lock);
2817                 if (sl->sl_mgmt_url_alloc_size > 0 &&
2818                     (url_sz == 0 || sl->sl_mgmt_url_alloc_size < url_sz)) {
2819                         kmem_free(sl->sl_mgmt_url, sl->sl_mgmt_url_alloc_size);
2820                         sl->sl_mgmt_url = NULL;
2821                         sl->sl_mgmt_url_alloc_size = 0;
2822                 }
2823                 if (url_sz > 0) {
2824                         if (sl->sl_mgmt_url_alloc_size == 0) {
2825                                 sl->sl_mgmt_url = kmem_alloc(url_sz, KM_SLEEP);
2826                                 sl->sl_mgmt_url_alloc_size = url_sz;
2827                         }
2828                         (void) strcpy(sl->sl_mgmt_url, (char *)mlu->mlu_buf +
2829                             mlu->mlu_mgmt_url_off);
2830                 }
2831                 for (it = sl->sl_it_list; it != NULL;
2832                     it = it->sbd_it_next) {
2833                         it->sbd_it_ua_conditions |=
2834                             SBD_UA_MODE_PARAMETERS_CHANGED;
2835                 }
2836                 mutex_exit(&sl->sl_lock);
2837         }
2838 
2839         if (mlu->mlu_write_protected_valid) {
2840                 mutex_enter(&sl->sl_lock);
2841                 if (mlu->mlu_write_protected) {
2842                         if ((sl->sl_flags & SL_WRITE_PROTECTED) == 0) {
2843                                 ua = 1;
2844                                 sl->sl_flags |= SL_WRITE_PROTECTED;
2845                         }
2846                 } else {
2847                         if (sl->sl_flags & SL_WRITE_PROTECTED) {
2848                                 ua = 1;
2849                                 sl->sl_flags &= ~SL_WRITE_PROTECTED;
2850                         }
2851                 }
2852                 for (it = sl->sl_it_list; ua && it != NULL;
2853                     it = it->sbd_it_next) {
2854                         it->sbd_it_ua_conditions |=
2855                             SBD_UA_MODE_PARAMETERS_CHANGED;
2856                 }
2857                 mutex_exit(&sl->sl_lock);
2858         }
2859 
2860         if (mlu->mlu_lu_size_valid) {
2861                 /*
2862                  * validate lu size and set
2863                  * For open file only (registered lu)
2864                  */
2865                 mutex_enter(&sl->sl_lock);
2866                 old_size = sl->sl_lu_size;
2867                 sl->sl_lu_size = mlu->mlu_lu_size;
2868                 mutex_exit(&sl->sl_lock);
2869                 ret = sbd_open_data_file(sl, err_ret, 1, 1, 1);
2870                 if (ret) {
2871                         mutex_enter(&sl->sl_lock);
2872                         sl->sl_lu_size = old_size;
2873                         mutex_exit(&sl->sl_lock);
2874                         goto smm_err_out;
2875                 }
2876                 if (old_size != mlu->mlu_lu_size) {
2877                         mutex_enter(&sl->sl_lock);
2878                         for (it = sl->sl_it_list; it != NULL;
2879                             it = it->sbd_it_next) {
2880                                 it->sbd_it_ua_conditions |=
2881                                     SBD_UA_CAPACITY_CHANGED;
2882                         }
2883                         mutex_exit(&sl->sl_lock);
2884                 }
2885         }
2886 
2887         if (sbd_write_lu_info(sl) != SBD_SUCCESS) {
2888                 *err_ret = SBD_RET_META_CREATION_FAILED;
2889                 ret = EIO;
2890         }
2891 
2892 smm_err_out:
2893         if (modify_unregistered) {
2894                 (void) sbd_close_delete_lu(sl, 0);
2895         } else {
2896                 sl->sl_trans_op = SL_OP_NONE;
2897         }
2898         return (ret);
2899 }
2900 
2901 int
2902 sbd_set_global_props(sbd_global_props_t *mlu, int struct_sz,
2903     uint32_t *err_ret)
2904 {
2905         sbd_lu_t *sl = NULL;
2906         int ret = 0;
2907         sbd_it_data_t *it;
2908         uint32_t sz;
2909 
2910         sz = struct_sz - sizeof (*mlu) + 8 + 1;
2911 
2912         /* if there is data in the buf, null terminate it */
2913         if (struct_sz > sizeof (*mlu)) {
2914                 mlu->mlu_buf[struct_sz - sizeof (*mlu) + 8 - 1] = 0;
2915         }
2916 
2917         *err_ret = 0;
2918 
2919         /* Lets validate offsets */
2920         if (((mlu->mlu_mgmt_url_valid) &&
2921             (mlu->mlu_mgmt_url_off >= sz))) {
2922                 return (EINVAL);
2923         }
2924 
2925         if (mlu->mlu_mgmt_url_valid) {
2926                 uint16_t url_sz;
2927 
2928                 url_sz = strlen((char *)mlu->mlu_buf + mlu->mlu_mgmt_url_off);
2929                 if (url_sz > 0)
2930                         url_sz++;
2931 
2932                 rw_enter(&sbd_global_prop_lock, RW_WRITER);
2933                 if (sbd_mgmt_url_alloc_size > 0 &&
2934                     (url_sz == 0 || sbd_mgmt_url_alloc_size < url_sz)) {
2935                         kmem_free(sbd_mgmt_url, sbd_mgmt_url_alloc_size);
2936                         sbd_mgmt_url = NULL;
2937                         sbd_mgmt_url_alloc_size = 0;
2938                 }
2939                 if (url_sz > 0) {
2940                         if (sbd_mgmt_url_alloc_size == 0) {
2941                                 sbd_mgmt_url = kmem_alloc(url_sz, KM_SLEEP);
2942                                 sbd_mgmt_url_alloc_size = url_sz;
2943                         }
2944                         (void) strcpy(sbd_mgmt_url, (char *)mlu->mlu_buf +
2945                             mlu->mlu_mgmt_url_off);
2946                 }
2947                 /*
2948                  * check each lu to determine whether a UA is needed.
2949                  */
2950                 mutex_enter(&sbd_lock);
2951                 for (sl = sbd_lu_list; sl; sl = sl->sl_next) {
2952                         if (sl->sl_mgmt_url) {
2953                                 continue;
2954                         }
2955                         mutex_enter(&sl->sl_lock);
2956                         for (it = sl->sl_it_list; it != NULL;
2957                             it = it->sbd_it_next) {
2958                                 it->sbd_it_ua_conditions |=
2959                                     SBD_UA_MODE_PARAMETERS_CHANGED;
2960                         }
2961                         mutex_exit(&sl->sl_lock);
2962                 }
2963                 mutex_exit(&sbd_lock);
2964                 rw_exit(&sbd_global_prop_lock);
2965         }
2966         return (ret);
2967 }
2968 
2969 /* ARGSUSED */
2970 int
2971 sbd_delete_locked_lu(sbd_lu_t *sl, uint32_t *err_ret,
2972     stmf_state_change_info_t *ssi)
2973 {
2974         int i;
2975         stmf_status_t ret;
2976 
2977         if ((sl->sl_state == STMF_STATE_OFFLINE) &&
2978             !sl->sl_state_not_acked) {
2979                 goto sdl_do_dereg;
2980         }
2981 
2982         if ((sl->sl_state != STMF_STATE_ONLINE) ||
2983             sl->sl_state_not_acked) {
2984                 return (EBUSY);
2985         }
2986 
2987         ret = stmf_ctl(STMF_CMD_LU_OFFLINE, sl->sl_lu, ssi);
2988         if ((ret != STMF_SUCCESS) && (ret != STMF_ALREADY)) {
2989                 return (EBUSY);
2990         }
2991 
2992         for (i = 0; i < 500; i++) {
2993                 if ((sl->sl_state == STMF_STATE_OFFLINE) &&
2994                     !sl->sl_state_not_acked) {
2995                         goto sdl_do_dereg;
2996                 }
2997                 delay(drv_usectohz(10000));
2998         }
2999         return (EBUSY);
3000 
3001 sdl_do_dereg:;
3002         if (stmf_deregister_lu(sl->sl_lu) != STMF_SUCCESS)
3003                 return (EBUSY);
3004         atomic_add_32(&sbd_lu_count, -1);
3005 
3006         return (sbd_close_delete_lu(sl, 0));
3007 }
3008 
3009 int
3010 sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret)
3011 {
3012         sbd_lu_t *sl;
3013         sbd_status_t sret;
3014         stmf_state_change_info_t ssi;
3015         int ret;
3016 
3017         if (dlu->dlu_by_meta_name) {
3018                 ((char *)dlu)[struct_sz - 1] = 0;
3019                 sret = sbd_find_and_lock_lu(NULL, dlu->dlu_meta_name,
3020                     SL_OP_DELETE_LU, &sl);
3021         } else {
3022                 sret = sbd_find_and_lock_lu(dlu->dlu_guid, NULL,
3023                     SL_OP_DELETE_LU, &sl);
3024         }
3025         if (sret != SBD_SUCCESS) {
3026                 if (sret == SBD_BUSY) {
3027                         *err_ret = SBD_RET_LU_BUSY;
3028                         return (EBUSY);
3029                 } else if (sret == SBD_NOT_FOUND) {
3030                         *err_ret = SBD_RET_NOT_FOUND;
3031                         return (ENOENT);
3032                 }
3033                 return (EIO);
3034         }
3035 
3036         ssi.st_rflags = STMF_RFLAG_USER_REQUEST;
3037         ssi.st_additional_info = "sbd_delete_lu call (ioctl)";
3038         ret = sbd_delete_locked_lu(sl, err_ret, &ssi);
3039 
3040         if (ret) {
3041                 /* Once its locked, no need to grab mutex again */
3042                 sl->sl_trans_op = SL_OP_NONE;
3043         }
3044         return (ret);
3045 }
3046 
3047 sbd_status_t
3048 sbd_data_read(sbd_lu_t *sl, struct scsi_task *task,
3049     uint64_t offset, uint64_t size, uint8_t *buf)
3050 {
3051         int ret;
3052         long resid;
3053         hrtime_t xfer_start, xfer_done;
3054 
3055         if ((offset + size) > sl->sl_lu_size) {
3056                 return (SBD_IO_PAST_EOF);
3057         }
3058 
3059         offset += sl->sl_data_offset;
3060 
3061         if ((offset + size) > sl->sl_data_readable_size) {
3062                 uint64_t store_end;
3063                 if (offset > sl->sl_data_readable_size) {
3064                         bzero(buf, size);
3065                         return (SBD_SUCCESS);
3066                 }
3067                 store_end = sl->sl_data_readable_size - offset;
3068                 bzero(buf + store_end, size - store_end);
3069                 size = store_end;
3070         }
3071 
3072         xfer_start = gethrtime();
3073         stmf_lu_xfer_start(task);
3074         DTRACE_PROBE5(backing__store__read__start, sbd_lu_t *, sl,
3075             uint8_t *, buf, uint64_t, size, uint64_t, offset,
3076             scsi_task_t *, task);
3077 
3078         /*
3079          * Don't proceed if the device has been closed
3080          * This can occur on an access state change to standby or
3081          * a delete. The writer lock is acquired before closing the
3082          * lu.
3083          */
3084         rw_enter(&sl->sl_access_state_lock, RW_READER);
3085         if ((sl->sl_flags & SL_MEDIA_LOADED) == 0) {
3086                 rw_exit(&sl->sl_access_state_lock);
3087                 return (SBD_FAILURE);
3088         }
3089         ret = vn_rdwr(UIO_READ, sl->sl_data_vp, (caddr_t)buf, (ssize_t)size,
3090             (offset_t)offset, UIO_SYSSPACE, 0, RLIM64_INFINITY, CRED(),
3091             &resid);
3092         rw_exit(&sl->sl_access_state_lock);
3093 
3094         xfer_done = gethrtime() - xfer_start;
3095         stmf_lu_xfer_done(task, B_TRUE /* read */, size, xfer_done);
3096         DTRACE_PROBE6(backing__store__read__end, sbd_lu_t *, sl,
3097             uint8_t *, buf, uint64_t, size, uint64_t, offset,
3098             int, ret, scsi_task_t *, task);
3099 
3100 over_sl_data_read:
3101         if (ret || resid) {
3102                 stmf_trace(0, "UIO_READ failed, ret = %d, resid = %d", ret,
3103                     resid);
3104                 return (SBD_FAILURE);
3105         }
3106 
3107         return (SBD_SUCCESS);
3108 }
3109 
3110 sbd_status_t
3111 sbd_data_write(sbd_lu_t *sl, struct scsi_task *task,
3112     uint64_t offset, uint64_t size, uint8_t *buf)
3113 {
3114         int ret;
3115         long resid;
3116         sbd_status_t sret = SBD_SUCCESS;
3117         int ioflag;
3118         hrtime_t xfer_start, xfer_done;
3119 
3120         if ((offset + size) > sl->sl_lu_size) {
3121                 return (SBD_IO_PAST_EOF);
3122         }
3123 
3124         offset += sl->sl_data_offset;
3125 
3126         if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) &&
3127             (sl->sl_flags & SL_FLUSH_ON_DISABLED_WRITECACHE)) {
3128                 ioflag = FSYNC;
3129         } else {
3130                 ioflag = 0;
3131         }
3132 
3133         xfer_start = gethrtime();
3134         stmf_lu_xfer_start(task);
3135         DTRACE_PROBE5(backing__store__write__start, sbd_lu_t *, sl,
3136             uint8_t *, buf, uint64_t, size, uint64_t, offset,
3137             scsi_task_t *, task);
3138 
3139         /*
3140          * Don't proceed if the device has been closed
3141          * This can occur on an access state change to standby or
3142          * a delete. The writer lock is acquired before closing the
3143          * lu.
3144          */
3145         rw_enter(&sl->sl_access_state_lock, RW_READER);
3146         if ((sl->sl_flags & SL_MEDIA_LOADED) == 0) {
3147                 rw_exit(&sl->sl_access_state_lock);
3148                 return (SBD_FAILURE);
3149         }
3150         ret = vn_rdwr(UIO_WRITE, sl->sl_data_vp, (caddr_t)buf, (ssize_t)size,
3151             (offset_t)offset, UIO_SYSSPACE, ioflag, RLIM64_INFINITY, CRED(),
3152             &resid);
3153         rw_exit(&sl->sl_access_state_lock);
3154 
3155         xfer_done = gethrtime() - xfer_start;
3156         stmf_lu_xfer_done(task, B_FALSE /* write */, size, xfer_done);
3157         DTRACE_PROBE6(backing__store__write__end, sbd_lu_t *, sl,
3158             uint8_t *, buf, uint64_t, size, uint64_t, offset,
3159             int, ret, scsi_task_t *, task);
3160 
3161         if ((ret == 0) && (resid == 0) &&
3162             (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) &&
3163             (sl->sl_flags & SL_FLUSH_ON_DISABLED_WRITECACHE)) {
3164                 sret = sbd_flush_data_cache(sl, 1);
3165         }
3166 over_sl_data_write:
3167 
3168         if ((ret || resid) || (sret != SBD_SUCCESS)) {
3169                 return (SBD_FAILURE);
3170         } else if ((offset + size) > sl->sl_data_readable_size) {
3171                 uint64_t old_size, new_size;
3172 
3173                 do {
3174                         old_size = sl->sl_data_readable_size;
3175                         if ((offset + size) <= old_size)
3176                                 break;
3177                         new_size = offset + size;
3178                 } while (atomic_cas_64(&sl->sl_data_readable_size, old_size,
3179                     new_size) != old_size);
3180         }
3181 
3182         return (SBD_SUCCESS);
3183 }
3184 
3185 int
3186 sbd_get_global_props(sbd_global_props_t *oslp, uint32_t oslp_sz,
3187     uint32_t *err_ret)
3188 {
3189         uint32_t sz = 0;
3190         uint16_t off;
3191 
3192         rw_enter(&sbd_global_prop_lock, RW_READER);
3193         if (sbd_mgmt_url) {
3194                 sz += strlen(sbd_mgmt_url) + 1;
3195         }
3196         bzero(oslp, sizeof (*oslp) - 8);
3197         oslp->mlu_buf_size_needed = sz;
3198 
3199         if (sz > (oslp_sz - sizeof (*oslp) + 8)) {
3200                 *err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE;
3201                 rw_exit(&sbd_global_prop_lock);
3202                 return (ENOMEM);
3203         }
3204 
3205         off = 0;
3206         if (sbd_mgmt_url) {
3207                 oslp->mlu_mgmt_url_valid = 1;
3208                 oslp->mlu_mgmt_url_off = off;
3209                 (void) strcpy((char *)&oslp->mlu_buf[off], sbd_mgmt_url);
3210                 off += strlen(sbd_mgmt_url) + 1;
3211         }
3212 
3213         rw_exit(&sbd_global_prop_lock);
3214         return (0);
3215 }
3216 
3217 static int
3218 sbd_get_unmap_props(sbd_unmap_props_t *sup,
3219     sbd_unmap_props_t *osup, uint32_t *err_ret)
3220 {
3221         sbd_status_t sret;
3222         sbd_lu_t *sl = NULL;
3223 
3224         if (sup->sup_guid_valid) {
3225                 sret = sbd_find_and_lock_lu(sup->sup_guid,
3226                     NULL, SL_OP_LU_PROPS, &sl);
3227         } else {
3228                 sret = sbd_find_and_lock_lu(NULL,
3229                     (uint8_t *)sup->sup_zvol_path, SL_OP_LU_PROPS,
3230                     &sl);
3231         }
3232         if (sret != SBD_SUCCESS) {
3233                 if (sret == SBD_BUSY) {
3234                         *err_ret = SBD_RET_LU_BUSY;
3235                         return (EBUSY);
3236                 } else if (sret == SBD_NOT_FOUND) {
3237                         *err_ret = SBD_RET_NOT_FOUND;
3238                         return (ENOENT);
3239                 }
3240                 return (EIO);
3241         }
3242 
3243         sup->sup_found_lu = 1;
3244         sup->sup_guid_valid = 1;
3245         bcopy(sl->sl_device_id + 4, sup->sup_guid, 16);
3246         if (sl->sl_flags & SL_UNMAP_ENABLED)
3247                 sup->sup_unmap_enabled = 1;
3248         else
3249                 sup->sup_unmap_enabled = 0;
3250 
3251         *osup = *sup;
3252         sl->sl_trans_op = SL_OP_NONE;
3253 
3254         return (0);
3255 }
3256 
3257 int
3258 sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
3259     sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret)
3260 {
3261         sbd_status_t sret;
3262         sbd_lu_t *sl = NULL;
3263         uint32_t sz;
3264         uint16_t off;
3265 
3266         if (islp->slp_input_guid) {
3267                 sret = sbd_find_and_lock_lu(islp->slp_guid, NULL,
3268                     SL_OP_LU_PROPS, &sl);
3269         } else {
3270                 ((char *)islp)[islp_sz - 1] = 0;
3271                 sret = sbd_find_and_lock_lu(NULL, islp->slp_buf,
3272                     SL_OP_LU_PROPS, &sl);
3273         }
3274         if (sret != SBD_SUCCESS) {
3275                 if (sret == SBD_BUSY) {
3276                         *err_ret = SBD_RET_LU_BUSY;
3277                         return (EBUSY);
3278                 } else if (sret == SBD_NOT_FOUND) {
3279                         *err_ret = SBD_RET_NOT_FOUND;
3280                         return (ENOENT);
3281                 }
3282                 return (EIO);
3283         }
3284 
3285         sz = strlen(sl->sl_name) + 1;
3286         if ((sl->sl_flags & (SL_ZFS_META | SL_SHARED_META)) == 0) {
3287                 if (sl->sl_data_filename) {
3288                         sz += strlen(sl->sl_data_filename) + 1;
3289                 }
3290         }
3291         sz += sl->sl_serial_no_size;
3292         if (sl->sl_alias) {
3293                 sz += strlen(sl->sl_alias) + 1;
3294         }
3295 
3296         rw_enter(&sbd_global_prop_lock, RW_READER);
3297         if (sl->sl_mgmt_url) {
3298                 sz += strlen(sl->sl_mgmt_url) + 1;
3299         } else if (sbd_mgmt_url) {
3300                 sz += strlen(sbd_mgmt_url) + 1;
3301         }
3302         bzero(oslp, sizeof (*oslp) - 8);
3303         oslp->slp_buf_size_needed = sz;
3304 
3305         if (sz > (oslp_sz - sizeof (*oslp) + 8)) {
3306                 sl->sl_trans_op = SL_OP_NONE;
3307                 *err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE;
3308                 rw_exit(&sbd_global_prop_lock);
3309                 return (ENOMEM);
3310         }
3311 
3312         off = 0;
3313         (void) strcpy((char *)oslp->slp_buf, sl->sl_name);
3314         oslp->slp_meta_fname_off = off;
3315         off += strlen(sl->sl_name) + 1;
3316         if ((sl->sl_flags & (SL_ZFS_META | SL_SHARED_META)) == 0) {
3317                 oslp->slp_meta_fname_valid = 1;
3318                 oslp->slp_separate_meta = 1;
3319                 if (sl->sl_data_filename) {
3320                         oslp->slp_data_fname_valid = 1;
3321                         oslp->slp_data_fname_off = off;
3322                         (void) strcpy((char *)&oslp->slp_buf[off],
3323                             sl->sl_data_filename);
3324                         off += strlen(sl->sl_data_filename) + 1;
3325                 }
3326         } else {
3327                 oslp->slp_data_fname_valid = 1;
3328                 oslp->slp_data_fname_off = oslp->slp_meta_fname_off;
3329                 if (sl->sl_flags & SL_ZFS_META) {
3330                         oslp->slp_zfs_meta = 1;
3331                 }
3332         }
3333         if (sl->sl_alias) {
3334                 oslp->slp_alias_valid = 1;
3335                 oslp->slp_alias_off = off;
3336                 (void) strcpy((char *)&oslp->slp_buf[off], sl->sl_alias);
3337                 off += strlen(sl->sl_alias) + 1;
3338         }
3339         if (sl->sl_mgmt_url) {
3340                 oslp->slp_mgmt_url_valid = 1;
3341                 oslp->slp_mgmt_url_off = off;
3342                 (void) strcpy((char *)&oslp->slp_buf[off], sl->sl_mgmt_url);
3343                 off += strlen(sl->sl_mgmt_url) + 1;
3344         } else if (sbd_mgmt_url) {
3345                 oslp->slp_mgmt_url_valid = 1;
3346                 oslp->slp_mgmt_url_off = off;
3347                 (void) strcpy((char *)&oslp->slp_buf[off], sbd_mgmt_url);
3348                 off += strlen(sbd_mgmt_url) + 1;
3349         }
3350         if (sl->sl_serial_no_size) {
3351                 oslp->slp_serial_off = off;
3352                 bcopy(sl->sl_serial_no, &oslp->slp_buf[off],
3353                     sl->sl_serial_no_size);
3354                 oslp->slp_serial_size = sl->sl_serial_no_size;
3355                 oslp->slp_serial_valid = 1;
3356                 off += sl->sl_serial_no_size;
3357         }
3358 
3359         oslp->slp_lu_size = sl->sl_lu_size;
3360         oslp->slp_blksize = ((uint16_t)1) << sl->sl_data_blocksize_shift;
3361 
3362         oslp->slp_access_state = sl->sl_access_state;
3363 
3364         if (sl->sl_flags & SL_VID_VALID) {
3365                 oslp->slp_lu_vid = 1;
3366                 bcopy(sl->sl_vendor_id, oslp->slp_vid, 8);
3367         } else {
3368                 bcopy(sbd_vendor_id, oslp->slp_vid, 8);
3369         }
3370         if (sl->sl_flags & SL_PID_VALID) {
3371                 oslp->slp_lu_pid = 1;
3372                 bcopy(sl->sl_product_id, oslp->slp_pid, 16);
3373         } else {
3374                 bcopy(sbd_product_id, oslp->slp_pid, 16);
3375         }
3376         if (sl->sl_flags & SL_REV_VALID) {
3377                 oslp->slp_lu_rev = 1;
3378                 bcopy(sl->sl_revision, oslp->slp_rev, 4);
3379         } else {
3380                 bcopy(sbd_revision, oslp->slp_rev, 4);
3381         }
3382         bcopy(sl->sl_device_id + 4, oslp->slp_guid, 16);
3383 
3384         if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE)
3385                 oslp->slp_writeback_cache_disable_cur = 1;
3386         if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE)
3387                 oslp->slp_writeback_cache_disable_saved = 1;
3388         if (sl->sl_flags & SL_WRITE_PROTECTED)
3389                 oslp->slp_write_protected = 1;
3390 
3391         sl->sl_trans_op = SL_OP_NONE;
3392 
3393         rw_exit(&sbd_global_prop_lock);
3394         return (0);
3395 }
3396 
3397 char *
3398 sbd_get_zvol_name(sbd_lu_t *sl)
3399 {
3400         char *src;
3401         char *p;
3402 
3403         if (sl->sl_data_filename)
3404                 src = sl->sl_data_filename;
3405         else
3406                 src = sl->sl_meta_filename;
3407         /* There has to be a better way */
3408         if (SBD_IS_ZVOL(src) != 0) {
3409                 ASSERT(0);
3410         }
3411         src += 14;
3412         if (*src == '/')
3413                 src++;
3414         p = (char *)kmem_alloc(strlen(src) + 1, KM_SLEEP);
3415         (void) strcpy(p, src);
3416         return (p);
3417 }
3418 
3419 /*
3420  * this function creates a local metadata zvol property
3421  */
3422 sbd_status_t
3423 sbd_create_zfs_meta_object(sbd_lu_t *sl)
3424 {
3425         /*
3426          * -allocate 1/2 the property size, the zfs property
3427          *  is 8k in size and stored as ascii hex string, all
3428          *  we needed is 4k buffer to store the binary data.
3429          * -initialize reader/write lock
3430          */
3431         if ((sl->sl_zfs_meta = kmem_zalloc(ZAP_MAXVALUELEN / 2, KM_SLEEP))
3432             == NULL)
3433                 return (SBD_FAILURE);
3434         rw_init(&sl->sl_zfs_meta_lock, NULL, RW_DRIVER, NULL);
3435         return (SBD_SUCCESS);
3436 }
3437 
3438 char
3439 sbd_ctoi(char c)
3440 {
3441         if ((c >= '0') && (c <= '9'))
3442                 c -= '0';
3443         else if ((c >= 'A') && (c <= 'F'))
3444                 c = c - 'A' + 10;
3445         else if ((c >= 'a') && (c <= 'f'))
3446                 c = c - 'a' + 10;
3447         else
3448                 c = -1;
3449         return (c);
3450 }
3451 
3452 /*
3453  * read zvol property and convert to binary
3454  */
3455 sbd_status_t
3456 sbd_open_zfs_meta(sbd_lu_t *sl)
3457 {
3458         char            *meta = NULL, cl, ch;
3459         int             i;
3460         char            *tmp, *ptr;
3461         uint64_t        rc = SBD_SUCCESS;
3462         int             len;
3463         char            *file;
3464 
3465         if (sl->sl_zfs_meta == NULL) {
3466                 if (sbd_create_zfs_meta_object(sl) == SBD_FAILURE)
3467                         return (SBD_FAILURE);
3468         } else {
3469                 bzero(sl->sl_zfs_meta, (ZAP_MAXVALUELEN / 2));
3470         }
3471 
3472         rw_enter(&sl->sl_zfs_meta_lock, RW_WRITER);
3473         file = sbd_get_zvol_name(sl);
3474         if (sbd_zvolget(file, &meta)) {
3475                 rc = SBD_FAILURE;
3476                 goto done;
3477         }
3478         tmp = meta;
3479         /* convert ascii hex to binary meta */
3480         len = strlen(meta);
3481         ptr = sl->sl_zfs_meta;
3482         for (i = 0; i < len; i += 2) {
3483                 ch = sbd_ctoi(*tmp++);
3484                 cl = sbd_ctoi(*tmp++);
3485                 if (ch == -1 || cl == -1) {
3486                         rc = SBD_FAILURE;
3487                         break;
3488                 }
3489                 *ptr++ = (ch << 4) + cl;
3490         }
3491 done:
3492         rw_exit(&sl->sl_zfs_meta_lock);
3493         if (meta)
3494                 kmem_free(meta, len + 1);
3495         kmem_free(file, strlen(file) + 1);
3496         return (rc);
3497 }
3498 
3499 sbd_status_t
3500 sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, uint64_t off)
3501 {
3502         ASSERT(sl->sl_zfs_meta);
3503         rw_enter(&sl->sl_zfs_meta_lock, RW_READER);
3504         bcopy(&sl->sl_zfs_meta[off], buf, sz);
3505         rw_exit(&sl->sl_zfs_meta_lock);
3506         return (SBD_SUCCESS);
3507 }
3508 
3509 sbd_status_t
3510 sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, uint64_t off)
3511 {
3512         ASSERT(sl->sl_zfs_meta);
3513         if ((off + sz) > (ZAP_MAXVALUELEN / 2 - 1)) {
3514                 return (SBD_META_CORRUPTED);
3515         }
3516         if ((off + sz) > sl->sl_meta_size_used) {
3517                 sl->sl_meta_size_used = off + sz;
3518                 if (sl->sl_total_meta_size < sl->sl_meta_size_used) {
3519                         uint64_t meta_align =
3520                             (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
3521                         sl->sl_total_meta_size = (sl->sl_meta_size_used +
3522                             meta_align) & (~meta_align);
3523                 }
3524         }
3525         rw_enter(&sl->sl_zfs_meta_lock, RW_WRITER);
3526         bcopy(buf, &sl->sl_zfs_meta[off], sz);
3527         rw_exit(&sl->sl_zfs_meta_lock);
3528         /*
3529          * During creation of a logical unit, sbd_update_zfs_prop will be
3530          * called separately to avoid multiple calls as each meta section
3531          * create/update will result in a call to sbd_write_zfs_meta().
3532          * We only need to update the zvol once during create.
3533          */
3534         mutex_enter(&sl->sl_lock);
3535         if (sl->sl_trans_op != SL_OP_CREATE_REGISTER_LU) {
3536                 mutex_exit(&sl->sl_lock);
3537                 return (sbd_update_zfs_prop(sl));
3538         }
3539         mutex_exit(&sl->sl_lock);
3540         return (SBD_SUCCESS);
3541 }
3542 
3543 sbd_status_t
3544 sbd_update_zfs_prop(sbd_lu_t *sl)
3545 {
3546         char    *ptr, *ah_meta;
3547         char    *dp = NULL;
3548         int     i, num;
3549         char    *file;
3550         sbd_status_t ret = SBD_SUCCESS;
3551 
3552         ASSERT(sl->sl_zfs_meta);
3553         ptr = ah_meta = kmem_zalloc(ZAP_MAXVALUELEN, KM_SLEEP);
3554         rw_enter(&sl->sl_zfs_meta_lock, RW_READER);
3555         /* convert local copy to ascii hex */
3556         dp = sl->sl_zfs_meta;
3557         for (i = 0; i < sl->sl_total_meta_size; i++, dp++) {
3558                 num = ((*dp) >> 4) & 0xF;
3559                 *ah_meta++ = (num < 10) ? (num + '0') : (num + ('a' - 10));
3560                 num = (*dp) & 0xF;
3561                 *ah_meta++ = (num < 10) ? (num + '0') : (num + ('a' - 10));
3562         }
3563         *ah_meta = NULL;
3564         file = sbd_get_zvol_name(sl);
3565         if (sbd_zvolset(file, (char *)ptr)) {
3566                 ret = SBD_META_CORRUPTED;
3567         }
3568         rw_exit(&sl->sl_zfs_meta_lock);
3569         kmem_free(ptr, ZAP_MAXVALUELEN);
3570         kmem_free(file, strlen(file) + 1);
3571         return (ret);
3572 }
3573 
3574 int
3575 sbd_is_zvol(char *path)
3576 {
3577         int is_zfs = 0;
3578 
3579         if (SBD_IS_ZVOL(path) == 0)
3580                 is_zfs = 1;
3581 
3582         return (is_zfs);
3583 }
3584 
3585 /*
3586  * set write cache disable
3587  * wcd - 1 = disable, 0 = enable
3588  */
3589 sbd_status_t
3590 sbd_wcd_set(int wcd, sbd_lu_t *sl)
3591 {
3592         /* translate to wce bit */
3593         int wce = wcd ? 0 : 1;
3594         int ret;
3595         sbd_status_t sret = SBD_SUCCESS;
3596 
3597         mutex_enter(&sl->sl_lock);
3598         sl->sl_flags &= ~SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
3599 
3600         if (sl->sl_data_vp->v_type == VREG) {
3601                 sl->sl_flags |= SL_FLUSH_ON_DISABLED_WRITECACHE;
3602                 goto done;
3603         }
3604 
3605         ret = VOP_IOCTL(sl->sl_data_vp, DKIOCSETWCE, (intptr_t)&wce, FKIOCTL,
3606             kcred, NULL, NULL);
3607         if (ret == 0) {
3608                 sl->sl_flags &= ~SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
3609                 sl->sl_flags &= ~SL_FLUSH_ON_DISABLED_WRITECACHE;
3610         } else {
3611                 sl->sl_flags |= SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
3612                 sl->sl_flags |= SL_FLUSH_ON_DISABLED_WRITECACHE;
3613                 sret = SBD_FAILURE;
3614                 goto done;
3615         }
3616 
3617 done:
3618         mutex_exit(&sl->sl_lock);
3619         return (sret);
3620 }
3621 
3622 /*
3623  * get write cache disable
3624  * wcd - 1 = disable, 0 = enable
3625  */
3626 void
3627 sbd_wcd_get(int *wcd, sbd_lu_t *sl)
3628 {
3629         int wce;
3630         int ret;
3631 
3632         if (sl->sl_data_vp->v_type == VREG) {
3633                 *wcd = 0;
3634                 return;
3635         }
3636 
3637         ret = VOP_IOCTL(sl->sl_data_vp, DKIOCGETWCE, (intptr_t)&wce, FKIOCTL,
3638             kcred, NULL, NULL);
3639         /* if write cache get failed, assume disabled */
3640         if (ret) {
3641                 *wcd = 1;
3642         } else {
3643                 /* translate to wcd bit */
3644                 *wcd = wce ? 0 : 1;
3645         }
3646 }
3647 
3648 int
3649 sbd_zvolget(char *zvol_name, char **comstarprop)
3650 {
3651         ldi_handle_t    zfs_lh;
3652         nvlist_t        *nv = NULL, *nv2;
3653         zfs_cmd_t       *zc;
3654         char            *ptr;
3655         int size = 1024;
3656         int unused;
3657         int rc;
3658 
3659         if ((rc = ldi_open_by_name("/dev/zfs", FREAD | FWRITE, kcred,
3660             &zfs_lh, sbd_zfs_ident)) != 0) {
3661                 cmn_err(CE_WARN, "ldi_open %d", rc);
3662                 return (ENXIO);
3663         }
3664 
3665         zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3666         (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3667 again:
3668         zc->zc_nvlist_dst = (uint64_t)(intptr_t)kmem_alloc(size,
3669             KM_SLEEP);
3670         zc->zc_nvlist_dst_size = size;
3671         rc = ldi_ioctl(zfs_lh, ZFS_IOC_OBJSET_STATS, (intptr_t)zc,
3672             FKIOCTL, kcred, &unused);
3673         /*
3674          * ENOMEM means the list is larger than what we've allocated
3675          * ldi_ioctl will fail with ENOMEM only once
3676          */
3677         if (rc == ENOMEM) {
3678                 int newsize;
3679                 newsize = zc->zc_nvlist_dst_size;
3680                 kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size);
3681                 size = newsize;
3682                 goto again;
3683         } else if (rc != 0) {
3684                 goto out;
3685         }
3686         rc = nvlist_unpack((char *)(uintptr_t)zc->zc_nvlist_dst,
3687             zc->zc_nvlist_dst_size, &nv, 0);
3688         ASSERT(rc == 0);        /* nvlist_unpack should not fail */
3689         if ((rc = nvlist_lookup_nvlist(nv, "stmf_sbd_lu", &nv2)) == 0) {
3690                 rc = nvlist_lookup_string(nv2, ZPROP_VALUE, &ptr);
3691                 if (rc != 0) {
3692                         cmn_err(CE_WARN, "couldn't get value");
3693                 } else {
3694                         *comstarprop = kmem_alloc(strlen(ptr) + 1,
3695                             KM_SLEEP);
3696                         (void) strcpy(*comstarprop, ptr);
3697                 }
3698         }
3699 out:
3700         if (nv != NULL)
3701                 nvlist_free(nv);
3702         kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size);
3703         kmem_free(zc, sizeof (zfs_cmd_t));
3704         (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
3705 
3706         return (rc);
3707 }
3708 
3709 int
3710 sbd_zvolset(char *zvol_name, char *comstarprop)
3711 {
3712         ldi_handle_t    zfs_lh;
3713         nvlist_t        *nv;
3714         char            *packed = NULL;
3715         size_t          len;
3716         zfs_cmd_t       *zc;
3717         int unused;
3718         int rc;
3719 
3720         if ((rc = ldi_open_by_name("/dev/zfs", FREAD | FWRITE, kcred,
3721             &zfs_lh, sbd_zfs_ident)) != 0) {
3722                 cmn_err(CE_WARN, "ldi_open %d", rc);
3723                 return (ENXIO);
3724         }
3725         (void) nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP);
3726         (void) nvlist_add_string(nv, "stmf_sbd_lu", comstarprop);
3727         if ((rc = nvlist_pack(nv, &packed, &len, NV_ENCODE_NATIVE, KM_SLEEP))) {
3728                 goto out;
3729         }
3730 
3731         zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3732         (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3733         zc->zc_nvlist_src = (uint64_t)(intptr_t)packed;
3734         zc->zc_nvlist_src_size = len;
3735         rc = ldi_ioctl(zfs_lh, ZFS_IOC_SET_PROP, (intptr_t)zc,
3736             FKIOCTL, kcred, &unused);
3737         if (rc != 0) {
3738                 cmn_err(CE_NOTE, "ioctl failed %d", rc);
3739         }
3740         kmem_free(zc, sizeof (zfs_cmd_t));
3741         if (packed)
3742                 kmem_free(packed, len);
3743 out:
3744         nvlist_free(nv);
3745         (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
3746         return (rc);
3747 }
3748 
3749 static nvlist_t *
3750 sbd_zvol_get_props(char *zvol_name)
3751 {
3752         ldi_handle_t    zfs_lh;
3753         nvlist_t        *nv = NULL;
3754         zfs_cmd_t       *zc;
3755         int size = 4096;
3756         int unused;
3757         int rc;
3758 
3759         if ((rc = ldi_open_by_name("/dev/zfs", FREAD | FWRITE, kcred,
3760             &zfs_lh, sbd_zfs_ident)) != 0) {
3761                 cmn_err(CE_WARN, "ldi_open %d", rc);
3762                 return (NULL);
3763         }
3764 
3765         zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3766         (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3767 szg_again:
3768         zc->zc_nvlist_dst = (uint64_t)(intptr_t)kmem_alloc(size,
3769             KM_SLEEP);
3770         zc->zc_nvlist_dst_size = size;
3771         rc = ldi_ioctl(zfs_lh, ZFS_IOC_OBJSET_STATS, (intptr_t)zc,
3772             FKIOCTL, kcred, &unused);
3773         /*
3774          * ENOMEM means the list is larger than what we've allocated
3775          * ldi_ioctl will fail with ENOMEM only once
3776          */
3777         if (rc == ENOMEM) {
3778                 int newsize;
3779                 newsize = zc->zc_nvlist_dst_size;
3780                 kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size);
3781                 size = newsize;
3782                 goto szg_again;
3783         } else if (rc != 0) {
3784                 goto szg_out;
3785         }
3786         rc = nvlist_unpack((char *)(uintptr_t)zc->zc_nvlist_dst,
3787             zc->zc_nvlist_dst_size, &nv, 0);
3788         ASSERT(rc == 0);        /* nvlist_unpack should not fail */
3789 szg_out:
3790         kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size);
3791         kmem_free(zc, sizeof (zfs_cmd_t));
3792         (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
3793 
3794         return (nv);
3795 }
3796 
3797 static int
3798 sbd_zvol_set_props(char *zvol_name, nvlist_t *nv)
3799 {
3800         ldi_handle_t    zfs_lh;
3801         char            *packed = NULL;
3802         size_t          len;
3803         zfs_cmd_t       *zc;
3804         int unused;
3805         int rc;
3806 
3807         if ((rc = ldi_open_by_name("/dev/zfs", FREAD | FWRITE, kcred,
3808             &zfs_lh, sbd_zfs_ident)) != 0) {
3809                 cmn_err(CE_WARN, "ldi_open %d", rc);
3810                 return (ENXIO);
3811         }
3812         if ((rc = nvlist_pack(nv, &packed, &len, NV_ENCODE_NATIVE, KM_SLEEP))) {
3813                 goto szs_out;
3814         }
3815 
3816         zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3817         (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3818         zc->zc_nvlist_src = (uint64_t)(intptr_t)packed;
3819         zc->zc_nvlist_src_size = len;
3820         rc = ldi_ioctl(zfs_lh, ZFS_IOC_SET_PROP, (intptr_t)zc,
3821             FKIOCTL, kcred, &unused);
3822         if (rc != 0) {
3823                 cmn_err(CE_NOTE, "ioctl failed %d", rc);
3824         }
3825         kmem_free(zc, sizeof (zfs_cmd_t));
3826         if (packed)
3827                 kmem_free(packed, len);
3828 szs_out:
3829         (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
3830         return (rc);
3831 }