Changeset View
Changeset View
Standalone View
Standalone View
sys/cam/ctl/ctl_backend_ramdisk.c
Show First 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | |||||
#include <sys/sx.h> | #include <sys/sx.h> | ||||
#include <sys/taskqueue.h> | #include <sys/taskqueue.h> | ||||
#include <sys/time.h> | #include <sys/time.h> | ||||
#include <sys/queue.h> | #include <sys/queue.h> | ||||
#include <sys/conf.h> | #include <sys/conf.h> | ||||
#include <sys/ioccom.h> | #include <sys/ioccom.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/nv.h> | |||||
#include <sys/dnv.h> | |||||
#include <cam/scsi/scsi_all.h> | #include <cam/scsi/scsi_all.h> | ||||
#include <cam/scsi/scsi_da.h> | #include <cam/scsi/scsi_da.h> | ||||
#include <cam/ctl/ctl_io.h> | #include <cam/ctl/ctl_io.h> | ||||
#include <cam/ctl/ctl.h> | #include <cam/ctl/ctl.h> | ||||
#include <cam/ctl/ctl_util.h> | #include <cam/ctl/ctl_util.h> | ||||
#include <cam/ctl/ctl_backend.h> | #include <cam/ctl/ctl_backend.h> | ||||
#include <cam/ctl/ctl_debug.h> | #include <cam/ctl/ctl_debug.h> | ||||
▲ Show 20 Lines • Show All 878 Lines • ▼ Show 20 Lines | if (retval == 0) { | ||||
softc->num_luns--; | softc->num_luns--; | ||||
} | } | ||||
mtx_unlock(&softc->lock); | mtx_unlock(&softc->lock); | ||||
if (retval == 0) { | if (retval == 0) { | ||||
taskqueue_drain_all(be_lun->io_taskqueue); | taskqueue_drain_all(be_lun->io_taskqueue); | ||||
taskqueue_free(be_lun->io_taskqueue); | taskqueue_free(be_lun->io_taskqueue); | ||||
ctl_free_opts(&be_lun->cbe_lun.options); | nvlist_destroy(be_lun->cbe_lun.options); | ||||
free(be_lun->zero_page, M_RAMDISK); | free(be_lun->zero_page, M_RAMDISK); | ||||
ctl_backend_ramdisk_freeallpages(be_lun->pages, be_lun->indir); | ctl_backend_ramdisk_freeallpages(be_lun->pages, be_lun->indir); | ||||
sx_destroy(&be_lun->page_lock); | sx_destroy(&be_lun->page_lock); | ||||
mtx_destroy(&be_lun->queue_lock); | mtx_destroy(&be_lun->queue_lock); | ||||
free(be_lun, M_RAMDISK); | free(be_lun, M_RAMDISK); | ||||
} | } | ||||
req->status = CTL_LUN_OK; | req->status = CTL_LUN_OK; | ||||
return (retval); | return (retval); | ||||
bailout_error: | bailout_error: | ||||
req->status = CTL_LUN_ERROR; | req->status = CTL_LUN_ERROR; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc, | ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc, | ||||
struct ctl_lun_req *req) | struct ctl_lun_req *req) | ||||
{ | { | ||||
struct ctl_be_ramdisk_lun *be_lun; | struct ctl_be_ramdisk_lun *be_lun; | ||||
struct ctl_be_lun *cbe_lun; | struct ctl_be_lun *cbe_lun; | ||||
struct ctl_lun_create_params *params; | struct ctl_lun_create_params *params; | ||||
char *value; | const char *value; | ||||
char tmpstr[32]; | char tmpstr[32]; | ||||
uint64_t t; | uint64_t t; | ||||
int retval; | int retval; | ||||
retval = 0; | retval = 0; | ||||
params = &req->reqdata.create; | params = &req->reqdata.create; | ||||
be_lun = malloc(sizeof(*be_lun), M_RAMDISK, M_ZERO | M_WAITOK); | be_lun = malloc(sizeof(*be_lun), M_RAMDISK, M_ZERO | M_WAITOK); | ||||
cbe_lun = &be_lun->cbe_lun; | cbe_lun = &be_lun->cbe_lun; | ||||
cbe_lun->be_lun = be_lun; | cbe_lun->be_lun = be_lun; | ||||
cbe_lun->options = nvlist_clone(req->args_nvl); | |||||
be_lun->params = req->reqdata.create; | be_lun->params = req->reqdata.create; | ||||
be_lun->softc = softc; | be_lun->softc = softc; | ||||
sprintf(be_lun->lunname, "cram%d", softc->num_luns); | sprintf(be_lun->lunname, "cram%d", softc->num_luns); | ||||
ctl_init_opts(&cbe_lun->options, req->num_be_args, req->kern_be_args); | |||||
if (params->flags & CTL_LUN_FLAG_DEV_TYPE) | if (params->flags & CTL_LUN_FLAG_DEV_TYPE) | ||||
cbe_lun->lun_type = params->device_type; | cbe_lun->lun_type = params->device_type; | ||||
else | else | ||||
cbe_lun->lun_type = T_DIRECT; | cbe_lun->lun_type = T_DIRECT; | ||||
be_lun->flags = CTL_BE_RAMDISK_LUN_UNCONFIGURED; | be_lun->flags = CTL_BE_RAMDISK_LUN_UNCONFIGURED; | ||||
cbe_lun->flags = 0; | cbe_lun->flags = 0; | ||||
value = ctl_get_opt(&cbe_lun->options, "ha_role"); | value = dnvlist_get_string(cbe_lun->options, "ha_role", NULL); | ||||
if (value != NULL) { | if (value != NULL) { | ||||
if (strcmp(value, "primary") == 0) | if (strcmp(value, "primary") == 0) | ||||
cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY; | cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY; | ||||
} else if (control_softc->flags & CTL_FLAG_ACTIVE_SHELF) | } else if (control_softc->flags & CTL_FLAG_ACTIVE_SHELF) | ||||
cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY; | cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY; | ||||
be_lun->pblocksize = PAGE_SIZE; | be_lun->pblocksize = PAGE_SIZE; | ||||
value = ctl_get_opt(&cbe_lun->options, "pblocksize"); | value = dnvlist_get_string(cbe_lun->options, "pblocksize", NULL); | ||||
if (value != NULL) { | if (value != NULL) { | ||||
ctl_expand_number(value, &t); | ctl_expand_number(value, &t); | ||||
be_lun->pblocksize = t; | be_lun->pblocksize = t; | ||||
} | } | ||||
if (be_lun->pblocksize < 512 || be_lun->pblocksize > 131072) { | if (be_lun->pblocksize < 512 || be_lun->pblocksize > 131072) { | ||||
snprintf(req->error_str, sizeof(req->error_str), | snprintf(req->error_str, sizeof(req->error_str), | ||||
"%s: unsupported pblocksize %u", __func__, | "%s: unsupported pblocksize %u", __func__, | ||||
be_lun->pblocksize); | be_lun->pblocksize); | ||||
Show All 32 Lines | if (cbe_lun->lun_type == T_DIRECT || | ||||
} | } | ||||
cbe_lun->maxlba = be_lun->size_blocks - 1; | cbe_lun->maxlba = be_lun->size_blocks - 1; | ||||
cbe_lun->pblockexp = fls(be_lun->pblockmul) - 1; | cbe_lun->pblockexp = fls(be_lun->pblockmul) - 1; | ||||
cbe_lun->pblockoff = 0; | cbe_lun->pblockoff = 0; | ||||
cbe_lun->ublockexp = cbe_lun->pblockexp; | cbe_lun->ublockexp = cbe_lun->pblockexp; | ||||
cbe_lun->ublockoff = 0; | cbe_lun->ublockoff = 0; | ||||
cbe_lun->atomicblock = be_lun->pblocksize; | cbe_lun->atomicblock = be_lun->pblocksize; | ||||
cbe_lun->opttxferlen = SGPP * be_lun->pblocksize; | cbe_lun->opttxferlen = SGPP * be_lun->pblocksize; | ||||
value = ctl_get_opt(&cbe_lun->options, "capacity"); | value = dnvlist_get_string(cbe_lun->options, "capacity", NULL); | ||||
if (value != NULL) | if (value != NULL) | ||||
ctl_expand_number(value, &be_lun->cap_bytes); | ctl_expand_number(value, &be_lun->cap_bytes); | ||||
} else { | } else { | ||||
be_lun->pblockmul = 1; | be_lun->pblockmul = 1; | ||||
cbe_lun->pblockexp = 0; | cbe_lun->pblockexp = 0; | ||||
} | } | ||||
/* Tell the user the blocksize we ended up using */ | /* Tell the user the blocksize we ended up using */ | ||||
params->blocksize_bytes = cbe_lun->blocksize; | params->blocksize_bytes = cbe_lun->blocksize; | ||||
params->lun_size_bytes = be_lun->size_bytes; | params->lun_size_bytes = be_lun->size_bytes; | ||||
value = ctl_get_opt(&cbe_lun->options, "unmap"); | value = dnvlist_get_string(cbe_lun->options, "unmap", NULL); | ||||
if (value == NULL || strcmp(value, "off") != 0) | if (value != NULL && strcmp(value, "off") != 0) | ||||
cbe_lun->flags |= CTL_LUN_FLAG_UNMAP; | cbe_lun->flags |= CTL_LUN_FLAG_UNMAP; | ||||
value = ctl_get_opt(&cbe_lun->options, "readonly"); | value = dnvlist_get_string(cbe_lun->options, "readonly", NULL); | ||||
if (value != NULL) { | if (value != NULL) { | ||||
if (strcmp(value, "on") == 0) | if (strcmp(value, "on") == 0) | ||||
cbe_lun->flags |= CTL_LUN_FLAG_READONLY; | cbe_lun->flags |= CTL_LUN_FLAG_READONLY; | ||||
} else if (cbe_lun->lun_type != T_DIRECT) | } else if (cbe_lun->lun_type != T_DIRECT) | ||||
cbe_lun->flags |= CTL_LUN_FLAG_READONLY; | cbe_lun->flags |= CTL_LUN_FLAG_READONLY; | ||||
cbe_lun->serseq = CTL_LUN_SERSEQ_OFF; | cbe_lun->serseq = CTL_LUN_SERSEQ_OFF; | ||||
value = ctl_get_opt(&cbe_lun->options, "serseq"); | value = dnvlist_get_string(cbe_lun->options, "serseq", NULL); | ||||
if (value != NULL && strcmp(value, "on") == 0) | if (value != NULL && strcmp(value, "on") == 0) | ||||
cbe_lun->serseq = CTL_LUN_SERSEQ_ON; | cbe_lun->serseq = CTL_LUN_SERSEQ_ON; | ||||
else if (value != NULL && strcmp(value, "read") == 0) | else if (value != NULL && strcmp(value, "read") == 0) | ||||
cbe_lun->serseq = CTL_LUN_SERSEQ_READ; | cbe_lun->serseq = CTL_LUN_SERSEQ_READ; | ||||
else if (value != NULL && strcmp(value, "off") == 0) | else if (value != NULL && strcmp(value, "off") == 0) | ||||
cbe_lun->serseq = CTL_LUN_SERSEQ_OFF; | cbe_lun->serseq = CTL_LUN_SERSEQ_OFF; | ||||
if (params->flags & CTL_LUN_FLAG_ID_REQ) { | if (params->flags & CTL_LUN_FLAG_ID_REQ) { | ||||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc, | ||||
req->status = CTL_LUN_OK; | req->status = CTL_LUN_OK; | ||||
return (retval); | return (retval); | ||||
bailout_error: | bailout_error: | ||||
req->status = CTL_LUN_ERROR; | req->status = CTL_LUN_ERROR; | ||||
if (be_lun != NULL) { | if (be_lun != NULL) { | ||||
if (be_lun->io_taskqueue != NULL) | if (be_lun->io_taskqueue != NULL) | ||||
taskqueue_free(be_lun->io_taskqueue); | taskqueue_free(be_lun->io_taskqueue); | ||||
ctl_free_opts(&cbe_lun->options); | nvlist_destroy(cbe_lun->options); | ||||
free(be_lun->zero_page, M_RAMDISK); | free(be_lun->zero_page, M_RAMDISK); | ||||
ctl_backend_ramdisk_freeallpages(be_lun->pages, be_lun->indir); | ctl_backend_ramdisk_freeallpages(be_lun->pages, be_lun->indir); | ||||
sx_destroy(&be_lun->page_lock); | sx_destroy(&be_lun->page_lock); | ||||
mtx_destroy(&be_lun->queue_lock); | mtx_destroy(&be_lun->queue_lock); | ||||
free(be_lun, M_RAMDISK); | free(be_lun, M_RAMDISK); | ||||
} | } | ||||
return (retval); | return (retval); | ||||
} | } | ||||
static int | static int | ||||
ctl_backend_ramdisk_modify(struct ctl_be_ramdisk_softc *softc, | ctl_backend_ramdisk_modify(struct ctl_be_ramdisk_softc *softc, | ||||
struct ctl_lun_req *req) | struct ctl_lun_req *req) | ||||
{ | { | ||||
struct ctl_be_ramdisk_lun *be_lun; | struct ctl_be_ramdisk_lun *be_lun; | ||||
struct ctl_be_lun *cbe_lun; | struct ctl_be_lun *cbe_lun; | ||||
struct ctl_lun_modify_params *params; | struct ctl_lun_modify_params *params; | ||||
char *value; | const char *value; | ||||
uint32_t blocksize; | uint32_t blocksize; | ||||
int wasprim; | int wasprim; | ||||
params = &req->reqdata.modify; | params = &req->reqdata.modify; | ||||
mtx_lock(&softc->lock); | mtx_lock(&softc->lock); | ||||
STAILQ_FOREACH(be_lun, &softc->lun_list, links) { | STAILQ_FOREACH(be_lun, &softc->lun_list, links) { | ||||
if (be_lun->cbe_lun.lun_id == params->lun_id) | if (be_lun->cbe_lun.lun_id == params->lun_id) | ||||
break; | break; | ||||
} | } | ||||
mtx_unlock(&softc->lock); | mtx_unlock(&softc->lock); | ||||
if (be_lun == NULL) { | if (be_lun == NULL) { | ||||
snprintf(req->error_str, sizeof(req->error_str), | snprintf(req->error_str, sizeof(req->error_str), | ||||
"%s: LUN %u is not managed by the ramdisk backend", | "%s: LUN %u is not managed by the ramdisk backend", | ||||
__func__, params->lun_id); | __func__, params->lun_id); | ||||
goto bailout_error; | goto bailout_error; | ||||
} | } | ||||
cbe_lun = &be_lun->cbe_lun; | cbe_lun = &be_lun->cbe_lun; | ||||
if (params->lun_size_bytes != 0) | if (params->lun_size_bytes != 0) | ||||
be_lun->params.lun_size_bytes = params->lun_size_bytes; | be_lun->params.lun_size_bytes = params->lun_size_bytes; | ||||
ctl_update_opts(&cbe_lun->options, req->num_be_args, req->kern_be_args); | |||||
nvlist_destroy(cbe_lun->options); | |||||
cbe_lun->options = nvlist_clone(req->args_nvl); | |||||
wasprim = (cbe_lun->flags & CTL_LUN_FLAG_PRIMARY); | wasprim = (cbe_lun->flags & CTL_LUN_FLAG_PRIMARY); | ||||
value = ctl_get_opt(&cbe_lun->options, "ha_role"); | value = dnvlist_get_string(cbe_lun->options, "ha_role", NULL); | ||||
if (value != NULL) { | if (value != NULL) { | ||||
if (strcmp(value, "primary") == 0) | if (strcmp(value, "primary") == 0) | ||||
cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY; | cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY; | ||||
else | else | ||||
cbe_lun->flags &= ~CTL_LUN_FLAG_PRIMARY; | cbe_lun->flags &= ~CTL_LUN_FLAG_PRIMARY; | ||||
} else if (control_softc->flags & CTL_FLAG_ACTIVE_SHELF) | } else if (control_softc->flags & CTL_FLAG_ACTIVE_SHELF) | ||||
cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY; | cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY; | ||||
else | else | ||||
▲ Show 20 Lines • Show All 100 Lines • Show Last 20 Lines |