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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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); }