Author: mav
Date: Mon Oct  5 11:42:44 2015
New Revision: 288816
URL: https://svnweb.freebsd.org/changeset/base/288816

Log:
  MFC r288369: Really implement PREVENT ALLOW MEDIUM REMOVAL command.

Modified:
  stable/10/sys/cam/ctl/ctl.c
  stable/10/sys/cam/ctl/ctl_backend_block.c
  stable/10/sys/cam/ctl/ctl_backend_ramdisk.c
  stable/10/sys/cam/ctl/ctl_cmd_table.c
  stable/10/sys/cam/ctl/ctl_private.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/cam/ctl/ctl.c
==============================================================================
--- stable/10/sys/cam/ctl/ctl.c Mon Oct  5 11:41:52 2015        (r288815)
+++ stable/10/sys/cam/ctl/ctl.c Mon Oct  5 11:42:44 2015        (r288816)
@@ -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_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);
@@ -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 *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);
 }
@@ -11807,9 +11835,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);
        /*
@@ -11844,6 +11870,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);
@@ -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);
        }

Modified: stable/10/sys/cam/ctl/ctl_backend_block.c
==============================================================================
--- stable/10/sys/cam/ctl/ctl_backend_block.c   Mon Oct  5 11:41:52 2015        
(r288815)
+++ stable/10/sys/cam/ctl/ctl_backend_block.c   Mon Oct  5 11:42:44 2015        
(r288816)
@@ -2768,6 +2768,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: stable/10/sys/cam/ctl/ctl_backend_ramdisk.c
==============================================================================
--- stable/10/sys/cam/ctl/ctl_backend_ramdisk.c Mon Oct  5 11:41:52 2015        
(r288815)
+++ stable/10/sys/cam/ctl/ctl_backend_ramdisk.c Mon Oct  5 11:42:44 2015        
(r288816)
@@ -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: stable/10/sys/cam/ctl/ctl_cmd_table.c
==============================================================================
--- stable/10/sys/cam/ctl/ctl_cmd_table.c       Mon Oct  5 11:41:52 2015        
(r288815)
+++ stable/10/sys/cam/ctl/ctl_cmd_table.c       Mon Oct  5 11:42:44 2015        
(r288816)
@@ -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: stable/10/sys/cam/ctl/ctl_private.h
==============================================================================
--- stable/10/sys/cam/ctl/ctl_private.h Mon Oct  5 11:41:52 2015        
(r288815)
+++ stable/10/sys/cam/ctl/ctl_private.h Mon Oct  5 11:42:44 2015        
(r288816)
@@ -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;
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to