FreeBSD Bugzilla – Attachment 183925 Details for
Bug 220371
[patch] camdd: Add support for other protocols
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
patch to make camdd protocol aware
v3-0001-Make-camdd-protocol-aware.patch (text/plain), 13.58 KB, created by
chuck
on 2017-06-29 22:36:28 UTC
(
hide
)
Description:
patch to make camdd protocol aware
Filename:
MIME Type:
Creator:
chuck
Created:
2017-06-29 22:36:28 UTC
Size:
13.58 KB
patch
obsolete
>From e58b40f8e41344430d2120200b0dddb908087ba6 Mon Sep 17 00:00:00 2001 >Message-Id: <e58b40f8e41344430d2120200b0dddb908087ba6.1498759895.git-series.chuck@tuffli.net> >In-Reply-To: <cover.c6985da8b5849d2cf336b34d132126e69b3002bd.1498759895.git-series.chuck@tuffli.net> >References: <cover.c6985da8b5849d2cf336b34d132126e69b3002bd.1498759895.git-series.chuck@tuffli.net> >From: Chuck Tuffli <chuck@tuffli.net> >Date: Thu, 29 Jun 2017 10:07:50 -0700 >Subject: [PATCH v3 1/3] Make camdd protocol aware > >This change introduces the concept of the current storage protocol >(SCSI, SATA, NVMe) to camdd. Functional, there are no changes. >Structurally, camdd now determines the protocol of the device, breaks >out the probe function into protocol dependent and independent parts, >and switches on the protocol type to parse the CCB status, setup IOs, >etc. > >Submitted by: Chuck Tuffli <chuck@tuffli.net> >Differential Review: https://reviews.freebsd.org/D11230 >--- > usr.sbin/camdd/camdd.c | 305 ++++++++++++++++++++++++++++-------------- > 1 file changed, 208 insertions(+), 97 deletions(-) > >diff --git a/usr.sbin/camdd/camdd.c b/usr.sbin/camdd/camdd.c >index a51bd7d..f85bf5f 100644 >--- a/usr.sbin/camdd/camdd.c >+++ b/usr.sbin/camdd/camdd.c >@@ -260,6 +260,7 @@ struct camdd_buf { > > struct camdd_dev_pass { > int scsi_dev_type; >+ int protocol; > struct cam_device *dev; > uint64_t max_sector; > uint32_t block_len; >@@ -477,6 +478,9 @@ uint32_t camdd_buf_get_len(struct camdd_buf *buf); > void camdd_buf_add_child(struct camdd_buf *buf, struct camdd_buf *child_buf); > int camdd_probe_tape(int fd, char *filename, uint64_t *max_iosize, > uint64_t *max_blk, uint64_t *min_blk, uint64_t *blk_gran); >+int camdd_probe_pass_scsi(struct cam_device *cam_dev, union ccb *ccb, >+ camdd_argmask arglist, int probe_retry_count, >+ int probe_timeout, uint64_t *maxsector, uint32_t *block_len); > struct camdd_dev *camdd_probe_file(int fd, struct camdd_io_opts *io_opts, > int retry_count, int timeout); > struct camdd_dev *camdd_probe_pass(struct cam_device *cam_dev, >@@ -485,7 +489,8 @@ struct camdd_dev *camdd_probe_pass(struct cam_device *cam_dev, > int probe_timeout, int io_retry_count, > int io_timeout); > void *camdd_file_worker(void *arg); >-camdd_buf_status camdd_ccb_status(union ccb *ccb); >+camdd_buf_status camdd_ccb_status(union ccb *ccb, int protocol); >+int camdd_get_cgd(struct cam_device *device, struct ccb_getdev *cgd); > int camdd_queue_peer_buf(struct camdd_dev *dev, struct camdd_buf *buf); > int camdd_complete_peer_buf(struct camdd_dev *dev, struct camdd_buf *peer_buf); > void camdd_peer_done(struct camdd_buf *buf); >@@ -1248,56 +1253,59 @@ bailout_error: > } > > /* >- * Need to implement this. Do a basic probe: >- * - Check the inquiry data, make sure we're talking to a device that we >- * can reasonably expect to talk to -- direct, RBC, CD, WORM. >- * - Send a test unit ready, make sure the device is available. >- * - Get the capacity and block size. >+ * Get a get device CCB for the specified device. > */ >-struct camdd_dev * >-camdd_probe_pass(struct cam_device *cam_dev, struct camdd_io_opts *io_opts, >- camdd_argmask arglist, int probe_retry_count, >- int probe_timeout, int io_retry_count, int io_timeout) >+int >+camdd_get_cgd(struct cam_device *device, struct ccb_getdev *cgd) > { >- union ccb *ccb; >- uint64_t maxsector; >- uint32_t cpi_maxio, max_iosize, pass_numblocks; >- uint32_t block_len; >- struct scsi_read_capacity_data rcap; >- struct scsi_read_capacity_data_long rcaplong; >- struct camdd_dev *dev; >- struct camdd_dev_pass *pass_dev; >- struct kevent ke; >- int scsi_dev_type; >+ union ccb *ccb; >+ int retval = 0; > >- dev = NULL; >+ ccb = cam_getccb(device); >+ >+ if (ccb == NULL) { >+ warnx("%s: couldn't allocate CCB", __func__); >+ return -1; >+ } > >- scsi_dev_type = SID_TYPE(&cam_dev->inq_data); >- maxsector = 0; >- block_len = 0; >+ CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cgd); > >- /* >- * For devices that support READ CAPACITY, we'll attempt to get the >- * capacity. Otherwise, we really don't support tape or other >- * devices via SCSI passthrough, so just return an error in that case. >- */ >- switch (scsi_dev_type) { >- case T_DIRECT: >- case T_WORM: >- case T_CDROM: >- case T_OPTICAL: >- case T_RBC: >- case T_ZBC_HM: >- break; >- default: >- errx(1, "Unsupported SCSI device type %d", scsi_dev_type); >- break; /*NOTREACHED*/ >+ ccb->ccb_h.func_code = XPT_GDEV_TYPE; >+ >+ if (cam_send_ccb(device, ccb) < 0) { >+ warn("%s: error sending Get Device Information CCB", __func__); >+ cam_error_print(device, ccb, CAM_ESF_ALL, >+ CAM_EPF_ALL, stderr); >+ retval = -1; >+ goto bailout; > } > >- ccb = cam_getccb(cam_dev); >+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { >+ cam_error_print(device, ccb, CAM_ESF_ALL, >+ CAM_EPF_ALL, stderr); >+ retval = -1; >+ goto bailout; >+ } >+ >+ bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev)); >+ >+bailout: >+ cam_freeccb(ccb); >+ >+ return retval; >+} >+ >+int >+camdd_probe_pass_scsi(struct cam_device *cam_dev, union ccb *ccb, >+ camdd_argmask arglist, int probe_retry_count, >+ int probe_timeout, uint64_t *maxsector, uint32_t *block_len) >+{ >+ struct scsi_read_capacity_data rcap; >+ struct scsi_read_capacity_data_long rcaplong; >+ int retval = -1; > > if (ccb == NULL) { >- warnx("%s: error allocating ccb", __func__); >+ warnx("%s: error passed ccb is NULL", __func__); > goto bailout; > } > >@@ -1331,16 +1339,18 @@ camdd_probe_pass(struct cam_device *cam_dev, struct camdd_io_opts *io_opts, > goto bailout; > } > >- maxsector = scsi_4btoul(rcap.addr); >- block_len = scsi_4btoul(rcap.length); >+ *maxsector = scsi_4btoul(rcap.addr); >+ *block_len = scsi_4btoul(rcap.length); > > /* > * A last block of 2^32-1 means that the true capacity is over 2TB, > * and we need to issue the long READ CAPACITY to get the real > * capacity. Otherwise, we're all set. > */ >- if (maxsector != 0xffffffff) >- goto rcap_done; >+ if (*maxsector != 0xffffffff) { >+ retval = 0; >+ goto bailout; >+ } > > scsi_read_capacity_16(&ccb->csio, > /*retries*/ probe_retry_count, >@@ -1352,7 +1362,8 @@ camdd_probe_pass(struct cam_device *cam_dev, struct camdd_io_opts *io_opts, > (uint8_t *)&rcaplong, > sizeof(rcaplong), > /*sense_len*/ SSD_FULL_SIZE, >- /*timeout*/ probe_timeout ? probe_timeout : 5000); >+ /*timeout*/ probe_timeout ? >+ probe_timeout : 5000); > > /* Disable freezing the device queue */ > ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; >@@ -1368,14 +1379,88 @@ camdd_probe_pass(struct cam_device *cam_dev, struct camdd_io_opts *io_opts, > } > > if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { >- cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); >+ cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, >+ stderr); > goto bailout; > } > >- maxsector = scsi_8btou64(rcaplong.addr); >- block_len = scsi_4btoul(rcaplong.length); >+ *maxsector = scsi_8btou64(rcaplong.addr); >+ *block_len = scsi_4btoul(rcaplong.length); >+ >+ retval = 0; >+ >+bailout: >+ return retval; >+} >+ >+/* >+ * Need to implement this. Do a basic probe: >+ * - Check the inquiry data, make sure we're talking to a device that we >+ * can reasonably expect to talk to -- direct, RBC, CD, WORM. >+ * - Send a test unit ready, make sure the device is available. >+ * - Get the capacity and block size. >+ */ >+struct camdd_dev * >+camdd_probe_pass(struct cam_device *cam_dev, struct camdd_io_opts *io_opts, >+ camdd_argmask arglist, int probe_retry_count, >+ int probe_timeout, int io_retry_count, int io_timeout) >+{ >+ union ccb *ccb; >+ uint64_t maxsector = 0; >+ uint32_t cpi_maxio, max_iosize, pass_numblocks; >+ uint32_t block_len = 0; >+ struct camdd_dev *dev = NULL; >+ struct camdd_dev_pass *pass_dev; >+ struct kevent ke; >+ struct ccb_getdev cgd; >+ int retval; >+ int scsi_dev_type; >+ >+ if ((retval = camdd_get_cgd(cam_dev, &cgd)) != 0) { >+ warnx("%s: error retrieving CGD", __func__); >+ return NULL; >+ } >+ >+ ccb = cam_getccb(cam_dev); >+ >+ if (ccb == NULL) { >+ warnx("%s: error allocating ccb", __func__); >+ goto bailout; >+ } >+ >+ switch (cgd.protocol) { >+ case PROTO_SCSI: >+ scsi_dev_type = SID_TYPE(&cam_dev->inq_data); >+ >+ /* >+ * For devices that support READ CAPACITY, we'll attempt to get the >+ * capacity. Otherwise, we really don't support tape or other >+ * devices via SCSI passthrough, so just return an error in that case. >+ */ >+ switch (scsi_dev_type) { >+ case T_DIRECT: >+ case T_WORM: >+ case T_CDROM: >+ case T_OPTICAL: >+ case T_RBC: >+ case T_ZBC_HM: >+ break; >+ default: >+ errx(1, "Unsupported SCSI device type %d", scsi_dev_type); >+ break; /*NOTREACHED*/ >+ } >+ >+ if ((retval = camdd_probe_pass_scsi(cam_dev, ccb, probe_retry_count, >+ arglist, probe_timeout, &maxsector, >+ &block_len))) { >+ goto bailout; >+ } >+ break; >+ default: >+ errx(1, "Unsupported PROTO type %d", cgd.protocol); >+ break; /*NOTREACHED*/ >+ } > >-rcap_done: > if (block_len == 0) { > warnx("Sector size for %s%u is 0, cannot continue", > cam_dev->device_name, cam_dev->dev_unit_num); >@@ -1405,6 +1490,7 @@ rcap_done: > > pass_dev = &dev->dev_spec.pass; > pass_dev->scsi_dev_type = scsi_dev_type; >+ pass_dev->protocol = cgd.protocol; > pass_dev->dev = cam_dev; > pass_dev->max_sector = maxsector; > pass_dev->block_len = block_len; >@@ -1715,43 +1801,50 @@ bailout: > * Simplistic translation of CCB status to our local status. > */ > camdd_buf_status >-camdd_ccb_status(union ccb *ccb) >+camdd_ccb_status(union ccb *ccb, int protocol) > { > camdd_buf_status status = CAMDD_STATUS_NONE; > cam_status ccb_status; > > ccb_status = ccb->ccb_h.status & CAM_STATUS_MASK; > >- switch (ccb_status) { >- case CAM_REQ_CMP: { >- if (ccb->csio.resid == 0) { >- status = CAMDD_STATUS_OK; >- } else if (ccb->csio.dxfer_len > ccb->csio.resid) { >- status = CAMDD_STATUS_SHORT_IO; >- } else { >- status = CAMDD_STATUS_EOF; >+ switch (protocol) { >+ case PROTO_SCSI: >+ switch (ccb_status) { >+ case CAM_REQ_CMP: { >+ if (ccb->csio.resid == 0) { >+ status = CAMDD_STATUS_OK; >+ } else if (ccb->csio.dxfer_len > ccb->csio.resid) { >+ status = CAMDD_STATUS_SHORT_IO; >+ } else { >+ status = CAMDD_STATUS_EOF; >+ } >+ break; > } >- break; >- } >- case CAM_SCSI_STATUS_ERROR: { >- switch (ccb->csio.scsi_status) { >- case SCSI_STATUS_OK: >- case SCSI_STATUS_COND_MET: >- case SCSI_STATUS_INTERMED: >- case SCSI_STATUS_INTERMED_COND_MET: >- status = CAMDD_STATUS_OK; >+ case CAM_SCSI_STATUS_ERROR: { >+ switch (ccb->csio.scsi_status) { >+ case SCSI_STATUS_OK: >+ case SCSI_STATUS_COND_MET: >+ case SCSI_STATUS_INTERMED: >+ case SCSI_STATUS_INTERMED_COND_MET: >+ status = CAMDD_STATUS_OK; >+ break; >+ case SCSI_STATUS_CMD_TERMINATED: >+ case SCSI_STATUS_CHECK_COND: >+ case SCSI_STATUS_QUEUE_FULL: >+ case SCSI_STATUS_BUSY: >+ case SCSI_STATUS_RESERV_CONFLICT: >+ default: >+ status = CAMDD_STATUS_ERROR; >+ break; >+ } > break; >- case SCSI_STATUS_CMD_TERMINATED: >- case SCSI_STATUS_CHECK_COND: >- case SCSI_STATUS_QUEUE_FULL: >- case SCSI_STATUS_BUSY: >- case SCSI_STATUS_RESERV_CONFLICT: >+ } > default: > status = CAMDD_STATUS_ERROR; > break; > } > break; >- } > default: > status = CAMDD_STATUS_ERROR; > break; >@@ -2149,11 +2242,18 @@ camdd_pass_fetch(struct camdd_dev *dev) > CAM_EPF_ALL, stderr); > } > >- data->resid = ccb.csio.resid; >- dev->bytes_transferred += (ccb.csio.dxfer_len - ccb.csio.resid); >+ switch (pass_dev->protocol) { >+ case PROTO_SCSI: >+ data->resid = ccb.csio.resid; >+ dev->bytes_transferred += (ccb.csio.dxfer_len - ccb.csio.resid); >+ break; >+ default: >+ return -1; >+ break; >+ } > > if (buf->status == CAMDD_STATUS_NONE) >- buf->status = camdd_ccb_status(&ccb); >+ buf->status = camdd_ccb_status(&ccb, pass_dev->protocol); > if (buf->status == CAMDD_STATUS_ERROR) > error_count++; > else if (buf->status == CAMDD_STATUS_EOF) { >@@ -2433,9 +2533,6 @@ camdd_pass_run(struct camdd_dev *dev) > > data = &buf->buf_type_spec.data; > >- ccb = &data->ccb; >- CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); >- > /* > * In almost every case the number of blocks should be the device > * block size. The exception may be at the end of an I/O stream >@@ -2446,21 +2543,36 @@ camdd_pass_run(struct camdd_dev *dev) > else > num_blocks = data->fill_len / pass_dev->block_len; > >- scsi_read_write(&ccb->csio, >- /*retries*/ dev->retry_count, >- /*cbfcnp*/ NULL, >- /*tag_action*/ MSG_SIMPLE_Q_TAG, >- /*readop*/ (dev->write_dev == 0) ? SCSI_RW_READ : >- SCSI_RW_WRITE, >- /*byte2*/ 0, >- /*minimum_cmd_size*/ dev->min_cmd_size, >- /*lba*/ buf->lba, >- /*block_count*/ num_blocks, >- /*data_ptr*/ (data->sg_count != 0) ? >- (uint8_t *)data->segs : data->buf, >- /*dxfer_len*/ (num_blocks * pass_dev->block_len), >- /*sense_len*/ SSD_FULL_SIZE, >- /*timeout*/ dev->io_timeout); >+ ccb = &data->ccb; >+ >+ switch (pass_dev->protocol) { >+ case PROTO_SCSI: >+ CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); >+ >+ scsi_read_write(&ccb->csio, >+ /*retries*/ dev->retry_count, >+ /*cbfcnp*/ NULL, >+ /*tag_action*/ MSG_SIMPLE_Q_TAG, >+ /*readop*/ (dev->write_dev == 0) ? SCSI_RW_READ : >+ SCSI_RW_WRITE, >+ /*byte2*/ 0, >+ /*minimum_cmd_size*/ dev->min_cmd_size, >+ /*lba*/ buf->lba, >+ /*block_count*/ num_blocks, >+ /*data_ptr*/ (data->sg_count != 0) ? >+ (uint8_t *)data->segs : data->buf, >+ /*dxfer_len*/ (num_blocks * pass_dev->block_len), >+ /*sense_len*/ SSD_FULL_SIZE, >+ /*timeout*/ dev->io_timeout); >+ >+ if (data->sg_count != 0) { >+ ccb->csio.sglist_cnt = data->sg_count; >+ } >+ break; >+ default: >+ retval = -1; >+ goto bailout; >+ } > > /* Disable freezing the device queue */ > ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; >@@ -2469,7 +2581,6 @@ camdd_pass_run(struct camdd_dev *dev) > ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; > > if (data->sg_count != 0) { >- ccb->csio.sglist_cnt = data->sg_count; > ccb->ccb_h.flags |= CAM_DATA_SG; > } > >-- >git-series 0.9.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 220371
: 183925