Date: Thu, 15 Feb 2018 16:31:36 +0000 (UTC) From: Andriy Gapon <avg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r329319 - in stable/10/sys: cam/scsi geom Message-ID: <201802151631.w1FGVarH023681@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: avg Date: Thu Feb 15 16:31:35 2018 New Revision: 329319 URL: https://svnweb.freebsd.org/changeset/base/329319 Log: MFC r327996: geom_disk / scsi_da: deny opening write-protected disks for writing Ths change consists of two parts. geom_disk: deny opening a disk for writing if it's marked as write-protected. A new disk(9) flag is added to mark write protected disks. A possible alternative could be to add another parameter to d_open, so that the open mode could be passed to it and the disk drivers could make the decision internally, but the flag required less churn. scsi_da: add a new phase of disk probing to query the all pages mode sense page. We can determine if the disk is write protected using bit 7 of the device specific field in the mode parameter header returned by MODE SENSE. PR: 224037 Modified: stable/10/sys/cam/scsi/scsi_da.c stable/10/sys/geom/geom_disk.c stable/10/sys/geom/geom_disk.h Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/cam/scsi/scsi_da.c ============================================================================== --- stable/10/sys/cam/scsi/scsi_da.c Thu Feb 15 16:29:35 2018 (r329318) +++ stable/10/sys/cam/scsi/scsi_da.c Thu Feb 15 16:31:35 2018 (r329319) @@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$"); #ifdef _KERNEL typedef enum { + DA_STATE_PROBE_WP, DA_STATE_PROBE_RC, DA_STATE_PROBE_RC16, DA_STATE_PROBE_LBP, @@ -126,8 +127,9 @@ typedef enum { DA_CCB_DUMP = 0x0A, DA_CCB_DELETE = 0x0B, DA_CCB_TUR = 0x0C, - DA_CCB_TYPE_MASK = 0x0F, - DA_CCB_RETRY_UA = 0x10 + DA_CCB_PROBE_WP = 0x12, + DA_CCB_TYPE_MASK = 0x1F, + DA_CCB_RETRY_UA = 0x20 } da_ccb_state; /* @@ -2096,7 +2098,7 @@ daregister(struct cam_periph *periph, void *arg) } LIST_INIT(&softc->pending_ccbs); - softc->state = DA_STATE_PROBE_RC; + softc->state = DA_STATE_PROBE_WP; bioq_init(&softc->bio_queue); bioq_init(&softc->delete_queue); bioq_init(&softc->delete_run_queue); @@ -2183,7 +2185,6 @@ daregister(struct cam_periph *periph, void *arg) if (SID_ANSI_REV(&cgd->inq_data) >= SCSI_REV_SPC3 && (softc->quirks & DA_Q_NO_RC16) == 0) { softc->flags |= DA_FLAG_CAN_RC16; - softc->state = DA_STATE_PROBE_RC16; } /* @@ -2415,6 +2416,36 @@ out: daschedule(periph); break; } + case DA_STATE_PROBE_WP: + { + void *mode_buf; + int mode_buf_len; + + mode_buf_len = 192; + mode_buf = malloc(mode_buf_len, M_SCSIDA, M_NOWAIT); + if (mode_buf == NULL) { + xpt_print(periph->path, "Unable to send mode sense - " + "malloc failure\n"); + softc->state = DA_STATE_PROBE_RC; + goto skipstate; + } + scsi_mode_sense_len(&start_ccb->csio, + /*retries*/ da_retry_count, + /*cbfcnp*/ dadone, + /*tag_action*/ MSG_SIMPLE_Q_TAG, + /*dbd*/ FALSE, + /*pc*/ SMS_PAGE_CTRL_CURRENT, + /*page*/ SMS_ALL_PAGES_PAGE, + /*param_buf*/ mode_buf, + /*param_len*/ mode_buf_len, + /*minimum_cmd_size*/ softc->minimum_cmd_size, + /*sense_len*/ SSD_FULL_SIZE, + /*timeout*/ da_default_timeout * 1000); + start_ccb->ccb_h.ccb_bp = NULL; + start_ccb->ccb_h.ccb_state = DA_CCB_PROBE_WP; + xpt_action(start_ccb); + break; + } case DA_STATE_PROBE_RC: { struct scsi_read_capacity_data *rcap; @@ -3095,6 +3126,52 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) biodone(bp); return; } + case DA_CCB_PROBE_WP: + { + struct scsi_mode_header_6 *mode_hdr6; + struct scsi_mode_header_10 *mode_hdr10; + uint8_t dev_spec; + + 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; + + 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); + } + } + } + + 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; + } case DA_CCB_PROBE_RC: case DA_CCB_PROBE_RC16: { @@ -3612,11 +3689,7 @@ dareprobe(struct cam_periph *periph) KASSERT(status == CAM_REQ_CMP, ("dareprobe: cam_periph_acquire failed")); - if (softc->flags & DA_FLAG_CAN_RC16) - softc->state = DA_STATE_PROBE_RC16; - else - softc->state = DA_STATE_PROBE_RC; - + softc->state = DA_STATE_PROBE_WP; xpt_schedule(periph, CAM_PRIORITY_DEV); } Modified: stable/10/sys/geom/geom_disk.c ============================================================================== --- stable/10/sys/geom/geom_disk.c Thu Feb 15 16:29:35 2018 (r329318) +++ stable/10/sys/geom/geom_disk.c Thu Feb 15 16:31:35 2018 (r329319) @@ -134,16 +134,21 @@ g_disk_access(struct g_provider *pp, int r, int w, int e += pp->ace; error = 0; if ((pp->acr + pp->acw + pp->ace) == 0 && (r + w + e) > 0) { - if (dp->d_open != NULL) { + /* + * It would be better to defer this decision to d_open if + * it was able to take flags. + */ + if (w > 0 && (dp->d_flags & DISKFLAG_WRITE_PROTECT) != 0) + error = EROFS; + if (error == 0 && dp->d_open != NULL) { g_disk_lock_giant(dp); error = dp->d_open(dp); - if (bootverbose && error != 0) - printf("Opened disk %s -> %d\n", - pp->name, error); g_disk_unlock_giant(dp); - if (error != 0) - return (error); } + if (bootverbose && error != 0) + printf("Opened disk %s -> %d\n", pp->name, error); + if (error != 0) + return (error); pp->mediasize = dp->d_mediasize; pp->sectorsize = dp->d_sectorsize; if (dp->d_maxsize == 0) { Modified: stable/10/sys/geom/geom_disk.h ============================================================================== --- stable/10/sys/geom/geom_disk.h Thu Feb 15 16:29:35 2018 (r329318) +++ stable/10/sys/geom/geom_disk.h Thu Feb 15 16:31:35 2018 (r329319) @@ -105,13 +105,14 @@ struct disk { uint16_t d_rotation_rate; }; -#define DISKFLAG_NEEDSGIANT 0x1 -#define DISKFLAG_OPEN 0x2 -#define DISKFLAG_CANDELETE 0x4 -#define DISKFLAG_CANFLUSHCACHE 0x8 -#define DISKFLAG_UNMAPPED_BIO 0x10 -#define DISKFLAG_DIRECT_COMPLETION 0x20 -#define DISKFLAG_LACKS_ROTRATE 0x40 +#define DISKFLAG_NEEDSGIANT 0x0001 +#define DISKFLAG_OPEN 0x0002 +#define DISKFLAG_CANDELETE 0x0004 +#define DISKFLAG_CANFLUSHCACHE 0x0008 +#define DISKFLAG_UNMAPPED_BIO 0x0010 +#define DISKFLAG_DIRECT_COMPLETION 0x0020 +#define DISKFLAG_LACKS_ROTRATE 0x0040 +#define DISKFLAG_WRITE_PROTECT 0x0100 #define DISK_RR_UNKNOWN 0 #define DISK_RR_NON_ROTATING 1
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802151631.w1FGVarH023681>