# HG changeset patch # User Dan McDonald # Date 1299275829 28800 # Node ID 4b9dc4ca8e9ffdd2b3bf9e10d991a1b57af48b45 # Parent f7734d6b8e807eb7e8784039244826b30795037a 701 UNMAP support for COMSTAR Reviewed by: Garrett D'Amore Reviewed by: Eric Schrock Reviewed by: George Wilson Approved by: Garrett D'Amore diff -r f7734d6b8e80 -r 4b9dc4ca8e9f usr/src/uts/common/fs/zfs/zvol.c --- a/usr/src/uts/common/fs/zfs/zvol.c Fri Mar 04 15:27:25 2011 -0500 +++ b/usr/src/uts/common/fs/zfs/zvol.c Fri Mar 04 13:57:09 2011 -0800 @@ -20,10 +20,12 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Portions Copyright 2010 Robert Milkowski + * + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ -/* Portions Copyright 2010 Robert Milkowski */ - /* * ZFS volume emulation driver. * @@ -342,6 +344,24 @@ } /* + * Replay a TX_TRUNCATE ZIL transaction if asked. TX_TRUNCATE is how we + * implement DKIOCFREE/free-long-range. + */ +static int +zvol_replay_truncate(zvol_state_t *zv, lr_truncate_t *lr, boolean_t byteswap) +{ + uint64_t offset, length; + + if (byteswap) + byteswap_uint64_array(lr, sizeof (*lr)); + + offset = lr->lr_offset; + length = lr->lr_length; + + return (dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, offset, length)); +} + +/* * Replay a TX_WRITE ZIL transaction that didn't get committed * after a system failure */ @@ -391,7 +411,7 @@ /* * Callback vectors for replaying records. - * Only TX_WRITE is needed for zvol. + * Only TX_WRITE and TX_TRUNCATE are needed for zvol. */ zil_replay_func_t *zvol_replay_vector[TX_MAX_TYPE] = { zvol_replay_err, /* 0 no such transaction type */ @@ -404,7 +424,7 @@ zvol_replay_err, /* TX_LINK */ zvol_replay_err, /* TX_RENAME */ zvol_replay_write, /* TX_WRITE */ - zvol_replay_err, /* TX_TRUNCATE */ + zvol_replay_truncate, /* TX_TRUNCATE */ zvol_replay_err, /* TX_SETATTR */ zvol_replay_err, /* TX_ACL */ zvol_replay_err, /* TX_CREATE_ACL */ @@ -1512,7 +1532,32 @@ */ /* + * Log a DKIOCFREE/free-long-range to the ZIL with TX_TRUNCATE. + */ +static void +zvol_log_truncate(zvol_state_t *zv, dmu_tx_t *tx, uint64_t off, uint64_t len, + boolean_t sync) +{ + itx_t *itx; + lr_truncate_t *lr; + zilog_t *zilog = zv->zv_zilog; + + if (zil_replaying(zilog, tx)) + return; + + itx = zil_itx_create(TX_TRUNCATE, sizeof (*lr)); + lr = (lr_truncate_t *)&itx->itx_lr; + lr->lr_foid = ZVOL_OBJ; + lr->lr_offset = off; + lr->lr_length = len; + + itx->itx_sync = sync; + zil_itx_assign(zilog, itx, tx); +} + +/* * Dirtbag ioctls to support mkfs(1M) for UFS filesystems. See dkio(7I). + * Also a dirtbag dkio ioctl for unmap/free-block functionality. */ /*ARGSUSED*/ int @@ -1631,6 +1676,65 @@ zfs_range_unlock(rl); break; + case DKIOCFREE: + { + dkioc_free_t df; + dmu_tx_t *tx; + + if (ddi_copyin((void *)arg, &df, sizeof (df), flag)) { + error = EFAULT; + break; + } + + /* + * Apply Postel's Law to length-checking. If they overshoot, + * just blank out until the end, if there's a need to blank + * out anything. + */ + if (df.df_start >= zv->zv_volsize) + break; /* No need to do anything... */ + if (df.df_start + df.df_length > zv->zv_volsize) + df.df_length = DMU_OBJECT_END; + + rl = zfs_range_lock(&zv->zv_znode, df.df_start, df.df_length, + RL_WRITER); + tx = dmu_tx_create(zv->zv_objset); + error = dmu_tx_assign(tx, TXG_WAIT); + if (error != 0) { + dmu_tx_abort(tx); + } else { + zvol_log_truncate(zv, tx, df.df_start, + df.df_length, B_TRUE); + error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, + df.df_start, df.df_length); + dmu_tx_commit(tx); + } + + zfs_range_unlock(rl); + + if (error == 0) { + /* + * If the write-cache is disabled or 'sync' property + * is set to 'always' then treat this as a synchronous + * operation (i.e. commit to zil). + */ + if (!(zv->zv_flags & ZVOL_WCE) || + (zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS)) + zil_commit(zv->zv_zilog, ZVOL_OBJ); + + /* + * If the caller really wants synchronous writes, and + * can't wait for them, don't return until the write + * is done. + */ + if (df.df_flags & DF_WAIT_SYNC) { + txg_wait_synced( + dmu_objset_pool(zv->zv_objset), 0); + } + } + break; + } + default: error = ENOTTY; break; diff -r f7734d6b8e80 -r 4b9dc4ca8e9f usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c --- a/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c Fri Mar 04 15:27:25 2011 -0500 +++ b/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c Fri Mar 04 13:57:09 2011 -0800 @@ -20,6 +20,8 @@ */ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ #include @@ -83,7 +85,9 @@ uint32_t *err_ret); int sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz, sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret); -char *sbd_get_zvol_name(sbd_lu_t *sl); +static char *sbd_get_zvol_name(sbd_lu_t *); +static int sbd_get_unmap_props(sbd_unmap_props_t *sup, sbd_unmap_props_t *osup, + uint32_t *err_ret); sbd_status_t sbd_create_zfs_meta_object(sbd_lu_t *sl); sbd_status_t sbd_open_zfs_meta(sbd_lu_t *sl); sbd_status_t sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, @@ -448,6 +452,18 @@ ret = 0; iocd->stmf_error = 0; break; + case SBD_IOCTL_GET_UNMAP_PROPS: + if (iocd->stmf_ibuf_size < sizeof (sbd_unmap_props_t)) { + ret = EFAULT; + break; + } + if (iocd->stmf_obuf_size < sizeof (sbd_unmap_props_t)) { + ret = EINVAL; + break; + } + ret = sbd_get_unmap_props((sbd_unmap_props_t *)ibuf, + (sbd_unmap_props_t *)obuf, &iocd->stmf_error); + break; default: ret = ENOTTY; } @@ -1372,12 +1388,28 @@ return (ret); } +/* + * Will scribble SL_UNMAP_ENABLED into sl_flags if we succeed. + */ +static void +do_unmap_setup(sbd_lu_t *sl) +{ + ASSERT((sl->sl_flags & SL_UNMAP_ENABLED) == 0); + + if ((sl->sl_flags & SL_ZFS_META) == 0) + return; /* No UNMAP for you. */ + + sl->sl_flags |= SL_UNMAP_ENABLED; +} + int sbd_populate_and_register_lu(sbd_lu_t *sl, uint32_t *err_ret) { stmf_lu_t *lu = sl->sl_lu; stmf_status_t ret; + do_unmap_setup(sl); + lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id; if (sl->sl_alias) { lu->lu_alias = sl->sl_alias; @@ -3132,6 +3164,46 @@ return (0); } +static int +sbd_get_unmap_props(sbd_unmap_props_t *sup, + sbd_unmap_props_t *osup, uint32_t *err_ret) +{ + sbd_status_t sret; + sbd_lu_t *sl = NULL; + + if (sup->sup_guid_valid) { + sret = sbd_find_and_lock_lu(sup->sup_guid, + NULL, SL_OP_LU_PROPS, &sl); + } else { + sret = sbd_find_and_lock_lu(NULL, + (uint8_t *)sup->sup_zvol_path, SL_OP_LU_PROPS, + &sl); + } + if (sret != SBD_SUCCESS) { + if (sret == SBD_BUSY) { + *err_ret = SBD_RET_LU_BUSY; + return (EBUSY); + } else if (sret == SBD_NOT_FOUND) { + *err_ret = SBD_RET_NOT_FOUND; + return (ENOENT); + } + return (EIO); + } + + sup->sup_found_lu = 1; + sup->sup_guid_valid = 1; + bcopy(sl->sl_device_id + 4, sup->sup_guid, 16); + if (sl->sl_flags & SL_UNMAP_ENABLED) + sup->sup_unmap_enabled = 1; + else + sup->sup_unmap_enabled = 0; + + *osup = *sup; + sl->sl_trans_op = SL_OP_NONE; + + return (0); +} + int sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz, sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret) @@ -3272,7 +3344,10 @@ return (0); } -char * +/* + * Returns an allocated string with the "/..." form of the zvol name. + */ +static char * sbd_get_zvol_name(sbd_lu_t *sl) { char *src; @@ -3286,9 +3361,9 @@ if (SBD_IS_ZVOL(src) != 0) { ASSERT(0); } - src += 14; + src += 14; /* Past /dev/zvol/dsk/ */ if (*src == '/') - src++; + src++; /* or /dev/zvol/rdsk/ */ p = (char *)kmem_alloc(strlen(src) + 1, KM_SLEEP); (void) strcpy(p, src); return (p); @@ -3623,3 +3698,33 @@ (void) ldi_close(zfs_lh, FREAD|FWRITE, kcred); return (rc); } + +/* + * Unmap a region in a volume. Currently only supported for zvols. + */ +int +sbd_unmap(sbd_lu_t *sl, uint64_t offset, uint64_t length) +{ + vnode_t *vp; + int unused; + dkioc_free_t df; + + /* Right now, we only support UNMAP on zvols. */ + if (!(sl->sl_flags & SL_ZFS_META)) + return (EIO); + + df.df_flags = (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) ? + DF_WAIT_SYNC : 0; + df.df_start = offset; + df.df_length = length; + + /* Use the data vnode we have to send a fop_ioctl(). */ + vp = sl->sl_data_vp; + if (vp == NULL) { + cmn_err(CE_WARN, "Cannot unmap - no vnode pointer."); + return (EIO); + } + + return (VOP_IOCTL(vp, DKIOCFREE, (intptr_t)(&df), FKIOCTL, kcred, + &unused, NULL)); +} diff -r f7734d6b8e80 -r 4b9dc4ca8e9f usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_scsi.c --- a/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_scsi.c Fri Mar 04 15:27:25 2011 -0500 +++ b/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_scsi.c Fri Mar 04 13:57:09 2011 -0800 @@ -20,6 +20,8 @@ */ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ #include @@ -98,6 +100,11 @@ void sbd_handle_mode_select(scsi_task_t *task, stmf_data_buf_t *dbuf); void sbd_handle_identifying_info(scsi_task_t *task, stmf_data_buf_t *dbuf); +static void sbd_handle_unmap_xfer(scsi_task_t *task, uint8_t *buf, + uint32_t buflen); +static void sbd_handle_unmap(scsi_task_t *task, stmf_data_buf_t *dbuf); +static void sbd_handle_write_same(scsi_task_t *task); + extern void sbd_pgr_initialize_it(scsi_task_t *, sbd_it_data_t *); extern int sbd_pgr_reservation_conflict(scsi_task_t *); extern void sbd_pgr_reset(sbd_lu_t *); @@ -1754,6 +1761,10 @@ dbuf->db_sglist[0].seg_addr, dbuf->db_data_size); } break; + case SCMD_UNMAP: + sbd_handle_unmap_xfer(task, + dbuf->db_sglist[0].seg_addr, dbuf->db_data_size); + break; case SCMD_PERSISTENT_RESERVE_OUT: if (sl->sl_access_state == SBD_LU_STANDBY) { st_ret = stmf_proxy_scsi_cmd(task, dbuf); @@ -1815,6 +1826,9 @@ p[7] = s & 0xff; p[10] = (blksize >> 8) & 0xff; p[11] = blksize & 0xff; + if (sl->sl_flags & SL_UNMAP_ENABLED) { + p[14] = 0x80; + } sbd_handle_short_read_transfers(task, initial_dbuf, p, cdb_len, 32); break; @@ -2216,6 +2230,105 @@ return (url_length); } +static void +sbd_handle_write_same(scsi_task_t *task) +{ + sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private; + uint64_t addr, len; + uint8_t *p; + + task->task_cmd_xfer_length = 0; + if (task->task_additional_flags & + TASK_AF_NO_EXPECTED_XFER_LENGTH) { + task->task_expected_xfer_length = 0; + } + if (task->task_cdb[1] & 0xF7) { + stmf_scsilib_send_status(task, STATUS_CHECK, + STMF_SAA_INVALID_FIELD_IN_CDB); + return; + } + p = &task->task_cdb[2]; + addr = READ_SCSI64(p, uint64_t); + addr <<= sl->sl_data_blocksize_shift; + len = READ_SCSI32(p+8, uint64_t); + len <<= sl->sl_data_blocksize_shift; + + /* TODO -> full write_same support with data checks... */ + if (sbd_unmap(sl, addr, len) != 0) { + stmf_scsilib_send_status(task, STATUS_CHECK, + STMF_SAA_LBA_OUT_OF_RANGE); + return; + } + stmf_scsilib_send_status(task, STATUS_GOOD, 0); +} + +static void +sbd_handle_unmap(scsi_task_t *task, stmf_data_buf_t *dbuf) +{ + uint32_t cmd_xfer_len; + + cmd_xfer_len = READ_SCSI16(&task->task_cdb[7], uint32_t); + + if (task->task_cdb[1] & 1) { + stmf_scsilib_send_status(task, STATUS_CHECK, + STMF_SAA_INVALID_FIELD_IN_CDB); + return; + } + + if (cmd_xfer_len == 0) { + task->task_cmd_xfer_length = 0; + if (task->task_additional_flags & + TASK_AF_NO_EXPECTED_XFER_LENGTH) { + task->task_expected_xfer_length = 0; + } + stmf_scsilib_send_status(task, STATUS_GOOD, 0); + return; + } + + sbd_handle_short_write_transfers(task, dbuf, cmd_xfer_len); +} + +static void +sbd_handle_unmap_xfer(scsi_task_t *task, uint8_t *buf, uint32_t buflen) +{ + sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private; + uint32_t ulen, dlen, num_desc; + uint64_t addr, len; + uint8_t *p; + int ret; + + if (buflen < 24) { + stmf_scsilib_send_status(task, STATUS_CHECK, + STMF_SAA_INVALID_FIELD_IN_CDB); + return; + } + ulen = READ_SCSI16(buf, uint32_t); + dlen = READ_SCSI16(buf + 2, uint32_t); + num_desc = dlen >> 4; + if (((ulen + 2) != buflen) || ((dlen + 8) != buflen) || (dlen & 0xf) || + (num_desc == 0)) { + stmf_scsilib_send_status(task, STATUS_CHECK, + STMF_SAA_INVALID_FIELD_IN_CDB); + return; + } + + for (p = buf + 8; num_desc; num_desc--, p += 16) { + addr = READ_SCSI64(p, uint64_t); + addr <<= sl->sl_data_blocksize_shift; + len = READ_SCSI32(p+8, uint64_t); + len <<= sl->sl_data_blocksize_shift; + ret = sbd_unmap(sl, addr, len); + if (ret != 0) { + stmf_scsilib_send_status(task, STATUS_CHECK, + STMF_SAA_LBA_OUT_OF_RANGE); + return; + } + } + +unmap_done: + stmf_scsilib_send_status(task, STATUS_GOOD, 0); +} + void sbd_handle_inquiry(struct scsi_task *task, struct stmf_data_buf *initial_dbuf) { @@ -2228,6 +2341,8 @@ uint16_t cmd_size; uint32_t xfer_size = 4; uint32_t mgmt_url_size = 0; + uint8_t exp; + uint64_t s; char *mgmt_url = NULL; @@ -2380,6 +2495,8 @@ switch (cdbp[2]) { case 0x00: page_length = 4 + (mgmt_url_size ? 1 : 0); + if (sl->sl_flags & SL_UNMAP_ENABLED) + page_length += 2; p[0] = byte0; p[3] = page_length; @@ -2392,6 +2509,10 @@ if (mgmt_url_size != 0) p[i++] = 0x85; p[i++] = 0x86; + if (sl->sl_flags & SL_UNMAP_ENABLED) { + p[i++] = 0xb0; + p[i++] = 0xb2; + } } xfer_size = page_length + 4; break; @@ -2482,6 +2603,43 @@ xfer_size = page_length + 4; break; + case 0xb0: + if ((sl->sl_flags & SL_UNMAP_ENABLED) == 0) { + stmf_scsilib_send_status(task, STATUS_CHECK, + STMF_SAA_INVALID_FIELD_IN_CDB); + goto err_done; + } + page_length = 0x3c; + p[0] = byte0; + p[1] = 0xb0; + p[3] = page_length; + p[20] = p[21] = p[22] = p[23] = 0xFF; + p[24] = p[25] = p[26] = p[27] = 0xFF; + xfer_size = page_length + 4; + break; + + case 0xb2: + if ((sl->sl_flags & SL_UNMAP_ENABLED) == 0) { + stmf_scsilib_send_status(task, STATUS_CHECK, + STMF_SAA_INVALID_FIELD_IN_CDB); + goto err_done; + } + page_length = 4; + p[0] = byte0; + p[1] = 0xb2; + p[3] = page_length; + + exp = (uint8_t)sl->sl_data_blocksize_shift; + s = sl->sl_lu_size >> sl->sl_data_blocksize_shift; + while (s & ((uint64_t)0xFFFFFFFF80000000ull)) { + s >>= 1; + exp++; + } + p[4] = exp; + p[5] = 0xc0; + xfer_size = page_length + 4; + break; + default: stmf_scsilib_send_status(task, STATUS_CHECK, STMF_SAA_INVALID_FIELD_IN_CDB); @@ -2908,6 +3066,16 @@ return; } + if ((cdb0 == SCMD_UNMAP) && (sl->sl_flags & SL_UNMAP_ENABLED)) { + sbd_handle_unmap(task, initial_dbuf); + return; + } + + if ((cdb0 == SCMD_WRITE_SAME_G4) && (sl->sl_flags & SL_UNMAP_ENABLED)) { + sbd_handle_write_same(task); + return; + } + if (cdb0 == SCMD_TEST_UNIT_READY) { /* Test unit ready */ task->task_cmd_xfer_length = 0; stmf_scsilib_send_status(task, STATUS_GOOD, 0); diff -r f7734d6b8e80 -r 4b9dc4ca8e9f usr/src/uts/common/io/comstar/lu/stmf_sbd/stmf_sbd.h --- a/usr/src/uts/common/io/comstar/lu/stmf_sbd/stmf_sbd.h Fri Mar 04 15:27:25 2011 -0500 +++ b/usr/src/uts/common/io/comstar/lu/stmf_sbd/stmf_sbd.h Fri Mar 04 13:57:09 2011 -0800 @@ -20,6 +20,8 @@ */ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ #ifndef _STMF_SBD_H @@ -247,26 +249,27 @@ /* * sl_flags */ -#define SL_LINKED 0x00001 -#define SL_META_OPENED 0x00002 -#define SL_REGISTERED 0x00004 -#define SL_META_NEEDS_FLUSH 0x00008 -#define SL_DATA_NEEDS_FLUSH 0x00010 -#define SL_VID_VALID 0x00020 -#define SL_PID_VALID 0x00040 -#define SL_REV_VALID 0x00080 -#define SL_WRITE_PROTECTED 0x00100 -#define SL_MEDIA_LOADED 0x00200 -#define SL_LU_HAS_SCSI2_RESERVATION 0x00400 -#define SL_WRITEBACK_CACHE_DISABLE 0x00800 -#define SL_SAVED_WRITE_CACHE_DISABLE 0x01000 -#define SL_MEDIUM_REMOVAL_PREVENTED 0x02000 -#define SL_NO_DATA_DKIOFLUSH 0x04000 -#define SL_SHARED_META 0x08000 -#define SL_ZFS_META 0x10000 -#define SL_WRITEBACK_CACHE_SET_UNSUPPORTED 0x20000 -#define SL_FLUSH_ON_DISABLED_WRITECACHE 0x40000 -#define SL_CALL_ZVOL 0x80000 +#define SL_LINKED 0x00000001 +#define SL_META_OPENED 0x00000002 +#define SL_REGISTERED 0x00000004 +#define SL_META_NEEDS_FLUSH 0x00000008 +#define SL_DATA_NEEDS_FLUSH 0x00000010 +#define SL_VID_VALID 0x00000020 +#define SL_PID_VALID 0x00000040 +#define SL_REV_VALID 0x00000080 +#define SL_WRITE_PROTECTED 0x00000100 +#define SL_MEDIA_LOADED 0x00000200 +#define SL_LU_HAS_SCSI2_RESERVATION 0x00000400 +#define SL_WRITEBACK_CACHE_DISABLE 0x00000800 +#define SL_SAVED_WRITE_CACHE_DISABLE 0x00001000 +#define SL_MEDIUM_REMOVAL_PREVENTED 0x00002000 +#define SL_NO_DATA_DKIOFLUSH 0x00004000 +#define SL_SHARED_META 0x00008000 +#define SL_ZFS_META 0x00010000 +#define SL_WRITEBACK_CACHE_SET_UNSUPPORTED 0x00020000 +#define SL_FLUSH_ON_DISABLED_WRITECACHE 0x00040000 +#define SL_CALL_ZVOL 0x00080000 +#define SL_UNMAP_ENABLED 0x00100000 /* * sl_trans_op. LU is undergoing some transition and this field @@ -297,6 +300,7 @@ sbd_status_t sbd_flush_data_cache(sbd_lu_t *sl, int fsync_done); sbd_status_t sbd_wcd_set(int wcd, sbd_lu_t *sl); void sbd_wcd_get(int *wcd, sbd_lu_t *sl); +int sbd_unmap(sbd_lu_t *, uint64_t, uint64_t); #ifdef __cplusplus } diff -r f7734d6b8e80 -r 4b9dc4ca8e9f usr/src/uts/common/sys/dkio.h --- a/usr/src/uts/common/sys/dkio.h Fri Mar 04 15:27:25 2011 -0500 +++ b/usr/src/uts/common/sys/dkio.h Fri Mar 04 13:57:09 2011 -0800 @@ -21,6 +21,8 @@ /* * Copyright (c) 1982, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ #ifndef _SYS_DKIO_H @@ -515,6 +517,19 @@ #define FW_TYPE_TEMP 0x0 /* temporary use */ #define FW_TYPE_PERM 0x1 /* permanent use */ +/* + * ioctl to free space (e.g. SCSI UNMAP) off a disk. + */ +#define DKIOCFREE (DKIOC|50) + +typedef struct dkioc_free_s { + uint32_t df_flags; + uint32_t df_reserved; /* For easy 64-bit alignment below... */ + diskaddr_t df_start; + diskaddr_t df_length; +} dkioc_free_t; + +#define DF_WAIT_SYNC 0x00000001 /* Wait for full write-out of free. */ #ifdef __cplusplus } diff -r f7734d6b8e80 -r 4b9dc4ca8e9f usr/src/uts/common/sys/scsi/generic/commands.h --- a/usr/src/uts/common/sys/scsi/generic/commands.h Fri Mar 04 15:27:25 2011 -0500 +++ b/usr/src/uts/common/sys/scsi/generic/commands.h Fri Mar 04 13:57:09 2011 -0800 @@ -21,6 +21,8 @@ /* * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ #ifndef _SYS_SCSI_GENERIC_COMMANDS_H @@ -233,13 +235,15 @@ #define SCMD_READ_BUFFER 0x3c #define SCMD_READ_LONG 0x3E #define SCMD_WRITE_LONG 0x3F +#define SCMD_WRITE_SAME_G1 0x41 +#define SCMD_UNMAP 0x42 +#define SCMD_GET_CONFIGURATION 0x46 +#define SCMD_LOG_SELECT_G1 0x4c +#define SCMD_LOG_SENSE_G1 0x4d #define SCMD_RESERVE_G1 0x56 #define SCMD_RELEASE_G1 0x57 #define SCMD_MODE_SELECT_G1 0x55 #define SCMD_MODE_SENSE_G1 0x5A -#define SCMD_GET_CONFIGURATION 0x46 -#define SCMD_LOG_SELECT_G1 0x4C -#define SCMD_LOG_SENSE_G1 0x4d /* @@ -333,6 +337,7 @@ #define SCMD_READ_G4 0x88 #define SCMD_WRITE_G4 0x8a #define SCMD_WRITE_VERIFY_G4 0x8e +#define SCMD_WRITE_SAME_G4 0x93 #define SCMD_SVC_ACTION_IN_G4 0x9e #define SCMD_SVC_ACTION_OUT_G4 0x9f @@ -455,9 +460,12 @@ /* 0x3c */ SCMD_READ_BUFFER, "read_buffer", \ /* 0x3e */ SCMD_READ_LONG, "read_long", \ /* 0x3f */ SCMD_WRITE_LONG, "write_long", \ +/* 0x41 */ SCMD_WRITE_SAME_G1, "write_same(10)", \ +/* 0x42 */ SCMD_UNMAP, "unmap", \ /* 0x44 */ SCMD_REPORT_DENSITIES | \ /* SCMD_READ_HEADER (from cdio.h) | */ \ 0, "report_densities/read_header", \ +/* 0x46 */ SCMD_GET_CONFIGURATION, "get_configuration", \ /* 0x4c */ SCMD_LOG_SELECT_G1, "log_select", \ /* 0x4d */ SCMD_LOG_SENSE_G1, "log_sense", \ /* 0x55 */ SCMD_MODE_SELECT_G1, "mode_select(10)", \ @@ -477,6 +485,7 @@ /* 0x8f */ SCMD_VERIFY_G4, "verify(16)", \ /* 0x91 */ SCMD_SPACE_G4, "space(16)", \ /* 0x92 */ SCMD_LOCATE_G4, "locate(16)", \ +/* 0x92 */ SCMD_WRITE_SAME_G4, "write_same(16)", \ /* 0x9e */ SCMD_SVC_ACTION_IN_G4, "service_action_in(16)", \ /* 0x9f */ SCMD_SVC_ACTION_OUT_G4, "service_action_out(16)", \ /* 0xa0 */ SCMD_REPORT_LUNS, "report_luns", \ diff -r f7734d6b8e80 -r 4b9dc4ca8e9f usr/src/uts/common/sys/stmf_sbd_ioctl.h --- a/usr/src/uts/common/sys/stmf_sbd_ioctl.h Fri Mar 04 15:27:25 2011 -0500 +++ b/usr/src/uts/common/sys/stmf_sbd_ioctl.h Fri Mar 04 13:57:09 2011 -0800 @@ -21,6 +21,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ #ifndef _STMF_SBD_IOCTL_H @@ -76,6 +78,7 @@ #define SBD_IOCTL_SET_LU_STANDBY SBD_IOCTL_DEF(7) #define SBD_IOCTL_SET_GLOBAL_LU SBD_IOCTL_DEF(8) #define SBD_IOCTL_GET_GLOBAL_LU SBD_IOCTL_DEF(9) +#define SBD_IOCTL_GET_UNMAP_PROPS SBD_IOCTL_DEF(10) typedef struct sbd_create_and_reg_lu { uint32_t slu_struct_size; @@ -222,6 +225,16 @@ uint8_t slp_buf[8]; /* likely more than 8 */ } sbd_lu_props_t; +typedef struct sbd_unmap_props { + uint32_t sup_found_lu:1, + sup_zvol_path_valid:1, + sup_guid_valid:1, + sup_unmap_enabled; + uint32_t sup_rsvd; + char sup_zvol_path[256]; + uint8_t sup_guid[16]; +} sbd_unmap_props_t; + #ifdef __cplusplus } #endif