svn commit: r275474 - in head/sys: cam/ctl cam/scsi cddl/contrib/opensolaris/uts/common/fs/zfs

Alexander Motin mav at FreeBSD.org
Thu Dec 4 11:34:22 UTC 2014


Author: mav
Date: Thu Dec  4 11:34:19 2014
New Revision: 275474
URL: https://svnweb.freebsd.org/changeset/base/275474

Log:
  Add GET LBA STATUS command support to CTL.
  
  It is implemented for LUNs backed by ZVOLs in "dev" mode and files.
  GEOM has no such API, so for LUNs backed by raw devices all LBAs will
  be reported as mapped/unknown.
  
  MFC after:	2 weeks
  Sponsored by:	iXsystems, Inc.

Modified:
  head/sys/cam/ctl/ctl.c
  head/sys/cam/ctl/ctl.h
  head/sys/cam/ctl/ctl_backend_block.c
  head/sys/cam/ctl/ctl_backend_ramdisk.c
  head/sys/cam/ctl/ctl_cmd_table.c
  head/sys/cam/ctl/ctl_private.h
  head/sys/cam/scsi/scsi_all.h
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c

Modified: head/sys/cam/ctl/ctl.c
==============================================================================
--- head/sys/cam/ctl/ctl.c	Thu Dec  4 05:02:12 2014	(r275473)
+++ head/sys/cam/ctl/ctl.c	Thu Dec  4 11:34:19 2014	(r275474)
@@ -5172,6 +5172,40 @@ ctl_config_write_done(union ctl_io *io)
 		free(buf, M_CTL);
 }
 
+void
+ctl_config_read_done(union ctl_io *io)
+{
+	uint8_t *buf;
+
+	/*
+	 * If there is some error -- we are done, skip data transfer.
+	 */
+	if ((io->io_hdr.flags & CTL_FLAG_ABORT) != 0 ||
+	    ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE &&
+	     (io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)) {
+		if (io->io_hdr.flags & CTL_FLAG_ALLOCATED)
+			buf = io->scsiio.kern_data_ptr;
+		else
+			buf = NULL;
+		ctl_done(io);
+		if (buf)
+			free(buf, M_CTL);
+		return;
+	}
+
+	/*
+	 * If the IO_CONT flag is set, we need to call the supplied
+	 * function to continue processing the I/O, instead of completing
+	 * the I/O just yet.
+	 */
+	if (io->io_hdr.flags & CTL_FLAG_IO_CONT) {
+		io->scsiio.io_cont(io);
+		return;
+	}
+
+	ctl_datamove(io);
+}
+
 /*
  * SCSI release command.
  */
@@ -7173,6 +7207,66 @@ ctl_read_capacity_16(struct ctl_scsiio *
 }
 
 int
+ctl_get_lba_status(struct ctl_scsiio *ctsio)
+{
+	struct scsi_get_lba_status *cdb;
+	struct scsi_get_lba_status_data *data;
+	struct ctl_lun *lun;
+	struct ctl_lba_len_flags *lbalen;
+	uint64_t lba;
+	uint32_t alloc_len, total_len;
+	int retval;
+
+	CTL_DEBUG_PRINT(("ctl_get_lba_status\n"));
+
+	lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
+	cdb = (struct scsi_get_lba_status *)ctsio->cdb;
+	lba = scsi_8btou64(cdb->addr);
+	alloc_len = scsi_4btoul(cdb->alloc_len);
+
+	if (lba > lun->be_lun->maxlba) {
+		ctl_set_lba_out_of_range(ctsio);
+		ctl_done((union ctl_io *)ctsio);
+		return (CTL_RETVAL_COMPLETE);
+	}
+
+	total_len = sizeof(*data) + sizeof(data->descr[0]);
+	ctsio->kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
+	data = (struct scsi_get_lba_status_data *)ctsio->kern_data_ptr;
+
+	if (total_len < alloc_len) {
+		ctsio->residual = alloc_len - total_len;
+		ctsio->kern_data_len = total_len;
+		ctsio->kern_total_len = total_len;
+	} else {
+		ctsio->residual = 0;
+		ctsio->kern_data_len = alloc_len;
+		ctsio->kern_total_len = alloc_len;
+	}
+	ctsio->kern_data_resid = 0;
+	ctsio->kern_rel_offset = 0;
+	ctsio->kern_sg_entries = 0;
+
+	/* Fill dummy data in case backend can't tell anything. */
+	scsi_ulto4b(4 + sizeof(data->descr[0]), data->length);
+	scsi_u64to8b(lba, data->descr[0].addr);
+	scsi_ulto4b(MIN(UINT32_MAX, lun->be_lun->maxlba + 1 - lba),
+	    data->descr[0].length);
+	data->descr[0].status = 0; /* Mapped or unknown. */
+
+	ctl_set_success(ctsio);
+	ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
+	ctsio->be_move_done = ctl_config_move_done;
+
+	lbalen = (struct ctl_lba_len_flags *)&ctsio->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
+	lbalen->lba = lba;
+	lbalen->len = total_len;
+	lbalen->flags = 0;
+	retval = lun->backend->config_read((union ctl_io *)ctsio);
+	return (CTL_RETVAL_COMPLETE);
+}
+
+int
 ctl_read_defect(struct ctl_scsiio *ctsio)
 {
 	struct scsi_read_defect_data_10 *ccb10;
@@ -10642,6 +10736,14 @@ ctl_get_lba_len(union ctl_io *io, uint64
 		*len = UINT64_MAX;
 		break;
 	}
+	case SERVICE_ACTION_IN: {	/* GET LBA STATUS */
+		struct scsi_get_lba_status *cdb;
+
+		cdb = (struct scsi_get_lba_status *)io->scsiio.cdb;
+		*lba = scsi_8btou64(cdb->addr);
+		*len = UINT32_MAX;
+		break;
+	}
 	default:
 		return (1);
 		break; /* NOTREACHED */

Modified: head/sys/cam/ctl/ctl.h
==============================================================================
--- head/sys/cam/ctl/ctl.h	Thu Dec  4 05:02:12 2014	(r275473)
+++ head/sys/cam/ctl/ctl.h	Thu Dec  4 11:34:19 2014	(r275474)
@@ -186,6 +186,7 @@ int ctl_config_move_done(union ctl_io *i
 void ctl_datamove(union ctl_io *io);
 void ctl_done(union ctl_io *io);
 void ctl_data_submit_done(union ctl_io *io);
+void ctl_config_read_done(union ctl_io *io);
 void ctl_config_write_done(union ctl_io *io);
 void ctl_portDB_changed(int portnum);
 void ctl_init_isc_msg(void);

Modified: head/sys/cam/ctl/ctl_backend_block.c
==============================================================================
--- head/sys/cam/ctl/ctl_backend_block.c	Thu Dec  4 05:02:12 2014	(r275473)
+++ head/sys/cam/ctl/ctl_backend_block.c	Thu Dec  4 11:34:19 2014	(r275474)
@@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/disk.h>
 #include <sys/fcntl.h>
 #include <sys/filedesc.h>
+#include <sys/filio.h>
 #include <sys/proc.h>
 #include <sys/pcpu.h>
 #include <sys/module.h>
@@ -163,6 +164,7 @@ struct ctl_be_block_lun {
 	cbb_dispatch_t dispatch;
 	cbb_dispatch_t lun_flush;
 	cbb_dispatch_t unmap;
+	cbb_dispatch_t get_lba_status;
 	cbb_getattr_t getattr;
 	uma_zone_t lun_zone;
 	uint64_t size_blocks;
@@ -180,6 +182,7 @@ struct ctl_be_block_lun {
 	struct task io_task;
 	int num_threads;
 	STAILQ_HEAD(, ctl_io_hdr) input_queue;
+	STAILQ_HEAD(, ctl_io_hdr) config_read_queue;
 	STAILQ_HEAD(, ctl_io_hdr) config_write_queue;
 	STAILQ_HEAD(, ctl_io_hdr) datamove_queue;
 	struct mtx_padalign io_lock;
@@ -237,6 +240,8 @@ static void ctl_be_block_flush_file(stru
 				    struct ctl_be_block_io *beio);
 static void ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun,
 				       struct ctl_be_block_io *beio);
+static void ctl_be_block_gls_file(struct ctl_be_block_lun *be_lun,
+				  struct ctl_be_block_io *beio);
 static void ctl_be_block_flush_dev(struct ctl_be_block_lun *be_lun,
 				   struct ctl_be_block_io *beio);
 static void ctl_be_block_unmap_dev(struct ctl_be_block_lun *be_lun,
@@ -245,6 +250,8 @@ static void ctl_be_block_dispatch_dev(st
 				      struct ctl_be_block_io *beio);
 static uint64_t ctl_be_block_getattr_dev(struct ctl_be_block_lun *be_lun,
 					 const char *attrname);
+static void ctl_be_block_cr_dispatch(struct ctl_be_block_lun *be_lun,
+				    union ctl_io *io);
 static void ctl_be_block_cw_dispatch(struct ctl_be_block_lun *be_lun,
 				    union ctl_io *io);
 static void ctl_be_block_dispatch(struct ctl_be_block_lun *be_lun,
@@ -753,6 +760,46 @@ ctl_be_block_dispatch_file(struct ctl_be
 }
 
 static void
+ctl_be_block_gls_file(struct ctl_be_block_lun *be_lun,
+			struct ctl_be_block_io *beio)
+{
+	union ctl_io *io = beio->io;
+	struct ctl_lba_len_flags *lbalen = ARGS(io);
+	struct scsi_get_lba_status_data *data;
+	off_t roff, off;
+	int error, status;
+
+	DPRINTF("entered\n");
+
+	off = roff = ((off_t)lbalen->lba) << be_lun->blocksize_shift;
+	vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
+	error = VOP_IOCTL(be_lun->vn, FIOSEEKHOLE, &off,
+	    0, curthread->td_ucred, curthread);
+	if (error == 0 && off > roff)
+		status = 0;	/* mapped up to off */
+	else {
+		error = VOP_IOCTL(be_lun->vn, FIOSEEKDATA, &off,
+		    0, curthread->td_ucred, curthread);
+		if (error == 0 && off > roff)
+			status = 1;	/* deallocated up to off */
+		else {
+			status = 0;	/* unknown up to the end */
+			off = be_lun->size_bytes;
+		}
+	}
+	VOP_UNLOCK(be_lun->vn, 0);
+
+	off >>= be_lun->blocksize_shift;
+	data = (struct scsi_get_lba_status_data *)io->scsiio.kern_data_ptr;
+	scsi_u64to8b(lbalen->lba, data->descr[0].addr);
+	scsi_ulto4b(MIN(UINT32_MAX, off - lbalen->lba),
+	    data->descr[0].length);
+	data->descr[0].status = status;
+
+	ctl_complete_beio(beio);
+}
+
+static void
 ctl_be_block_dispatch_zvol(struct ctl_be_block_lun *be_lun,
 			   struct ctl_be_block_io *beio)
 {
@@ -845,6 +892,45 @@ ctl_be_block_dispatch_zvol(struct ctl_be
 }
 
 static void
+ctl_be_block_gls_zvol(struct ctl_be_block_lun *be_lun,
+			struct ctl_be_block_io *beio)
+{
+	struct ctl_be_block_devdata *dev_data = &be_lun->backend.dev;
+	union ctl_io *io = beio->io;
+	struct ctl_lba_len_flags *lbalen = ARGS(io);
+	struct scsi_get_lba_status_data *data;
+	off_t roff, off;
+	int error, status;
+
+	DPRINTF("entered\n");
+
+	off = roff = ((off_t)lbalen->lba) << be_lun->blocksize_shift;
+	error = (*dev_data->csw->d_ioctl)(dev_data->cdev, FIOSEEKHOLE,
+	    (caddr_t)&off, FREAD, curthread);
+	if (error == 0 && off > roff)
+		status = 0;	/* mapped up to off */
+	else {
+		error = (*dev_data->csw->d_ioctl)(dev_data->cdev, FIOSEEKDATA,
+		    (caddr_t)&off, FREAD, curthread);
+		if (error == 0 && off > roff)
+			status = 1;	/* deallocated up to off */
+		else {
+			status = 0;	/* unknown up to the end */
+			off = be_lun->size_bytes;
+		}
+	}
+
+	off >>= be_lun->blocksize_shift;
+	data = (struct scsi_get_lba_status_data *)io->scsiio.kern_data_ptr;
+	scsi_u64to8b(lbalen->lba, data->descr[0].addr);
+	scsi_ulto4b(MIN(UINT32_MAX, off - lbalen->lba),
+	    data->descr[0].length);
+	data->descr[0].status = status;
+
+	ctl_complete_beio(beio);
+}
+
+static void
 ctl_be_block_flush_dev(struct ctl_be_block_lun *be_lun,
 		       struct ctl_be_block_io *beio)
 {
@@ -1217,6 +1303,49 @@ ctl_be_block_cw_dispatch_unmap(struct ct
 }
 
 static void
+ctl_be_block_cr_done(struct ctl_be_block_io *beio)
+{
+	union ctl_io *io;
+
+	io = beio->io;
+	ctl_free_beio(beio);
+	ctl_config_read_done(io);
+}
+
+static void
+ctl_be_block_cr_dispatch(struct ctl_be_block_lun *be_lun,
+			 union ctl_io *io)
+{
+	struct ctl_be_block_io *beio;
+	struct ctl_be_block_softc *softc;
+
+	DPRINTF("entered\n");
+
+	softc = be_lun->softc;
+	beio = ctl_alloc_beio(softc);
+	beio->io = io;
+	beio->lun = be_lun;
+	beio->beio_cont = ctl_be_block_cr_done;
+	PRIV(io)->ptr = (void *)beio;
+
+	switch (io->scsiio.cdb[0]) {
+	case SERVICE_ACTION_IN:		/* GET LBA STATUS */
+		beio->bio_cmd = -1;
+		beio->ds_trans_type = DEVSTAT_NO_DATA;
+		beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
+		beio->io_len = 0;
+		if (be_lun->get_lba_status)
+			be_lun->get_lba_status(be_lun, beio);
+		else
+			ctl_be_block_cr_done(beio);
+		break;
+	default:
+		panic("Unhandled CDB type %#x", io->scsiio.cdb[0]);
+		break;
+	}
+}
+
+static void
 ctl_be_block_cw_done(struct ctl_be_block_io *beio)
 {
 	union ctl_io *io;
@@ -1451,16 +1580,21 @@ ctl_be_block_worker(void *context, int p
 		}
 		io = (union ctl_io *)STAILQ_FIRST(&be_lun->config_write_queue);
 		if (io != NULL) {
-
 			DPRINTF("config write queue\n");
-
 			STAILQ_REMOVE(&be_lun->config_write_queue, &io->io_hdr,
 				      ctl_io_hdr, links);
-
 			mtx_unlock(&be_lun->queue_lock);
-
 			ctl_be_block_cw_dispatch(be_lun, io);
-
+			mtx_lock(&be_lun->queue_lock);
+			continue;
+		}
+		io = (union ctl_io *)STAILQ_FIRST(&be_lun->config_read_queue);
+		if (io != NULL) {
+			DPRINTF("config read queue\n");
+			STAILQ_REMOVE(&be_lun->config_read_queue, &io->io_hdr,
+				      ctl_io_hdr, links);
+			mtx_unlock(&be_lun->queue_lock);
+			ctl_be_block_cr_dispatch(be_lun, io);
 			mtx_lock(&be_lun->queue_lock);
 			continue;
 		}
@@ -1589,6 +1723,7 @@ ctl_be_block_open_file(struct ctl_be_blo
 	be_lun->dev_type = CTL_BE_BLOCK_FILE;
 	be_lun->dispatch = ctl_be_block_dispatch_file;
 	be_lun->lun_flush = ctl_be_block_flush_file;
+	be_lun->get_lba_status = ctl_be_block_gls_file;
 
 	error = VOP_GETATTR(be_lun->vn, &vattr, curthread->td_ucred);
 	if (error != 0) {
@@ -1675,9 +1810,10 @@ ctl_be_block_open_dev(struct ctl_be_bloc
 					     &be_lun->backend.dev.dev_ref);
 	if (be_lun->backend.dev.csw == NULL)
 		panic("Unable to retrieve device switch");
-	if (strcmp(be_lun->backend.dev.csw->d_name, "zvol") == 0)
+	if (strcmp(be_lun->backend.dev.csw->d_name, "zvol") == 0) {
 		be_lun->dispatch = ctl_be_block_dispatch_zvol;
-	else
+		be_lun->get_lba_status = ctl_be_block_gls_zvol;
+	} else
 		be_lun->dispatch = ctl_be_block_dispatch_dev;
 	be_lun->lun_flush = ctl_be_block_flush_dev;
 	be_lun->unmap = ctl_be_block_unmap_dev;
@@ -1952,6 +2088,7 @@ ctl_be_block_create(struct ctl_be_block_
 	be_lun->params = req->reqdata.create;
 	be_lun->softc = softc;
 	STAILQ_INIT(&be_lun->input_queue);
+	STAILQ_INIT(&be_lun->config_read_queue);
 	STAILQ_INIT(&be_lun->config_write_queue);
 	STAILQ_INIT(&be_lun->datamove_queue);
 	sprintf(be_lun->lunname, "cblk%d", softc->num_luns);
@@ -2582,13 +2719,50 @@ ctl_be_block_config_write(union ctl_io *
 	}
 
 	return (retval);
-
 }
 
 static int
 ctl_be_block_config_read(union ctl_io *io)
 {
-	return (0);
+	struct ctl_be_block_lun *be_lun;
+	struct ctl_be_lun *ctl_be_lun;
+	int retval = 0;
+
+	DPRINTF("entered\n");
+
+	ctl_be_lun = (struct ctl_be_lun *)io->io_hdr.ctl_private[
+		CTL_PRIV_BACKEND_LUN].ptr;
+	be_lun = (struct ctl_be_block_lun *)ctl_be_lun->be_lun;
+
+	switch (io->scsiio.cdb[0]) {
+	case SERVICE_ACTION_IN:
+		if (io->scsiio.cdb[1] == SGLS_SERVICE_ACTION) {
+			mtx_lock(&be_lun->queue_lock);
+			STAILQ_INSERT_TAIL(&be_lun->config_read_queue,
+			    &io->io_hdr, links);
+			mtx_unlock(&be_lun->queue_lock);
+			taskqueue_enqueue(be_lun->io_taskqueue,
+			    &be_lun->io_task);
+			retval = CTL_RETVAL_QUEUED;
+			break;
+		}
+		ctl_set_invalid_field(&io->scsiio,
+				      /*sks_valid*/ 1,
+				      /*command*/ 1,
+				      /*field*/ 1,
+				      /*bit_valid*/ 1,
+				      /*bit*/ 4);
+		ctl_config_read_done(io);
+		retval = CTL_RETVAL_COMPLETE;
+		break;
+	default:
+		ctl_set_invalid_opcode(&io->scsiio);
+		ctl_config_read_done(io);
+		retval = CTL_RETVAL_COMPLETE;
+		break;
+	}
+
+	return (retval);
 }
 
 static int

Modified: head/sys/cam/ctl/ctl_backend_ramdisk.c
==============================================================================
--- head/sys/cam/ctl/ctl_backend_ramdisk.c	Thu Dec  4 05:02:12 2014	(r275473)
+++ head/sys/cam/ctl/ctl_backend_ramdisk.c	Thu Dec  4 11:34:19 2014	(r275474)
@@ -967,8 +967,31 @@ ctl_backend_ramdisk_config_write(union c
 static int
 ctl_backend_ramdisk_config_read(union ctl_io *io)
 {
-	/*
-	 * XXX KDM need to implement!!
-	 */
-	return (0);
+	int retval = 0;
+
+	switch (io->scsiio.cdb[0]) {
+	case SERVICE_ACTION_IN:
+		if (io->scsiio.cdb[1] == SGLS_SERVICE_ACTION) {
+			/* We have nothing to tell, leave default data. */
+			ctl_config_read_done(io);
+			retval = CTL_RETVAL_COMPLETE;
+			break;
+		}
+		ctl_set_invalid_field(&io->scsiio,
+				      /*sks_valid*/ 1,
+				      /*command*/ 1,
+				      /*field*/ 1,
+				      /*bit_valid*/ 1,
+				      /*bit*/ 4);
+		ctl_config_read_done(io);
+		retval = CTL_RETVAL_COMPLETE;
+		break;
+	default:
+		ctl_set_invalid_opcode(&io->scsiio);
+		ctl_config_read_done(io);
+		retval = CTL_RETVAL_COMPLETE;
+		break;
+	}
+
+	return (retval);
 }

Modified: head/sys/cam/ctl/ctl_cmd_table.c
==============================================================================
--- head/sys/cam/ctl/ctl_cmd_table.c	Thu Dec  4 05:02:12 2014	(r275473)
+++ head/sys/cam/ctl/ctl_cmd_table.c	Thu Dec  4 11:34:19 2014	(r275474)
@@ -433,7 +433,7 @@ const struct ctl_cmd_entry ctl_cmd_table
 /* 0F */
 {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
 
-/* 10 */
+/* 10 READ CAPACITY(16) */
 {ctl_read_capacity_16, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_SLUN |
 					  CTL_CMD_FLAG_OK_ON_STOPPED |
 					  CTL_CMD_FLAG_OK_ON_INOPERABLE |
@@ -443,7 +443,18 @@ const struct ctl_cmd_entry ctl_cmd_table
  CTL_LUN_PAT_READCAP,
  16, {0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0x07}},
 
-/* 11-1f */
+/* 11 */
+{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
+
+/* 12 GET LBA STATUS */
+{ctl_get_lba_status, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_SLUN |
+				      CTL_FLAG_DATA_IN |
+				      CTL_CMD_FLAG_ALLOW_ON_PR_WRESV,
+ CTL_LUN_PAT_READ | CTL_LUN_PAT_RANGE,
+ 16, {0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0, 0x07}},
+
+/* 13-1f */
 };
 
 /* A3 MAINTENANCE IN */

Modified: head/sys/cam/ctl/ctl_private.h
==============================================================================
--- head/sys/cam/ctl/ctl_private.h	Thu Dec  4 05:02:12 2014	(r275473)
+++ head/sys/cam/ctl/ctl_private.h	Thu Dec  4 11:34:19 2014	(r275474)
@@ -516,6 +516,7 @@ int ctl_report_supported_opcodes(struct 
 int ctl_report_supported_tmf(struct ctl_scsiio *ctsio);
 int ctl_report_timestamp(struct ctl_scsiio *ctsio);
 int ctl_isc(struct ctl_scsiio *ctsio);
+int ctl_get_lba_status(struct ctl_scsiio *ctsio);
 
 void ctl_tpc_init(struct ctl_softc *softc);
 void ctl_tpc_shutdown(struct ctl_softc *softc);

Modified: head/sys/cam/scsi/scsi_all.h
==============================================================================
--- head/sys/cam/scsi/scsi_all.h	Thu Dec  4 05:02:12 2014	(r275473)
+++ head/sys/cam/scsi/scsi_all.h	Thu Dec  4 11:34:19 2014	(r275474)
@@ -2518,6 +2518,32 @@ struct scsi_read_capacity_data_long
 	uint8_t	reserved[16];
 };
 
+struct scsi_get_lba_status
+{
+	uint8_t opcode;
+#define	SGLS_SERVICE_ACTION	0x12
+	uint8_t service_action;
+	uint8_t addr[8];
+	uint8_t alloc_len[4];
+	uint8_t reserved;
+	uint8_t control;
+};
+
+struct scsi_get_lba_status_data_descr
+{
+	uint8_t addr[8];
+	uint8_t length[4];
+	uint8_t status;
+	uint8_t reserved[3];
+};
+
+struct scsi_get_lba_status_data
+{
+	uint8_t length[4];
+	uint8_t reserved[4];
+	struct scsi_get_lba_status_data_descr descr[];
+};
+
 struct scsi_report_luns
 {
 	uint8_t opcode;

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c	Thu Dec  4 05:02:12 2014	(r275473)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c	Thu Dec  4 11:34:19 2014	(r275474)
@@ -91,6 +91,7 @@
 #include <sys/dmu_tx.h>
 #include <sys/zfeature.h>
 #include <sys/zio_checksum.h>
+#include <sys/filio.h>
 
 #include <geom/geom.h>
 
@@ -2914,6 +2915,18 @@ zvol_d_ioctl(struct cdev *dev, u_long cm
 			error = ENOIOCTL;
 		break;
 	}
+	case FIOSEEKHOLE:
+	case FIOSEEKDATA: {
+		off_t *off = (off_t *)data;
+		uint64_t noff;
+		boolean_t hole;
+
+		hole = (cmd == FIOSEEKHOLE);
+		noff = *off;
+		error = dmu_offset_next(zv->zv_objset, ZVOL_OBJ, hole, &noff);
+		*off = noff;
+		break;
+	}
 	default:
 		error = ENOIOCTL;
 	}


More information about the svn-src-head mailing list