Date: Thu, 15 Feb 2018 15:33:18 +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-11@freebsd.org Subject: svn commit: r329316 - in stable/11/sys: cam/scsi geom Message-ID: <201802151533.w1FFXI0B089691@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: avg Date: Thu Feb 15 15:33:17 2018 New Revision: 329316 URL: https://svnweb.freebsd.org/changeset/base/329316 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/11/sys/cam/scsi/scsi_da.c stable/11/sys/geom/geom_disk.c stable/11/sys/geom/geom_disk.h Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/cam/scsi/scsi_da.c ============================================================================== --- stable/11/sys/cam/scsi/scsi_da.c Thu Feb 15 15:01:07 2018 (r329315) +++ stable/11/sys/cam/scsi/scsi_da.c Thu Feb 15 15:33:17 2018 (r329316) @@ -79,6 +79,7 @@ __FBSDID("$FreeBSD$"); * ATA -> LOGDIR -> IDDIR -> SUP -> ATA_ZONE */ typedef enum { + DA_STATE_PROBE_WP, DA_STATE_PROBE_RC, DA_STATE_PROBE_RC16, DA_STATE_PROBE_LBP, @@ -155,6 +156,7 @@ typedef enum { DA_CCB_PROBE_ATA_IDDIR = 0x0F, DA_CCB_PROBE_ATA_SUP = 0x10, DA_CCB_PROBE_ATA_ZONE = 0x11, + DA_CCB_PROBE_WP = 0x12, DA_CCB_TYPE_MASK = 0x1F, DA_CCB_RETRY_UA = 0x20 } da_ccb_state; @@ -2402,7 +2404,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->delete_run_queue); if (SID_IS_REMOVABLE(&cgd->inq_data)) softc->flags |= DA_FLAG_PACK_REMOVABLE; @@ -2506,7 +2508,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; } /* @@ -3070,6 +3071,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; @@ -4219,6 +4250,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: { @@ -5286,11 +5363,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/11/sys/geom/geom_disk.c ============================================================================== --- stable/11/sys/geom/geom_disk.c Thu Feb 15 15:01:07 2018 (r329315) +++ stable/11/sys/geom/geom_disk.c Thu Feb 15 15:33:17 2018 (r329316) @@ -118,14 +118,18 @@ 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) error = dp->d_open(dp); - if (bootverbose && error != 0) - printf("Opened disk %s -> %d\n", - pp->name, error); - if (error != 0) - return (error); - } + if (bootverbose && error != 0) + printf("Opened disk %s -> %d\n", pp->name, error); + if (error != 0) + return (error); pp->sectorsize = dp->d_sectorsize; if (dp->d_maxsize == 0) { printf("WARNING: Disk drive %s%d has no d_maxsize\n", Modified: stable/11/sys/geom/geom_disk.h ============================================================================== --- stable/11/sys/geom/geom_disk.h Thu Feb 15 15:01:07 2018 (r329315) +++ stable/11/sys/geom/geom_disk.h Thu Feb 15 15:33:17 2018 (r329316) @@ -116,13 +116,14 @@ struct disk { void *d_drv1; }; -#define DISKFLAG_RESERVED 0x1 /* Was NEEDSGIANT */ -#define DISKFLAG_OPEN 0x2 -#define DISKFLAG_CANDELETE 0x4 -#define DISKFLAG_CANFLUSHCACHE 0x8 -#define DISKFLAG_UNMAPPED_BIO 0x10 -#define DISKFLAG_DIRECT_COMPLETION 0x20 -#define DISKFLAG_CANZONE 0x80 +#define DISKFLAG_RESERVED 0x0001 /* Was NEEDSGIANT */ +#define DISKFLAG_OPEN 0x0002 +#define DISKFLAG_CANDELETE 0x0004 +#define DISKFLAG_CANFLUSHCACHE 0x0008 +#define DISKFLAG_UNMAPPED_BIO 0x0010 +#define DISKFLAG_DIRECT_COMPLETION 0x0020 +#define DISKFLAG_CANZONE 0x0080 +#define DISKFLAG_WRITE_PROTECT 0x0100 struct disk *disk_alloc(void); void disk_create(struct disk *disk, int version);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802151533.w1FFXI0B089691>