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