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);
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);
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);
}
#if 0
uint32_t initidx;
#endif
-#ifdef CTL_WITH_CA
int i;
-#endif
mtx_lock(&lun->lun_lock);
/*
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);
#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);
}