diff options
Diffstat (limited to 'sys/cam/scsi/scsi_pass.c')
-rw-r--r-- | sys/cam/scsi/scsi_pass.c | 102 |
1 files changed, 67 insertions, 35 deletions
diff --git a/sys/cam/scsi/scsi_pass.c b/sys/cam/scsi/scsi_pass.c index 5d6febe74539..5a24f11e60e2 100644 --- a/sys/cam/scsi/scsi_pass.c +++ b/sys/cam/scsi/scsi_pass.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. * Copyright (c) 1997, 1998, 1999 Kenneth D. Merry. @@ -27,9 +27,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -128,7 +125,7 @@ struct pass_io_req { struct pass_softc { pass_state state; pass_flags flags; - u_int8_t pd_type; + uint8_t pd_type; int open_count; u_int maxio; struct devstat *device_stats; @@ -165,7 +162,7 @@ static periph_dtor_t passcleanup; static periph_start_t passstart; static void pass_shutdown_kqueue(void *context, int pending); static void pass_add_physpath(void *context, int pending); -static void passasync(void *callback_arg, u_int32_t code, +static void passasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg); static void passdone(struct cam_periph *periph, union ccb *done_ccb); @@ -179,10 +176,12 @@ static int passmemsetup(struct cam_periph *periph, struct pass_io_req *io_req); static int passmemdone(struct cam_periph *periph, struct pass_io_req *io_req); -static int passerror(union ccb *ccb, u_int32_t cam_flags, - u_int32_t sense_flags); +static int passerror(union ccb *ccb, uint32_t cam_flags, + uint32_t sense_flags); static int passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb); +static void passflags(union ccb *ccb, uint32_t *cam_flags, + uint32_t *sense_flags); static struct periph_driver passdriver = { @@ -397,6 +396,18 @@ passcleanup(struct cam_periph *periph) */ taskqueue_drain(taskqueue_thread, &softc->add_physpath_task); + /* + * It should be safe to destroy the zones from here, because all + * of the references to this peripheral have been freed, and all + * I/O has been terminated and freed. We check the zones for NULL + * because they may not have been allocated yet if the device went + * away before any asynchronous I/O has been issued. + */ + if (softc->pass_zone != NULL) + uma_zdestroy(softc->pass_zone); + if (softc->pass_io_zone != NULL) + uma_zdestroy(softc->pass_io_zone); + cam_periph_lock(periph); free(softc, M_DEVBUF); @@ -445,8 +456,9 @@ pass_add_physpath(void *context, int pending) "GEOM::physpath", periph->path) == 0 && strlen(physpath) != 0) { mtx_unlock(mtx); - make_dev_physpath_alias(MAKEDEV_WAITOK, &softc->alias_dev, - softc->dev, softc->alias_dev, physpath); + make_dev_physpath_alias(MAKEDEV_WAITOK | MAKEDEV_CHECKNAME, + &softc->alias_dev, softc->dev, + softc->alias_dev, physpath); mtx_lock(mtx); } @@ -470,7 +482,7 @@ out: } static void -passasync(void *callback_arg, u_int32_t code, +passasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) { struct cam_periph *periph; @@ -899,19 +911,17 @@ passdone(struct cam_periph *periph, union ccb *done_ccb) xpt_print(periph->path, "%s: called for user CCB %p\n", __func__, io_req->user_ccb_ptr); #endif - if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) - && (done_ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) - && ((io_req->flags & PASS_IO_ABANDONED) == 0)) { + if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) && + ((io_req->flags & PASS_IO_ABANDONED) == 0)) { int error; + uint32_t cam_flags, sense_flags; - error = passerror(done_ccb, CAM_RETRY_SELTO, - SF_RETRY_UA | SF_NO_PRINT); + passflags(done_ccb, &cam_flags, &sense_flags); + error = passerror(done_ccb, cam_flags, sense_flags); if (error == ERESTART) { - /* - * A retry was scheduled, so - * just return. - */ + KASSERT(((sense_flags & SF_NO_RETRY) == 0), + ("passerror returned ERESTART with no retry requested\n")); return; } } @@ -1073,7 +1083,7 @@ passcreatezone(struct cam_periph *periph) /* * Set the flags appropriately and notify any other waiters. */ - softc->flags &= PASS_FLAG_ZONE_INPROG; + softc->flags &= ~PASS_FLAG_ZONE_INPROG; softc->flags |= PASS_FLAG_ZONE_VALID; wakeup(&softc->pass_zone); } else { @@ -1107,7 +1117,7 @@ static void passiocleanup(struct pass_softc *softc, struct pass_io_req *io_req) { union ccb *ccb; - u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS]; + uint8_t **data_ptrs[CAM_PERIPH_MAXMAPS]; int i, numbufs; ccb = &io_req->ccb; @@ -1117,10 +1127,10 @@ passiocleanup(struct pass_softc *softc, struct pass_io_req *io_req) numbufs = min(io_req->num_bufs, 2); if (numbufs == 1) { - data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches; + data_ptrs[0] = (uint8_t **)&ccb->cdm.matches; } else { - data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns; - data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches; + data_ptrs[0] = (uint8_t **)&ccb->cdm.patterns; + data_ptrs[1] = (uint8_t **)&ccb->cdm.matches; } break; case XPT_SCSI_IO: @@ -1295,15 +1305,15 @@ passmemsetup(struct cam_periph *periph, struct pass_io_req *io_req) return(EINVAL); } if (ccb->cdm.pattern_buf_len > 0) { - data_ptrs[0] = (u_int8_t **)&ccb->cdm.patterns; + data_ptrs[0] = (uint8_t **)&ccb->cdm.patterns; lengths[0] = ccb->cdm.pattern_buf_len; dirs[0] = CAM_DIR_OUT; - data_ptrs[1] = (u_int8_t **)&ccb->cdm.matches; + data_ptrs[1] = (uint8_t **)&ccb->cdm.matches; lengths[1] = ccb->cdm.match_buf_len; dirs[1] = CAM_DIR_IN; numbufs = 2; } else { - data_ptrs[0] = (u_int8_t **)&ccb->cdm.matches; + data_ptrs[0] = (uint8_t **)&ccb->cdm.matches; lengths[0] = ccb->cdm.match_buf_len; dirs[0] = CAM_DIR_IN; numbufs = 1; @@ -2217,24 +2227,46 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb) * that request. Otherwise, it's up to the user to perform any * error recovery. */ - cam_periph_runccb(ccb, (ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ? - passerror : NULL, /* cam_flags */ CAM_RETRY_SELTO, - /* sense_flags */ SF_RETRY_UA | SF_NO_PRINT, - softc->device_stats); + { + uint32_t cam_flags, sense_flags; + + passflags(ccb, &cam_flags, &sense_flags); + cam_periph_runccb(ccb, passerror, cam_flags, + sense_flags, softc->device_stats); + } cam_periph_unlock(periph); - cam_periph_unmapmem(ccb, &mapinfo); + error = cam_periph_unmapmem(ccb, &mapinfo); cam_periph_lock(periph); ccb->ccb_h.cbfcnp = NULL; ccb->ccb_h.periph_priv = inccb->ccb_h.periph_priv; bcopy(ccb, inccb, sizeof(union ccb)); - return(0); + return (error); +} + +/* + * Set the cam_flags and sense_flags based on whether or not the request wants + * error recovery. In order to log errors via devctl, we need to do at least + * minimal recovery. We do this by not retrying unit attention (we let the + * requester do it, or not, if appropriate) and specifically asking for no + * recovery, like we do during device probing. + */ +static void +passflags(union ccb *ccb, uint32_t *cam_flags, uint32_t *sense_flags) +{ + if ((ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) != 0) { + *cam_flags = CAM_RETRY_SELTO; + *sense_flags = SF_RETRY_UA | SF_NO_PRINT; + } else { + *cam_flags = 0; + *sense_flags = SF_NO_RETRY | SF_NO_RECOVERY | SF_NO_PRINT; + } } static int -passerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) +passerror(union ccb *ccb, uint32_t cam_flags, uint32_t sense_flags) { return(cam_periph_error(ccb, cam_flags, sense_flags)); |