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