5255 uts shouldn't open-code ISP2

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