diff options
Diffstat (limited to 'sys/cam/ctl/ctl_backend_block.c')
-rw-r--r-- | sys/cam/ctl/ctl_backend_block.c | 230 |
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); } |