diff options
Diffstat (limited to 'sys/cam')
-rw-r--r-- | sys/cam/ctl/ctl.c | 73 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_backend_block.c | 5 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_backend_ramdisk.c | 5 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_cmd_table.c | 2 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_private.h | 2 |
5 files changed, 66 insertions, 21 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index ab21581..6d4851b 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -5131,30 +5131,43 @@ ctl_start_stop(struct ctl_scsiio *ctsio) lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; cdb = (struct scsi_start_stop_unit *)ctsio->cdb; - if ((lun->flags & CTL_LUN_PR_RESERVED) - && ((cdb->how & SSS_START)==0)) { - uint32_t residx; + if ((cdb->how & SSS_PC_MASK) == 0) { + if ((lun->flags & CTL_LUN_PR_RESERVED) && + (cdb->how & SSS_START) == 0) { + uint32_t residx; - residx = ctl_get_initindex(&ctsio->io_hdr.nexus); - if (ctl_get_prkey(lun, residx) == 0 - || (lun->pr_res_idx!=residx && lun->res_type < 4)) { + residx = ctl_get_initindex(&ctsio->io_hdr.nexus); + if (ctl_get_prkey(lun, residx) == 0 || + (lun->pr_res_idx != residx && lun->res_type < 4)) { - ctl_set_reservation_conflict(ctsio); + ctl_set_reservation_conflict(ctsio); + ctl_done((union ctl_io *)ctsio); + return (CTL_RETVAL_COMPLETE); + } + } + + if ((cdb->how & SSS_LOEJ) && + (lun->flags & CTL_LUN_REMOVABLE) == 0) { + ctl_set_invalid_field(ctsio, + /*sks_valid*/ 1, + /*command*/ 1, + /*field*/ 4, + /*bit_valid*/ 1, + /*bit*/ 1); ctl_done((union ctl_io *)ctsio); return (CTL_RETVAL_COMPLETE); } - } - if ((cdb->how & SSS_LOEJ) && - (lun->flags & CTL_LUN_REMOVABLE) == 0) { - ctl_set_invalid_field(ctsio, - /*sks_valid*/ 1, - /*command*/ 1, - /*field*/ 4, - /*bit_valid*/ 1, - /*bit*/ 1); - ctl_done((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); + if ((cdb->how & SSS_START) == 0 && (cdb->how & SSS_LOEJ) && + lun->prevent_count > 0) { + /* "Medium removal prevented" */ + ctl_set_sense(ctsio, /*current_error*/ 1, + /*sense_key*/(lun->flags & CTL_LUN_NO_MEDIA) ? + SSD_KEY_NOT_READY : SSD_KEY_ILLEGAL_REQUEST, + /*asc*/ 0x53, /*ascq*/ 0x02, SSD_ELEM_NONE); + ctl_done((union ctl_io *)ctsio); + return (CTL_RETVAL_COMPLETE); + } } retval = lun->backend->config_write((union ctl_io *)ctsio); @@ -5165,11 +5178,14 @@ int ctl_prevent_allow(struct ctl_scsiio *ctsio) { struct ctl_lun *lun; + struct scsi_prevent *cdb; int retval; + uint32_t initidx; CTL_DEBUG_PRINT(("ctl_prevent_allow\n")); lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; + cdb = (struct scsi_prevent *)ctsio->cdb; if ((lun->flags & CTL_LUN_REMOVABLE) == 0) { ctl_set_invalid_opcode(ctsio); @@ -5177,6 +5193,18 @@ ctl_prevent_allow(struct ctl_scsiio *ctsio) return (CTL_RETVAL_COMPLETE); } + initidx = ctl_get_initindex(&ctsio->io_hdr.nexus); + mtx_lock(&lun->lun_lock); + if ((cdb->how & PR_PREVENT) && + ctl_is_set(lun->prevent, initidx) == 0) { + ctl_set_mask(lun->prevent, initidx); + lun->prevent_count++; + } else if ((cdb->how & PR_PREVENT) == 0 && + ctl_is_set(lun->prevent, initidx)) { + ctl_clear_mask(lun->prevent, initidx); + lun->prevent_count--; + } + mtx_unlock(&lun->lun_lock); retval = lun->backend->config_write((union ctl_io *)ctsio); return (retval); } @@ -11807,9 +11835,7 @@ ctl_do_lun_reset(struct ctl_lun *lun, union ctl_io *io, ctl_ua_type ua_type) #if 0 uint32_t initidx; #endif -#ifdef CTL_WITH_CA int i; -#endif mtx_lock(&lun->lun_lock); /* @@ -11844,6 +11870,9 @@ ctl_do_lun_reset(struct ctl_lun *lun, union ctl_io *io, ctl_ua_type ua_type) for (i = 0; i < CTL_MAX_INITIATORS; i++) ctl_clear_mask(lun->have_ca, i); #endif + lun->prevent_count = 0; + for (i = 0; i < CTL_MAX_INITIATORS; i++) + ctl_clear_mask(lun->prevent, i); mtx_unlock(&lun->lun_lock); return (0); @@ -11989,6 +12018,10 @@ ctl_i_t_nexus_reset(union ctl_io *io) #endif if ((lun->flags & CTL_LUN_RESERVED) && (lun->res_idx == initidx)) lun->flags &= ~CTL_LUN_RESERVED; + if (ctl_is_set(lun->prevent, initidx)) { + ctl_clear_mask(lun->prevent, initidx); + lun->prevent_count--; + } ctl_est_ua(lun, initidx, CTL_UA_I_T_NEXUS_LOSS); mtx_unlock(&lun->lun_lock); } diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c index 3da6153..7e0dc74 100644 --- a/sys/cam/ctl/ctl_backend_block.c +++ b/sys/cam/ctl/ctl_backend_block.c @@ -2768,6 +2768,11 @@ ctl_be_block_config_write(union ctl_io *io) struct ctl_lun_req req; cdb = (struct scsi_start_stop_unit *)io->scsiio.cdb; + if ((cdb->how & SSS_PC_MASK) != 0) { + ctl_set_success(&io->scsiio); + ctl_config_write_done(io); + break; + } if (cdb->how & SSS_START) { if ((cdb->how & SSS_LOEJ) && be_lun->vn == NULL) { retval = ctl_be_block_open(be_lun, &req); diff --git a/sys/cam/ctl/ctl_backend_ramdisk.c b/sys/cam/ctl/ctl_backend_ramdisk.c index e210122..b15ae85 100644 --- a/sys/cam/ctl/ctl_backend_ramdisk.c +++ b/sys/cam/ctl/ctl_backend_ramdisk.c @@ -880,6 +880,11 @@ ctl_backend_ramdisk_config_write(union ctl_io *io) struct scsi_start_stop_unit *cdb; cdb = (struct scsi_start_stop_unit *)io->scsiio.cdb; + if ((cdb->how & SSS_PC_MASK) != 0) { + ctl_set_success(&io->scsiio); + ctl_config_write_done(io); + break; + } if (cdb->how & SSS_START) { if (cdb->how & SSS_LOEJ) ctl_lun_has_media(cbe_lun); diff --git a/sys/cam/ctl/ctl_cmd_table.c b/sys/cam/ctl/ctl_cmd_table.c index 4636342..498f7c5 100644 --- a/sys/cam/ctl/ctl_cmd_table.c +++ b/sys/cam/ctl/ctl_cmd_table.c @@ -658,7 +658,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_FLAG_DATA_NONE | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, - CTL_LUN_PAT_NONE, 6, {0x01, 0, 0, 0x03, 0x07}}, + CTL_LUN_PAT_NONE, 6, {0x01, 0, 0x0f, 0xf7, 0x07}}, /* 1C RECEIVE DIAGNOSTIC RESULTS */ {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, diff --git a/sys/cam/ctl/ctl_private.h b/sys/cam/ctl/ctl_private.h index 04fab60..826d004 100644 --- a/sys/cam/ctl/ctl_private.h +++ b/sys/cam/ctl/ctl_private.h @@ -397,6 +397,8 @@ struct ctl_lun { int pr_key_count; uint32_t pr_res_idx; uint8_t res_type; + int prevent_count; + uint32_t prevent[(CTL_MAX_INITIATORS+31)/32]; uint8_t *write_buffer; struct ctl_devid *lun_devid; TAILQ_HEAD(tpc_lists, tpc_list) tpc_lists; |