aboutsummaryrefslogtreecommitdiff
path: root/sys/cam/ctl/ctl_backend_block.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cam/ctl/ctl_backend_block.c')
-rw-r--r--sys/cam/ctl/ctl_backend_block.c230
1 files changed, 76 insertions, 154 deletions
diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c
index 6323c47271f5..4a2feb712443 100644
--- a/sys/cam/ctl/ctl_backend_block.c
+++ b/sys/cam/ctl/ctl_backend_block.c
@@ -80,6 +80,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/nv.h>
#include <sys/dnv.h>
+#include <sys/sx.h>
#include <geom/geom.h>
@@ -121,7 +122,6 @@ SDT_PROVIDER_DEFINE(cbb);
typedef enum {
CTL_BE_BLOCK_LUN_UNCONFIGURED = 0x01,
- CTL_BE_BLOCK_LUN_CONFIG_ERR = 0x02,
CTL_BE_BLOCK_LUN_WAITING = 0x04,
} ctl_be_block_lun_flags;
@@ -153,7 +153,6 @@ typedef uint64_t (*cbb_getattr_t)(struct ctl_be_block_lun *be_lun,
*/
struct ctl_be_block_lun {
struct ctl_lun_create_params params;
- char lunname[32];
char *dev_path;
ctl_be_block_type dev_type;
struct vnode *vn;
@@ -169,7 +168,7 @@ struct ctl_be_block_lun {
struct ctl_be_block_softc *softc;
struct devstat *disk_stats;
ctl_be_block_lun_flags flags;
- STAILQ_ENTRY(ctl_be_block_lun) links;
+ SLIST_ENTRY(ctl_be_block_lun) links;
struct ctl_be_lun cbe_lun;
struct taskqueue *io_taskqueue;
struct task io_task;
@@ -186,10 +185,11 @@ struct ctl_be_block_lun {
* Overall softc structure for the block backend module.
*/
struct ctl_be_block_softc {
+ struct sx modify_lock;
struct mtx lock;
uma_zone_t beio_zone;
int num_luns;
- STAILQ_HEAD(, ctl_be_block_lun) lun_list;
+ SLIST_HEAD(, ctl_be_block_lun) lun_list;
};
static struct ctl_be_block_softc backend_block_softc;
@@ -272,8 +272,6 @@ static int ctl_be_block_rm(struct ctl_be_block_softc *softc,
static int ctl_be_block_modify(struct ctl_be_block_softc *softc,
struct ctl_lun_req *req);
static void ctl_be_block_lun_shutdown(void *be_lun);
-static void ctl_be_block_lun_config_status(void *be_lun,
- ctl_lun_config_status status);
static int ctl_be_block_config_write(union ctl_io *io);
static int ctl_be_block_config_read(union ctl_io *io);
static int ctl_be_block_lun_info(void *be_lun, struct sbuf *sb);
@@ -296,7 +294,7 @@ static struct ctl_backend_driver ctl_be_block_driver =
.lun_attr = ctl_be_block_lun_attr
};
-MALLOC_DEFINE(M_CTLBLK, "ctlblk", "Memory used for CTL block backend");
+MALLOC_DEFINE(M_CTLBLK, "ctlblock", "Memory used for CTL block backend");
CTL_BACKEND_DECLARE(cbb, ctl_be_block_driver);
static struct ctl_be_block_io *
@@ -1761,13 +1759,10 @@ static int
ctl_be_block_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
int flag, struct thread *td)
{
- struct ctl_be_block_softc *softc;
+ struct ctl_be_block_softc *softc = &backend_block_softc;
int error;
- softc = &backend_block_softc;
-
error = 0;
-
switch (cmd) {
case CTL_LUN_REQ: {
struct ctl_lun_req *lun_req;
@@ -2230,11 +2225,10 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
STAILQ_INIT(&be_lun->config_read_queue);
STAILQ_INIT(&be_lun->config_write_queue);
STAILQ_INIT(&be_lun->datamove_queue);
- sprintf(be_lun->lunname, "cblk%d", softc->num_luns);
- mtx_init(&be_lun->io_lock, "cblk io lock", NULL, MTX_DEF);
- mtx_init(&be_lun->queue_lock, "cblk queue lock", NULL, MTX_DEF);
+ mtx_init(&be_lun->io_lock, "ctlblock io", NULL, MTX_DEF);
+ mtx_init(&be_lun->queue_lock, "ctlblock queue", NULL, MTX_DEF);
cbe_lun->options = nvlist_clone(req->args_nvl);
- be_lun->lun_zone = uma_zcreate(be_lun->lunname, CTLBLK_MAX_SEG,
+ be_lun->lun_zone = uma_zcreate("ctlblock", CTLBLK_MAX_SEG,
NULL, NULL, NULL, NULL, /*align*/ 0, /*flags*/0);
if (be_lun->lun_zone == NULL) {
snprintf(req->error_str, sizeof(req->error_str),
@@ -2246,7 +2240,7 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
cbe_lun->lun_type = params->device_type;
else
cbe_lun->lun_type = T_DIRECT;
- be_lun->flags = CTL_BE_BLOCK_LUN_UNCONFIGURED;
+ be_lun->flags = 0;
cbe_lun->flags = 0;
value = dnvlist_get_string(cbe_lun->options, "ha_role", NULL);
if (value != NULL) {
@@ -2311,7 +2305,6 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
cbe_lun->req_lun_id = 0;
cbe_lun->lun_shutdown = ctl_be_block_lun_shutdown;
- cbe_lun->lun_config_status = ctl_be_block_lun_config_status;
cbe_lun->be = &ctl_be_block_driver;
if ((params->flags & CTL_LUN_FLAG_SERIAL_NUM) == 0) {
@@ -2344,7 +2337,7 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
TASK_INIT(&be_lun->io_task, /*priority*/0, ctl_be_block_worker, be_lun);
- be_lun->io_taskqueue = taskqueue_create(be_lun->lunname, M_WAITOK,
+ be_lun->io_taskqueue = taskqueue_create("ctlblocktq", M_WAITOK,
taskqueue_thread_enqueue, /*context*/&be_lun->io_taskqueue);
if (be_lun->io_taskqueue == NULL) {
@@ -2371,27 +2364,15 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
/*num threads*/num_threads,
/*priority*/PUSER,
/*proc*/control_softc->ctl_proc,
- /*thread name*/
- "%s taskq", be_lun->lunname);
+ /*thread name*/"block");
if (retval != 0)
goto bailout_error;
be_lun->num_threads = num_threads;
- mtx_lock(&softc->lock);
- softc->num_luns++;
- STAILQ_INSERT_TAIL(&softc->lun_list, be_lun, links);
-
- mtx_unlock(&softc->lock);
-
retval = ctl_add_lun(&be_lun->cbe_lun);
if (retval != 0) {
- mtx_lock(&softc->lock);
- STAILQ_REMOVE(&softc->lun_list, be_lun, ctl_be_block_lun,
- links);
- softc->num_luns--;
- mtx_unlock(&softc->lock);
snprintf(req->error_str, sizeof(req->error_str),
"ctl_add_lun() returned error %d, see dmesg for "
"details", retval);
@@ -2399,42 +2380,20 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
goto bailout_error;
}
- mtx_lock(&softc->lock);
-
- /*
- * Tell the config_status routine that we're waiting so it won't
- * clean up the LUN in the event of an error.
- */
- be_lun->flags |= CTL_BE_BLOCK_LUN_WAITING;
-
- while (be_lun->flags & CTL_BE_BLOCK_LUN_UNCONFIGURED) {
- retval = msleep(be_lun, &softc->lock, PCATCH, "ctlblk", 0);
- if (retval == EINTR)
- break;
- }
- be_lun->flags &= ~CTL_BE_BLOCK_LUN_WAITING;
-
- if (be_lun->flags & CTL_BE_BLOCK_LUN_CONFIG_ERR) {
- snprintf(req->error_str, sizeof(req->error_str),
- "LUN configuration error, see dmesg for details");
- STAILQ_REMOVE(&softc->lun_list, be_lun, ctl_be_block_lun,
- links);
- softc->num_luns--;
- mtx_unlock(&softc->lock);
- goto bailout_error;
- } else {
- params->req_lun_id = cbe_lun->lun_id;
- }
-
- mtx_unlock(&softc->lock);
-
- be_lun->disk_stats = devstat_new_entry("cbb", params->req_lun_id,
+ be_lun->disk_stats = devstat_new_entry("cbb", cbe_lun->lun_id,
cbe_lun->blocksize,
DEVSTAT_ALL_SUPPORTED,
cbe_lun->lun_type
| DEVSTAT_TYPE_IF_OTHER,
DEVSTAT_PRIORITY_OTHER);
+ mtx_lock(&softc->lock);
+ softc->num_luns++;
+ SLIST_INSERT_HEAD(&softc->lun_list, be_lun, links);
+ mtx_unlock(&softc->lock);
+
+ params->req_lun_id = cbe_lun->lun_id;
+
return (retval);
bailout_error:
@@ -2465,12 +2424,18 @@ ctl_be_block_rm(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
params = &req->reqdata.rm;
+ sx_xlock(&softc->modify_lock);
mtx_lock(&softc->lock);
- STAILQ_FOREACH(be_lun, &softc->lun_list, links) {
- if (be_lun->cbe_lun.lun_id == params->lun_id)
+ SLIST_FOREACH(be_lun, &softc->lun_list, links) {
+ if (be_lun->cbe_lun.lun_id == params->lun_id) {
+ SLIST_REMOVE(&softc->lun_list, be_lun,
+ ctl_be_block_lun, links);
+ softc->num_luns--;
break;
+ }
}
mtx_unlock(&softc->lock);
+ sx_xunlock(&softc->modify_lock);
if (be_lun == NULL) {
snprintf(req->error_str, sizeof(req->error_str),
"LUN %u is not managed by the block backend",
@@ -2479,14 +2444,6 @@ ctl_be_block_rm(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
}
cbe_lun = &be_lun->cbe_lun;
- retval = ctl_disable_lun(cbe_lun);
- if (retval != 0) {
- snprintf(req->error_str, sizeof(req->error_str),
- "error %d returned from ctl_disable_lun() for "
- "LUN %d", retval, params->lun_id);
- goto bailout_error;
- }
-
if (be_lun->vn != NULL) {
cbe_lun->flags |= CTL_LUN_FLAG_NO_MEDIA;
ctl_lun_no_media(cbe_lun);
@@ -2494,49 +2451,36 @@ ctl_be_block_rm(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
ctl_be_block_close(be_lun);
}
- retval = ctl_invalidate_lun(cbe_lun);
+ mtx_lock(&softc->lock);
+ be_lun->flags |= CTL_BE_BLOCK_LUN_WAITING;
+ mtx_unlock(&softc->lock);
+
+ retval = ctl_remove_lun(cbe_lun);
if (retval != 0) {
snprintf(req->error_str, sizeof(req->error_str),
- "error %d returned from ctl_invalidate_lun() for "
+ "error %d returned from ctl_remove_lun() for "
"LUN %d", retval, params->lun_id);
+ mtx_lock(&softc->lock);
+ be_lun->flags &= ~CTL_BE_BLOCK_LUN_WAITING;
+ mtx_unlock(&softc->lock);
goto bailout_error;
}
mtx_lock(&softc->lock);
- be_lun->flags |= CTL_BE_BLOCK_LUN_WAITING;
while ((be_lun->flags & CTL_BE_BLOCK_LUN_UNCONFIGURED) == 0) {
- retval = msleep(be_lun, &softc->lock, PCATCH, "ctlblk", 0);
- if (retval == EINTR)
- break;
- }
+ retval = msleep(be_lun, &softc->lock, PCATCH, "ctlblockrm", 0);
+ if (retval == EINTR)
+ break;
+ }
be_lun->flags &= ~CTL_BE_BLOCK_LUN_WAITING;
-
- if ((be_lun->flags & CTL_BE_BLOCK_LUN_UNCONFIGURED) == 0) {
- snprintf(req->error_str, sizeof(req->error_str),
- "interrupted waiting for LUN to be freed");
+ if (be_lun->flags & CTL_BE_BLOCK_LUN_UNCONFIGURED) {
mtx_unlock(&softc->lock);
- goto bailout_error;
+ free(be_lun, M_CTLBLK);
+ } else {
+ mtx_unlock(&softc->lock);
+ return (EINTR);
}
- STAILQ_REMOVE(&softc->lun_list, be_lun, ctl_be_block_lun, links);
-
- softc->num_luns--;
- mtx_unlock(&softc->lock);
-
- taskqueue_drain_all(be_lun->io_taskqueue);
- taskqueue_free(be_lun->io_taskqueue);
-
- if (be_lun->disk_stats != NULL)
- devstat_remove_entry(be_lun->disk_stats);
-
- uma_zdestroy(be_lun->lun_zone);
-
- nvlist_destroy(cbe_lun->options);
- free(be_lun->dev_path, M_CTLBLK);
- mtx_destroy(&be_lun->queue_lock);
- mtx_destroy(&be_lun->io_lock);
- free(be_lun, M_CTLBLK);
-
req->status = CTL_LUN_OK;
return (0);
@@ -2557,8 +2501,9 @@ ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
params = &req->reqdata.modify;
+ sx_xlock(&softc->modify_lock);
mtx_lock(&softc->lock);
- STAILQ_FOREACH(be_lun, &softc->lun_list, links) {
+ SLIST_FOREACH(be_lun, &softc->lun_list, links) {
if (be_lun->cbe_lun.lun_id == params->lun_id)
break;
}
@@ -2635,66 +2580,41 @@ ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
/* Tell the user the exact size we ended up using */
params->lun_size_bytes = be_lun->size_bytes;
+ sx_xunlock(&softc->modify_lock);
req->status = error ? CTL_LUN_WARNING : CTL_LUN_OK;
return (0);
bailout_error:
+ sx_xunlock(&softc->modify_lock);
req->status = CTL_LUN_ERROR;
return (0);
}
static void
-ctl_be_block_lun_shutdown(void *be_lun)
-{
- struct ctl_be_block_lun *lun = be_lun;
- struct ctl_be_block_softc *softc = lun->softc;
-
- mtx_lock(&softc->lock);
- lun->flags |= CTL_BE_BLOCK_LUN_UNCONFIGURED;
- if (lun->flags & CTL_BE_BLOCK_LUN_WAITING)
- wakeup(lun);
- mtx_unlock(&softc->lock);
-}
-
-static void
-ctl_be_block_lun_config_status(void *be_lun, ctl_lun_config_status status)
+ctl_be_block_lun_shutdown(void *lun)
{
- struct ctl_be_block_lun *lun;
- struct ctl_be_block_softc *softc;
-
- lun = (struct ctl_be_block_lun *)be_lun;
- softc = lun->softc;
-
- if (status == CTL_LUN_CONFIG_OK) {
- mtx_lock(&softc->lock);
- lun->flags &= ~CTL_BE_BLOCK_LUN_UNCONFIGURED;
- if (lun->flags & CTL_BE_BLOCK_LUN_WAITING)
- wakeup(lun);
- mtx_unlock(&softc->lock);
-
- /*
- * We successfully added the LUN, attempt to enable it.
- */
- if (ctl_enable_lun(&lun->cbe_lun) != 0) {
- printf("%s: ctl_enable_lun() failed!\n", __func__);
- if (ctl_invalidate_lun(&lun->cbe_lun) != 0) {
- printf("%s: ctl_invalidate_lun() failed!\n",
- __func__);
- }
- }
-
- return;
- }
+ struct ctl_be_block_lun *be_lun = lun;
+ struct ctl_be_block_softc *softc = be_lun->softc;
+ taskqueue_drain_all(be_lun->io_taskqueue);
+ taskqueue_free(be_lun->io_taskqueue);
+ if (be_lun->disk_stats != NULL)
+ devstat_remove_entry(be_lun->disk_stats);
+ uma_zdestroy(be_lun->lun_zone);
+ nvlist_destroy(be_lun->cbe_lun.options);
+ free(be_lun->dev_path, M_CTLBLK);
+ mtx_destroy(&be_lun->queue_lock);
+ mtx_destroy(&be_lun->io_lock);
mtx_lock(&softc->lock);
- lun->flags &= ~CTL_BE_BLOCK_LUN_UNCONFIGURED;
- lun->flags |= CTL_BE_BLOCK_LUN_CONFIG_ERR;
- wakeup(lun);
+ be_lun->flags |= CTL_BE_BLOCK_LUN_UNCONFIGURED;
+ if (be_lun->flags & CTL_BE_BLOCK_LUN_WAITING)
+ wakeup(be_lun);
+ else
+ free(be_lun, M_CTLBLK);
mtx_unlock(&softc->lock);
}
-
static int
ctl_be_block_config_write(union ctl_io *io)
{
@@ -2858,10 +2778,11 @@ ctl_be_block_init(void)
{
struct ctl_be_block_softc *softc = &backend_block_softc;
+ sx_init(&softc->modify_lock, "ctlblock modify");
mtx_init(&softc->lock, "ctlblock", NULL, MTX_DEF);
softc->beio_zone = uma_zcreate("beio", sizeof(struct ctl_be_block_io),
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
- STAILQ_INIT(&softc->lun_list);
+ SLIST_INIT(&softc->lun_list);
return (0);
}
@@ -2870,23 +2791,24 @@ static int
ctl_be_block_shutdown(void)
{
struct ctl_be_block_softc *softc = &backend_block_softc;
- struct ctl_be_block_lun *lun, *next_lun;
+ struct ctl_be_block_lun *lun;
mtx_lock(&softc->lock);
- STAILQ_FOREACH_SAFE(lun, &softc->lun_list, links, next_lun) {
+ while ((lun = SLIST_FIRST(&softc->lun_list)) != NULL) {
+ SLIST_REMOVE_HEAD(&softc->lun_list, links);
+ softc->num_luns--;
/*
- * Drop our lock here. Since ctl_invalidate_lun() can call
+ * Drop our lock here. Since ctl_remove_lun() can call
* back into us, this could potentially lead to a recursive
* lock of the same mutex, which would cause a hang.
*/
mtx_unlock(&softc->lock);
- ctl_disable_lun(&lun->cbe_lun);
- ctl_invalidate_lun(&lun->cbe_lun);
+ ctl_remove_lun(&lun->cbe_lun);
mtx_lock(&softc->lock);
}
mtx_unlock(&softc->lock);
-
uma_zdestroy(softc->beio_zone);
mtx_destroy(&softc->lock);
+ sx_destroy(&softc->modify_lock);
return (0);
}