Print this page
701 UNMAP support for COMSTAR
Contributed by: Sumit Gupta <sumit.gupta@nexenta.com>
Reviewed by: Garrett D'Amore <garrett@nexenta.com>
Reviewed by: Eric Schrock <eric.schrock@delphix.com>
Reviewed by: George Wilson <gwilson@zfsmail.com>

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
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
       23 + *
       24 + * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  23   25   */
  24   26  
  25   27  #include <sys/conf.h>
  26   28  #include <sys/file.h>
  27   29  #include <sys/ddi.h>
  28   30  #include <sys/sunddi.h>
  29   31  #include <sys/modctl.h>
  30   32  #include <sys/scsi/scsi.h>
  31   33  #include <sys/scsi/impl/scsi_reset_notify.h>
  32   34  #include <sys/disp.h>
↓ open down ↓ 43 lines elided ↑ open up ↑
  76   78      int no_register, sbd_lu_t **slr);
  77   79  int sbd_import_active_lu(sbd_import_lu_t *ilu, sbd_lu_t *sl, uint32_t *err_ret);
  78   80  int sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret);
  79   81  int sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret);
  80   82  int sbd_set_global_props(sbd_global_props_t *mlu, int struct_sz,
  81   83      uint32_t *err_ret);
  82   84  int sbd_get_global_props(sbd_global_props_t *oslp, uint32_t oslp_sz,
  83   85      uint32_t *err_ret);
  84   86  int sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
  85   87      sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret);
  86      -char *sbd_get_zvol_name(sbd_lu_t *sl);
       88 +static char *sbd_get_zvol_name(sbd_lu_t *);
       89 +static int sbd_get_unmap_props(sbd_unmap_props_t *sup, sbd_unmap_props_t *osup,
       90 +    uint32_t *err_ret);
  87   91  sbd_status_t sbd_create_zfs_meta_object(sbd_lu_t *sl);
  88   92  sbd_status_t sbd_open_zfs_meta(sbd_lu_t *sl);
  89   93  sbd_status_t sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
  90   94      uint64_t off);
  91   95  sbd_status_t sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
  92   96      uint64_t off);
  93   97  sbd_status_t sbd_update_zfs_prop(sbd_lu_t *sl);
  94   98  int sbd_is_zvol(char *path);
  95   99  int sbd_zvolget(char *zvol_name, char **comstarprop);
  96  100  int sbd_zvolset(char *zvol_name, char *comstarprop);
↓ open down ↓ 344 lines elided ↑ open up ↑
 441  445                      sbd_lu_count);
 442  446                  for (nsl = sbd_lu_list, i = 0; nsl &&
 443  447                      (i < iocd->stmf_obuf_nentries); i++, nsl = nsl->sl_next) {
 444  448                          bcopy(nsl->sl_device_id + 4,
 445  449                              &(((uint8_t *)obuf)[i << 4]), 16);
 446  450                  }
 447  451                  mutex_exit(&sbd_lock);
 448  452                  ret = 0;
 449  453                  iocd->stmf_error = 0;
 450  454                  break;
      455 +        case SBD_IOCTL_GET_UNMAP_PROPS:
      456 +                if (iocd->stmf_ibuf_size < sizeof (sbd_unmap_props_t)) {
      457 +                        ret = EFAULT;
      458 +                        break;
      459 +                }
      460 +                if (iocd->stmf_obuf_size < sizeof (sbd_unmap_props_t)) {
      461 +                        ret = EINVAL;
      462 +                        break;
      463 +                }
      464 +                ret = sbd_get_unmap_props((sbd_unmap_props_t *)ibuf,
      465 +                    (sbd_unmap_props_t *)obuf, &iocd->stmf_error);
      466 +                break;
 451  467          default:
 452  468                  ret = ENOTTY;
 453  469          }
 454  470  
 455  471          if (ret == 0) {
 456  472                  ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
 457  473          } else if (iocd->stmf_error) {
 458  474                  (void) stmf_copyout_iocdata(data, mode, iocd, obuf);
 459  475          }
 460  476          if (obuf) {
↓ open down ↓ 904 lines elided ↑ open up ↑
1365 1381          sli->sli_sms_header.sms_size = sizeof (*sli) + s;
1366 1382          sli->sli_sms_header.sms_id = SMS_ID_LU_INFO_1_1;
1367 1383          sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER;
1368 1384  
1369 1385          mutex_exit(&sl->sl_lock);
1370 1386          ret = sbd_write_meta_section(sl, (sm_section_hdr_t *)sli);
1371 1387          kmem_free(sli, sizeof (*sli) + s);
1372 1388          return (ret);
1373 1389  }
1374 1390  
     1391 +/*
     1392 + * Will scribble SL_UNMAP_ENABLED into sl_flags if we succeed.
     1393 + */
     1394 +static void
     1395 +do_unmap_setup(sbd_lu_t *sl)
     1396 +{
     1397 +        ASSERT((sl->sl_flags & SL_UNMAP_ENABLED) == 0);
     1398 +
     1399 +        if ((sl->sl_flags & SL_ZFS_META) == 0)
     1400 +                return; /* No UNMAP for you. */
     1401 +
     1402 +        sl->sl_flags |= SL_UNMAP_ENABLED;
     1403 +}
     1404 +
1375 1405  int
1376 1406  sbd_populate_and_register_lu(sbd_lu_t *sl, uint32_t *err_ret)
1377 1407  {
1378 1408          stmf_lu_t *lu = sl->sl_lu;
1379 1409          stmf_status_t ret;
1380 1410  
     1411 +        do_unmap_setup(sl);
     1412 +
1381 1413          lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
1382 1414          if (sl->sl_alias) {
1383 1415                  lu->lu_alias = sl->sl_alias;
1384 1416          } else {
1385 1417                  lu->lu_alias = sl->sl_name;
1386 1418          }
1387 1419          if (sl->sl_access_state == SBD_LU_STANDBY) {
1388 1420                  /* call set access state */
1389 1421                  ret = stmf_set_lu_access(lu, STMF_LU_STANDBY);
1390 1422                  if (ret != STMF_SUCCESS) {
↓ open down ↓ 1734 lines elided ↑ open up ↑
3125 3157                  oslp->mlu_mgmt_url_valid = 1;
3126 3158                  oslp->mlu_mgmt_url_off = off;
3127 3159                  (void) strcpy((char *)&oslp->mlu_buf[off], sbd_mgmt_url);
3128 3160                  off += strlen(sbd_mgmt_url) + 1;
3129 3161          }
3130 3162  
3131 3163          rw_exit(&sbd_global_prop_lock);
3132 3164          return (0);
3133 3165  }
3134 3166  
     3167 +static int
     3168 +sbd_get_unmap_props(sbd_unmap_props_t *sup,
     3169 +    sbd_unmap_props_t *osup, uint32_t *err_ret)
     3170 +{
     3171 +        sbd_status_t sret;
     3172 +        sbd_lu_t *sl = NULL;
     3173 +
     3174 +        if (sup->sup_guid_valid) {
     3175 +                sret = sbd_find_and_lock_lu(sup->sup_guid,
     3176 +                    NULL, SL_OP_LU_PROPS, &sl);
     3177 +        } else {
     3178 +                sret = sbd_find_and_lock_lu(NULL,
     3179 +                    (uint8_t *)sup->sup_zvol_path, SL_OP_LU_PROPS,
     3180 +                    &sl);
     3181 +        }
     3182 +        if (sret != SBD_SUCCESS) {
     3183 +                if (sret == SBD_BUSY) {
     3184 +                        *err_ret = SBD_RET_LU_BUSY;
     3185 +                        return (EBUSY);
     3186 +                } else if (sret == SBD_NOT_FOUND) {
     3187 +                        *err_ret = SBD_RET_NOT_FOUND;
     3188 +                        return (ENOENT);
     3189 +                }
     3190 +                return (EIO);
     3191 +        }
     3192 +
     3193 +        sup->sup_found_lu = 1;
     3194 +        sup->sup_guid_valid = 1;
     3195 +        bcopy(sl->sl_device_id + 4, sup->sup_guid, 16);
     3196 +        if (sl->sl_flags & SL_UNMAP_ENABLED)
     3197 +                sup->sup_unmap_enabled = 1;
     3198 +        else
     3199 +                sup->sup_unmap_enabled = 0;
     3200 +
     3201 +        *osup = *sup;
     3202 +        sl->sl_trans_op = SL_OP_NONE;
     3203 +
     3204 +        return (0);
     3205 +}
     3206 +
3135 3207  int
3136 3208  sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
3137 3209      sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret)
3138 3210  {
3139 3211          sbd_status_t sret;
3140 3212          sbd_lu_t *sl = NULL;
3141 3213          uint32_t sz;
3142 3214          uint16_t off;
3143 3215  
3144 3216          if (islp->slp_input_guid) {
↓ open down ↓ 120 lines elided ↑ open up ↑
3265 3337                  oslp->slp_writeback_cache_disable_saved = 1;
3266 3338          if (sl->sl_flags & SL_WRITE_PROTECTED)
3267 3339                  oslp->slp_write_protected = 1;
3268 3340  
3269 3341          sl->sl_trans_op = SL_OP_NONE;
3270 3342  
3271 3343          rw_exit(&sbd_global_prop_lock);
3272 3344          return (0);
3273 3345  }
3274 3346  
3275      -char *
     3347 +/*
     3348 + * Returns an allocated string with the "<pool>/..." form of the zvol name.
     3349 + */
     3350 +static char *
3276 3351  sbd_get_zvol_name(sbd_lu_t *sl)
3277 3352  {
3278 3353          char *src;
3279 3354          char *p;
3280 3355  
3281 3356          if (sl->sl_data_filename)
3282 3357                  src = sl->sl_data_filename;
3283 3358          else
3284 3359                  src = sl->sl_meta_filename;
3285 3360          /* There has to be a better way */
3286 3361          if (SBD_IS_ZVOL(src) != 0) {
3287 3362                  ASSERT(0);
3288 3363          }
3289      -        src += 14;
     3364 +        src += 14;      /* Past /dev/zvol/dsk/ */
3290 3365          if (*src == '/')
3291      -                src++;
     3366 +                src++;  /* or /dev/zvol/rdsk/ */
3292 3367          p = (char *)kmem_alloc(strlen(src) + 1, KM_SLEEP);
3293 3368          (void) strcpy(p, src);
3294 3369          return (p);
3295 3370  }
3296 3371  
3297 3372  /*
3298 3373   * this function creates a local metadata zvol property
3299 3374   */
3300 3375  sbd_status_t
3301 3376  sbd_create_zfs_meta_object(sbd_lu_t *sl)
↓ open down ↓ 313 lines elided ↑ open up ↑
3615 3690          if (rc != 0) {
3616 3691                  cmn_err(CE_NOTE, "ioctl failed %d", rc);
3617 3692          }
3618 3693          kmem_free(zc, sizeof (zfs_cmd_t));
3619 3694          if (packed)
3620 3695                  kmem_free(packed, len);
3621 3696  out:
3622 3697          nvlist_free(nv);
3623 3698          (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
3624 3699          return (rc);
     3700 +}
     3701 +
     3702 +/*
     3703 + * Unmap a region in a volume.  Currently only supported for zvols.
     3704 + */
     3705 +int
     3706 +sbd_unmap(sbd_lu_t *sl, uint64_t offset, uint64_t length)
     3707 +{
     3708 +        vnode_t *vp;
     3709 +        int unused;
     3710 +        dkioc_free_t df;
     3711 +
     3712 +        /* Right now, we only support UNMAP on zvols. */
     3713 +        if (!(sl->sl_flags & SL_ZFS_META))
     3714 +                return (EIO);
     3715 +
     3716 +        df.df_flags = (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) ?
     3717 +            DF_WAIT_SYNC : 0;
     3718 +        df.df_start = offset;
     3719 +        df.df_length = length;
     3720 +
     3721 +        /* Use the data vnode we have to send a fop_ioctl(). */
     3722 +        vp = sl->sl_data_vp;
     3723 +        if (vp == NULL) {
     3724 +                cmn_err(CE_WARN, "Cannot unmap - no vnode pointer.");
     3725 +                return (EIO);
     3726 +        }
     3727 +
     3728 +        return (VOP_IOCTL(vp, DKIOCFREE, (intptr_t)(&df), FKIOCTL, kcred,
     3729 +            &unused, NULL));
3625 3730  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX