50#include <sys/kernel.h>
51#include <sys/condvar.h>
53#include <sys/limits.h>
56#include <sys/malloc.h>
58#include <sys/taskqueue.h>
62#include <sys/ioccom.h>
63#include <sys/module.h>
64#include <sys/sysctl.h>
81 ((struct ctl_ptr_len_flags *)&(io)->io_hdr.ctl_private[CTL_PRIV_BACKEND])
83 ((struct ctl_lba_len_flags *)&(io)->io_hdr.ctl_private[CTL_PRIV_LBA_LEN])
85#define PPP (PAGE_SIZE / sizeof(uint8_t **))
87#define PPPS (PAGE_SHIFT - 3)
89#define PPPS (PAGE_SHIFT - 2)
91#define SGPP (PAGE_SIZE / sizeof(struct ctl_sg_entry))
93#define P_UNMAPPED NULL
94#define P_ANCHORED ((void *)(uintptr_t)1)
124 struct taskqueue *io_taskqueue;
127 struct mtx_padalign queue_lock;
151 caddr_t addr,
int flag,
struct thread *td);
181 memset(softc, 0,
sizeof(*softc));
183 mtx_init(&softc->
lock,
"ctlram", NULL, MTX_DEF);
184 SLIST_INIT(&softc->lun_list);
195 while ((lun = SLIST_FIRST(&
softc->lun_list)) != NULL) {
196 SLIST_REMOVE_HEAD(&
softc->lun_list, links);
226 return ((uint8_t *)be_lun->
pages);
238 *pp = malloc(PAGE_SIZE, M_RAMDISK,
242 pp = (uint8_t ***)&(*pp)[i];
257 return ((uint8_t *)*pp);
265 p = (uint8_t **)p[i];
271 return ((uint8_t *)p);
290 pp = (uint8_t ***)&(*pp)[i];
297 free(*pp, M_RAMDISK);
320 pp = (uint8_t ***)&(*pp)[i];
327 free(*pp, M_RAMDISK);
345 for (i = 0; i <
PPP; i++) {
354cmp(uint8_t *a, uint8_t *b,
size_t size)
358 for (i = 0; i < size; i++) {
373 u_int lbaoff, lbas, res, off;
376 lba =
ARGS(io)->lba +
PRIV(io)->len - lbas;
378 for (; lbas > 0; lbas--, lba++) {
386 if (res < cbe_lun->blocksize)
421 if (
ARGS(io)->len >
PRIV(io)->len) {
422 mtx_lock(&be_lun->queue_lock);
423 STAILQ_INSERT_TAIL(&be_lun->cont_queue,
425 mtx_unlock(&be_lun->queue_lock);
426 taskqueue_enqueue(be_lun->io_taskqueue,
443 lbas =
ARGS(io)->len -
PRIV(io)->len;
444 lbas = MIN(lbas, 131072 / cbe_lun->
blocksize);
452 PRIV(io)->len += lbas;
464 u_int i,
len, lbaoff, lbas, sgs, off;
467 lba =
ARGS(io)->lba +
PRIV(io)->len;
468 lbaoff = lba & ~(UINT_MAX << cbe_lun->
pblockexp);
469 lbas =
ARGS(io)->len -
PRIV(io)->len;
476 sgs, M_RAMDISK, M_WAITOK);
479 for (i = 0; i < sgs; i++) {
489 sg_entries[i].
addr = page + off;
507 PRIV(io)->len += lbas;
542 mtx_lock(&be_lun->queue_lock);
544 io = (
union ctl_io *)STAILQ_FIRST(&be_lun->cont_queue);
546 STAILQ_REMOVE_HEAD(&be_lun->cont_queue, links);
547 mtx_unlock(&be_lun->queue_lock);
552 mtx_lock(&be_lun->queue_lock);
562 mtx_unlock(&be_lun->queue_lock);
645 if (p <= lp && lbaoff != 0) {
689 for (
lba = lbalen->
lba, lbas = lbalen->
len; lbas > 0;
lba++, lbas--) {
731 end = buf + ptrlen->
len /
sizeof(*buf);
732 for (; buf < end; buf++) {
808 if (strcmp(attrname,
"blocksused") == 0) {
810 }
else if (strcmp(attrname,
"blocksavail") == 0) {
820 int flag,
struct thread *td)
843 "%s: invalid LUN request type %d", __func__,
866 mtx_lock(&softc->
lock);
867 SLIST_FOREACH(be_lun, &softc->lun_list, links) {
869 SLIST_REMOVE(&softc->lun_list, be_lun,
875 mtx_unlock(&softc->
lock);
877 if (be_lun == NULL) {
879 "%s: LUN %u is not managed by the ramdisk backend",
880 __func__, params->
lun_id);
892 mtx_lock(&softc->
lock);
894 mtx_unlock(&softc->
lock);
899 "%s: error %d returned from ctl_remove_lun() for "
900 "LUN %d", __func__, retval, params->
lun_id);
901 mtx_lock(&softc->
lock);
902 be_lun->
flags &= ~CTL_BE_RAMDISK_LUN_WAITING;
903 mtx_unlock(&softc->
lock);
907 mtx_lock(&softc->
lock);
909 retval = msleep(be_lun, &softc->
lock, PCATCH,
"ctlramrm", 0);
913 be_lun->
flags &= ~CTL_BE_RAMDISK_LUN_WAITING;
915 mtx_unlock(&softc->
lock);
916 free(be_lun, M_RAMDISK);
918 mtx_unlock(&softc->
lock);
945 be_lun = malloc(
sizeof(*be_lun), M_RAMDISK, M_ZERO | M_WAITOK);
949 be_lun->
softc = softc;
957 value = dnvlist_get_string(cbe_lun->
options,
"ha_role", NULL);
959 if (strcmp(value,
"primary") == 0)
965 value = dnvlist_get_string(cbe_lun->
options,
"pblocksize", NULL);
972 "%s: unsupported pblocksize %u", __func__,
988 "%s: pblocksize %u not exp2 of blocksize %u",
995 "%s: LUN size %ju < blocksize %u", __func__,
1014 value = dnvlist_get_string(cbe_lun->
options,
"capacity", NULL);
1026 value = dnvlist_get_string(cbe_lun->
options,
"unmap", NULL);
1027 if (value == NULL || strcmp(value,
"off") != 0)
1029 value = dnvlist_get_string(cbe_lun->
options,
"readonly", NULL);
1030 if (value != NULL) {
1031 if (strcmp(value,
"on") == 0)
1036 value = dnvlist_get_string(cbe_lun->
options,
"serseq", NULL);
1037 if (value != NULL && strcmp(value,
"on") == 0)
1039 else if (value != NULL && strcmp(value,
"read") == 0)
1041 else if (value != NULL && strcmp(value,
"soft") == 0)
1043 else if (value != NULL && strcmp(value,
"off") == 0)
1055 snprintf(tmpstr,
sizeof(tmpstr),
"MYSERIAL%04d",
1058 MIN(
sizeof(cbe_lun->
serial_num),
sizeof(tmpstr)));
1062 MIN(
sizeof(params->
serial_num),
sizeof(tmpstr)));
1069 snprintf(tmpstr,
sizeof(tmpstr),
"MYDEVID%04d", softc->
num_luns);
1070 strncpy((
char *)cbe_lun->
device_id, tmpstr,
1071 MIN(
sizeof(cbe_lun->
device_id),
sizeof(tmpstr)));
1074 strncpy((
char *)params->
device_id, tmpstr,
1075 MIN(
sizeof(params->
device_id),
sizeof(tmpstr)));
1082 STAILQ_INIT(&be_lun->cont_queue);
1083 sx_init(&be_lun->
page_lock,
"ctlram page");
1090 mtx_init(&be_lun->queue_lock,
"ctlram queue", NULL, MTX_DEF);
1094 be_lun->io_taskqueue = taskqueue_create(
"ctlramtq", M_WAITOK,
1095 taskqueue_thread_enqueue, &be_lun->io_taskqueue);
1096 if (be_lun->io_taskqueue == NULL) {
1098 "%s: Unable to create taskqueue", __func__);
1102 retval = taskqueue_start_threads_in_proc(&be_lun->io_taskqueue,
1113 "%s: ctl_add_lun() returned error %d, see dmesg for "
1114 "details", __func__, retval);
1119 mtx_lock(&softc->
lock);
1121 SLIST_INSERT_HEAD(&softc->lun_list, be_lun, links);
1122 mtx_unlock(&softc->
lock);
1131 if (be_lun != NULL) {
1132 if (be_lun->io_taskqueue != NULL)
1133 taskqueue_free(be_lun->io_taskqueue);
1134 nvlist_destroy(cbe_lun->
options);
1138 mtx_destroy(&be_lun->queue_lock);
1139 free(be_lun, M_RAMDISK);
1157 mtx_lock(&softc->
lock);
1158 SLIST_FOREACH(be_lun, &softc->lun_list, links) {
1162 mtx_unlock(&softc->
lock);
1163 if (be_lun == NULL) {
1165 "%s: LUN %u is not managed by the ramdisk backend",
1166 __func__, params->
lun_id);
1175 nvlist_destroy(cbe_lun->
options);
1180 value = dnvlist_get_string(cbe_lun->
options,
"ha_role", NULL);
1181 if (value != NULL) {
1182 if (strcmp(value,
"primary") == 0)
1185 cbe_lun->
flags &= ~CTL_LUN_FLAG_PRIMARY;
1189 cbe_lun->
flags &= ~CTL_LUN_FLAG_PRIMARY;
1200 "%s: LUN size %ju < blocksize %u", __func__,
1228 taskqueue_drain_all(be_lun->io_taskqueue);
1229 taskqueue_free(be_lun->io_taskqueue);
1234 mtx_destroy(&be_lun->queue_lock);
1236 mtx_lock(&softc->
lock);
1241 free(be_lun, M_RAMDISK);
1242 mtx_unlock(&softc->
lock);
SLIST_HEAD(ccb_hdr_slist, ccb_hdr)
int ctl_add_lun(struct ctl_be_lun *be_lun)
int ctl_start_lun(struct ctl_be_lun *be_lun)
void ctl_serseq_done(union ctl_io *io)
void ctl_datamove(union ctl_io *io)
int ctl_expand_number(const char *buf, uint64_t *num)
int ctl_lun_ejected(struct ctl_be_lun *be_lun)
int ctl_remove_lun(struct ctl_be_lun *be_lun)
int ctl_lun_has_media(struct ctl_be_lun *be_lun)
void ctl_config_write_done(union ctl_io *io)
int ctl_lun_primary(struct ctl_be_lun *be_lun)
int ctl_stop_lun(struct ctl_be_lun *be_lun)
int ctl_lun_secondary(struct ctl_be_lun *be_lun)
void ctl_lun_capacity_changed(struct ctl_be_lun *be_lun)
void ctl_config_read_done(union ctl_io *io)
void ctl_data_submit_done(union ctl_io *io)
#define CTL_RETVAL_COMPLETE
static size_t cmp(uint8_t *a, uint8_t *b, size_t size)
static void ctl_backend_ramdisk_delete(struct ctl_be_lun *cbe_lun, off_t lba, off_t len, int anchor)
static void ctl_backend_ramdisk_freeallpages(uint8_t **p, int indir)
static int ctl_backend_ramdisk_rm(struct ctl_be_ramdisk_softc *softc, struct ctl_lun_req *req)
static void ctl_backend_ramdisk_unmap(union ctl_io *io)
struct ctl_softc * control_softc
static int ctl_backend_ramdisk_init(void)
@ CTL_BE_RAMDISK_LUN_WAITING
@ CTL_BE_RAMDISK_LUN_UNCONFIGURED
static struct ctl_be_ramdisk_softc rd_softc
static int ctl_backend_ramdisk_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
static int ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc, struct ctl_lun_req *req)
static int ctl_backend_ramdisk_submit(union ctl_io *io)
CTL_BACKEND_DECLARE(cbr, ctl_be_ramdisk_driver)
static void ctl_backend_ramdisk_unmappage(struct ctl_be_ramdisk_lun *be_lun, off_t pn)
static uint64_t ctl_backend_ramdisk_lun_attr(struct ctl_be_lun *cbe_lun, const char *attrname)
static uint8_t * ctl_backend_ramdisk_getpage(struct ctl_be_ramdisk_lun *be_lun, off_t pn, getpage_op_t op)
static int ctl_backend_ramdisk_cmp(union ctl_io *io)
static void ctl_backend_ramdisk_worker(void *context, int pending)
static int ctl_backend_ramdisk_move_done(union ctl_io *io, bool samethr)
static void ctl_backend_ramdisk_anchorpage(struct ctl_be_ramdisk_lun *be_lun, off_t pn)
static int ctl_backend_ramdisk_config_read(union ctl_io *io)
static void ctl_backend_ramdisk_lun_shutdown(struct ctl_be_lun *cbe_lun)
static int ctl_backend_ramdisk_gls(union ctl_io *io)
static int ctl_backend_ramdisk_config_write(union ctl_io *io)
static void ctl_backend_ramdisk_ws(union ctl_io *io)
static void ctl_backend_ramdisk_compare(union ctl_io *io)
static int ctl_backend_ramdisk_shutdown(void)
MALLOC_DEFINE(M_RAMDISK, "ctlramdisk", "Memory used for CTL RAMdisk")
static struct ctl_backend_driver ctl_be_ramdisk_driver
static void ctl_backend_ramdisk_rw(union ctl_io *io)
static int ctl_backend_ramdisk_modify(struct ctl_be_ramdisk_softc *softc, struct ctl_lun_req *req)
#define CTL_DEBUG_PRINT(X)
void ctl_set_space_alloc_fail(struct ctl_scsiio *ctsio)
void ctl_set_invalid_field(struct ctl_scsiio *ctsio, int sks_valid, int command, int field, int bit_valid, int bit)
void ctl_set_success(struct ctl_scsiio *ctsio)
void ctl_set_invalid_opcode(struct ctl_scsiio *ctsio)
void ctl_set_sense(struct ctl_scsiio *ctsio, int current_error, int sense_key, int asc, int ascq,...)
#define CTL_BACKEND_LUN(io)
@ CTL_LUN_FLAG_SERIAL_NUM
#define SYNCHRONIZE_CACHE_16
static __inline uint64_t scsi_8btou64(const uint8_t *bytes)
#define SSD_KEY_MISCOMPARE
#define SGLS_SERVICE_ACTION
#define SYNCHRONIZE_CACHE
static __inline uint32_t scsi_4btoul(const uint8_t *bytes)
static __inline void scsi_ulto4b(u_int32_t val, u_int8_t *bytes)
static __inline void scsi_u64to8b(u_int64_t val, u_int8_t *bytes)
#define SERVICE_ACTION_IN
char name[CTL_BE_NAME_LEN]
uint8_t device_id[CTL_DEVID_LEN]
uint8_t serial_num[CTL_SN_LEN]
be_callback_t lun_shutdown
struct ctl_backend_driver * be
ctl_backend_lun_flags flags
ctl_be_ramdisk_lun_flags flags
struct ctl_lun_create_params params
struct ctl_be_lun cbe_lun
struct ctl_be_ramdisk_softc * softc
ctl_backend_lun_flags flags
uint8_t serial_num[CTL_SN_LEN]
uint8_t device_id[CTL_DEVID_LEN]
char error_str[CTL_ERROR_STR_LEN]
union ctl_lunreq_data reqdata
int(* be_move_done)(union ctl_io *io, bool samethr)
uint8_t cdb[CTL_MAX_CDBLEN]
struct scsi_get_lba_status_data_descr descr[]
struct ctl_lun_rm_params rm
struct ctl_lun_modify_params modify
struct ctl_lun_create_params create