summaryrefslogtreecommitdiffstats
path: root/sys/cam/ctl/ctl_backend_block.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-10-05 11:31:24 +0000
committermav <mav@FreeBSD.org>2015-10-05 11:31:24 +0000
commit85b5a86dbdd825182ee25aabfb085017635d26a5 (patch)
tree49d54efdf87b86f89da67d47a7e3a16fa0ca13cb /sys/cam/ctl/ctl_backend_block.c
parent3e85febb126fcf3fc33ad9460816254312716ff6 (diff)
downloadFreeBSD-src-85b5a86dbdd825182ee25aabfb085017635d26a5.zip
FreeBSD-src-85b5a86dbdd825182ee25aabfb085017635d26a5.tar.gz
MFC r288348: Umplement media load/eject support for removable devices.
In case of block backend eject really closes the backing store, while load tries to open it back. Failed store open is reported as no media.
Diffstat (limited to 'sys/cam/ctl/ctl_backend_block.c')
-rw-r--r--sys/cam/ctl/ctl_backend_block.c83
1 files changed, 47 insertions, 36 deletions
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;
}
OpenPOWER on IntegriCloud