svn commit: r288369 - head/sys/cam/ctl

Alexander Motin mav at FreeBSD.org
Tue Sep 29 15:12:43 UTC 2015


Author: mav
Date: Tue Sep 29 15:12:40 2015
New Revision: 288369
URL: https://svnweb.freebsd.org/changeset/base/288369

Log:
  Really implement PREVENT ALLOW MEDIUM REMOVAL command.

Modified:
  head/sys/cam/ctl/ctl.c
  head/sys/cam/ctl/ctl_backend_block.c
  head/sys/cam/ctl/ctl_backend_ramdisk.c
  head/sys/cam/ctl/ctl_cmd_table.c
  head/sys/cam/ctl/ctl_private.h

Modified: head/sys/cam/ctl/ctl.c
==============================================================================
--- head/sys/cam/ctl/ctl.c	Tue Sep 29 13:58:27 2015	(r288368)
+++ head/sys/cam/ctl/ctl.c	Tue Sep 29 15:12:40 2015	(r288369)
@@ -5129,30 +5129,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_done((union ctl_io *)ctsio);
+				return (CTL_RETVAL_COMPLETE);
+			}
+		}
 
-			ctl_set_reservation_conflict(ctsio);
+		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);
@@ -5163,11 +5176,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);
@@ -5175,6 +5191,18 @@ ctl_prevent_allow(struct ctl_scsiio *cts
 		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);
 }
@@ -11805,9 +11833,7 @@ ctl_do_lun_reset(struct ctl_lun *lun, un
 #if 0
 	uint32_t initidx;
 #endif
-#ifdef CTL_WITH_CA
 	int i;
-#endif
 
 	mtx_lock(&lun->lun_lock);
 	/*
@@ -11842,6 +11868,9 @@ ctl_do_lun_reset(struct ctl_lun *lun, un
 	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);
@@ -11987,6 +12016,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);
 	}

Modified: head/sys/cam/ctl/ctl_backend_block.c
==============================================================================
--- head/sys/cam/ctl/ctl_backend_block.c	Tue Sep 29 13:58:27 2015	(r288368)
+++ head/sys/cam/ctl/ctl_backend_block.c	Tue Sep 29 15:12:40 2015	(r288369)
@@ -2754,6 +2754,11 @@ ctl_be_block_config_write(union ctl_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);

Modified: head/sys/cam/ctl/ctl_backend_ramdisk.c
==============================================================================
--- head/sys/cam/ctl/ctl_backend_ramdisk.c	Tue Sep 29 13:58:27 2015	(r288368)
+++ head/sys/cam/ctl/ctl_backend_ramdisk.c	Tue Sep 29 15:12:40 2015	(r288369)
@@ -880,6 +880,11 @@ ctl_backend_ramdisk_config_write(union c
 		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);

Modified: head/sys/cam/ctl/ctl_cmd_table.c
==============================================================================
--- head/sys/cam/ctl/ctl_cmd_table.c	Tue Sep 29 13:58:27 2015	(r288368)
+++ head/sys/cam/ctl/ctl_cmd_table.c	Tue Sep 29 15:12:40 2015	(r288369)
@@ -658,7 +658,7 @@ const struct ctl_cmd_entry ctl_cmd_table
 				   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},

Modified: head/sys/cam/ctl/ctl_private.h
==============================================================================
--- head/sys/cam/ctl/ctl_private.h	Tue Sep 29 13:58:27 2015	(r288368)
+++ head/sys/cam/ctl/ctl_private.h	Tue Sep 29 15:12:40 2015	(r288369)
@@ -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;


More information about the svn-src-all mailing list