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>


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.


  23  */
  24 
  25 #include <sys/conf.h>
  26 #include <sys/file.h>
  27 #include <sys/ddi.h>
  28 #include <sys/sunddi.h>
  29 #include <sys/modctl.h>
  30 #include <sys/scsi/scsi.h>
  31 #include <sys/scsi/impl/scsi_reset_notify.h>
  32 #include <sys/disp.h>
  33 #include <sys/byteorder.h>
  34 #include <sys/pathname.h>
  35 #include <sys/atomic.h>
  36 #include <sys/nvpair.h>
  37 #include <sys/fs/zfs.h>
  38 #include <sys/sdt.h>
  39 #include <sys/dkio.h>
  40 #include <sys/zfs_ioctl.h>
  41 
  42 #include <sys/stmf.h>


  66     uint32_t proxy_reg_arg_len);
  67 stmf_status_t sbd_proxy_dereg_lu(uint8_t *luid, void *proxy_reg_arg,
  68     uint32_t proxy_reg_arg_len);
  69 stmf_status_t sbd_proxy_msg(uint8_t *luid, void *proxy_arg,
  70     uint32_t proxy_arg_len, uint32_t type);
  71 int sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz,
  72     uint32_t *err_ret);
  73 int sbd_create_standby_lu(sbd_create_standby_lu_t *slu, uint32_t *err_ret);
  74 int sbd_set_lu_standby(sbd_set_lu_standby_t *stlu, uint32_t *err_ret);
  75 int sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret,
  76     int no_register, sbd_lu_t **slr);
  77 int sbd_import_active_lu(sbd_import_lu_t *ilu, sbd_lu_t *sl, uint32_t *err_ret);
  78 int sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret);
  79 int sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret);
  80 int sbd_set_global_props(sbd_global_props_t *mlu, int struct_sz,
  81     uint32_t *err_ret);
  82 int sbd_get_global_props(sbd_global_props_t *oslp, uint32_t oslp_sz,
  83     uint32_t *err_ret);
  84 int sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
  85     sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret);
  86 char *sbd_get_zvol_name(sbd_lu_t *sl);


  87 sbd_status_t sbd_create_zfs_meta_object(sbd_lu_t *sl);
  88 sbd_status_t sbd_open_zfs_meta(sbd_lu_t *sl);
  89 sbd_status_t sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
  90     uint64_t off);
  91 sbd_status_t sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
  92     uint64_t off);
  93 sbd_status_t sbd_update_zfs_prop(sbd_lu_t *sl);
  94 int sbd_is_zvol(char *path);
  95 int sbd_zvolget(char *zvol_name, char **comstarprop);
  96 int sbd_zvolset(char *zvol_name, char *comstarprop);
  97 char sbd_ctoi(char c);
  98 void sbd_close_lu(sbd_lu_t *sl);
  99 
 100 static ldi_ident_t      sbd_zfs_ident;
 101 static stmf_lu_provider_t *sbd_lp;
 102 static sbd_lu_t         *sbd_lu_list = NULL;
 103 static kmutex_t         sbd_lock;
 104 static dev_info_t       *sbd_dip;
 105 static uint32_t         sbd_lu_count = 0;
 106 


 431                         break;
 432                 }
 433                 ret = sbd_get_lu_props((sbd_lu_props_t *)ibuf,
 434                     iocd->stmf_ibuf_size, (sbd_lu_props_t *)obuf,
 435                     iocd->stmf_obuf_size, &iocd->stmf_error);
 436                 break;
 437         case SBD_IOCTL_GET_LU_LIST:
 438                 mutex_enter(&sbd_lock);
 439                 iocd->stmf_obuf_max_nentries = sbd_lu_count;
 440                 iocd->stmf_obuf_nentries = min((iocd->stmf_obuf_size >> 4),
 441                     sbd_lu_count);
 442                 for (nsl = sbd_lu_list, i = 0; nsl &&
 443                     (i < iocd->stmf_obuf_nentries); i++, nsl = nsl->sl_next) {
 444                         bcopy(nsl->sl_device_id + 4,
 445                             &(((uint8_t *)obuf)[i << 4]), 16);
 446                 }
 447                 mutex_exit(&sbd_lock);
 448                 ret = 0;
 449                 iocd->stmf_error = 0;
 450                 break;












 451         default:
 452                 ret = ENOTTY;
 453         }
 454 
 455         if (ret == 0) {
 456                 ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
 457         } else if (iocd->stmf_error) {
 458                 (void) stmf_copyout_iocdata(data, mode, iocd, obuf);
 459         }
 460         if (obuf) {
 461                 kmem_free(obuf, iocd->stmf_obuf_size);
 462                 obuf = NULL;
 463         }
 464         if (ibuf) {
 465                 kmem_free(ibuf, iocd->stmf_ibuf_size);
 466                 ibuf = NULL;
 467         }
 468         kmem_free(iocd, sizeof (stmf_iocdata_t));
 469         return (ret);
 470 }


1355                 sli->sli_serial_offset =
1356                     (uintptr_t)p - (uintptr_t)sli->sli_buf;
1357                 sli->sli_flags |= SLI_SERIAL_VALID;
1358                 p += sli->sli_serial_size;
1359         }
1360         sli->sli_lu_size = sl->sl_lu_size;
1361         sli->sli_data_blocksize_shift = sl->sl_data_blocksize_shift;
1362         sli->sli_data_order = SMS_DATA_ORDER;
1363         bcopy(sl->sl_device_id, sli->sli_device_id, 20);
1364 
1365         sli->sli_sms_header.sms_size = sizeof (*sli) + s;
1366         sli->sli_sms_header.sms_id = SMS_ID_LU_INFO_1_1;
1367         sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER;
1368 
1369         mutex_exit(&sl->sl_lock);
1370         ret = sbd_write_meta_section(sl, (sm_section_hdr_t *)sli);
1371         kmem_free(sli, sizeof (*sli) + s);
1372         return (ret);
1373 }
1374 














1375 int
1376 sbd_populate_and_register_lu(sbd_lu_t *sl, uint32_t *err_ret)
1377 {
1378         stmf_lu_t *lu = sl->sl_lu;
1379         stmf_status_t ret;
1380 


1381         lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
1382         if (sl->sl_alias) {
1383                 lu->lu_alias = sl->sl_alias;
1384         } else {
1385                 lu->lu_alias = sl->sl_name;
1386         }
1387         if (sl->sl_access_state == SBD_LU_STANDBY) {
1388                 /* call set access state */
1389                 ret = stmf_set_lu_access(lu, STMF_LU_STANDBY);
1390                 if (ret != STMF_SUCCESS) {
1391                         *err_ret = SBD_RET_ACCESS_STATE_FAILED;
1392                         return (EIO);
1393                 }
1394         }
1395         /* set proxy_reg_cb_arg to meta filename */
1396         if (sl->sl_meta_filename) {
1397                 lu->lu_proxy_reg_arg = sl->sl_meta_filename;
1398                 lu->lu_proxy_reg_arg_len = strlen(sl->sl_meta_filename) + 1;
1399         } else {
1400                 lu->lu_proxy_reg_arg = sl->sl_data_filename;


3115         oslp->mlu_buf_size_needed = sz;
3116 
3117         if (sz > (oslp_sz - sizeof (*oslp) + 8)) {
3118                 *err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE;
3119                 rw_exit(&sbd_global_prop_lock);
3120                 return (ENOMEM);
3121         }
3122 
3123         off = 0;
3124         if (sbd_mgmt_url) {
3125                 oslp->mlu_mgmt_url_valid = 1;
3126                 oslp->mlu_mgmt_url_off = off;
3127                 (void) strcpy((char *)&oslp->mlu_buf[off], sbd_mgmt_url);
3128                 off += strlen(sbd_mgmt_url) + 1;
3129         }
3130 
3131         rw_exit(&sbd_global_prop_lock);
3132         return (0);
3133 }
3134 








































3135 int
3136 sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
3137     sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret)
3138 {
3139         sbd_status_t sret;
3140         sbd_lu_t *sl = NULL;
3141         uint32_t sz;
3142         uint16_t off;
3143 
3144         if (islp->slp_input_guid) {
3145                 sret = sbd_find_and_lock_lu(islp->slp_guid, NULL,
3146                     SL_OP_LU_PROPS, &sl);
3147         } else {
3148                 ((char *)islp)[islp_sz - 1] = 0;
3149                 sret = sbd_find_and_lock_lu(NULL, islp->slp_buf,
3150                     SL_OP_LU_PROPS, &sl);
3151         }
3152         if (sret != SBD_SUCCESS) {
3153                 if (sret == SBD_BUSY) {
3154                         *err_ret = SBD_RET_LU_BUSY;


3255                 oslp->slp_lu_rev = 1;
3256                 bcopy(sl->sl_revision, oslp->slp_rev, 4);
3257         } else {
3258                 bcopy(sbd_revision, oslp->slp_rev, 4);
3259         }
3260         bcopy(sl->sl_device_id + 4, oslp->slp_guid, 16);
3261 
3262         if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE)
3263                 oslp->slp_writeback_cache_disable_cur = 1;
3264         if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE)
3265                 oslp->slp_writeback_cache_disable_saved = 1;
3266         if (sl->sl_flags & SL_WRITE_PROTECTED)
3267                 oslp->slp_write_protected = 1;
3268 
3269         sl->sl_trans_op = SL_OP_NONE;
3270 
3271         rw_exit(&sbd_global_prop_lock);
3272         return (0);
3273 }
3274 
3275 char *



3276 sbd_get_zvol_name(sbd_lu_t *sl)
3277 {
3278         char *src;
3279         char *p;
3280 
3281         if (sl->sl_data_filename)
3282                 src = sl->sl_data_filename;
3283         else
3284                 src = sl->sl_meta_filename;
3285         /* There has to be a better way */
3286         if (SBD_IS_ZVOL(src) != 0) {
3287                 ASSERT(0);
3288         }
3289         src += 14;
3290         if (*src == '/')
3291                 src++;
3292         p = (char *)kmem_alloc(strlen(src) + 1, KM_SLEEP);
3293         (void) strcpy(p, src);
3294         return (p);
3295 }
3296 
3297 /*
3298  * this function creates a local metadata zvol property
3299  */
3300 sbd_status_t
3301 sbd_create_zfs_meta_object(sbd_lu_t *sl)
3302 {
3303         /*
3304          * -allocate 1/2 the property size, the zfs property
3305          *  is 8k in size and stored as ascii hex string, all
3306          *  we needed is 4k buffer to store the binary data.
3307          * -initialize reader/write lock
3308          */
3309         if ((sl->sl_zfs_meta = kmem_zalloc(ZAP_MAXVALUELEN / 2, KM_SLEEP))
3310             == NULL)
3311                 return (SBD_FAILURE);


3605         if ((rc = nvlist_pack(nv, &packed, &len, NV_ENCODE_NATIVE, KM_SLEEP))) {
3606                 goto out;
3607         }
3608 
3609         zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3610         (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3611         zc->zc_nvlist_src = (uint64_t)(intptr_t)packed;
3612         zc->zc_nvlist_src_size = len;
3613         rc = ldi_ioctl(zfs_lh, ZFS_IOC_SET_PROP, (intptr_t)zc,
3614             FKIOCTL, kcred, &unused);
3615         if (rc != 0) {
3616                 cmn_err(CE_NOTE, "ioctl failed %d", rc);
3617         }
3618         kmem_free(zc, sizeof (zfs_cmd_t));
3619         if (packed)
3620                 kmem_free(packed, len);
3621 out:
3622         nvlist_free(nv);
3623         (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
3624         return (rc);






























3625 }


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  23  *
  24  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 #include <sys/conf.h>
  28 #include <sys/file.h>
  29 #include <sys/ddi.h>
  30 #include <sys/sunddi.h>
  31 #include <sys/modctl.h>
  32 #include <sys/scsi/scsi.h>
  33 #include <sys/scsi/impl/scsi_reset_notify.h>
  34 #include <sys/disp.h>
  35 #include <sys/byteorder.h>
  36 #include <sys/pathname.h>
  37 #include <sys/atomic.h>
  38 #include <sys/nvpair.h>
  39 #include <sys/fs/zfs.h>
  40 #include <sys/sdt.h>
  41 #include <sys/dkio.h>
  42 #include <sys/zfs_ioctl.h>
  43 
  44 #include <sys/stmf.h>


  68     uint32_t proxy_reg_arg_len);
  69 stmf_status_t sbd_proxy_dereg_lu(uint8_t *luid, void *proxy_reg_arg,
  70     uint32_t proxy_reg_arg_len);
  71 stmf_status_t sbd_proxy_msg(uint8_t *luid, void *proxy_arg,
  72     uint32_t proxy_arg_len, uint32_t type);
  73 int sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz,
  74     uint32_t *err_ret);
  75 int sbd_create_standby_lu(sbd_create_standby_lu_t *slu, uint32_t *err_ret);
  76 int sbd_set_lu_standby(sbd_set_lu_standby_t *stlu, uint32_t *err_ret);
  77 int sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret,
  78     int no_register, sbd_lu_t **slr);
  79 int sbd_import_active_lu(sbd_import_lu_t *ilu, sbd_lu_t *sl, uint32_t *err_ret);
  80 int sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret);
  81 int sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret);
  82 int sbd_set_global_props(sbd_global_props_t *mlu, int struct_sz,
  83     uint32_t *err_ret);
  84 int sbd_get_global_props(sbd_global_props_t *oslp, uint32_t oslp_sz,
  85     uint32_t *err_ret);
  86 int sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
  87     sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret);
  88 static char *sbd_get_zvol_name(sbd_lu_t *);
  89 static int sbd_get_unmap_props(sbd_unmap_props_t *sup, sbd_unmap_props_t *osup,
  90     uint32_t *err_ret);
  91 sbd_status_t sbd_create_zfs_meta_object(sbd_lu_t *sl);
  92 sbd_status_t sbd_open_zfs_meta(sbd_lu_t *sl);
  93 sbd_status_t sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
  94     uint64_t off);
  95 sbd_status_t sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
  96     uint64_t off);
  97 sbd_status_t sbd_update_zfs_prop(sbd_lu_t *sl);
  98 int sbd_is_zvol(char *path);
  99 int sbd_zvolget(char *zvol_name, char **comstarprop);
 100 int sbd_zvolset(char *zvol_name, char *comstarprop);
 101 char sbd_ctoi(char c);
 102 void sbd_close_lu(sbd_lu_t *sl);
 103 
 104 static ldi_ident_t      sbd_zfs_ident;
 105 static stmf_lu_provider_t *sbd_lp;
 106 static sbd_lu_t         *sbd_lu_list = NULL;
 107 static kmutex_t         sbd_lock;
 108 static dev_info_t       *sbd_dip;
 109 static uint32_t         sbd_lu_count = 0;
 110 


 435                         break;
 436                 }
 437                 ret = sbd_get_lu_props((sbd_lu_props_t *)ibuf,
 438                     iocd->stmf_ibuf_size, (sbd_lu_props_t *)obuf,
 439                     iocd->stmf_obuf_size, &iocd->stmf_error);
 440                 break;
 441         case SBD_IOCTL_GET_LU_LIST:
 442                 mutex_enter(&sbd_lock);
 443                 iocd->stmf_obuf_max_nentries = sbd_lu_count;
 444                 iocd->stmf_obuf_nentries = min((iocd->stmf_obuf_size >> 4),
 445                     sbd_lu_count);
 446                 for (nsl = sbd_lu_list, i = 0; nsl &&
 447                     (i < iocd->stmf_obuf_nentries); i++, nsl = nsl->sl_next) {
 448                         bcopy(nsl->sl_device_id + 4,
 449                             &(((uint8_t *)obuf)[i << 4]), 16);
 450                 }
 451                 mutex_exit(&sbd_lock);
 452                 ret = 0;
 453                 iocd->stmf_error = 0;
 454                 break;
 455         case SBD_IOCTL_GET_UNMAP_PROPS:
 456                 if (iocd->stmf_ibuf_size < sizeof (sbd_unmap_props_t)) {
 457                         ret = EFAULT;
 458                         break;
 459                 }
 460                 if (iocd->stmf_obuf_size < sizeof (sbd_unmap_props_t)) {
 461                         ret = EINVAL;
 462                         break;
 463                 }
 464                 ret = sbd_get_unmap_props((sbd_unmap_props_t *)ibuf,
 465                     (sbd_unmap_props_t *)obuf, &iocd->stmf_error);
 466                 break;
 467         default:
 468                 ret = ENOTTY;
 469         }
 470 
 471         if (ret == 0) {
 472                 ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
 473         } else if (iocd->stmf_error) {
 474                 (void) stmf_copyout_iocdata(data, mode, iocd, obuf);
 475         }
 476         if (obuf) {
 477                 kmem_free(obuf, iocd->stmf_obuf_size);
 478                 obuf = NULL;
 479         }
 480         if (ibuf) {
 481                 kmem_free(ibuf, iocd->stmf_ibuf_size);
 482                 ibuf = NULL;
 483         }
 484         kmem_free(iocd, sizeof (stmf_iocdata_t));
 485         return (ret);
 486 }


1371                 sli->sli_serial_offset =
1372                     (uintptr_t)p - (uintptr_t)sli->sli_buf;
1373                 sli->sli_flags |= SLI_SERIAL_VALID;
1374                 p += sli->sli_serial_size;
1375         }
1376         sli->sli_lu_size = sl->sl_lu_size;
1377         sli->sli_data_blocksize_shift = sl->sl_data_blocksize_shift;
1378         sli->sli_data_order = SMS_DATA_ORDER;
1379         bcopy(sl->sl_device_id, sli->sli_device_id, 20);
1380 
1381         sli->sli_sms_header.sms_size = sizeof (*sli) + s;
1382         sli->sli_sms_header.sms_id = SMS_ID_LU_INFO_1_1;
1383         sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER;
1384 
1385         mutex_exit(&sl->sl_lock);
1386         ret = sbd_write_meta_section(sl, (sm_section_hdr_t *)sli);
1387         kmem_free(sli, sizeof (*sli) + s);
1388         return (ret);
1389 }
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 
1405 int
1406 sbd_populate_and_register_lu(sbd_lu_t *sl, uint32_t *err_ret)
1407 {
1408         stmf_lu_t *lu = sl->sl_lu;
1409         stmf_status_t ret;
1410 
1411         do_unmap_setup(sl);
1412 
1413         lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
1414         if (sl->sl_alias) {
1415                 lu->lu_alias = sl->sl_alias;
1416         } else {
1417                 lu->lu_alias = sl->sl_name;
1418         }
1419         if (sl->sl_access_state == SBD_LU_STANDBY) {
1420                 /* call set access state */
1421                 ret = stmf_set_lu_access(lu, STMF_LU_STANDBY);
1422                 if (ret != STMF_SUCCESS) {
1423                         *err_ret = SBD_RET_ACCESS_STATE_FAILED;
1424                         return (EIO);
1425                 }
1426         }
1427         /* set proxy_reg_cb_arg to meta filename */
1428         if (sl->sl_meta_filename) {
1429                 lu->lu_proxy_reg_arg = sl->sl_meta_filename;
1430                 lu->lu_proxy_reg_arg_len = strlen(sl->sl_meta_filename) + 1;
1431         } else {
1432                 lu->lu_proxy_reg_arg = sl->sl_data_filename;


3147         oslp->mlu_buf_size_needed = sz;
3148 
3149         if (sz > (oslp_sz - sizeof (*oslp) + 8)) {
3150                 *err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE;
3151                 rw_exit(&sbd_global_prop_lock);
3152                 return (ENOMEM);
3153         }
3154 
3155         off = 0;
3156         if (sbd_mgmt_url) {
3157                 oslp->mlu_mgmt_url_valid = 1;
3158                 oslp->mlu_mgmt_url_off = off;
3159                 (void) strcpy((char *)&oslp->mlu_buf[off], sbd_mgmt_url);
3160                 off += strlen(sbd_mgmt_url) + 1;
3161         }
3162 
3163         rw_exit(&sbd_global_prop_lock);
3164         return (0);
3165 }
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 
3207 int
3208 sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
3209     sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret)
3210 {
3211         sbd_status_t sret;
3212         sbd_lu_t *sl = NULL;
3213         uint32_t sz;
3214         uint16_t off;
3215 
3216         if (islp->slp_input_guid) {
3217                 sret = sbd_find_and_lock_lu(islp->slp_guid, NULL,
3218                     SL_OP_LU_PROPS, &sl);
3219         } else {
3220                 ((char *)islp)[islp_sz - 1] = 0;
3221                 sret = sbd_find_and_lock_lu(NULL, islp->slp_buf,
3222                     SL_OP_LU_PROPS, &sl);
3223         }
3224         if (sret != SBD_SUCCESS) {
3225                 if (sret == SBD_BUSY) {
3226                         *err_ret = SBD_RET_LU_BUSY;


3327                 oslp->slp_lu_rev = 1;
3328                 bcopy(sl->sl_revision, oslp->slp_rev, 4);
3329         } else {
3330                 bcopy(sbd_revision, oslp->slp_rev, 4);
3331         }
3332         bcopy(sl->sl_device_id + 4, oslp->slp_guid, 16);
3333 
3334         if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE)
3335                 oslp->slp_writeback_cache_disable_cur = 1;
3336         if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE)
3337                 oslp->slp_writeback_cache_disable_saved = 1;
3338         if (sl->sl_flags & SL_WRITE_PROTECTED)
3339                 oslp->slp_write_protected = 1;
3340 
3341         sl->sl_trans_op = SL_OP_NONE;
3342 
3343         rw_exit(&sbd_global_prop_lock);
3344         return (0);
3345 }
3346 
3347 /*
3348  * Returns an allocated string with the "<pool>/..." form of the zvol name.
3349  */
3350 static char *
3351 sbd_get_zvol_name(sbd_lu_t *sl)
3352 {
3353         char *src;
3354         char *p;
3355 
3356         if (sl->sl_data_filename)
3357                 src = sl->sl_data_filename;
3358         else
3359                 src = sl->sl_meta_filename;
3360         /* There has to be a better way */
3361         if (SBD_IS_ZVOL(src) != 0) {
3362                 ASSERT(0);
3363         }
3364         src += 14;      /* Past /dev/zvol/dsk/ */
3365         if (*src == '/')
3366                 src++;  /* or /dev/zvol/rdsk/ */
3367         p = (char *)kmem_alloc(strlen(src) + 1, KM_SLEEP);
3368         (void) strcpy(p, src);
3369         return (p);
3370 }
3371 
3372 /*
3373  * this function creates a local metadata zvol property
3374  */
3375 sbd_status_t
3376 sbd_create_zfs_meta_object(sbd_lu_t *sl)
3377 {
3378         /*
3379          * -allocate 1/2 the property size, the zfs property
3380          *  is 8k in size and stored as ascii hex string, all
3381          *  we needed is 4k buffer to store the binary data.
3382          * -initialize reader/write lock
3383          */
3384         if ((sl->sl_zfs_meta = kmem_zalloc(ZAP_MAXVALUELEN / 2, KM_SLEEP))
3385             == NULL)
3386                 return (SBD_FAILURE);


3680         if ((rc = nvlist_pack(nv, &packed, &len, NV_ENCODE_NATIVE, KM_SLEEP))) {
3681                 goto out;
3682         }
3683 
3684         zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3685         (void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3686         zc->zc_nvlist_src = (uint64_t)(intptr_t)packed;
3687         zc->zc_nvlist_src_size = len;
3688         rc = ldi_ioctl(zfs_lh, ZFS_IOC_SET_PROP, (intptr_t)zc,
3689             FKIOCTL, kcred, &unused);
3690         if (rc != 0) {
3691                 cmn_err(CE_NOTE, "ioctl failed %d", rc);
3692         }
3693         kmem_free(zc, sizeof (zfs_cmd_t));
3694         if (packed)
3695                 kmem_free(packed, len);
3696 out:
3697         nvlist_free(nv);
3698         (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
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));
3730 }