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