From owner-svn-src-head@freebsd.org Tue May 1 21:42:28 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 9D8A6FB8D2E; Tue, 1 May 2018 21:42:27 +0000 (UTC) (envelope-from scottl@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 48D747A568; Tue, 1 May 2018 21:42:27 +0000 (UTC) (envelope-from scottl@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4378227BE3; Tue, 1 May 2018 21:42:27 +0000 (UTC) (envelope-from scottl@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w41LgROY074240; Tue, 1 May 2018 21:42:27 GMT (envelope-from scottl@FreeBSD.org) Received: (from scottl@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w41LgR9k074238; Tue, 1 May 2018 21:42:27 GMT (envelope-from scottl@FreeBSD.org) Message-Id: <201805012142.w41LgR9k074238@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: scottl set sender to scottl@FreeBSD.org using -f From: Scott Long Date: Tue, 1 May 2018 21:42:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r333154 - head/sys/cam/scsi X-SVN-Group: head X-SVN-Commit-Author: scottl X-SVN-Commit-Paths: head/sys/cam/scsi X-SVN-Commit-Revision: 333154 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 May 2018 21:42:28 -0000 Author: scottl Date: Tue May 1 21:42:27 2018 New Revision: 333154 URL: https://svnweb.freebsd.org/changeset/base/333154 Log: Refactor dadone(). There was no useful code sharing in it; it was just a 1500 line switch statement. Callers now specify a discrete completion handler, though they're still welcome to track state via ccb_state. Sponsored by: Netflix Modified: head/sys/cam/scsi/scsi_da.c Modified: head/sys/cam/scsi/scsi_da.c ============================================================================== --- head/sys/cam/scsi/scsi_da.c Tue May 1 20:17:22 2018 (r333153) +++ head/sys/cam/scsi/scsi_da.c Tue May 1 21:42:27 2018 (r333154) @@ -163,7 +163,7 @@ typedef enum { DA_CCB_PROBE_ATA_ZONE = 0x11, DA_CCB_PROBE_WP = 0x12, DA_CCB_TYPE_MASK = 0x1F, - DA_CCB_RETRY_UA = 0x20 + DA_CCB_RETRY_UA = 0x20 } da_ccb_state; /* @@ -358,7 +358,7 @@ struct da_softc { u_int timeouts; u_int invalidations; #endif -#define DA_ANNOUNCETMP_SZ 80 +#define DA_ANNOUNCETMP_SZ 160 char announce_temp[DA_ANNOUNCETMP_SZ]; #define DA_ANNOUNCE_SZ 400 char announcebuf[DA_ANNOUNCE_SZ]; @@ -1405,6 +1405,30 @@ static periph_oninv_t daoninvalidate; static void dazonedone(struct cam_periph *periph, union ccb *ccb); static void dadone(struct cam_periph *periph, union ccb *done_ccb); +static void dadone_probewp(struct cam_periph *periph, + union ccb *done_ccb); +static void dadone_proberc(struct cam_periph *periph, + union ccb *done_ccb); +static void dadone_probelbp(struct cam_periph *periph, + union ccb *done_ccb); +static void dadone_probeblklimits(struct cam_periph *periph, + union ccb *done_ccb); +static void dadone_probebdc(struct cam_periph *periph, + union ccb *done_ccb); +static void dadone_probeata(struct cam_periph *periph, + union ccb *done_ccb); +static void dadone_probeatalogdir(struct cam_periph *periph, + union ccb *done_ccb); +static void dadone_probeataiddir(struct cam_periph *periph, + union ccb *done_ccb); +static void dadone_probeatasup(struct cam_periph *periph, + union ccb *done_ccb); +static void dadone_probeatazone(struct cam_periph *periph, + union ccb *done_ccb); +static void dadone_probezone(struct cam_periph *periph, + union ccb *done_ccb); +static void dadone_tur(struct cam_periph *periph, + union ccb *done_ccb); static int daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags); static void daprevent(struct cam_periph *periph, int action); @@ -3114,12 +3138,14 @@ skipstate: more: bp = cam_iosched_next_bio(softc->cam_iosched); if (bp == NULL) { - if (cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR)) { + if (cam_iosched_has_work_flags(softc->cam_iosched, + DA_WORK_TUR)) { softc->flags |= DA_FLAG_TUR_PENDING; - cam_iosched_clr_work_flags(softc->cam_iosched, DA_WORK_TUR); + cam_iosched_clr_work_flags(softc->cam_iosched, + DA_WORK_TUR); scsi_test_unit_ready(&start_ccb->csio, /*retries*/ da_retry_count, - dadone, + dadone_tur, MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE, da_default_timeout * 1000); @@ -3136,14 +3162,19 @@ more: softc->delete_func(periph, start_ccb, bp); goto out; } else { - /* Not sure this is possible, but failsafe by lying and saying "sure, done." */ + /* + * Not sure this is possible, but failsafe by + * lying and saying "sure, done." + */ biofinish(bp, NULL, 0); goto more; } } - if (cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR)) { - cam_iosched_clr_work_flags(softc->cam_iosched, DA_WORK_TUR); + if (cam_iosched_has_work_flags(softc->cam_iosched, + DA_WORK_TUR)) { + cam_iosched_clr_work_flags(softc->cam_iosched, + DA_WORK_TUR); da_periph_release_locked(periph, DA_REF_TUR); } @@ -3201,7 +3232,7 @@ more: /* * If we don't support sync cache, or the disk * isn't dirty, FLUSH is a no-op. Use the - * allocated * CCB for the next bio if one is + * allocated CCB for the next bio if one is * available. */ if ((softc->quirks & DA_Q_NO_SYNC_CACHE) != 0 || @@ -3290,7 +3321,7 @@ out: } scsi_mode_sense_len(&start_ccb->csio, /*retries*/ da_retry_count, - /*cbfcnp*/ dadone, + /*cbfcnp*/ dadone_probewp, /*tag_action*/ MSG_SIMPLE_Q_TAG, /*dbd*/ FALSE, /*pc*/ SMS_PAGE_CTRL_CURRENT, @@ -3318,7 +3349,7 @@ out: } scsi_read_capacity(&start_ccb->csio, /*retries*/da_retry_count, - dadone, + dadone_proberc, MSG_SIMPLE_Q_TAG, rcap, SSD_FULL_SIZE, @@ -3341,7 +3372,7 @@ out: } scsi_read_capacity_16(&start_ccb->csio, /*retries*/ da_retry_count, - /*cbfcnp*/ dadone, + /*cbfcnp*/ dadone_proberc, /*tag_action*/ MSG_SIMPLE_Q_TAG, /*lba*/ 0, /*reladr*/ 0, @@ -3384,7 +3415,7 @@ out: scsi_inquiry(&start_ccb->csio, /*retries*/da_retry_count, - /*cbfcnp*/dadone, + /*cbfcnp*/dadone_probelbp, /*tag_action*/MSG_SIMPLE_Q_TAG, /*inq_buf*/(u_int8_t *)lbp, /*inq_len*/sizeof(*lbp), @@ -3418,7 +3449,7 @@ out: scsi_inquiry(&start_ccb->csio, /*retries*/da_retry_count, - /*cbfcnp*/dadone, + /*cbfcnp*/dadone_probeblklimits, /*tag_action*/MSG_SIMPLE_Q_TAG, /*inq_buf*/(u_int8_t *)block_limits, /*inq_len*/sizeof(*block_limits), @@ -3451,7 +3482,7 @@ out: scsi_inquiry(&start_ccb->csio, /*retries*/da_retry_count, - /*cbfcnp*/dadone, + /*cbfcnp*/dadone_probebdc, /*tag_action*/MSG_SIMPLE_Q_TAG, /*inq_buf*/(u_int8_t *)bdc, /*inq_len*/sizeof(*bdc), @@ -3497,7 +3528,7 @@ out: scsi_ata_identify(&start_ccb->csio, /*retries*/da_retry_count, - /*cbfcnp*/dadone, + /*cbfcnp*/dadone_probeata, /*tag_action*/MSG_SIMPLE_Q_TAG, /*data_ptr*/(u_int8_t *)ata_params, /*dxfer_len*/sizeof(*ata_params), @@ -3540,7 +3571,7 @@ out: retval = scsi_ata_read_log(&start_ccb->csio, /*retries*/ da_retry_count, - /*cbfcnp*/ dadone, + /*cbfcnp*/ dadone_probeatalogdir, /*tag_action*/ MSG_SIMPLE_Q_TAG, /*log_address*/ ATA_LOG_DIRECTORY, /*page_number*/ 0, @@ -3590,7 +3621,7 @@ out: retval = scsi_ata_read_log(&start_ccb->csio, /*retries*/ da_retry_count, - /*cbfcnp*/ dadone, + /*cbfcnp*/ dadone_probeataiddir, /*tag_action*/ MSG_SIMPLE_Q_TAG, /*log_address*/ ATA_IDENTIFY_DATA_LOG, /*page_number*/ ATA_IDL_PAGE_LIST, @@ -3639,7 +3670,7 @@ out: retval = scsi_ata_read_log(&start_ccb->csio, /*retries*/ da_retry_count, - /*cbfcnp*/ dadone, + /*cbfcnp*/ dadone_probeatasup, /*tag_action*/ MSG_SIMPLE_Q_TAG, /*log_address*/ ATA_IDENTIFY_DATA_LOG, /*page_number*/ ATA_IDL_SUP_CAP, @@ -3691,7 +3722,7 @@ out: retval = scsi_ata_read_log(&start_ccb->csio, /*retries*/ da_retry_count, - /*cbfcnp*/ dadone, + /*cbfcnp*/ dadone_probeatazone, /*tag_action*/ MSG_SIMPLE_Q_TAG, /*log_address*/ ATA_IDENTIFY_DATA_LOG, /*page_number*/ ATA_IDL_ZDI, @@ -3741,7 +3772,7 @@ out: } scsi_inquiry(&start_ccb->csio, /*retries*/da_retry_count, - /*cbfcnp*/dadone, + /*cbfcnp*/dadone_probezone, /*tag_action*/MSG_SIMPLE_Q_TAG, /*inq_buf*/(u_int8_t *)bdc, /*inq_len*/sizeof(*bdc), @@ -3830,7 +3861,8 @@ da_delete_unmap(struct cam_periph *periph, union ccb * totalcount -= c; lastlba -= c; lastcount -= c; - scsi_ulto4b(lastcount, d[ranges - 1].length); + scsi_ulto4b(lastcount, + d[ranges - 1].length); } } /* Align beginning of the new range. */ @@ -4301,1296 +4333,1360 @@ dazonedone(struct cam_periph *periph, union ccb *ccb) static void dadone(struct cam_periph *periph, union ccb *done_ccb) { + struct bio *bp, *bp1; struct da_softc *softc; struct ccb_scsiio *csio; u_int32_t priority; da_ccb_state state; - softc = (struct da_softc *)periph->softc; - priority = done_ccb->ccb_h.pinfo.priority; - CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone\n")); + softc = (struct da_softc *)periph->softc; + priority = done_ccb->ccb_h.pinfo.priority; csio = &done_ccb->csio; + #if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) if (csio->bio != NULL) biotrack(csio->bio, __func__); #endif state = csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK; - switch (state) { - case DA_CCB_BUFFER_IO: - case DA_CCB_DELETE: - { - struct bio *bp, *bp1; - cam_periph_lock(periph); + cam_periph_lock(periph); + bp = (struct bio *)done_ccb->ccb_h.ccb_bp; + if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + int error; + int sf; + + if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0) + sf = SF_RETRY_UA; + else + sf = 0; + + error = daerror(done_ccb, CAM_RETRY_SELTO, sf); + if (error == ERESTART) { + /* A retry was scheduled, so just return. */ + cam_periph_unlock(periph); + return; + } bp = (struct bio *)done_ccb->ccb_h.ccb_bp; - if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { - int error; - int sf; + if (error != 0) { + int queued_error; - if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0) - sf = SF_RETRY_UA; - else - sf = 0; + /* + * return all queued I/O with EIO, so that + * the client can retry these I/Os in the + * proper order should it attempt to recover. + */ + queued_error = EIO; - error = daerror(done_ccb, CAM_RETRY_SELTO, sf); - if (error == ERESTART) { + if (error == ENXIO + && (softc->flags & DA_FLAG_PACK_INVALID)== 0) { /* - * A retry was scheduled, so - * just return. + * Catastrophic error. Mark our pack as + * invalid. + * + * XXX See if this is really a media + * XXX change first? */ - cam_periph_unlock(periph); - return; - } - bp = (struct bio *)done_ccb->ccb_h.ccb_bp; - if (error != 0) { - int queued_error; - - /* - * return all queued I/O with EIO, so that - * the client can retry these I/Os in the - * proper order should it attempt to recover. - */ - queued_error = EIO; - - if (error == ENXIO - && (softc->flags & DA_FLAG_PACK_INVALID)== 0) { - /* - * Catastrophic error. Mark our pack as - * invalid. - */ - /* - * XXX See if this is really a media - * XXX change first? - */ - xpt_print(periph->path, - "Invalidating pack\n"); - softc->flags |= DA_FLAG_PACK_INVALID; + xpt_print(periph->path, "Invalidating pack\n"); + softc->flags |= DA_FLAG_PACK_INVALID; #ifdef CAM_IO_STATS - softc->invalidations++; + softc->invalidations++; #endif - queued_error = ENXIO; - } - cam_iosched_flush(softc->cam_iosched, NULL, - queued_error); - if (bp != NULL) { - bp->bio_error = error; - bp->bio_resid = bp->bio_bcount; - bp->bio_flags |= BIO_ERROR; - } - } else if (bp != NULL) { - if (state == DA_CCB_DELETE) - bp->bio_resid = 0; - else - bp->bio_resid = csio->resid; - bp->bio_error = 0; - if (bp->bio_resid != 0) - bp->bio_flags |= BIO_ERROR; + queued_error = ENXIO; } - if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) - cam_release_devq(done_ccb->ccb_h.path, - /*relsim_flags*/0, - /*reduction*/0, - /*timeout*/0, - /*getcount_only*/0); + cam_iosched_flush(softc->cam_iosched, NULL, + queued_error); + if (bp != NULL) { + bp->bio_error = error; + bp->bio_resid = bp->bio_bcount; + bp->bio_flags |= BIO_ERROR; + } } else if (bp != NULL) { - if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) - panic("REQ_CMP with QFRZN"); - if (bp->bio_cmd == BIO_ZONE) - dazonedone(periph, done_ccb); - else if (state == DA_CCB_DELETE) + if (state == DA_CCB_DELETE) bp->bio_resid = 0; else bp->bio_resid = csio->resid; - if ((csio->resid > 0) - && (bp->bio_cmd != BIO_ZONE)) + bp->bio_error = 0; + if (bp->bio_resid != 0) bp->bio_flags |= BIO_ERROR; - if (softc->error_inject != 0) { - bp->bio_error = softc->error_inject; - bp->bio_resid = bp->bio_bcount; - bp->bio_flags |= BIO_ERROR; - softc->error_inject = 0; - } } + if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) + cam_release_devq(done_ccb->ccb_h.path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); + } else if (bp != NULL) { + if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) + panic("REQ_CMP with QFRZN"); + if (bp->bio_cmd == BIO_ZONE) + dazonedone(periph, done_ccb); + else if (state == DA_CCB_DELETE) + bp->bio_resid = 0; + else + bp->bio_resid = csio->resid; + if ((csio->resid > 0) && (bp->bio_cmd != BIO_ZONE)) + bp->bio_flags |= BIO_ERROR; + if (softc->error_inject != 0) { + bp->bio_error = softc->error_inject; + bp->bio_resid = bp->bio_bcount; + bp->bio_flags |= BIO_ERROR; + softc->error_inject = 0; + } + } - if (bp != NULL) - biotrack(bp, __func__); - LIST_REMOVE(&done_ccb->ccb_h, periph_links.le); - if (LIST_EMPTY(&softc->pending_ccbs)) - softc->flags |= DA_FLAG_WAS_OTAG; + if (bp != NULL) + biotrack(bp, __func__); + LIST_REMOVE(&done_ccb->ccb_h, periph_links.le); + if (LIST_EMPTY(&softc->pending_ccbs)) + softc->flags |= DA_FLAG_WAS_OTAG; + /* + * We need to call cam_iosched before we call biodone so that we + * don't measure any activity that happens in the completion + * routine, which in the case of sendfile can be quite + * extensive. + */ + cam_iosched_bio_complete(softc->cam_iosched, bp, done_ccb); + xpt_release_ccb(done_ccb); + if (state == DA_CCB_DELETE) { + TAILQ_HEAD(, bio) queue; + + TAILQ_INIT(&queue); + TAILQ_CONCAT(&queue, &softc->delete_run_queue.queue, bio_queue); + softc->delete_run_queue.insert_point = NULL; /* - * We need to call cam_iosched before we call biodone so that we - * don't measure any activity that happens in the completion - * routine, which in the case of sendfile can be quite - * extensive. + * Normally, the xpt_release_ccb() above would make sure + * that when we have more work to do, that work would + * get kicked off. However, we specifically keep + * delete_running set to 0 before the call above to + * allow other I/O to progress when many BIO_DELETE + * requests are pushed down. We set delete_running to 0 + * and call daschedule again so that we don't stall if + * there are no other I/Os pending apart from BIO_DELETEs. */ - cam_iosched_bio_complete(softc->cam_iosched, bp, done_ccb); - xpt_release_ccb(done_ccb); - if (state == DA_CCB_DELETE) { - TAILQ_HEAD(, bio) queue; - - TAILQ_INIT(&queue); - TAILQ_CONCAT(&queue, &softc->delete_run_queue.queue, bio_queue); - softc->delete_run_queue.insert_point = NULL; - /* - * Normally, the xpt_release_ccb() above would make sure - * that when we have more work to do, that work would - * get kicked off. However, we specifically keep - * delete_running set to 0 before the call above to - * allow other I/O to progress when many BIO_DELETE - * requests are pushed down. We set delete_running to 0 - * and call daschedule again so that we don't stall if - * there are no other I/Os pending apart from BIO_DELETEs. - */ - cam_iosched_trim_done(softc->cam_iosched); - daschedule(periph); - cam_periph_unlock(periph); - while ((bp1 = TAILQ_FIRST(&queue)) != NULL) { - TAILQ_REMOVE(&queue, bp1, bio_queue); - bp1->bio_error = bp->bio_error; - if (bp->bio_flags & BIO_ERROR) { - bp1->bio_flags |= BIO_ERROR; - bp1->bio_resid = bp1->bio_bcount; - } else - bp1->bio_resid = 0; - biodone(bp1); - } - } else { - daschedule(periph); - cam_periph_unlock(periph); + cam_iosched_trim_done(softc->cam_iosched); + daschedule(periph); + cam_periph_unlock(periph); + while ((bp1 = TAILQ_FIRST(&queue)) != NULL) { + TAILQ_REMOVE(&queue, bp1, bio_queue); + bp1->bio_error = bp->bio_error; + if (bp->bio_flags & BIO_ERROR) { + bp1->bio_flags |= BIO_ERROR; + bp1->bio_resid = bp1->bio_bcount; + } else + bp1->bio_resid = 0; + biodone(bp1); } - if (bp != NULL) - biodone(bp); - return; + } else { + daschedule(periph); + cam_periph_unlock(periph); } - case DA_CCB_PROBE_WP: - { - struct scsi_mode_header_6 *mode_hdr6; - struct scsi_mode_header_10 *mode_hdr10; - uint8_t dev_spec; + if (bp != NULL) + biodone(bp); + return; +} - if (softc->minimum_cmd_size > 6) { - mode_hdr10 = (struct scsi_mode_header_10 *)csio->data_ptr; - dev_spec = mode_hdr10->dev_spec; - } else { - mode_hdr6 = (struct scsi_mode_header_6 *)csio->data_ptr; - dev_spec = mode_hdr6->dev_spec; - } - if (cam_ccb_status(done_ccb) == CAM_REQ_CMP) { - if ((dev_spec & 0x80) != 0) - softc->disk->d_flags |= DISKFLAG_WRITE_PROTECT; - else - softc->disk->d_flags &= ~DISKFLAG_WRITE_PROTECT; - } else { - int error; +static void +dadone_probewp(struct cam_periph *periph, union ccb *done_ccb) +{ + struct scsi_mode_header_6 *mode_hdr6; + struct scsi_mode_header_10 *mode_hdr10; + struct da_softc *softc; + struct ccb_scsiio *csio; + u_int32_t priority; + uint8_t dev_spec; - error = daerror(done_ccb, CAM_RETRY_SELTO, - SF_RETRY_UA|SF_NO_PRINT); - if (error == ERESTART) - return; - else if (error != 0) { - if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge this device's queue */ - cam_release_devq(done_ccb->ccb_h.path, - /*relsim_flags*/0, - /*reduction*/0, - /*timeout*/0, - /*getcount_only*/0); - } - } - } + CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone_probewp\n")); - free(csio->data_ptr, M_SCSIDA); - xpt_release_ccb(done_ccb); - if ((softc->flags & DA_FLAG_CAN_RC16) != 0) - softc->state = DA_STATE_PROBE_RC16; + softc = (struct da_softc *)periph->softc; + priority = done_ccb->ccb_h.pinfo.priority; + csio = &done_ccb->csio; + + if (softc->minimum_cmd_size > 6) { + mode_hdr10 = (struct scsi_mode_header_10 *)csio->data_ptr; + dev_spec = mode_hdr10->dev_spec; + } else { + mode_hdr6 = (struct scsi_mode_header_6 *)csio->data_ptr; + dev_spec = mode_hdr6->dev_spec; + } + if (cam_ccb_status(done_ccb) == CAM_REQ_CMP) { + if ((dev_spec & 0x80) != 0) + softc->disk->d_flags |= DISKFLAG_WRITE_PROTECT; else - softc->state = DA_STATE_PROBE_RC; - xpt_schedule(periph, priority); - return; + softc->disk->d_flags &= ~DISKFLAG_WRITE_PROTECT; + } else { + int error; + + error = daerror(done_ccb, CAM_RETRY_SELTO, + SF_RETRY_UA|SF_NO_PRINT); + if (error == ERESTART) + return; + else if (error != 0) { + if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { + /* Don't wedge this device's queue */ + cam_release_devq(done_ccb->ccb_h.path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); + } + } } - case DA_CCB_PROBE_RC: - case DA_CCB_PROBE_RC16: - { - struct scsi_read_capacity_data *rdcap; - struct scsi_read_capacity_data_long *rcaplong; - char *announce_buf; - int lbp; - lbp = 0; - rdcap = NULL; - rcaplong = NULL; - /* XXX TODO: can this be a malloc? */ - announce_buf = softc->announce_temp; - bzero(announce_buf, DA_ANNOUNCETMP_SZ); + free(csio->data_ptr, M_SCSIDA); + xpt_release_ccb(done_ccb); + if ((softc->flags & DA_FLAG_CAN_RC16) != 0) + softc->state = DA_STATE_PROBE_RC16; + else + softc->state = DA_STATE_PROBE_RC; + xpt_schedule(periph, priority); + return; +} - if (state == DA_CCB_PROBE_RC) - rdcap =(struct scsi_read_capacity_data *)csio->data_ptr; - else - rcaplong = (struct scsi_read_capacity_data_long *) - csio->data_ptr; +static void +dadone_proberc(struct cam_periph *periph, union ccb *done_ccb) +{ + struct scsi_read_capacity_data *rdcap; + struct scsi_read_capacity_data_long *rcaplong; + struct da_softc *softc; + struct ccb_scsiio *csio; + da_ccb_state state; + char *announce_buf; + u_int32_t priority; + int lbp; - if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { - struct disk_params *dp; - uint32_t block_size; - uint64_t maxsector; - u_int lalba; /* Lowest aligned LBA. */ + CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone_proberc\n")); - if (state == DA_CCB_PROBE_RC) { - block_size = scsi_4btoul(rdcap->length); - maxsector = scsi_4btoul(rdcap->addr); - lalba = 0; + softc = (struct da_softc *)periph->softc; + priority = done_ccb->ccb_h.pinfo.priority; + csio = &done_ccb->csio; + state = csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK; - /* - * According to SBC-2, if the standard 10 - * byte READ CAPACITY command returns 2^32, - * we should issue the 16 byte version of - * the command, since the device in question - * has more sectors than can be represented - * with the short version of the command. - */ - if (maxsector == 0xffffffff) { - free(rdcap, M_SCSIDA); - xpt_release_ccb(done_ccb); - softc->state = DA_STATE_PROBE_RC16; - xpt_schedule(periph, priority); - return; - } - } else { - block_size = scsi_4btoul(rcaplong->length); - maxsector = scsi_8btou64(rcaplong->addr); - lalba = scsi_2btoul(rcaplong->lalba_lbp); - } + lbp = 0; + rdcap = NULL; + rcaplong = NULL; + /* XXX TODO: can this be a malloc? */ + announce_buf = softc->announce_temp; + bzero(announce_buf, DA_ANNOUNCETMP_SZ); + if (state == DA_CCB_PROBE_RC) + rdcap =(struct scsi_read_capacity_data *)csio->data_ptr; + else + rcaplong = (struct scsi_read_capacity_data_long *) + csio->data_ptr; + + if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { + struct disk_params *dp; + uint32_t block_size; + uint64_t maxsector; + u_int lalba; /* Lowest aligned LBA. */ + + if (state == DA_CCB_PROBE_RC) { + block_size = scsi_4btoul(rdcap->length); + maxsector = scsi_4btoul(rdcap->addr); + lalba = 0; + /* - * Because GEOM code just will panic us if we - * give them an 'illegal' value we'll avoid that - * here. + * According to SBC-2, if the standard 10 + * byte READ CAPACITY command returns 2^32, + * we should issue the 16 byte version of + * the command, since the device in question + * has more sectors than can be represented + * with the short version of the command. */ - if (block_size == 0) { - block_size = 512; - if (maxsector == 0) - maxsector = -1; + if (maxsector == 0xffffffff) { + free(rdcap, M_SCSIDA); + xpt_release_ccb(done_ccb); + softc->state = DA_STATE_PROBE_RC16; + xpt_schedule(periph, priority); + return; } - if (block_size >= MAXPHYS) { - xpt_print(periph->path, - "unsupportable block size %ju\n", - (uintmax_t) block_size); - announce_buf = NULL; - cam_periph_invalidate(periph); - } else { - /* - * We pass rcaplong into dasetgeom(), - * because it will only use it if it is - * non-NULL. - */ - dasetgeom(periph, block_size, maxsector, - rcaplong, sizeof(*rcaplong)); - lbp = (lalba & SRC16_LBPME_A); - dp = &softc->params; - snprintf(announce_buf, DA_ANNOUNCETMP_SZ, - "%juMB (%ju %u byte sectors)", - ((uintmax_t)dp->secsize * dp->sectors) / - (1024 * 1024), - (uintmax_t)dp->sectors, dp->secsize); - } } else { - int error; + block_size = scsi_4btoul(rcaplong->length); + maxsector = scsi_8btou64(rcaplong->addr); + lalba = scsi_2btoul(rcaplong->lalba_lbp); + } + /* + * Because GEOM code just will panic us if we + * give them an 'illegal' value we'll avoid that + * here. + */ + if (block_size == 0) { + block_size = 512; + if (maxsector == 0) + maxsector = -1; + } + if (block_size >= MAXPHYS) { + xpt_print(periph->path, + "unsupportable block size %ju\n", + (uintmax_t) block_size); + announce_buf = NULL; + cam_periph_invalidate(periph); + } else { /* - * Retry any UNIT ATTENTION type errors. They - * are expected at boot. + * We pass rcaplong into dasetgeom(), + * because it will only use it if it is + * non-NULL. */ - error = daerror(done_ccb, CAM_RETRY_SELTO, - SF_RETRY_UA|SF_NO_PRINT); - if (error == ERESTART) { - /* - * A retry was scheuled, so - * just return. - */ - return; - } else if (error != 0) { - int asc, ascq; - int sense_key, error_code; - int have_sense; - cam_status status; - struct ccb_getdev cgd; + dasetgeom(periph, block_size, maxsector, + rcaplong, sizeof(*rcaplong)); + lbp = (lalba & SRC16_LBPME_A); + dp = &softc->params; + snprintf(announce_buf, DA_ANNOUNCETMP_SZ, + "%juMB (%ju %u byte sectors)", + ((uintmax_t)dp->secsize * dp->sectors) / + (1024 * 1024), + (uintmax_t)dp->sectors, dp->secsize); + } + } else { + int error; - /* Don't wedge this device's queue */ - status = done_ccb->ccb_h.status; - if ((status & CAM_DEV_QFRZN) != 0) - cam_release_devq(done_ccb->ccb_h.path, - /*relsim_flags*/0, - /*reduction*/0, - /*timeout*/0, - /*getcount_only*/0); + /* + * Retry any UNIT ATTENTION type errors. They + * are expected at boot. + */ + error = daerror(done_ccb, CAM_RETRY_SELTO, + SF_RETRY_UA|SF_NO_PRINT); + if (error == ERESTART) { + /* + * A retry was scheuled, so + * just return. + */ + return; + } else if (error != 0) { + int asc, ascq; + int sense_key, error_code; + int have_sense; + cam_status status; + struct ccb_getdev cgd; + /* Don't wedge this device's queue */ + status = done_ccb->ccb_h.status; + if ((status & CAM_DEV_QFRZN) != 0) + cam_release_devq(done_ccb->ccb_h.path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); - xpt_setup_ccb(&cgd.ccb_h, - done_ccb->ccb_h.path, - CAM_PRIORITY_NORMAL); - cgd.ccb_h.func_code = XPT_GDEV_TYPE; - xpt_action((union ccb *)&cgd); - if (scsi_extract_sense_ccb(done_ccb, - &error_code, &sense_key, &asc, &ascq)) - have_sense = TRUE; - else - have_sense = FALSE; + xpt_setup_ccb(&cgd.ccb_h, done_ccb->ccb_h.path, + CAM_PRIORITY_NORMAL); + cgd.ccb_h.func_code = XPT_GDEV_TYPE; + xpt_action((union ccb *)&cgd); - /* - * If we tried READ CAPACITY(16) and failed, - * fallback to READ CAPACITY(10). - */ - if ((state == DA_CCB_PROBE_RC16) && - (softc->flags & DA_FLAG_CAN_RC16) && - (((csio->ccb_h.status & CAM_STATUS_MASK) == - CAM_REQ_INVALID) || - ((have_sense) && - (error_code == SSD_CURRENT_ERROR || - error_code == SSD_DESC_CURRENT_ERROR) && - (sense_key == SSD_KEY_ILLEGAL_REQUEST)))) { - cam_periph_assert(periph, MA_OWNED); - softc->flags &= ~DA_FLAG_CAN_RC16; - free(rdcap, M_SCSIDA); - xpt_release_ccb(done_ccb); - softc->state = DA_STATE_PROBE_RC; - xpt_schedule(periph, priority); - return; - } + if (scsi_extract_sense_ccb(done_ccb, + &error_code, &sense_key, &asc, &ascq)) + have_sense = TRUE; + else + have_sense = FALSE; - /* - * Attach to anything that claims to be a - * direct access or optical disk device, - * as long as it doesn't return a "Logical - * unit not supported" (0x25) error. - * "Internal Target Failure" (0x44) is also - * special and typically means that the - * device is a SATA drive behind a SATL - * translation that's fallen into a - * terminally fatal state. - */ - if ((have_sense) - && (asc != 0x25) && (asc != 0x44) - && (error_code == SSD_CURRENT_ERROR - || error_code == SSD_DESC_CURRENT_ERROR)) { - const char *sense_key_desc; - const char *asc_desc; - - dasetgeom(periph, 512, -1, NULL, 0); - scsi_sense_desc(sense_key, asc, ascq, - &cgd.inq_data, - &sense_key_desc, - &asc_desc); - snprintf(announce_buf, - DA_ANNOUNCETMP_SZ, - "Attempt to query device " - "size failed: %s, %s", - sense_key_desc, asc_desc); - } else { - if (have_sense) - scsi_sense_print( - &done_ccb->csio); - else { - xpt_print(periph->path, - "got CAM status %#x\n", - done_ccb->ccb_h.status); - } - - xpt_print(periph->path, "fatal error, " - "failed to attach to device\n"); - - announce_buf = NULL; - - /* - * Free up resources. - */ - cam_periph_invalidate(periph); - } + /* + * If we tried READ CAPACITY(16) and failed, + * fallback to READ CAPACITY(10). + */ + if ((state == DA_CCB_PROBE_RC16) && + (softc->flags & DA_FLAG_CAN_RC16) && + (((csio->ccb_h.status & CAM_STATUS_MASK) == + CAM_REQ_INVALID) || + ((have_sense) && + (error_code == SSD_CURRENT_ERROR || + error_code == SSD_DESC_CURRENT_ERROR) && + (sense_key == SSD_KEY_ILLEGAL_REQUEST)))) { + cam_periph_assert(periph, MA_OWNED); + softc->flags &= ~DA_FLAG_CAN_RC16; + free(rdcap, M_SCSIDA); + xpt_release_ccb(done_ccb); + softc->state = DA_STATE_PROBE_RC; + xpt_schedule(periph, priority); + return; } - } - free(csio->data_ptr, M_SCSIDA); - if (announce_buf != NULL && - ((softc->flags & DA_FLAG_ANNOUNCED) == 0)) { - struct sbuf sb; - sbuf_new(&sb, softc->announcebuf, DA_ANNOUNCE_SZ, - SBUF_FIXEDLEN); - xpt_announce_periph_sbuf(periph, &sb, announce_buf); - xpt_announce_quirks_sbuf(periph, &sb, softc->quirks, - DA_Q_BIT_STRING); - sbuf_finish(&sb); - sbuf_putbuf(&sb); - /* - * Create our sysctl variables, now that we know - * we have successfully attached. + * Attach to anything that claims to be a + * direct access or optical disk device, + * as long as it doesn't return a "Logical + * unit not supported" (0x25) error. + * "Internal Target Failure" (0x44) is also + * special and typically means that the + * device is a SATA drive behind a SATL + * translation that's fallen into a + * terminally fatal state. */ - /* increase the refcount */ - if (da_periph_acquire(periph, DA_REF_SYSCTL) == 0) { + if ((have_sense) + && (asc != 0x25) && (asc != 0x44) + && (error_code == SSD_CURRENT_ERROR + || error_code == SSD_DESC_CURRENT_ERROR)) { + const char *sense_key_desc; + const char *asc_desc; - taskqueue_enqueue(taskqueue_thread, - &softc->sysctl_task); - } else { - /* XXX This message is useless! */ + dasetgeom(periph, 512, -1, NULL, 0); + scsi_sense_desc(sense_key, asc, ascq, + &cgd.inq_data, &sense_key_desc, + &asc_desc); + snprintf(announce_buf, DA_ANNOUNCETMP_SZ, + "Attempt to query device " + "size failed: %s, %s", + sense_key_desc, asc_desc); + } else { + if (have_sense) + scsi_sense_print(&done_ccb->csio); + else { + xpt_print(periph->path, + "got CAM status %#x\n", + done_ccb->ccb_h.status); + } *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***