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