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