diff options
-rw-r--r-- | sys/cam/ctl/ctl.c | 221 | ||||
-rw-r--r-- | sys/cam/ctl/ctl.h | 9 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_backend.h | 38 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_backend_block.c | 83 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_backend_ramdisk.c | 33 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_cmd_table.c | 121 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_error.c | 34 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_error.h | 5 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_io.h | 2 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_private.h | 20 |
10 files changed, 228 insertions, 338 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index 1364f3c..e1bcd18 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -3718,46 +3718,6 @@ ctl_zero_io(union ctl_io *io) io->io_hdr.pool = pool_ref; } -/* - * This routine is currently used for internal copies of ctl_ios that need - * to persist for some reason after we've already returned status to the - * FETD. (Thus the flag set.) - * - * XXX XXX - * Note that this makes a blind copy of all fields in the ctl_io, except - * for the pool reference. This includes any memory that has been - * allocated! That memory will no longer be valid after done has been - * called, so this would be VERY DANGEROUS for command that actually does - * any reads or writes. Right now (11/7/2005), this is only used for immediate - * start and stop commands, which don't transfer any data, so this is not a - * problem. If it is used for anything else, the caller would also need to - * allocate data buffer space and this routine would need to be modified to - * copy the data buffer(s) as well. - */ -void -ctl_copy_io(union ctl_io *src, union ctl_io *dest) -{ - void *pool_ref; - - if ((src == NULL) - || (dest == NULL)) - return; - - /* - * May need to preserve linked list pointers at some point too. - */ - pool_ref = dest->io_hdr.pool; - - memcpy(dest, src, MIN(sizeof(*src), sizeof(*dest))); - - dest->io_hdr.pool = pool_ref; - /* - * We need to know that this is an internal copy, and doesn't need - * to get passed back to the FETD that allocated it. - */ - dest->io_hdr.flags |= CTL_FLAG_INT_COPY; -} - int ctl_expand_number(const char *buf, uint64_t *num) { @@ -4451,15 +4411,13 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun, be_lun->ctl_lun = lun; be_lun->lun_id = lun_number; atomic_add_int(&be_lun->be->num_luns, 1); - if (be_lun->flags & CTL_LUN_FLAG_OFFLINE) - lun->flags |= CTL_LUN_OFFLINE; - - if (be_lun->flags & CTL_LUN_FLAG_POWERED_OFF) + if (be_lun->flags & CTL_LUN_FLAG_EJECTED) + lun->flags |= CTL_LUN_EJECTED; + if (be_lun->flags & CTL_LUN_FLAG_NO_MEDIA) + lun->flags |= CTL_LUN_NO_MEDIA; + if (be_lun->flags & CTL_LUN_FLAG_STOPPED) lun->flags |= CTL_LUN_STOPPED; - if (be_lun->flags & CTL_LUN_FLAG_INOPERABLE) - lun->flags |= CTL_LUN_INOPERABLE; - if (be_lun->flags & CTL_LUN_FLAG_PRIMARY) lun->flags |= CTL_LUN_PRIMARY_SC; @@ -4719,23 +4677,51 @@ ctl_stop_lun(struct ctl_be_lun *be_lun) } int -ctl_lun_offline(struct ctl_be_lun *be_lun) +ctl_lun_no_media(struct ctl_be_lun *be_lun) +{ + struct ctl_lun *lun = (struct ctl_lun *)be_lun->ctl_lun; + + mtx_lock(&lun->lun_lock); + lun->flags |= CTL_LUN_NO_MEDIA; + mtx_unlock(&lun->lun_lock); + return (0); +} + +int +ctl_lun_has_media(struct ctl_be_lun *be_lun) { struct ctl_lun *lun = (struct ctl_lun *)be_lun->ctl_lun; + union ctl_ha_msg msg; mtx_lock(&lun->lun_lock); - lun->flags |= CTL_LUN_OFFLINE; + lun->flags &= ~(CTL_LUN_NO_MEDIA | CTL_LUN_EJECTED); + if (lun->flags & CTL_LUN_REMOVABLE) + ctl_est_ua_all(lun, -1, CTL_UA_MEDIUM_CHANGE); mtx_unlock(&lun->lun_lock); + if ((lun->flags & CTL_LUN_REMOVABLE) && + lun->ctl_softc->ha_mode == CTL_HA_MODE_XFER) { + bzero(&msg.ua, sizeof(msg.ua)); + msg.hdr.msg_type = CTL_MSG_UA; + msg.hdr.nexus.initid = -1; + msg.hdr.nexus.targ_port = -1; + msg.hdr.nexus.targ_lun = lun->lun; + msg.hdr.nexus.targ_mapped_lun = lun->lun; + msg.ua.ua_all = 1; + msg.ua.ua_set = 1; + msg.ua.ua_type = CTL_UA_MEDIUM_CHANGE; + ctl_ha_msg_send(CTL_HA_CHAN_CTL, &msg, sizeof(msg.ua), + M_WAITOK); + } return (0); } int -ctl_lun_online(struct ctl_be_lun *be_lun) +ctl_lun_ejected(struct ctl_be_lun *be_lun) { struct ctl_lun *lun = (struct ctl_lun *)be_lun->ctl_lun; mtx_lock(&lun->lun_lock); - lun->flags &= ~CTL_LUN_OFFLINE; + lun->flags |= CTL_LUN_EJECTED; mtx_unlock(&lun->lun_lock); return (0); } @@ -4805,28 +4791,6 @@ ctl_invalidate_lun(struct ctl_be_lun *be_lun) return (0); } -int -ctl_lun_inoperable(struct ctl_be_lun *be_lun) -{ - struct ctl_lun *lun = (struct ctl_lun *)be_lun->ctl_lun; - - mtx_lock(&lun->lun_lock); - lun->flags |= CTL_LUN_INOPERABLE; - mtx_unlock(&lun->lun_lock); - return (0); -} - -int -ctl_lun_operable(struct ctl_be_lun *be_lun) -{ - struct ctl_lun *lun = (struct ctl_lun *)be_lun->ctl_lun; - - mtx_lock(&lun->lun_lock); - lun->flags &= ~CTL_LUN_INOPERABLE; - mtx_unlock(&lun->lun_lock); - return (0); -} - void ctl_lun_capacity_changed(struct ctl_be_lun *be_lun) { @@ -4834,7 +4798,7 @@ ctl_lun_capacity_changed(struct ctl_be_lun *be_lun) union ctl_ha_msg msg; mtx_lock(&lun->lun_lock); - ctl_est_ua_all(lun, -1, CTL_UA_CAPACITY_CHANGED); + ctl_est_ua_all(lun, -1, CTL_UA_CAPACITY_CHANGE); mtx_unlock(&lun->lun_lock); if (lun->ctl_softc->ha_mode == CTL_HA_MODE_XFER) { /* Send msg to other side. */ @@ -4846,7 +4810,7 @@ ctl_lun_capacity_changed(struct ctl_be_lun *be_lun) msg.hdr.nexus.targ_mapped_lun = lun->lun; msg.ua.ua_all = 1; msg.ua.ua_set = 1; - msg.ua.ua_type = CTL_UA_CAPACITY_CHANGED; + msg.ua.ua_type = CTL_UA_CAPACITY_CHANGE; ctl_ha_msg_send(CTL_HA_CHAN_CTL, &msg, sizeof(msg.ua), M_WAITOK); } @@ -5104,34 +5068,6 @@ 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; - /* - * XXX KDM - * We don't support the immediate bit on a stop unit. In order to - * do that, we would need to code up a way to know that a stop is - * pending, and hold off any new commands until it completes, one - * way or another. Then we could accept or reject those commands - * depending on its status. We would almost need to do the reverse - * of what we do below for an immediate start -- return the copy of - * the ctl_io to the FETD with status to send to the host (and to - * free the copy!) and then free the original I/O once the stop - * actually completes. That way, the OOA queue mechanism can work - * to block commands that shouldn't proceed. Another alternative - * would be to put the copy in the queue in place of the original, - * and return the original back to the caller. That could be - * slightly safer.. - */ - if ((cdb->byte2 & SSS_IMMED) - && ((cdb->how & SSS_START) == 0)) { - ctl_set_invalid_field(ctsio, - /*sks_valid*/ 1, - /*command*/ 1, - /*field*/ 1, - /*bit_valid*/ 1, - /*bit*/ 0); - ctl_done((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); - } - if ((lun->flags & CTL_LUN_PR_RESERVED) && ((cdb->how & SSS_START)==0)) { uint32_t residx; @@ -5158,28 +5094,7 @@ ctl_start_stop(struct ctl_scsiio *ctsio) return (CTL_RETVAL_COMPLETE); } - /* - * In the non-immediate case, we send the request to - * the backend and return status to the user when - * it is done. - * - * In the immediate case, we allocate a new ctl_io - * to hold a copy of the request, and send that to - * the backend. We then set good status on the - * user's request and return it immediately. - */ - if (cdb->byte2 & SSS_IMMED) { - union ctl_io *new_io; - - new_io = ctl_alloc_io(ctsio->io_hdr.pool); - ctl_copy_io((union ctl_io *)ctsio, new_io); - retval = lun->backend->config_write(new_io); - ctl_set_success(ctsio); - ctl_done((union ctl_io *)ctsio); - } else { - retval = lun->backend->config_write( - (union ctl_io *)ctsio); - } + retval = lun->backend->config_write((union ctl_io *)ctsio); return (retval); } @@ -5348,17 +5263,6 @@ ctl_format(struct ctl_scsiio *ctsio) } } - /* - * The format command will clear out the "Medium format corrupted" - * status if set by the configuration code. That status is really - * just a way to notify the host that we have lost the media, and - * get them to issue a command that will basically make them think - * they're blowing away the media. - */ - mtx_lock(&lun->lun_lock); - lun->flags &= ~CTL_LUN_INOPERABLE; - mtx_unlock(&lun->lun_lock); - ctl_set_success(ctsio); bailout: @@ -10313,7 +10217,7 @@ ctl_get_config(struct ctl_scsiio *ctsio) ctsio->kern_rel_offset = 0; hdr = (struct scsi_get_config_header *)ctsio->kern_data_ptr; - if (lun->flags & CTL_LUN_OFFLINE) + if (lun->flags & CTL_LUN_NO_MEDIA) scsi_ulto2b(0x0000, hdr->current_profile); else scsi_ulto2b(0x0010, hdr->current_profile); @@ -10372,13 +10276,13 @@ f3: /* Removable Medium */ feature = (struct scsi_get_config_feature *) &feature->feature_data[feature->add_length]; - if (rt == SGC_RT_CURRENT && (lun->flags & CTL_LUN_OFFLINE)) + if (rt == SGC_RT_CURRENT && (lun->flags & CTL_LUN_NO_MEDIA)) goto done; f10: /* Random Read */ scsi_ulto2b(0x0010, feature->feature_code); feature->flags = 0x00; - if ((lun->flags & CTL_LUN_OFFLINE) == 0) + if ((lun->flags & CTL_LUN_NO_MEDIA) == 0) feature->flags |= SGC_F_CURRENT; feature->add_length = 8; scsi_ulto4b(lun->be_lun->blocksize, &feature->feature_data[0]); @@ -10390,7 +10294,7 @@ f10: /* Random Read */ f1d: /* Multi-Read */ scsi_ulto2b(0x001D, feature->feature_code); feature->flags = 0x00; - if ((lun->flags & CTL_LUN_OFFLINE) == 0) + if ((lun->flags & CTL_LUN_NO_MEDIA) == 0) feature->flags |= SGC_F_CURRENT; feature->add_length = 0; feature = (struct scsi_get_config_feature *) @@ -10399,7 +10303,7 @@ f1d: /* Multi-Read */ f1e: /* CD Read */ scsi_ulto2b(0x001E, feature->feature_code); feature->flags = 0x00; - if ((lun->flags & CTL_LUN_OFFLINE) == 0) + if ((lun->flags & CTL_LUN_NO_MEDIA) == 0) feature->flags |= SGC_F_CURRENT; feature->add_length = 4; feature->feature_data[0] = 0x00; @@ -10409,7 +10313,7 @@ f1e: /* CD Read */ f1f: /* DVD Read */ scsi_ulto2b(0x001F, feature->feature_code); feature->flags = 0x08; - if ((lun->flags & CTL_LUN_OFFLINE) == 0) + if ((lun->flags & CTL_LUN_NO_MEDIA) == 0) feature->flags |= SGC_F_CURRENT; feature->add_length = 4; feature->feature_data[0] = 0x01; @@ -11263,25 +11167,18 @@ ctl_scsiio_lun_check(struct ctl_lun *lun, } } - if ((lun->flags & CTL_LUN_OFFLINE) - && ((entry->flags & CTL_CMD_FLAG_OK_ON_STANDBY) == 0)) { - ctl_set_lun_not_ready(ctsio); - retval = 1; - goto bailout; - } - - if ((lun->flags & CTL_LUN_STOPPED) - && ((entry->flags & CTL_CMD_FLAG_OK_ON_STOPPED) == 0)) { - /* "Logical unit not ready, initializing cmd. required" */ - ctl_set_lun_stopped(ctsio); - retval = 1; - goto bailout; - } - - if ((lun->flags & CTL_LUN_INOPERABLE) - && ((entry->flags & CTL_CMD_FLAG_OK_ON_INOPERABLE) == 0)) { - /* "Medium format corrupted" */ - ctl_set_medium_format_corrupted(ctsio); + if ((entry->flags & CTL_CMD_FLAG_OK_ON_NO_MEDIA) == 0) { + if (lun->flags & CTL_LUN_EJECTED) + ctl_set_lun_ejected(ctsio); + else if (lun->flags & CTL_LUN_NO_MEDIA) { + if (lun->flags & CTL_LUN_REMOVABLE) + ctl_set_lun_no_media(ctsio); + else + ctl_set_lun_int_reqd(ctsio); + } else if (lun->flags & CTL_LUN_STOPPED) + ctl_set_lun_stopped(ctsio); + else + goto bailout; retval = 1; goto bailout; } @@ -13486,7 +13383,7 @@ ctl_thresh_thread(void *arg) mtx_lock(&softc->ctl_lock); STAILQ_FOREACH(lun, &softc->lun_list, links) { if ((lun->flags & CTL_LUN_DISABLED) || - (lun->flags & CTL_LUN_OFFLINE) || + (lun->flags & CTL_LUN_NO_MEDIA) || lun->backend->lun_attr == NULL) continue; if ((lun->flags & CTL_LUN_PRIMARY_SC) == 0 && diff --git a/sys/cam/ctl/ctl.h b/sys/cam/ctl/ctl.h index 9fd6cce..35fc4c3 100644 --- a/sys/cam/ctl/ctl.h +++ b/sys/cam/ctl/ctl.h @@ -123,10 +123,11 @@ typedef enum { CTL_UA_INQ_CHANGE = 0x0100, CTL_UA_RES_PREEMPT = 0x0400, CTL_UA_RES_RELEASE = 0x0800, - CTL_UA_REG_PREEMPT = 0x1000, - CTL_UA_ASYM_ACC_CHANGE = 0x2000, - CTL_UA_CAPACITY_CHANGED = 0x4000, - CTL_UA_THIN_PROV_THRES = 0x8000 + CTL_UA_REG_PREEMPT = 0x1000, + CTL_UA_ASYM_ACC_CHANGE = 0x2000, + CTL_UA_CAPACITY_CHANGE = 0x4000, + CTL_UA_THIN_PROV_THRES = 0x8000, + CTL_UA_MEDIUM_CHANGE = 0x10000 } ctl_ua_type; #ifdef _KERNEL diff --git a/sys/cam/ctl/ctl_backend.h b/sys/cam/ctl/ctl_backend.h index f5bfd83..4177e2d 100644 --- a/sys/cam/ctl/ctl_backend.h +++ b/sys/cam/ctl/ctl_backend.h @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003 Silicon Graphics International Corp. + * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,14 +50,11 @@ * particular LUN ID in the req_lun_id field. If we cannot allocate that * LUN ID, the ctl_add_lun() call will fail. * - * The POWERED_OFF flag tells us that the LUN should default to the powered + * The STOPPED flag tells us that the LUN should default to the powered * off state. It will return 0x04,0x02 until it is powered up. ("Logical * unit not ready, initializing command required.") * - * The INOPERABLE flag tells us that this LUN is not operable for whatever - * reason. This means that user data may have been (or has been?) lost. - * We will return 0x31,0x00 ("Medium format corrupted") until the host - * issues a FORMAT UNIT command to clear the error. + * The NO_MEDIA flag tells us that the LUN has no media inserted. * * The PRIMARY flag tells us that this LUN is registered as a Primary LUN * which is accessible via the Master shelf controller in an HA. This flag @@ -72,20 +70,22 @@ * * The DEV_TYPE flag tells us that the device_type field is filled in. * + * The EJECTED flag tells us that the removable LUN has tray open. + * * The UNMAP flag tells us that this LUN supports UNMAP. * * The OFFLINE flag tells us that this LUN can not access backing store. */ typedef enum { CTL_LUN_FLAG_ID_REQ = 0x01, - CTL_LUN_FLAG_POWERED_OFF = 0x02, - CTL_LUN_FLAG_INOPERABLE = 0x04, + CTL_LUN_FLAG_STOPPED = 0x02, + CTL_LUN_FLAG_NO_MEDIA = 0x04, CTL_LUN_FLAG_PRIMARY = 0x08, CTL_LUN_FLAG_SERIAL_NUM = 0x10, CTL_LUN_FLAG_DEVID = 0x20, CTL_LUN_FLAG_DEV_TYPE = 0x40, CTL_LUN_FLAG_UNMAP = 0x80, - CTL_LUN_FLAG_OFFLINE = 0x100, + CTL_LUN_FLAG_EJECTED = 0x100, CTL_LUN_FLAG_READONLY = 0x200 } ctl_backend_lun_flags; @@ -289,23 +289,11 @@ int ctl_start_lun(struct ctl_be_lun *be_lun); int ctl_stop_lun(struct ctl_be_lun *be_lun); /* - * If a LUN is inoperable, call ctl_lun_inoperable(). Generally the LUN - * will become operable once again when the user issues the SCSI FORMAT UNIT - * command. (CTL will automatically clear the inoperable flag.) If we - * need to re-enable the LUN, we can call ctl_lun_operable() to enable it - * without a SCSI command. - */ -int ctl_lun_inoperable(struct ctl_be_lun *be_lun); -int ctl_lun_operable(struct ctl_be_lun *be_lun); - -/* - * To take a LUN offline, call ctl_lun_offline(). Generally the LUN will - * be online again once the user sends a SCSI START STOP UNIT command with - * the start and on/offline bits set. The backend can bring the LUN back - * online via the ctl_lun_online() function, if necessary. + * Methods to notify about media and tray status changes. */ -int ctl_lun_offline(struct ctl_be_lun *be_lun); -int ctl_lun_online(struct ctl_be_lun *be_lun); +int ctl_lun_no_media(struct ctl_be_lun *be_lun); +int ctl_lun_has_media(struct ctl_be_lun *be_lun); +int ctl_lun_ejected(struct ctl_be_lun *be_lun); /* * Called on LUN HA role change. @@ -314,7 +302,7 @@ int ctl_lun_primary(struct ctl_be_lun *be_lun); int ctl_lun_secondary(struct ctl_be_lun *be_lun); /* - * Let the backend notify the initiator about changed capacity. + * Let the backend notify the initiators about changes. */ void ctl_lun_capacity_changed(struct ctl_be_lun *be_lun); diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c index 71ea521..3da6153 100644 --- a/sys/cam/ctl/ctl_backend_block.c +++ b/sys/cam/ctl/ctl_backend_block.c @@ -2,6 +2,7 @@ * Copyright (c) 2003 Silicon Graphics International Corp. * Copyright (c) 2009-2011 Spectra Logic Corporation * Copyright (c) 2012 The FreeBSD Foundation + * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org> * All rights reserved. * * Portions of this software were developed by Edward Tomasz Napierala @@ -259,8 +260,7 @@ static int ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, static int ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req); static int ctl_be_block_close(struct ctl_be_block_lun *be_lun); -static int ctl_be_block_open(struct ctl_be_block_softc *softc, - struct ctl_be_block_lun *be_lun, +static int ctl_be_block_open(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req); static int ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req); @@ -1663,7 +1663,7 @@ ctl_be_block_worker(void *context, int pending) DPRINTF("entered\n"); /* * Fetch and process I/Os from all queues. If we detect LUN - * CTL_LUN_FLAG_OFFLINE status here -- it is result of a race, + * CTL_LUN_FLAG_NO_MEDIA status here -- it is result of a race, * so make response maximally opaque to not confuse initiator. */ for (;;) { @@ -1675,7 +1675,7 @@ ctl_be_block_worker(void *context, int pending) ctl_io_hdr, links); mtx_unlock(&be_lun->queue_lock); beio = (struct ctl_be_block_io *)PRIV(io)->ptr; - if (cbe_lun->flags & CTL_LUN_FLAG_OFFLINE) { + if (cbe_lun->flags & CTL_LUN_FLAG_NO_MEDIA) { ctl_set_busy(&io->scsiio); ctl_complete_beio(beio); return; @@ -1689,7 +1689,7 @@ ctl_be_block_worker(void *context, int pending) STAILQ_REMOVE(&be_lun->config_write_queue, &io->io_hdr, ctl_io_hdr, links); mtx_unlock(&be_lun->queue_lock); - if (cbe_lun->flags & CTL_LUN_FLAG_OFFLINE) { + if (cbe_lun->flags & CTL_LUN_FLAG_NO_MEDIA) { ctl_set_busy(&io->scsiio); ctl_config_write_done(io); return; @@ -1703,7 +1703,7 @@ ctl_be_block_worker(void *context, int pending) STAILQ_REMOVE(&be_lun->config_read_queue, &io->io_hdr, ctl_io_hdr, links); mtx_unlock(&be_lun->queue_lock); - if (cbe_lun->flags & CTL_LUN_FLAG_OFFLINE) { + if (cbe_lun->flags & CTL_LUN_FLAG_NO_MEDIA) { ctl_set_busy(&io->scsiio); ctl_config_read_done(io); return; @@ -1717,7 +1717,7 @@ ctl_be_block_worker(void *context, int pending) STAILQ_REMOVE(&be_lun->input_queue, &io->io_hdr, ctl_io_hdr, links); mtx_unlock(&be_lun->queue_lock); - if (cbe_lun->flags & CTL_LUN_FLAG_OFFLINE) { + if (cbe_lun->flags & CTL_LUN_FLAG_NO_MEDIA) { ctl_set_busy(&io->scsiio); ctl_data_submit_done(io); return; @@ -2137,8 +2137,7 @@ ctl_be_block_close(struct ctl_be_block_lun *be_lun) } static int -ctl_be_block_open(struct ctl_be_block_softc *softc, - struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req) +ctl_be_block_open(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req) { struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun; struct nameidata nd; @@ -2309,7 +2308,7 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req) if ((cbe_lun->flags & CTL_LUN_FLAG_PRIMARY) || control_softc->ha_mode == CTL_HA_MODE_SER_ONLY) { - retval = ctl_be_block_open(softc, be_lun, req); + retval = ctl_be_block_open(be_lun, req); if (retval != 0) { retval = 0; req->status = CTL_LUN_WARNING; @@ -2339,7 +2338,7 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req) } if (be_lun->vn == NULL) - cbe_lun->flags |= CTL_LUN_FLAG_OFFLINE; + cbe_lun->flags |= CTL_LUN_FLAG_NO_MEDIA; /* Tell the user the blocksize we ended up using */ params->lun_size_bytes = be_lun->size_bytes; params->blocksize_bytes = cbe_lun->blocksize; @@ -2526,8 +2525,8 @@ ctl_be_block_rm(struct ctl_be_block_softc *softc, struct ctl_lun_req *req) } if (be_lun->vn != NULL) { - cbe_lun->flags |= CTL_LUN_FLAG_OFFLINE; - ctl_lun_offline(cbe_lun); + cbe_lun->flags |= CTL_LUN_FLAG_NO_MEDIA; + ctl_lun_no_media(cbe_lun); taskqueue_drain_all(be_lun->io_taskqueue); ctl_be_block_close(be_lun); } @@ -2635,22 +2634,27 @@ ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req) if ((cbe_lun->flags & CTL_LUN_FLAG_PRIMARY) || control_softc->ha_mode == CTL_HA_MODE_SER_ONLY) { if (be_lun->vn == NULL) - error = ctl_be_block_open(softc, be_lun, req); + error = ctl_be_block_open(be_lun, req); else if (vn_isdisk(be_lun->vn, &error)) error = ctl_be_block_open_dev(be_lun, req); else if (be_lun->vn->v_type == VREG) error = ctl_be_block_open_file(be_lun, req); else error = EINVAL; - if ((cbe_lun->flags & CTL_LUN_FLAG_OFFLINE) && + if ((cbe_lun->flags & CTL_LUN_FLAG_NO_MEDIA) && be_lun->vn != NULL) { - cbe_lun->flags &= ~CTL_LUN_FLAG_OFFLINE; - ctl_lun_online(cbe_lun); + cbe_lun->flags &= ~CTL_LUN_FLAG_NO_MEDIA; + ctl_lun_has_media(cbe_lun); + } else if ((cbe_lun->flags & CTL_LUN_FLAG_NO_MEDIA) == 0 && + be_lun->vn == NULL) { + cbe_lun->flags |= CTL_LUN_FLAG_NO_MEDIA; + ctl_lun_no_media(cbe_lun); } + cbe_lun->flags &= ~CTL_LUN_FLAG_EJECTED; } else { if (be_lun->vn != NULL) { - cbe_lun->flags |= CTL_LUN_FLAG_OFFLINE; - ctl_lun_offline(cbe_lun); + cbe_lun->flags |= CTL_LUN_FLAG_NO_MEDIA; + ctl_lun_no_media(cbe_lun); taskqueue_drain_all(be_lun->io_taskqueue); error = ctl_be_block_close(be_lun); } else @@ -2761,27 +2765,34 @@ ctl_be_block_config_write(union ctl_io *io) break; case START_STOP_UNIT: { struct scsi_start_stop_unit *cdb; + struct ctl_lun_req req; cdb = (struct scsi_start_stop_unit *)io->scsiio.cdb; - - if (cdb->how & SSS_START) - retval = ctl_start_lun(cbe_lun); - else - retval = ctl_stop_lun(cbe_lun); - - /* - * In general, the above routines should not fail. They - * just set state for the LUN. So we've got something - * pretty wrong here if we can't start or stop the LUN. - */ - if (retval != 0) { - ctl_set_internal_failure(&io->scsiio, - /*sks_valid*/ 1, - /*retry_count*/ 0xf051); - retval = CTL_RETVAL_COMPLETE; + if (cdb->how & SSS_START) { + if ((cdb->how & SSS_LOEJ) && be_lun->vn == NULL) { + retval = ctl_be_block_open(be_lun, &req); + cbe_lun->flags &= ~CTL_LUN_FLAG_EJECTED; + if (retval == 0) { + cbe_lun->flags &= ~CTL_LUN_FLAG_NO_MEDIA; + ctl_lun_has_media(cbe_lun); + } else { + cbe_lun->flags |= CTL_LUN_FLAG_NO_MEDIA; + ctl_lun_no_media(cbe_lun); + } + } + ctl_start_lun(cbe_lun); } else { - ctl_set_success(&io->scsiio); + ctl_stop_lun(cbe_lun); + if (cdb->how & SSS_LOEJ) { + cbe_lun->flags |= CTL_LUN_FLAG_NO_MEDIA; + cbe_lun->flags |= CTL_LUN_FLAG_EJECTED; + ctl_lun_ejected(cbe_lun); + if (be_lun->vn != NULL) + ctl_be_block_close(be_lun); + } } + + ctl_set_success(&io->scsiio); ctl_config_write_done(io); break; } diff --git a/sys/cam/ctl/ctl_backend_ramdisk.c b/sys/cam/ctl/ctl_backend_ramdisk.c index efa41e6..e210122 100644 --- a/sys/cam/ctl/ctl_backend_ramdisk.c +++ b/sys/cam/ctl/ctl_backend_ramdisk.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2003, 2008 Silicon Graphics International Corp. * Copyright (c) 2012 The FreeBSD Foundation + * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org> * All rights reserved. * * Portions of this software were developed by Edward Tomasz Napierala @@ -848,8 +849,11 @@ ctl_backend_ramdisk_lun_config_status(void *be_lun, static int ctl_backend_ramdisk_config_write(union ctl_io *io) { + struct ctl_be_lun *cbe_lun; int retval; + cbe_lun = (struct ctl_be_lun *)io->io_hdr.ctl_private[ + CTL_PRIV_BACKEND_LUN].ptr; retval = 0; switch (io->scsiio.cdb[0]) { case SYNCHRONIZE_CACHE: @@ -874,31 +878,18 @@ ctl_backend_ramdisk_config_write(union ctl_io *io) break; case START_STOP_UNIT: { struct scsi_start_stop_unit *cdb; - struct ctl_be_lun *cbe_lun; cdb = (struct scsi_start_stop_unit *)io->scsiio.cdb; - - cbe_lun = (struct ctl_be_lun *)io->io_hdr.ctl_private[ - CTL_PRIV_BACKEND_LUN].ptr; - - if (cdb->how & SSS_START) - retval = ctl_start_lun(cbe_lun); - else - retval = ctl_stop_lun(cbe_lun); - - /* - * In general, the above routines should not fail. They - * just set state for the LUN. So we've got something - * pretty wrong here if we can't start or stop the LUN. - */ - if (retval != 0) { - ctl_set_internal_failure(&io->scsiio, - /*sks_valid*/ 1, - /*retry_count*/ 0xf051); - retval = CTL_RETVAL_COMPLETE; + if (cdb->how & SSS_START) { + if (cdb->how & SSS_LOEJ) + ctl_lun_has_media(cbe_lun); + ctl_start_lun(cbe_lun); } else { - ctl_set_success(&io->scsiio); + ctl_stop_lun(cbe_lun); + if (cdb->how & SSS_LOEJ) + ctl_lun_ejected(cbe_lun); } + ctl_set_success(&io->scsiio); ctl_config_write_done(io); break; } diff --git a/sys/cam/ctl/ctl_cmd_table.c b/sys/cam/ctl/ctl_cmd_table.c index e7f298e..0f0cc5a 100644 --- a/sys/cam/ctl/ctl_cmd_table.c +++ b/sys/cam/ctl/ctl_cmd_table.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003, 2004, 2005, 2009 Silicon Graphics International Corp. + * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -67,8 +68,7 @@ const struct ctl_cmd_entry ctl_cmd_table_5e[32] = /* 00 READ KEYS */ {ctl_persistent_reserve_in, CTL_SERIDX_RES, CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, @@ -78,8 +78,7 @@ const struct ctl_cmd_entry ctl_cmd_table_5e[32] = /* 01 READ RESERVATION */ {ctl_persistent_reserve_in, CTL_SERIDX_RES, CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, @@ -89,8 +88,7 @@ const struct ctl_cmd_entry ctl_cmd_table_5e[32] = /* 02 REPORT CAPABILITIES */ {ctl_persistent_reserve_in, CTL_SERIDX_INQ, CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, @@ -100,8 +98,7 @@ const struct ctl_cmd_entry ctl_cmd_table_5e[32] = /* 03 READ FULL STATUS */ {ctl_persistent_reserve_in, CTL_SERIDX_INQ, CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, @@ -117,8 +114,7 @@ const struct ctl_cmd_entry ctl_cmd_table_5f[32] = /* 00 REGISTER */ {ctl_persistent_reserve_out, CTL_SERIDX_RES, CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_OUT | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, @@ -128,8 +124,7 @@ const struct ctl_cmd_entry ctl_cmd_table_5f[32] = /* 01 RESERVE */ {ctl_persistent_reserve_out, CTL_SERIDX_RES, CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_OUT | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, @@ -139,8 +134,7 @@ const struct ctl_cmd_entry ctl_cmd_table_5f[32] = /* 02 RELEASE */ {ctl_persistent_reserve_out, CTL_SERIDX_RES, CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_OUT | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, @@ -150,8 +144,7 @@ const struct ctl_cmd_entry ctl_cmd_table_5f[32] = /* 03 CLEAR */ {ctl_persistent_reserve_out, CTL_SERIDX_RES, CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_OUT | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, @@ -161,8 +154,7 @@ const struct ctl_cmd_entry ctl_cmd_table_5f[32] = /* 04 PREEMPT */ {ctl_persistent_reserve_out, CTL_SERIDX_RES, CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_OUT | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, @@ -172,8 +164,7 @@ const struct ctl_cmd_entry ctl_cmd_table_5f[32] = /* 05 PREEMPT AND ABORT */ {ctl_persistent_reserve_out, CTL_SERIDX_RES, CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_OUT | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, @@ -183,8 +174,7 @@ const struct ctl_cmd_entry ctl_cmd_table_5f[32] = /* 06 REGISTER AND IGNORE EXISTING KEY */ {ctl_persistent_reserve_out, CTL_SERIDX_RES, CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_OUT | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, @@ -202,12 +192,14 @@ const struct ctl_cmd_entry ctl_cmd_table_83[32] = { /* 00 EXTENDED COPY (LID1) */ {ctl_extended_copy_lid1, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_BOTH | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_FLAG_DATA_OUT, CTL_LUN_PAT_NONE, 16, { 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0x07}}, /* 01 EXTENDED COPY (LID4) */ {ctl_extended_copy_lid4, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_BOTH | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_FLAG_DATA_OUT, CTL_LUN_PAT_NONE, 16, { 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0x07}}, @@ -301,6 +293,7 @@ const struct ctl_cmd_entry ctl_cmd_table_83[32] = /* 1C COPY OPERATION ABORT */ {ctl_copy_operation_abort, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_BOTH | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_FLAG_DATA_NONE, CTL_LUN_PAT_NONE, 16, { 0x1c, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x07}}, @@ -312,6 +305,7 @@ const struct ctl_cmd_entry ctl_cmd_table_84[32] = /* 00 RECEIVE COPY STATUS (LID1) */ {ctl_receive_copy_status_lid1, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_BOTH | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, CTL_LUN_PAT_NONE, @@ -326,8 +320,7 @@ const struct ctl_cmd_entry ctl_cmd_table_84[32] = /* 03 RECEIVE COPY OPERATING PARAMETERS */ {ctl_receive_copy_operating_parameters, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, @@ -337,6 +330,7 @@ const struct ctl_cmd_entry ctl_cmd_table_84[32] = /* 04 RECEIVE COPY FAILURE DETAILS (LID1) */ {ctl_receive_copy_failure_details, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_BOTH | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, CTL_LUN_PAT_NONE, @@ -345,6 +339,7 @@ const struct ctl_cmd_entry ctl_cmd_table_84[32] = /* 05 RECEIVE COPY STATUS (LID4) */ {ctl_receive_copy_status_lid4, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_BOTH | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, CTL_LUN_PAT_NONE, @@ -356,6 +351,7 @@ const struct ctl_cmd_entry ctl_cmd_table_84[32] = /* 07 RECEIVE ROD TOKEN INFORMATION */ {ctl_receive_rod_token_information, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_BOTH | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, CTL_LUN_PAT_NONE, @@ -364,6 +360,7 @@ const struct ctl_cmd_entry ctl_cmd_table_84[32] = /* 08 REPORT ALL ROD TOKENS */ {ctl_report_all_rod_tokens, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_BOTH | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, CTL_LUN_PAT_NONE, @@ -423,8 +420,6 @@ const struct ctl_cmd_entry ctl_cmd_table_9e[32] = /* 10 READ CAPACITY(16) */ {ctl_read_capacity_16, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_DIRECT | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, CTL_LUN_PAT_READCAP, @@ -479,8 +474,7 @@ const struct ctl_cmd_entry ctl_cmd_table_a3[32] = /* 0A REPORT TARGET PORT GROUPS */ {ctl_report_tagret_port_groups, CTL_SERIDX_INQ, CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_CMD_FLAG_OK_ON_UNAVAIL | CTL_FLAG_DATA_IN | @@ -493,8 +487,7 @@ const struct ctl_cmd_entry ctl_cmd_table_a3[32] = /* 0C REPORT SUPPORTED_OPCODES */ {ctl_report_supported_opcodes, CTL_SERIDX_INQ, CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_CMD_FLAG_OK_ON_UNAVAIL | CTL_FLAG_DATA_IN | @@ -504,8 +497,7 @@ const struct ctl_cmd_entry ctl_cmd_table_a3[32] = /* 0D REPORT SUPPORTED_TASK MANAGEMENT FUNCTIONS */ {ctl_report_supported_tmf, CTL_SERIDX_INQ, CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_CMD_FLAG_OK_ON_UNAVAIL | CTL_FLAG_DATA_IN | @@ -518,8 +510,7 @@ const struct ctl_cmd_entry ctl_cmd_table_a3[32] = /* 0F REPORT TIMESTAMP */ {ctl_report_timestamp, CTL_SERIDX_INQ, CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_CMD_FLAG_OK_ON_UNAVAIL | CTL_FLAG_DATA_IN | @@ -550,8 +541,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = CTL_CMD_FLAG_OK_ON_BOTH | CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_NO_SENSE | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_CMD_FLAG_OK_ON_UNAVAIL | CTL_CMD_FLAG_ALLOW_ON_PR_RESV | @@ -560,7 +550,6 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 04 FORMAT UNIT */ {ctl_format, CTL_SERIDX_FORMAT, CTL_CMD_FLAG_OK_ON_DIRECT | - CTL_CMD_FLAG_OK_ON_INOPERABLE | CTL_FLAG_DATA_OUT, CTL_LUN_PAT_NONE, 6, {0xff, 0, 0, 0, 0x07}}, @@ -613,8 +602,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = CTL_CMD_FLAG_OK_ON_BOTH | CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_NO_SENSE | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_CMD_FLAG_OK_ON_UNAVAIL | CTL_FLAG_DATA_IN | @@ -629,8 +617,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 15 MODE SELECT(6) */ {ctl_mode_select, CTL_SERIDX_MD_SEL, CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_OUT, CTL_LUN_PAT_NONE, 6, {0x11, 0, 0, 0xff, 0x07}}, @@ -638,8 +625,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 16 RESERVE(6) */ {ctl_scsi_reserve, CTL_SERIDX_RES, CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_OUT, CTL_LUN_PAT_NONE, 6, {0, 0, 0, 0, 0x07}}, @@ -647,8 +633,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 17 RELEASE(6) */ {ctl_scsi_release, CTL_SERIDX_RES, CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_NONE, CTL_LUN_PAT_NONE, 6, {0, 0, 0, 0, 0x07}}, @@ -661,8 +646,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 1A MODE SENSE(6) */ {ctl_mode_sense, CTL_SERIDX_MD_SNS, CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_WRESV, @@ -671,8 +655,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 1B START STOP UNIT */ {ctl_start_stop, CTL_SERIDX_START, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_CMD_FLAG_OK_ON_CDROM | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + 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}}, @@ -686,8 +669,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 1E PREVENT ALLOW MEDIUM REMOVAL */ {ctl_prevent_allow, CTL_SERIDX_START, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_CMD_FLAG_OK_ON_CDROM | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_FLAG_DATA_NONE, CTL_LUN_PAT_NONE, 6, {0x01, 0, 0, 0x03, 0x07}}, @@ -712,8 +694,6 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 25 READ CAPACITY(10) */ {ctl_read_capacity, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_DIRECT | CTL_CMD_FLAG_OK_ON_CDROM | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, CTL_LUN_PAT_READCAP, 10, {0, 0, 0, 0, 0, 0, 0, 0, 0x07}}, @@ -803,8 +783,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 3B WRITE BUFFER */ {ctl_write_buffer, CTL_SERIDX_MD_SEL, CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_OUT, CTL_LUN_PAT_NONE, @@ -812,8 +791,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 3C READ BUFFER */ {ctl_read_buffer, CTL_SERIDX_MD_SNS, CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_WRESV, @@ -858,7 +836,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 46 GET CONFIGURATION */ {ctl_get_config, CTL_SERIDX_INQ, CTL_CMD_FLAG_OK_ON_CDROM | - CTL_CMD_FLAG_OK_ON_STOPPED | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_ALLOW_ON_PR_RESV | CTL_FLAG_DATA_IN, CTL_LUN_PAT_NONE, @@ -875,8 +853,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 4A GET EVENT STATUS NOTIFICATION */ {ctl_get_event_status, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_CDROM | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_ALLOW_ON_PR_RESV | CTL_FLAG_DATA_IN, CTL_LUN_PAT_NONE, @@ -890,8 +867,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 4D LOG SENSE */ {ctl_log_sense, CTL_SERIDX_LOG_SNS, CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, @@ -920,8 +896,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 55 MODE SELECT(10) */ {ctl_mode_select, CTL_SERIDX_MD_SEL, CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_OUT, CTL_LUN_PAT_NONE, 10, {0x11, 0, 0, 0, 0, 0, 0xff, 0xff, 0x07} }, @@ -929,8 +904,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 56 RESERVE(10) */ {ctl_scsi_reserve, CTL_SERIDX_RES, CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_OUT, CTL_LUN_PAT_NONE, 10, {0, 0, 0, 0, 0, 0, 0, 0, 0x07} }, @@ -938,8 +912,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 57 RELEASE(10) */ {ctl_scsi_release, CTL_SERIDX_RES, CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_OUT, CTL_LUN_PAT_NONE, 10, {0, 0, 0, 0, 0, 0, 0, 0, 0x07}}, @@ -952,8 +925,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 5A MODE SENSE(10) */ {ctl_mode_sense, CTL_SERIDX_MD_SNS, CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_WRESV, @@ -1183,8 +1155,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* 9B READ BUFFER(16) */ {ctl_read_buffer, CTL_SERIDX_MD_SNS, CTL_CMD_FLAG_OK_ON_BOTH | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_WRESV, @@ -1214,8 +1185,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = CTL_CMD_FLAG_OK_ON_BOTH | CTL_CMD_FLAG_ALLOW_ON_RESV | CTL_CMD_FLAG_NO_SENSE | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_OK_ON_STANDBY | CTL_CMD_FLAG_OK_ON_UNAVAIL | CTL_CMD_FLAG_ALLOW_ON_PR_RESV | @@ -1327,8 +1297,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] = /* BD SPARE OUT / MECHANISM STATUS */ {ctl_mechanism_status, CTL_SERIDX_RD_CAP, CTL_CMD_FLAG_OK_ON_CDROM | - CTL_CMD_FLAG_OK_ON_STOPPED | - CTL_CMD_FLAG_OK_ON_INOPERABLE | + CTL_CMD_FLAG_OK_ON_NO_MEDIA | CTL_CMD_FLAG_ALLOW_ON_PR_RESV | CTL_FLAG_DATA_IN, CTL_LUN_PAT_NONE, diff --git a/sys/cam/ctl/ctl_error.c b/sys/cam/ctl/ctl_error.c index bf3cbf0..61ec4ec 100644 --- a/sys/cam/ctl/ctl_error.c +++ b/sys/cam/ctl/ctl_error.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2003-2009 Silicon Graphics International Corp. * Copyright (c) 2011 Spectra Logic Corporation + * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -444,7 +445,7 @@ ctl_ua_to_acsq(struct ctl_lun *lun, ctl_ua_type ua_to_build, int *asc, *asc = 0x2A; *ascq = 0x06; break; - case CTL_UA_CAPACITY_CHANGED: + case CTL_UA_CAPACITY_CHANGE: /* 2Ah/09h CAPACITY DATA HAS CHANGED */ *asc = 0x2A; *ascq = 0x09; @@ -455,6 +456,11 @@ ctl_ua_to_acsq(struct ctl_lun *lun, ctl_ua_type ua_to_build, int *asc, *ascq = 0x07; *info = lun->ua_tpt_info; break; + case CTL_UA_MEDIUM_CHANGE: + /* 28h/00h NOT READY TO READY CHANGE, MEDIUM MAY HAVE CHANGED */ + *asc = 0x28; + *ascq = 0x00; + break; default: panic("%s: Unknown UA %x", __func__, ua_to_build); } @@ -741,7 +747,7 @@ ctl_set_lun_stopped(struct ctl_scsiio *ctsio) } void -ctl_set_lun_not_ready(struct ctl_scsiio *ctsio) +ctl_set_lun_int_reqd(struct ctl_scsiio *ctsio) { /* "Logical unit not ready, manual intervention required" */ ctl_set_sense(ctsio, @@ -753,6 +759,30 @@ ctl_set_lun_not_ready(struct ctl_scsiio *ctsio) } void +ctl_set_lun_ejected(struct ctl_scsiio *ctsio) +{ + /* "Medium not present - tray open" */ + ctl_set_sense(ctsio, + /*current_error*/ 1, + /*sense_key*/ SSD_KEY_NOT_READY, + /*asc*/ 0x3A, + /*ascq*/ 0x02, + SSD_ELEM_NONE); +} + +void +ctl_set_lun_no_media(struct ctl_scsiio *ctsio) +{ + /* "Medium not present - tray closed" */ + ctl_set_sense(ctsio, + /*current_error*/ 1, + /*sense_key*/ SSD_KEY_NOT_READY, + /*asc*/ 0x3A, + /*ascq*/ 0x01, + SSD_ELEM_NONE); +} + +void ctl_set_illegal_pr_release(struct ctl_scsiio *ctsio) { /* "Invalid release of persistent reservation" */ diff --git a/sys/cam/ctl/ctl_error.h b/sys/cam/ctl/ctl_error.h index 064f621..9870643 100644 --- a/sys/cam/ctl/ctl_error.h +++ b/sys/cam/ctl/ctl_error.h @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003 Silicon Graphics International Corp. + * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -77,7 +78,9 @@ void ctl_set_medium_error(struct ctl_scsiio *ctsio, int read); void ctl_set_aborted(struct ctl_scsiio *ctsio); void ctl_set_lba_out_of_range(struct ctl_scsiio *ctsio); void ctl_set_lun_stopped(struct ctl_scsiio *ctsio); -void ctl_set_lun_not_ready(struct ctl_scsiio *ctsio); +void ctl_set_lun_int_reqd(struct ctl_scsiio *ctsio); +void ctl_set_lun_ejected(struct ctl_scsiio *ctsio); +void ctl_set_lun_no_media(struct ctl_scsiio *ctsio); void ctl_set_illegal_pr_release(struct ctl_scsiio *ctsio); void ctl_set_medium_format_corrupted(struct ctl_scsiio *ctsio); void ctl_set_medium_magazine_inaccessible(struct ctl_scsiio *ctsio); diff --git a/sys/cam/ctl/ctl_io.h b/sys/cam/ctl/ctl_io.h index 7b3636e..21db94a 100644 --- a/sys/cam/ctl/ctl_io.h +++ b/sys/cam/ctl/ctl_io.h @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003 Silicon Graphics International Corp. + * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -577,7 +578,6 @@ union ctl_io *ctl_alloc_io(void *pool_ref); union ctl_io *ctl_alloc_io_nowait(void *pool_ref); void ctl_free_io(union ctl_io *io); void ctl_zero_io(union ctl_io *io); -void ctl_copy_io(union ctl_io *src, union ctl_io *dest); #endif /* _KERNEL */ diff --git a/sys/cam/ctl/ctl_private.h b/sys/cam/ctl/ctl_private.h index ad5fbcd..63709ab 100644 --- a/sys/cam/ctl/ctl_private.h +++ b/sys/cam/ctl/ctl_private.h @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003, 2004, 2005, 2008 Silicon Graphics International Corp. + * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -87,20 +88,19 @@ typedef enum { typedef enum { CTL_CMD_FLAG_NONE = 0x0000, CTL_CMD_FLAG_NO_SENSE = 0x0010, - CTL_CMD_FLAG_OK_ON_NO_LUN = 0x0020, - CTL_CMD_FLAG_ALLOW_ON_RESV = 0x0040, + CTL_CMD_FLAG_ALLOW_ON_RESV = 0x0020, + CTL_CMD_FLAG_ALLOW_ON_PR_RESV = 0x0040, CTL_CMD_FLAG_ALLOW_ON_PR_WRESV = 0x0080, CTL_CMD_FLAG_OK_ON_PROC = 0x0100, CTL_CMD_FLAG_OK_ON_DIRECT = 0x0200, CTL_CMD_FLAG_OK_ON_CDROM = 0x0400, CTL_CMD_FLAG_OK_ON_BOTH = 0x0700, - CTL_CMD_FLAG_OK_ON_INOPERABLE = 0x0800, - CTL_CMD_FLAG_OK_ON_STANDBY = 0x1000, - CTL_CMD_FLAG_OK_ON_UNAVAIL = 0x2000, - CTL_CMD_FLAG_ALLOW_ON_PR_RESV = 0x4000, + CTL_CMD_FLAG_OK_ON_NO_LUN = 0x0800, + CTL_CMD_FLAG_OK_ON_NO_MEDIA = 0x1000, + CTL_CMD_FLAG_OK_ON_STANDBY = 0x2000, + CTL_CMD_FLAG_OK_ON_UNAVAIL = 0x4000, CTL_CMD_FLAG_SA5 = 0x8000, - CTL_CMD_FLAG_RUN_HERE = 0x10000, - CTL_CMD_FLAG_OK_ON_STOPPED = 0x20000 + CTL_CMD_FLAG_RUN_HERE = 0x10000 } ctl_cmd_flags; typedef enum { @@ -143,8 +143,8 @@ typedef enum { CTL_LUN_DISABLED = 0x008, CTL_LUN_MALLOCED = 0x010, CTL_LUN_STOPPED = 0x020, - CTL_LUN_INOPERABLE = 0x040, - CTL_LUN_OFFLINE = 0x080, + CTL_LUN_NO_MEDIA = 0x040, + CTL_LUN_EJECTED = 0x080, CTL_LUN_PR_RESERVED = 0x100, CTL_LUN_PRIMARY_SC = 0x200, CTL_LUN_SENSE_DESC = 0x400, |