summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-10-05 11:42:44 +0000
committermav <mav@FreeBSD.org>2015-10-05 11:42:44 +0000
commit9bfaae3f56e02aaea2d1363f3a19c66e506632e3 (patch)
tree5bf8659b713bea49f8e855bae909e1c5bbb73406 /sys/cam
parent125fd313ca33a0f626dc757d02251bbf9e279412 (diff)
downloadFreeBSD-src-9bfaae3f56e02aaea2d1363f3a19c66e506632e3.zip
FreeBSD-src-9bfaae3f56e02aaea2d1363f3a19c66e506632e3.tar.gz
MFC r288369: Really implement PREVENT ALLOW MEDIUM REMOVAL command.
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/ctl/ctl.c73
-rw-r--r--sys/cam/ctl/ctl_backend_block.c5
-rw-r--r--sys/cam/ctl/ctl_backend_ramdisk.c5
-rw-r--r--sys/cam/ctl/ctl_cmd_table.c2
-rw-r--r--sys/cam/ctl/ctl_private.h2
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;
OpenPOWER on IntegriCloud