예제 #1
0
파일: mgmt.c 프로젝트: fujita/tgt
static tgtadm_err sys_mgmt(int lld_no, struct mgmt_task *mtask)
{
	struct tgtadm_req *req = &mtask->req;
	tgtadm_err adm_err = TGTADM_INVALID_REQUEST;

	switch (req->op) {
	case OP_UPDATE:
		if (!strncmp(mtask->req_buf, "debug=", 6)) {
			if (!strncmp(mtask->req_buf+6, "on", 2)) {
				is_debug = 1;
				adm_err = TGTADM_SUCCESS;
			} else if (!strncmp(mtask->req_buf+6, "off", 3)) {
				is_debug = 0;
				adm_err = TGTADM_SUCCESS;
			}
			if (adm_err == TGTADM_SUCCESS)
				eprintf("set debug to: %d\n", is_debug);
		} else if (tgt_drivers[lld_no]->update)
			adm_err = tgt_drivers[lld_no]->update(req->mode, req->op,
							  req->tid,
							  req->sid, req->lun,
							  req->cid, mtask->req_buf);

		break;
	case OP_SHOW:
		concat_buf_init(&mtask->rsp_concat);
		adm_err = system_show(req->mode, &mtask->rsp_concat);
		if (tgt_drivers[lld_no]->show)
			adm_err = tgt_drivers[lld_no]->show(req->mode,
							req->tid, req->sid,
							req->cid, req->lun,
							&mtask->rsp_concat);
		concat_buf_finish(&mtask->rsp_concat);
		break;
	case OP_STATS:
		concat_buf_init(&mtask->rsp_concat);
		adm_err = tgt_stat_system(&mtask->rsp_concat);
		concat_buf_finish(&mtask->rsp_concat);
		break;
	case OP_DELETE:
		if (is_system_inactive())
			adm_err = TGTADM_SUCCESS;
		break;
	default:
		break;
	}

	return adm_err;
}
예제 #2
0
파일: mgmt.c 프로젝트: fujita/tgt
static tgtadm_err session_mgmt(int lld_no, struct mgmt_task *mtask)
{
	struct tgtadm_req *req = &mtask->req;
	int adm_err = TGTADM_INVALID_REQUEST;

	switch (req->op) {
	case OP_STATS:
		if (tgt_drivers[lld_no]->stat) {
			concat_buf_init(&mtask->rsp_concat);
			adm_err = tgt_drivers[lld_no]->stat(req->mode,
							    req->tid, req->sid,
							    req->cid, req->lun,
							    &mtask->rsp_concat);
			concat_buf_finish(&mtask->rsp_concat);
		}
		break;
	default:
		if (tgt_drivers[lld_no]->update)
			adm_err = tgt_drivers[lld_no]->update(req->mode, req->op,
							      req->tid,
							      req->sid, req->lun,
							      req->cid, mtask->req_buf);
		break;
	}

	return adm_err;
}
예제 #3
0
파일: mgmt.c 프로젝트: fujita/tgt
static tgtadm_err device_mgmt(int lld_no, struct mgmt_task *mtask)
{
	struct tgtadm_req *req = &mtask->req;
	char *params = mtask->req_buf;
	tgtadm_err adm_err = TGTADM_UNSUPPORTED_OPERATION;

	switch (req->op) {
	case OP_NEW:
		eprintf("sz:%d params:%s\n",mtask->req_bsize,params);
		adm_err = tgt_device_create(req->tid, req->device_type, req->lun,
					    params, 1);
		break;
	case OP_DELETE:
		adm_err = tgt_device_destroy(req->tid, req->lun, 0);
		break;
	case OP_UPDATE:
		adm_err = tgt_device_update(req->tid, req->lun, params);
		break;
	case OP_STATS:
		concat_buf_init(&mtask->rsp_concat);
		if (!req->sid)
			adm_err = tgt_stat_device_by_id(req->tid, req->lun,
							&mtask->rsp_concat);
		else if (tgt_drivers[lld_no]->stat)
			adm_err = tgt_drivers[lld_no]->stat(req->mode, req->tid,
							    req->sid, req->cid, req->lun,
							    &mtask->rsp_concat);
		concat_buf_finish(&mtask->rsp_concat);
		break;
	default:
		break;
	}

	return adm_err;
}
예제 #4
0
파일: mgmt.c 프로젝트: fujita/tgt
static tgtadm_err portal_mgmt(int lld_no, struct mgmt_task *mtask)
{
	struct tgtadm_req *req = &mtask->req;
	tgtadm_err adm_err = TGTADM_INVALID_REQUEST;

	switch (req->op) {
	case OP_SHOW:
		if (tgt_drivers[lld_no]->show) {
			concat_buf_init(&mtask->rsp_concat);
			adm_err = tgt_drivers[lld_no]->show(req->mode,
							req->tid, req->sid,
							req->cid, req->lun,
							&mtask->rsp_concat);
			concat_buf_finish(&mtask->rsp_concat);
		}
		break;
	case OP_NEW:
		adm_err = tgt_portal_create(lld_no, mtask->req_buf);
		break;
	case OP_DELETE:
		adm_err = tgt_portal_destroy(lld_no, mtask->req_buf);
		break;
	default:
		break;
	}

	return adm_err;
}
예제 #5
0
파일: mgmt.c 프로젝트: fujita/tgt
static tgtadm_err account_mgmt(int lld_no,  struct mgmt_task *mtask)
{
	struct tgtadm_req *req = &mtask->req;
	char *user, *password;
	tgtadm_err adm_err = TGTADM_UNSUPPORTED_OPERATION;

	switch (req->op) {
	case OP_NEW:
	case OP_DELETE:
	case OP_BIND:
	case OP_UNBIND:
		user = strstr(mtask->req_buf, "user="******"password=");

			adm_err = account_add(user, password);
		} else {
			if (req->op == OP_DELETE) {
				adm_err = account_del(user);
			} else
				adm_err = account_ctl(req->tid, req->ac_dir,
						      user, req->op == OP_BIND);
		}
		break;
	case OP_SHOW:
		concat_buf_init(&mtask->rsp_concat);
		adm_err = account_show(&mtask->rsp_concat);
		concat_buf_finish(&mtask->rsp_concat);
		break;
	default:
		break;
	}

	return adm_err;
}
예제 #6
0
파일: mgmt.c 프로젝트: fujita/tgt
static tgtadm_err lld_mgmt(int lld_no, struct mgmt_task *mtask)
{
	struct tgtadm_req *req = &mtask->req;
	tgtadm_err adm_err = TGTADM_INVALID_REQUEST;

	switch (req->op) {
	case OP_START:
		if (tgt_drivers[lld_no]->drv_state != DRIVER_INIT) {
			if (!lld_init_one(lld_no))
				adm_err = TGTADM_SUCCESS;
			else
				adm_err = TGTADM_UNKNOWN_ERR;
		} else
			adm_err = TGTADM_SUCCESS;
		break;
	case OP_STOP:
		if (tgt_drivers[lld_no]->drv_state == DRIVER_INIT) {
			if (list_empty(&tgt_drivers[lld_no]->target_list)) {
				if (tgt_drivers[lld_no]->exit) {
					tgt_drivers[lld_no]->exit();
					tgt_drivers[lld_no]->drv_state = DRIVER_EXIT;
				}
				adm_err = TGTADM_SUCCESS;
			} else
				adm_err = TGTADM_DRIVER_ACTIVE;
		} else
			adm_err = TGTADM_SUCCESS;
		break;
	case OP_SHOW:
		concat_buf_init(&mtask->rsp_concat);
		adm_err = lld_show(&mtask->rsp_concat);
		concat_buf_finish(&mtask->rsp_concat);
		break;
	default:
		break;
	}

	return adm_err;
}
예제 #7
0
파일: mgmt.c 프로젝트: fujita/tgt
static tgtadm_err target_mgmt(int lld_no, struct mgmt_task *mtask)
{
	struct tgtadm_req *req = &mtask->req;
	tgtadm_err adm_err = TGTADM_INVALID_REQUEST;

	switch (req->op) {
	case OP_NEW:
		adm_err = tgt_target_create(lld_no, req->tid, mtask->req_buf);
		break;
	case OP_DELETE:
		adm_err = tgt_target_destroy(lld_no, req->tid, req->force);
		break;
	case OP_BIND:
		/* FIXME */
		if (req->len == sizeof(*req))
			adm_err = tgt_bind_host_to_target(req->tid, req->host_no);
		else {
			char *p;

			p = strstr(mtask->req_buf, "initiator-address=");
			if (p) {
				p += strlen("initiator-address=");
				adm_err = acl_add(req->tid, p);
				if (adm_err != TGTADM_SUCCESS) {
					eprintf("Failed to bind by address: %s\n", p);
					break;
				}
			}

			p = strstr(mtask->req_buf, "initiator-name=");
			if (p) {
				p += strlen("initiator-name=");
				adm_err = iqn_acl_add(req->tid, p);
				if (adm_err != TGTADM_SUCCESS) {
					eprintf("Failed to bind by name: %s\n", p);
					break;
				}
			}
		}
		break;
	case OP_UNBIND:
		if (req->len == sizeof(*req))
			adm_err = tgt_unbind_host_to_target(req->tid, req->host_no);
		else {
			char *p;

			p = strstr(mtask->req_buf, "initiator-address=");
			if (p) {
				p += strlen("initiator-address=");
				adm_err = acl_del(req->tid, p);
				if (adm_err != TGTADM_SUCCESS) {
					eprintf("Failed to unbind by address: %s\n", p);
					break;
				}
			}

			p = strstr(mtask->req_buf, "initiator-name=");
			if (p) {
				p += strlen("initiator-name=");
				adm_err = iqn_acl_del(req->tid, p);
				if (adm_err != TGTADM_SUCCESS) {
					eprintf("Failed to unbind by name: %s\n", p);
					break;
				}
			}
		}
		break;
	case OP_UPDATE:
	{
		char *p;
		adm_err = TGTADM_UNSUPPORTED_OPERATION;

		p = strchr(mtask->req_buf, '=');
		if (!p)
			break;
		*p++ = '\0';

		if (!strcmp(mtask->req_buf, "state")) {
			adm_err = tgt_set_target_state(req->tid, p);
		} else if (tgt_drivers[lld_no]->update)
			adm_err = tgt_drivers[lld_no]->update(req->mode, req->op, req->tid,
							  req->sid, req->lun,
							  req->cid, mtask->req_buf);
		break;
	}
	case OP_SHOW:
	{
		concat_buf_init(&mtask->rsp_concat);
		if (req->tid < 0)
			adm_err = tgt_target_show_all(&mtask->rsp_concat);
		else if (tgt_drivers[lld_no]->show)
			adm_err = tgt_drivers[lld_no]->show(req->mode,
							req->tid,
							req->sid,
							req->cid, req->lun,
							&mtask->rsp_concat);
		concat_buf_finish(&mtask->rsp_concat);
		break;
	}
	case OP_STATS:
	{
		concat_buf_init(&mtask->rsp_concat);
		adm_err = tgt_stat_target_by_id(req->tid, &mtask->rsp_concat);
		concat_buf_finish(&mtask->rsp_concat);
		break;
	}
	default:
		break;
	}

	return adm_err;
}
예제 #8
0
파일: mgmt.c 프로젝트: fujita/tgt
static tgtadm_err mtask_execute(struct mgmt_task *mtask)
{
	struct tgtadm_req *req = &mtask->req;
	int lld_no;
	tgtadm_err adm_err = TGTADM_INVALID_REQUEST;

	req->lld[TGT_LLD_NAME_LEN - 1] = '\0';

	if (!strlen(req->lld))
		lld_no = 0;
	else {
		lld_no = get_driver_index(req->lld);
		if (lld_no < 0 ||
		   (tgt_drivers[lld_no]->drv_state != DRIVER_INIT &&
		    req->mode != MODE_LLD))
		{
			if (lld_no < 0)
				eprintf("can't find the driver %s\n", req->lld);
			else
				eprintf("driver %s is in state: %s\n",
					req->lld, driver_state_name(tgt_drivers[lld_no]));
			return TGTADM_NO_DRIVER;
		}
	}

	dprintf("%d %d %d %d %d %" PRIx64 " %" PRIx64 " %s %d\n",
		req->len, lld_no, req->mode, req->op,
		req->tid, req->sid, req->lun, mtask->req_buf, getpid());

	switch (req->mode) {
	case MODE_SYSTEM:
		adm_err = sys_mgmt(lld_no, mtask);
		break;
	case MODE_TARGET:
		adm_err = target_mgmt(lld_no, mtask);
		break;
	case MODE_PORTAL:
		adm_err = portal_mgmt(lld_no, mtask);
		break;
	case MODE_DEVICE:
		adm_err = device_mgmt(lld_no, mtask);
		break;
	case MODE_ACCOUNT:
		adm_err = account_mgmt(lld_no, mtask);
		break;
	case MODE_SESSION:
		adm_err = session_mgmt(lld_no, mtask);
		break;
	case MODE_CONNECTION:
		adm_err = connection_mgmt(lld_no, mtask);
		break;
	case MODE_LLD:
		adm_err = lld_mgmt(lld_no, mtask);
		break;
	default:
		if (req->op == OP_SHOW && tgt_drivers[lld_no]->show) {
			concat_buf_init(&mtask->rsp_concat);
			adm_err = tgt_drivers[lld_no]->show(req->mode,
							    req->tid, req->sid,
							    req->cid, req->lun,
							    &mtask->rsp_concat);
			concat_buf_finish(&mtask->rsp_concat);
		} else
			eprintf("unsupported mode: %d\n", req->mode);
		break;
	}

	return adm_err;
}
예제 #9
0
파일: tgtadm.c 프로젝트: cnanakos/tgt
int main(int argc, char **argv)
{
    int ch, longindex, rc;
    int op, tid, mode, dev_type, ac_dir;
    uint32_t cid, hostno;
    uint64_t sid, lun, force;
    char *name, *value, *path, *targetname, *address, *iqnname, *targetOps;
    char *portalOps, *bstype, *bsopts;
    char *bsoflags;
    char *blocksize;
    char *user, *password;
    struct tgtadm_req adm_req = {0}, *req = &adm_req;
    struct concat_buf b;

    op = tid = mode = -1;
    cid = hostno = sid = 0;
    lun = UINT64_MAX;

    rc = 0;
    dev_type = TYPE_DISK;
    ac_dir = ACCOUNT_TYPE_INCOMING;
    name = value = path = targetname = address = iqnname = NULL;
    targetOps = portalOps = bstype = bsopts = NULL;
    bsoflags = blocksize = user = password = NULL;
    force = 0;

    optind = 1;
    while ((ch = getopt_long(argc, argv, short_options,
                             long_options, &longindex)) >= 0) {
        errno = 0;
        switch (ch) {
        case 'L':
            strncpy(req->lld, optarg, sizeof(req->lld));
            break;
        case 'o':
            op = str_to_op(optarg);
            break;
        case 'm':
            mode = str_to_mode(optarg);
            break;
        case 't':
            rc = str_to_int_ge(optarg, tid, 0);
            if (rc)
                bad_optarg(rc, ch, optarg);
            break;
        case 's':
            rc = str_to_int(optarg, sid);
            if (rc)
                bad_optarg(rc, ch, optarg);
            break;
        case 'c':
            rc = str_to_int(optarg, cid);
            if (rc)
                bad_optarg(rc, ch, optarg);
            break;
        case 'l':
            rc = str_to_int(optarg, lun);
            if (rc)
                bad_optarg(rc, ch, optarg);
            break;
        case 'P':
            if (mode == MODE_PORTAL)
                portalOps = optarg;
            else
                targetOps = optarg;
            break;
        case 'n':
            name = optarg;
            break;
        case 'v':
            value = optarg;
            break;
        case 'b':
            path = optarg;
            break;
        case 'T':
            targetname = optarg;
            break;
        case 'I':
            address = optarg;
            break;
        case 'Q':
            iqnname = optarg;
            break;
        case 'u':
            user = optarg;
            break;
        case 'p':
            password = optarg;
            break;
        case 'B':
            hostno = bus_to_host(optarg);
            break;
        case 'H':
            rc = str_to_int_ge(optarg, hostno, 0);
            if (rc)
                bad_optarg(rc, ch, optarg);
            break;
        case 'F':
            force = 1;
            break;
        case 'f':
            bsoflags = optarg;
            break;
        case 'y':
            blocksize = optarg;
            break;
        case 'E':
            bstype = optarg;
            break;
        case 'S':
            bsopts = optarg;
            break;
        case 'Y':
            dev_type = str_to_device_type(optarg);
            break;
        case 'O':
            ac_dir = ACCOUNT_TYPE_OUTGOING;
            break;
        case 'C':
            rc = str_to_int_gt(optarg, control_port, 0);
            if (rc)
                bad_optarg(rc, ch, optarg);
            break;
        case 'V':
            version();
            break;
        case 'd':
            debug = 1;
            break;
        case 'h':
            usage(0);
            break;
        default:
            usage(1);
        }
    }

    if (optind < argc) {
        eprintf("unrecognized option '%s'\n", argv[optind]);
        usage(1);
    }

    if (op < 0) {
        eprintf("specify the operation type\n");
        exit(EINVAL);
    }

    if (mode < 0) {
        eprintf("specify the mode\n");
        exit(EINVAL);
    }

    if (mode == MODE_SYSTEM) {
        switch (op) {
        case OP_UPDATE:
            rc = verify_mode_params(argc, argv, "LmonvC");
            if (rc) {
                eprintf("system mode: option '-%c' is not "
                        "allowed/supported\n", rc);
                exit(EINVAL);
            }
            if ((!name || !value)) {
                eprintf("update operation requires 'name'"
                        " and 'value' options\n");
                exit(EINVAL);
            }
            break;
        case OP_SHOW:
        case OP_DELETE:
        case OP_STATS:
            break;
        default:
            eprintf("option %d not supported in system mode\n", op);
            exit(EINVAL);
            break;
        }
    }

    if (mode == MODE_TARGET) {
        if ((tid <= 0 && (op != OP_SHOW))) {
            if (tid == 0)
                eprintf("'tid' cannot be 0\n");
            else
                eprintf("'tid' option is necessary\n");

            exit(EINVAL);
        }
        switch (op) {
        case OP_NEW:
            rc = verify_mode_params(argc, argv, "LmotTC");
            if (rc) {
                eprintf("target mode: option '-%c' is not "
                        "allowed/supported\n", rc);
                exit(EINVAL);
            }
            if (!targetname) {
                eprintf("creating new target requires "
                        "a name, use --targetname\n");
                exit(EINVAL);
            }
            break;
        case OP_DELETE:
            rc = verify_mode_params(argc, argv, "LmotCF");
            if (rc) {
                eprintf("target mode: option '-%c' is not "
                        "allowed/supported\n", rc);
                exit(EINVAL);
            }
            break;
        case OP_SHOW:
        case OP_STATS:
            rc = verify_mode_params(argc, argv, "LmotC");
            if (rc) {
                eprintf("target mode: option '-%c' is not "
                        "allowed/supported\n", rc);
                exit(EINVAL);
            }
            break;
        case OP_BIND:
        case OP_UNBIND:
            rc = verify_mode_params(argc, argv, "LmotIQBHC");
            if (rc) {
                eprintf("target mode: option '-%c' is not "
                        "allowed/supported\n", rc);
                exit(EINVAL);
            }
            if (!address && !iqnname && !hostno) {
                eprintf("%s operation requires"
                        " initiator-address, initiator-name or bus\n",
                        op == OP_BIND ? "bind" : "unbind");
                exit(EINVAL);
            }
            break;
        case OP_UPDATE:
            rc = verify_mode_params(argc, argv, "LmotnvC");
            if (rc) {
                eprintf("target mode: option '-%c' is not " \
                        "allowed/supported\n", rc);
                exit(EINVAL);
            }
            if ((!name || !value)) {
                eprintf("update operation requires 'name'" \
                        " and 'value' options\n");
                exit(EINVAL);
            }
            break;
        default:
            eprintf("option %d not supported in target mode\n", op);
            exit(EINVAL);
            break;
        }
    }

    if (mode == MODE_ACCOUNT) {
        switch (op) {
        case OP_NEW:
            rc = verify_mode_params(argc, argv, "LmoupfC");
            if (rc) {
                eprintf("logicalunit mode: option '-%c' is "
                        "not allowed/supported\n", rc);
                exit(EINVAL);
            }
            if (!user || !password) {
                eprintf("'user' and 'password' options "
                        "are required\n");
                exit(EINVAL);
            }
            break;
        case OP_SHOW:
            rc = verify_mode_params(argc, argv, "LmoC");
            if (rc) {
                eprintf("target mode: option '-%c' is not "
                        "allowed/supported\n", rc);
                exit(EINVAL);
            }
            break;
        case OP_DELETE:
            rc = verify_mode_params(argc, argv, "LmouC");
            if (rc) {
                eprintf("target mode: option '-%c' is not "
                        "allowed/supported\n", rc);
                exit(EINVAL);
            }
            break;
        case OP_BIND:
            rc = verify_mode_params(argc, argv, "LmotuOC");
            if (rc) {
                eprintf("target mode: option '-%c' is not "
                        "allowed/supported\n", rc);
                exit(EINVAL);
            }
            if (!user) {
                eprintf("'user' option is necessary\n");
                exit(EINVAL);
            }
            if (tid == -1)
                tid = GLOBAL_TID;
            break;
        case OP_UNBIND:
            rc = verify_mode_params(argc, argv, "LmotuOC");
            if (rc) {
                eprintf("target mode: option '-%c' is not "
                        "allowed/supported\n", rc);
                exit(EINVAL);
            }
            if (!user) {
                eprintf("'user' option is necessary\n");
                exit(EINVAL);
            }
            if (tid == -1)
                tid = GLOBAL_TID;
            break;
        default:
            eprintf("option %d not supported in account mode\n",
                    op);
            exit(EINVAL);
            break;
        }
    }

    if (mode == MODE_DEVICE) {
        if (tid <= 0) {
            if (tid == 0)
                eprintf("'tid' must not be 0\n");
            else
                eprintf("'tid' option is necessary\n");
            exit(EINVAL);
        }
        if (lun == UINT64_MAX) {
            eprintf("'lun' option is necessary\n");
            exit(EINVAL);
        }
        switch (op) {
        case OP_NEW:
            rc = verify_mode_params(argc, argv, "LmofytlbEYCS");
            if (rc) {
                eprintf("target mode: option '-%c' is not "
                        "allowed/supported\n", rc);
                exit(EINVAL);
            }
            if (!path && dev_type != TYPE_MMC
                    && dev_type != TYPE_TAPE
                    && dev_type != TYPE_DISK) {
                eprintf("'backing-store' option "
                        "is necessary\n");
                exit(EINVAL);
            }
            break;
        case OP_DELETE:
        case OP_STATS:
            rc = verify_mode_params(argc, argv, "LmotlC");
            if (rc) {
                eprintf("target mode: option '-%c' is not "
                        "allowed/supported\n", rc);
                exit(EINVAL);
            }
            break;
        case OP_UPDATE:
            rc = verify_mode_params(argc, argv, "LmofytlPC");
            if (rc) {
                eprintf("option '-%c' not supported in "
                        "logicalunit mode\n", rc);
                exit(EINVAL);
            }
            break;
        default:
            eprintf("option %d not supported in "
                    "logicalunit mode\n", op);
            exit(EINVAL);
            break;
        }
    }

    if (mode == MODE_PORTAL) {
        switch (op) {
        case OP_NEW:
            rc = verify_mode_params(argc, argv, "LmoCP");
            if (rc) {
                eprintf("portal mode: option '-%c' is not "
                        "allowed/supported\n", rc);
                exit(EINVAL);
            }
            if (!portalOps) {
                eprintf("you must specify --param "
                        "portal=<portal>\n");
                exit(EINVAL);
            }
            break;
        case OP_DELETE:
            rc = verify_mode_params(argc, argv, "LmoCP");
            if (rc) {
                eprintf("portal mode: option '-%c' is not "
                        "allowed/supported\n", rc);
                exit(EINVAL);
            }
            if (!portalOps) {
                eprintf("you must specify --param "
                        "portal=<portal>\n");
                exit(EINVAL);
            }
            break;
        case OP_SHOW:
            rc = verify_mode_params(argc, argv, "LmoC");
            if (rc) {
                eprintf("option '-%c' not supported in "
                        "portal mode\n", rc);
                exit(EINVAL);
            }
            break;
        default:
            eprintf("option %d not supported in "
                    "portal mode\n", op);
            exit(EINVAL);
            break;
        }
    }

    if (mode == MODE_LLD) {
        switch (op) {
        case OP_START:
        case OP_STOP:
        case OP_SHOW:
            rc = verify_mode_params(argc, argv, "LmoC");
            if (rc) {
                eprintf("system mode: option '-%c' is not "
                        "allowed/supported\n", rc);
                exit(EINVAL);
            }
            break;
        default:
            eprintf("option %d not supported in lld mode\n", op);
            exit(EINVAL);
            break;
        }
    }

    req->op = op;
    req->tid = tid;
    req->sid = sid;
    req->cid = cid;
    req->lun = lun;
    req->mode = mode;
    req->host_no = hostno;
    req->device_type = dev_type;
    req->ac_dir = ac_dir;
    req->force = force;

    concat_buf_init(&b);

    if (name)
        concat_printf(&b, "%s=%s", name, value);
    if (path)
        concat_printf(&b, "%spath=%s", concat_delim(&b, ","), path);

    if (req->device_type == TYPE_TAPE)
        concat_printf(&b, "%sbstype=%s", concat_delim(&b, ","),
                      "ssc");
    else if (bstype)
        concat_printf(&b, "%sbstype=%s", concat_delim(&b, ","),
                      bstype);
    if (bsopts)
        concat_printf(&b, "%sbsopts=%s", concat_delim(&b, ","),
                      bsopts);
    if (bsoflags)
        concat_printf(&b, "%sbsoflags=%s", concat_delim(&b, ","),
                      bsoflags);
    if (blocksize)
        concat_printf(&b, "%sblocksize=%s", concat_delim(&b, ","),
                      blocksize);
    if (targetname)
        concat_printf(&b, "%stargetname=%s", concat_delim(&b, ","),
                      targetname);
    if (address)
        concat_printf(&b, "%sinitiator-address=%s",
                      concat_delim(&b, ","), address);
    if (iqnname)
        concat_printf(&b, "%sinitiator-name=%s", concat_delim(&b, ","),
                      iqnname);
    if (user)
        concat_printf(&b, "%suser=%s", concat_delim(&b, ","),
                      user);
    if (password)
        concat_printf(&b, "%spassword=%s", concat_delim(&b, ","),
                      password);
    /* Trailing ',' makes parsing params in modules easier.. */
    if (targetOps)
        concat_printf(&b, "%stargetOps %s,", concat_delim(&b, ","),
                      targetOps);
    if (portalOps)
        concat_printf(&b, "%sportalOps %s,", concat_delim(&b, ","),
                      portalOps);

    if (b.err) {
        eprintf("BUFSIZE (%d bytes) isn't long enough\n", BUFSIZE);
        return EINVAL;
    }

    rc = concat_buf_finish(&b);
    if (rc) {
        eprintf("failed to create request, errno:%d\n", rc);
        exit(rc);
    }

    return ipc_mgmt_req(req, &b);
}