summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-10-05 08:52:37 +0000
committermav <mav@FreeBSD.org>2015-10-05 08:52:37 +0000
commit3f61db5756a866fb4ec6b09cacd0ccbce7410361 (patch)
treed369d267fc93dd2f4f997f191e4630af47e29402
parentc060972cd4ad911e494f964ecbd92d6c4ffd0f10 (diff)
downloadFreeBSD-src-3f61db5756a866fb4ec6b09cacd0ccbce7410361.zip
FreeBSD-src-3f61db5756a866fb4ec6b09cacd0ccbce7410361.tar.gz
MFC r287500: Allow LUN options modification via CTL_LUNREQ_MODIFY.
Not all changes take effect, but that is a different question.
-rw-r--r--sys/cam/ctl/ctl.h2
-rw-r--r--sys/cam/ctl/ctl_backend.c41
-rw-r--r--sys/cam/ctl/ctl_backend_block.c18
-rw-r--r--sys/cam/ctl/ctl_backend_ramdisk.c29
-rw-r--r--usr.sbin/ctladm/ctladm.89
-rw-r--r--usr.sbin/ctladm/ctladm.c83
-rw-r--r--usr.sbin/ctld/ctld.c18
-rw-r--r--usr.sbin/ctld/ctld.h2
-rw-r--r--usr.sbin/ctld/kernel.c29
9 files changed, 181 insertions, 50 deletions
diff --git a/sys/cam/ctl/ctl.h b/sys/cam/ctl/ctl.h
index f672610..0e0bfb6 100644
--- a/sys/cam/ctl/ctl.h
+++ b/sys/cam/ctl/ctl.h
@@ -208,6 +208,8 @@ typedef STAILQ_HEAD(ctl_options, ctl_option) ctl_options_t;
struct ctl_be_arg;
void ctl_init_opts(ctl_options_t *opts, int num_args, struct ctl_be_arg *args);
+void ctl_update_opts(ctl_options_t *opts, int num_args,
+ struct ctl_be_arg *args);
void ctl_free_opts(ctl_options_t *opts);
char * ctl_get_opt(ctl_options_t *opts, const char *name);
int ctl_expand_number(const char *buf, uint64_t *num);
diff --git a/sys/cam/ctl/ctl_backend.c b/sys/cam/ctl/ctl_backend.c
index ae5034b..f243d0b 100644
--- a/sys/cam/ctl/ctl_backend.c
+++ b/sys/cam/ctl/ctl_backend.c
@@ -185,15 +185,48 @@ ctl_init_opts(ctl_options_t *opts, int num_args, struct ctl_be_arg *args)
if ((args[i].flags & CTL_BEARG_ASCII) == 0)
continue;
opt = malloc(sizeof(*opt), M_CTL, M_WAITOK);
- opt->name = malloc(strlen(args[i].kname) + 1, M_CTL, M_WAITOK);
- strcpy(opt->name, args[i].kname);
- opt->value = malloc(strlen(args[i].kvalue) + 1, M_CTL, M_WAITOK);
- strcpy(opt->value, args[i].kvalue);
+ opt->name = strdup(args[i].kname, M_CTL);
+ opt->value = strdup(args[i].kvalue, M_CTL);
STAILQ_INSERT_TAIL(opts, opt, links);
}
}
void
+ctl_update_opts(ctl_options_t *opts, int num_args, struct ctl_be_arg *args)
+{
+ struct ctl_option *opt;
+ int i;
+
+ for (i = 0; i < num_args; i++) {
+ if ((args[i].flags & CTL_BEARG_RD) == 0)
+ continue;
+ if ((args[i].flags & CTL_BEARG_ASCII) == 0)
+ continue;
+ STAILQ_FOREACH(opt, opts, links) {
+ if (strcmp(opt->name, args[i].kname) == 0)
+ break;
+ }
+ if (args[i].kvalue != NULL &&
+ ((char *)args[i].kvalue)[0] != 0) {
+ if (opt) {
+ free(opt->value, M_CTL);
+ opt->value = strdup(args[i].kvalue, M_CTL);
+ } else {
+ opt = malloc(sizeof(*opt), M_CTL, M_WAITOK);
+ opt->name = strdup(args[i].kname, M_CTL);
+ opt->value = strdup(args[i].kvalue, M_CTL);
+ STAILQ_INSERT_TAIL(opts, opt, links);
+ }
+ } else if (opt) {
+ STAILQ_REMOVE(opts, opt, ctl_option, links);
+ free(opt->name, M_CTL);
+ free(opt->value, M_CTL);
+ free(opt, M_CTL);
+ }
+ }
+}
+
+void
ctl_free_opts(ctl_options_t *opts)
{
struct ctl_option *opt;
diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c
index 2d5a47f..7fd15b9 100644
--- a/sys/cam/ctl/ctl_backend_block.c
+++ b/sys/cam/ctl/ctl_backend_block.c
@@ -2437,9 +2437,6 @@ ctl_be_block_rm(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
params = &req->reqdata.rm;
mtx_lock(&softc->lock);
-
- be_lun = NULL;
-
STAILQ_FOREACH(be_lun, &softc->lun_list, links) {
if (be_lun->cbe_lun.lun_id == params->lun_id)
break;
@@ -2603,13 +2600,13 @@ ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
{
struct ctl_lun_modify_params *params;
struct ctl_be_block_lun *be_lun;
+ struct ctl_be_lun *cbe_lun;
uint64_t oldsize;
int error;
params = &req->reqdata.modify;
mtx_lock(&softc->lock);
- be_lun = NULL;
STAILQ_FOREACH(be_lun, &softc->lun_list, links) {
if (be_lun->cbe_lun.lun_id == params->lun_id)
break;
@@ -2622,8 +2619,11 @@ ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
params->lun_id);
goto bailout_error;
}
+ cbe_lun = &be_lun->cbe_lun;
- be_lun->params.lun_size_bytes = params->lun_size_bytes;
+ if (params->lun_size_bytes != 0)
+ be_lun->params.lun_size_bytes = params->lun_size_bytes;
+ ctl_update_opts(&cbe_lun->options, req->num_be_args, req->kern_be_args);
oldsize = be_lun->size_blocks;
if (be_lun->vn == NULL)
@@ -2636,11 +2636,11 @@ ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
error = EINVAL;
if (be_lun->size_blocks != oldsize)
- ctl_lun_capacity_changed(&be_lun->cbe_lun);
- if ((be_lun->cbe_lun.flags & CTL_LUN_FLAG_OFFLINE) &&
+ ctl_lun_capacity_changed(cbe_lun);
+ if ((cbe_lun->flags & CTL_LUN_FLAG_OFFLINE) &&
be_lun->vn != NULL) {
- be_lun->cbe_lun.flags &= ~CTL_LUN_FLAG_OFFLINE;
- ctl_lun_online(&be_lun->cbe_lun);
+ cbe_lun->flags &= ~CTL_LUN_FLAG_OFFLINE;
+ ctl_lun_online(cbe_lun);
}
/* Tell the user the exact size we ended up using */
diff --git a/sys/cam/ctl/ctl_backend_ramdisk.c b/sys/cam/ctl/ctl_backend_ramdisk.c
index 368c8dc..c39d1b6 100644
--- a/sys/cam/ctl/ctl_backend_ramdisk.c
+++ b/sys/cam/ctl/ctl_backend_ramdisk.c
@@ -73,6 +73,7 @@ typedef enum {
} ctl_be_ramdisk_lun_flags;
struct ctl_be_ramdisk_lun {
+ struct ctl_lun_create_params params;
char lunname[32];
uint64_t size_bytes;
uint64_t size_blocks;
@@ -535,6 +536,7 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
be_lun = malloc(sizeof(*be_lun), M_RAMDISK, M_ZERO | M_WAITOK);
cbe_lun = &be_lun->cbe_lun;
cbe_lun->be_lun = be_lun;
+ be_lun->params = req->reqdata.create;
be_lun->softc = softc;
sprintf(be_lun->lunname, "cram%d", softc->num_luns);
ctl_init_opts(&cbe_lun->options, req->num_be_args, req->kern_be_args);
@@ -713,13 +715,12 @@ ctl_backend_ramdisk_modify(struct ctl_be_ramdisk_softc *softc,
struct ctl_lun_req *req)
{
struct ctl_be_ramdisk_lun *be_lun;
+ struct ctl_be_lun *cbe_lun;
struct ctl_lun_modify_params *params;
uint32_t blocksize;
params = &req->reqdata.modify;
- be_lun = NULL;
-
mtx_lock(&softc->lock);
STAILQ_FOREACH(be_lun, &softc->lun_list, links) {
if (be_lun->cbe_lun.lun_id == params->lun_id)
@@ -733,32 +734,22 @@ ctl_backend_ramdisk_modify(struct ctl_be_ramdisk_softc *softc,
__func__, params->lun_id);
goto bailout_error;
}
+ cbe_lun = &be_lun->cbe_lun;
- if (params->lun_size_bytes == 0) {
- snprintf(req->error_str, sizeof(req->error_str),
- "%s: LUN size \"auto\" not supported "
- "by the ramdisk backend", __func__);
- goto bailout_error;
- }
-
+ if (params->lun_size_bytes != 0)
+ be_lun->params.lun_size_bytes = params->lun_size_bytes;
+ ctl_update_opts(&cbe_lun->options, req->num_be_args, req->kern_be_args);
blocksize = be_lun->cbe_lun.blocksize;
- if (params->lun_size_bytes < blocksize) {
+ if (be_lun->params.lun_size_bytes < blocksize) {
snprintf(req->error_str, sizeof(req->error_str),
"%s: LUN size %ju < blocksize %u", __func__,
- params->lun_size_bytes, blocksize);
+ be_lun->params.lun_size_bytes, blocksize);
goto bailout_error;
}
- be_lun->size_blocks = params->lun_size_bytes / blocksize;
+ be_lun->size_blocks = be_lun->params.lun_size_bytes / blocksize;
be_lun->size_bytes = be_lun->size_blocks * blocksize;
-
- /*
- * The maximum LBA is the size - 1.
- *
- * XXX: Note that this field is being updated without locking,
- * which might cause problems on 32-bit architectures.
- */
be_lun->cbe_lun.maxlba = be_lun->size_blocks - 1;
ctl_lun_capacity_changed(&be_lun->cbe_lun);
diff --git a/usr.sbin/ctladm/ctladm.8 b/usr.sbin/ctladm/ctladm.8
index 545676f..11b953c 100644
--- a/usr.sbin/ctladm/ctladm.8
+++ b/usr.sbin/ctladm/ctladm.8
@@ -34,7 +34,7 @@
.\" $Id: //depot/users/kenm/FreeBSD-test2/usr.sbin/ctladm/ctladm.8#3 $
.\" $FreeBSD$
.\"
-.Dd May 22, 2015
+.Dd September 6, 2015
.Dt CTLADM 8
.Os
.Sh NAME
@@ -166,6 +166,7 @@
.Ic modify
.Aq Fl b Ar backend
.Aq Fl l Ar lun_id
+.Op Fl o Ar name=value
.Aq Fl s Ar size_bytes
.Nm
.Ic devlist
@@ -859,6 +860,12 @@ and
.Dq block .
.It Fl l Ar lun_id
Specify the LUN number to remove.
+.It Fl o Ar name=value
+Specify a backend-specific name/value pair.
+Multiple
+.Fl o
+arguments may be specified.
+Refer to the backend documentation for arguments that may be used.
.It Fl s Ar size_bytes
Specify the size of the LUN in bytes.
For the
diff --git a/usr.sbin/ctladm/ctladm.c b/usr.sbin/ctladm/ctladm.c
index 4f66b30..71fd5f3 100644
--- a/usr.sbin/ctladm/ctladm.c
+++ b/usr.sbin/ctladm/ctladm.c
@@ -183,7 +183,7 @@ static struct ctladm_opts option_table[] = {
{"lunlist", CTLADM_CMD_LUNLIST, CTLADM_ARG_NONE, NULL},
{"lunmap", CTLADM_CMD_LUNMAP, CTLADM_ARG_NONE, "p:l:L:"},
{"modesense", CTLADM_CMD_MODESENSE, CTLADM_ARG_NEED_TL, "P:S:dlm:c:"},
- {"modify", CTLADM_CMD_MODIFY, CTLADM_ARG_NONE, "b:l:s:"},
+ {"modify", CTLADM_CMD_MODIFY, CTLADM_ARG_NONE, "b:l:o:s:"},
{"port", CTLADM_CMD_PORT, CTLADM_ARG_NONE, "lo:p:qt:w:W:x"},
{"portlist", CTLADM_CMD_PORTLIST, CTLADM_ARG_NONE, "f:ilp:qvx"},
{"prin", CTLADM_CMD_PRES_IN, CTLADM_ARG_NEED_TL, "a:"},
@@ -3169,8 +3169,11 @@ cctl_modify_lun(int fd, int argc, char **argv, char *combinedopt)
uint32_t lun_id = 0;
int lun_id_set = 0, lun_size_set = 0;
char *backend_name = NULL;
+ STAILQ_HEAD(, cctl_req_option) option_list;
+ int num_options = 0;
int retval = 0, c;
+ STAILQ_INIT(&option_list);
while ((c = getopt(argc, argv, combinedopt)) != -1) {
switch (c) {
case 'b':
@@ -3180,6 +3183,43 @@ cctl_modify_lun(int fd, int argc, char **argv, char *combinedopt)
lun_id = strtoul(optarg, NULL, 0);
lun_id_set = 1;
break;
+ case 'o': {
+ struct cctl_req_option *option;
+ char *tmpstr;
+ char *name, *value;
+
+ tmpstr = strdup(optarg);
+ name = strsep(&tmpstr, "=");
+ if (name == NULL) {
+ warnx("%s: option -o takes \"name=value\""
+ "argument", __func__);
+ retval = 1;
+ goto bailout;
+ }
+ value = strsep(&tmpstr, "=");
+ if (value == NULL) {
+ warnx("%s: option -o takes \"name=value\""
+ "argument", __func__);
+ retval = 1;
+ goto bailout;
+ }
+ option = malloc(sizeof(*option));
+ if (option == NULL) {
+ warn("%s: error allocating %zd bytes",
+ __func__, sizeof(*option));
+ retval = 1;
+ goto bailout;
+ }
+ option->name = strdup(name);
+ option->namelen = strlen(name) + 1;
+ option->value = strdup(value);
+ option->vallen = strlen(value) + 1;
+ free(tmpstr);
+
+ STAILQ_INSERT_TAIL(&option_list, option, links);
+ num_options++;
+ break;
+ }
case 's':
if (strcasecmp(optarg, "auto") != 0) {
retval = expand_number(optarg, &lun_size);
@@ -3203,8 +3243,9 @@ cctl_modify_lun(int fd, int argc, char **argv, char *combinedopt)
if (lun_id_set == 0)
errx(1, "%s: LUN id (-l) must be specified", __func__);
- if (lun_size_set == 0)
- errx(1, "%s: size (-s) must be specified", __func__);
+ if (lun_size_set == 0 && num_options == 0)
+ errx(1, "%s: size (-s) or options (-o) must be specified",
+ __func__);
bzero(&req, sizeof(req));
@@ -3214,6 +3255,42 @@ cctl_modify_lun(int fd, int argc, char **argv, char *combinedopt)
req.reqdata.modify.lun_id = lun_id;
req.reqdata.modify.lun_size_bytes = lun_size;
+ req.num_be_args = num_options;
+ if (num_options > 0) {
+ struct cctl_req_option *option, *next_option;
+ int i;
+
+ req.be_args = malloc(num_options * sizeof(*req.be_args));
+ if (req.be_args == NULL) {
+ warn("%s: error allocating %zd bytes", __func__,
+ num_options * sizeof(*req.be_args));
+ retval = 1;
+ goto bailout;
+ }
+
+ for (i = 0, option = STAILQ_FIRST(&option_list);
+ i < num_options; i++, option = next_option) {
+ next_option = STAILQ_NEXT(option, links);
+
+ req.be_args[i].namelen = option->namelen;
+ req.be_args[i].name = strdup(option->name);
+ req.be_args[i].vallen = option->vallen;
+ req.be_args[i].value = strdup(option->value);
+ /*
+ * XXX KDM do we want a way to specify a writeable
+ * flag of some sort? Do we want a way to specify
+ * binary data?
+ */
+ req.be_args[i].flags = CTL_BEARG_ASCII | CTL_BEARG_RD;
+
+ STAILQ_REMOVE(&option_list, option, cctl_req_option,
+ links);
+ free(option->name);
+ free(option->value);
+ free(option);
+ }
+ }
+
if (ioctl(fd, CTL_LUN_REQ, &req) == -1) {
warn("%s: error issuing CTL_LUN_REQ ioctl", __func__);
retval = 1;
diff --git a/usr.sbin/ctld/ctld.c b/usr.sbin/ctld/ctld.c
index dc33224..85f1133 100644
--- a/usr.sbin/ctld/ctld.c
+++ b/usr.sbin/ctld/ctld.c
@@ -1944,18 +1944,14 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
TAILQ_FOREACH_SAFE(newlun, &newconf->conf_luns, l_next, tmplun) {
oldlun = lun_find(oldconf, newlun->l_name);
if (oldlun != NULL) {
- if (newlun->l_size != oldlun->l_size ||
- newlun->l_size == 0) {
- log_debugx("resizing lun \"%s\", CTL lun %d",
+ log_debugx("modifying lun \"%s\", CTL lun %d",
+ newlun->l_name, newlun->l_ctl_lun);
+ error = kernel_lun_modify(newlun);
+ if (error != 0) {
+ log_warnx("failed to "
+ "modify lun \"%s\", CTL lun %d",
newlun->l_name, newlun->l_ctl_lun);
- error = kernel_lun_resize(newlun);
- if (error != 0) {
- log_warnx("failed to "
- "resize lun \"%s\", CTL lun %d",
- newlun->l_name,
- newlun->l_ctl_lun);
- cumulated_error++;
- }
+ cumulated_error++;
}
continue;
}
diff --git a/usr.sbin/ctld/ctld.h b/usr.sbin/ctld/ctld.h
index ab6186b..a4e260b 100644
--- a/usr.sbin/ctld/ctld.h
+++ b/usr.sbin/ctld/ctld.h
@@ -387,7 +387,7 @@ void lun_option_set(struct lun_option *clo,
void kernel_init(void);
int kernel_lun_add(struct lun *lun);
-int kernel_lun_resize(struct lun *lun);
+int kernel_lun_modify(struct lun *lun);
int kernel_lun_remove(struct lun *lun);
void kernel_handoff(struct connection *conn);
int kernel_port_add(struct port *port);
diff --git a/usr.sbin/ctld/kernel.c b/usr.sbin/ctld/kernel.c
index 3c714ea..914d027 100644
--- a/usr.sbin/ctld/kernel.c
+++ b/usr.sbin/ctld/kernel.c
@@ -743,9 +743,11 @@ kernel_lun_add(struct lun *lun)
}
int
-kernel_lun_resize(struct lun *lun)
+kernel_lun_modify(struct lun *lun)
{
+ struct lun_option *lo;
struct ctl_lun_req req;
+ int error, i, num_options;
bzero(&req, sizeof(req));
@@ -755,7 +757,30 @@ kernel_lun_resize(struct lun *lun)
req.reqdata.modify.lun_id = lun->l_ctl_lun;
req.reqdata.modify.lun_size_bytes = lun->l_size;
- if (ioctl(ctl_fd, CTL_LUN_REQ, &req) == -1) {
+ num_options = 0;
+ TAILQ_FOREACH(lo, &lun->l_options, lo_next)
+ num_options++;
+
+ req.num_be_args = num_options;
+ if (num_options > 0) {
+ req.be_args = malloc(num_options * sizeof(*req.be_args));
+ if (req.be_args == NULL) {
+ log_warn("error allocating %zd bytes",
+ num_options * sizeof(*req.be_args));
+ return (1);
+ }
+
+ i = 0;
+ TAILQ_FOREACH(lo, &lun->l_options, lo_next) {
+ str_arg(&req.be_args[i], lo->lo_name, lo->lo_value);
+ i++;
+ }
+ assert(i == num_options);
+ }
+
+ error = ioctl(ctl_fd, CTL_LUN_REQ, &req);
+ free(req.be_args);
+ if (error != 0) {
log_warn("error issuing CTL_LUN_REQ ioctl");
return (1);
}
OpenPOWER on IntegriCloud