mtask.buf is split into req_buf and rsp_buf; Request buffer is allocated dynamically, response buffer's speculative static alloc is meanwhile retained; Some structuring of mtask handler flow. Signed-off-by: Alexander Nezhinsky <alexandern@xxxxxxxxxxxx> --- usr/mgmt.c | 217 +++++++++++++++++++++++++++++++++++++----------------------- 1 files changed, 133 insertions(+), 84 deletions(-) diff --git a/usr/mgmt.c b/usr/mgmt.c index 26a360d..4397850 100644 --- a/usr/mgmt.c +++ b/usr/mgmt.c @@ -51,16 +51,23 @@ struct mgmt_task { enum mgmt_task_state mtask_state; int retry; int done; - char *buf; - int bsize; struct tgtadm_req req; + char *req_buf; + int req_bsize; struct tgtadm_rsp rsp; + char *rsp_buf; + int rsp_bsize; /* struct tgt_work work; */ }; +#define MAX_MGT_BUFSIZE (8*1024) /* limit incoming mgmt request data size */ + static int ipc_fd; char mgmt_path[256]; +static struct mgmt_task *mtask_alloc(void); +static void mtask_free(struct mgmt_task *mtask); + static void set_show_results(struct tgtadm_rsp *rsp, int *err) { if (*err < 0) @@ -80,7 +87,7 @@ static int target_mgmt(int lld_no, struct mgmt_task *mtask) switch (req->op) { case OP_NEW: - err = tgt_target_create(lld_no, req->tid, mtask->buf); + err = tgt_target_create(lld_no, req->tid, mtask->req_buf); break; case OP_DELETE: err = tgt_target_destroy(lld_no, req->tid, req->force); @@ -92,11 +99,11 @@ static int target_mgmt(int lld_no, struct mgmt_task *mtask) else { char *p; - p = strstr(mtask->buf, "initiator-address="); + p = strstr(mtask->req_buf, "initiator-address="); if (p) err = acl_add(req->tid, p + strlen("initiator-address=")); - p = strstr(mtask->buf, "initiator-name="); + p = strstr(mtask->req_buf, "initiator-name="); if (p) err = iqn_acl_add(req->tid, p + strlen("initiator-name=")); } @@ -107,12 +114,12 @@ static int target_mgmt(int lld_no, struct mgmt_task *mtask) else { char *p; - p = strstr(mtask->buf, "initiator-address="); + p = strstr(mtask->req_buf, "initiator-address="); if (p) { err = acl_del(req->tid, p + strlen("initiator-address=")); } - p = strstr(mtask->buf, "initiator-name="); + p = strstr(mtask->req_buf, "initiator-name="); if (p) { err = iqn_acl_del(req->tid, p + strlen("initiator-name=")); } @@ -123,29 +130,29 @@ static int target_mgmt(int lld_no, struct mgmt_task *mtask) char *p; err = TGTADM_UNSUPPORTED_OPERATION; - p = strchr(mtask->buf, '='); + p = strchr(mtask->req_buf, '='); if (!p) break; *p++ = '\0'; - if (!strcmp(mtask->buf, "state")) + if (!strcmp(mtask->req_buf, "state")) err = tgt_set_target_state(req->tid, p); else if (tgt_drivers[lld_no]->update) err = tgt_drivers[lld_no]->update(req->mode, req->op, req->tid, req->sid, req->lun, - req->cid, mtask->buf); + req->cid, mtask->req_buf); break; } case OP_SHOW: if (req->tid < 0) { retry: - err = tgt_target_show_all(mtask->buf, mtask->bsize); - if (err == mtask->bsize) { + err = tgt_target_show_all(mtask->rsp_buf, mtask->rsp_bsize); + if (err == mtask->rsp_bsize) { char *p; - mtask->bsize <<= 1; - p = realloc(mtask->buf, mtask->bsize); + mtask->rsp_bsize <<= 1; + p = realloc(mtask->rsp_buf, mtask->rsp_bsize); if (p) { - mtask->buf = p; + mtask->rsp_buf = p; goto retry; } else { eprintf("out of memory\n"); @@ -157,7 +164,7 @@ static int target_mgmt(int lld_no, struct mgmt_task *mtask) req->tid, req->sid, req->cid, req->lun, - mtask->buf, mtask->bsize); + mtask->rsp_buf, mtask->rsp_bsize); break; default: break; @@ -184,18 +191,18 @@ static int portal_mgmt(int lld_no, struct mgmt_task *mtask, err = tgt_drivers[lld_no]->show(req->mode, req->tid, req->sid, req->cid, req->lun, - mtask->buf, - mtask->bsize); + mtask->rsp_buf, + mtask->rsp_bsize); set_show_results(rsp, &err); return err; } break; case OP_NEW: - err = tgt_portal_create(lld_no, mtask->buf); + err = tgt_portal_create(lld_no, mtask->req_buf); break; case OP_DELETE: - err = tgt_portal_destroy(lld_no, mtask->buf); + err = tgt_portal_destroy(lld_no, mtask->req_buf); break; default: break; @@ -245,7 +252,7 @@ static int account_mgmt(int lld_no, struct mgmt_task *mtask) case OP_DELETE: case OP_BIND: case OP_UNBIND: - user = strstr(mtask->buf, "user="); + user = strstr(mtask->req_buf, "user="); if (!user) goto out; user += 5; @@ -269,13 +276,13 @@ static int account_mgmt(int lld_no, struct mgmt_task *mtask) break; case OP_SHOW: retry: - err = account_show(mtask->buf, mtask->bsize); - if (err == mtask->bsize) { + err = account_show(mtask->rsp_buf, mtask->rsp_bsize); + if (err == mtask->rsp_bsize) { char *p; - mtask->bsize <<= 1; - p = realloc(mtask->buf, mtask->bsize); + mtask->rsp_bsize <<= 1; + p = realloc(mtask->rsp_buf, mtask->rsp_bsize); if (p) { - mtask->buf = p; + mtask->rsp_buf = p; goto retry; } else err = TGTADM_NOMEM; @@ -298,15 +305,15 @@ static int sys_mgmt(int lld_no, struct mgmt_task *mtask) { struct tgtadm_req *req = &mtask->req; struct tgtadm_rsp *rsp = &mtask->rsp; - int err = TGTADM_INVALID_REQUEST, len = mtask->bsize; + int err = TGTADM_INVALID_REQUEST; switch (req->op) { case OP_UPDATE: - if (!strncmp(mtask->buf, "debug=", 6)) { - if (!strncmp(mtask->buf+6, "on", 2)) { + if (!strncmp(mtask->req_buf, "debug=", 6)) { + if (!strncmp(mtask->req_buf+6, "on", 2)) { is_debug = 1; err = 0; - } else if (!strncmp(mtask->buf+6, "off", 3)) { + } else if (!strncmp(mtask->req_buf+6, "off", 3)) { is_debug = 0; err = 0; } @@ -316,18 +323,19 @@ static int sys_mgmt(int lld_no, struct mgmt_task *mtask) err = tgt_drivers[lld_no]->update(req->mode, req->op, req->tid, req->sid, req->lun, - req->cid, mtask->buf); + req->cid, mtask->req_buf); rsp->err = err; rsp->len = sizeof(*rsp); break; case OP_SHOW: - err = system_show(req->mode, mtask->buf, len); + err = system_show(req->mode, mtask->rsp_buf, mtask->rsp_bsize); if (err >= 0 && tgt_drivers[lld_no]->show) { err += tgt_drivers[lld_no]->show(req->mode, req->tid, req->sid, req->cid, req->lun, - mtask->buf + err, len - err); + mtask->rsp_buf + err, + mtask->rsp_bsize - err); } set_show_results(rsp, &err); break; @@ -357,8 +365,8 @@ static int connection_mgmt(int lld_no, struct mgmt_task *mtask, err = tgt_drivers[lld_no]->show(req->mode, req->tid, req->sid, req->cid, req->lun, - mtask->buf, - mtask->bsize); + mtask->rsp_buf, + mtask->rsp_bsize); set_show_results(rsp, &err); return err; } @@ -368,7 +376,7 @@ static int connection_mgmt(int lld_no, struct mgmt_task *mtask, err = tgt_drivers[lld_no]->update(req->mode, req->op, req->tid, req->sid, req->lun, - req->cid, mtask->buf); + req->cid, mtask->req_buf); rsp->err = err; rsp->len = sizeof(*rsp); break; @@ -377,11 +385,12 @@ static int connection_mgmt(int lld_no, struct mgmt_task *mtask, return err; } -static int tgt_mgmt(struct mgmt_task *mtask) +static int mtask_execute(struct mgmt_task *mtask) { struct tgtadm_req *req = &mtask->req; struct tgtadm_rsp *rsp = &mtask->rsp; - int lld_no, err = TGTADM_INVALID_REQUEST, len = mtask->bsize; + int lld_no, err = TGTADM_INVALID_REQUEST; + int len; if (!strlen(req->lld)) lld_no = 0; @@ -401,7 +410,7 @@ static int tgt_mgmt(struct mgmt_task *mtask) 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->buf, getpid()); + req->tid, req->sid, req->lun, mtask->req_buf, getpid()); switch (req->mode) { case MODE_SYSTEM: @@ -414,7 +423,7 @@ static int tgt_mgmt(struct mgmt_task *mtask) err = portal_mgmt(lld_no, mtask, req, rsp); break; case MODE_DEVICE: - err = device_mgmt(lld_no, req, mtask->buf, rsp, &len); + err = device_mgmt(lld_no, req, mtask->req_buf, rsp, &len); break; case MODE_ACCOUNT: err = account_mgmt(lld_no, mtask); @@ -427,7 +436,8 @@ static int tgt_mgmt(struct mgmt_task *mtask) err = tgt_drivers[lld_no]->show(req->mode, req->tid, req->sid, req->cid, req->lun, - mtask->buf, len); + mtask->rsp_buf, + mtask->rsp_bsize); set_show_results(rsp, &err); } else { @@ -472,6 +482,59 @@ static int ipc_perm(int fd) return 0; } +static struct mgmt_task *mtask_alloc(void) +{ + struct mgmt_task *mtask; + + mtask = zalloc(sizeof(*mtask)); + if (!mtask) { + eprintf("can't allocate mtask\n"); + return NULL; + } + mtask->mtask_state = MTASK_STATE_HDR_RECV; + + dprintf("mtask:%p\n", mtask); + return mtask; +} + +static void mtask_free(struct mgmt_task *mtask) +{ + dprintf("mtask:%p\n", mtask); + + if (mtask->req_buf) + free(mtask->req_buf); + if (mtask->rsp_buf) + free(mtask->rsp_buf); + free(mtask); +} + +static int mtask_received(struct mgmt_task *mtask, int fd) +{ + int err; + + mtask->rsp_buf = zalloc(MAX_MGT_BUFSIZE); + if (!mtask->rsp_buf) { + eprintf("failed to allocate response data buffer\n"); + return -ENOMEM; + } + mtask->rsp_bsize = MAX_MGT_BUFSIZE; + + err = mtask_execute(mtask); + if (err) { + eprintf("mgmt task processing failed\n"); + return err; + } + + mtask->mtask_state = MTASK_STATE_RSP_SEND; + mtask->done = 0; + err = tgt_event_modify(fd, EPOLLOUT); + if (err) { + eprintf("failed to modify mgmt task event out\n"); + return err; + } + return 0; +} + static void mtask_handler(int fd, int events, void *data) { int err, len; @@ -487,24 +550,28 @@ static void mtask_handler(int fd, int events, void *data) if (err > 0) { mtask->done += err; if (mtask->done == sizeof(*req)) { - if (req->len == sizeof(*req)) { - tgt_mgmt(mtask); - mtask->mtask_state = - MTASK_STATE_RSP_SEND; - if (tgt_event_modify(fd, EPOLLOUT)) - eprintf("failed to modify\n"); - - mtask->done = 0; + mtask->req_bsize = req->len - sizeof(*req); + if (!mtask->req_bsize) { + err = mtask_received(mtask, fd); + if (err) + goto out; } else { /* the pdu exists */ - mtask->done = 0; - mtask->mtask_state = - MTASK_STATE_PDU_RECV; - - if (mtask->bsize < req->len) { - eprintf("FIXME: %d\n", req->len); + if (mtask->req_bsize > MAX_MGT_BUFSIZE) { + eprintf("mtask buffer len: %d too large\n", + mtask->req_bsize); + mtask->req_bsize = 0; + goto out; + } + mtask->req_buf = zalloc(mtask->req_bsize); + if (!mtask->req_buf) { + eprintf("can't allocate mtask buffer len: %d\n", + mtask->req_bsize); + mtask->req_bsize = 0; goto out; } + mtask->mtask_state = MTASK_STATE_PDU_RECV; + mtask->done = 0; } } } else @@ -513,17 +580,14 @@ static void mtask_handler(int fd, int events, void *data) break; case MTASK_STATE_PDU_RECV: - len = req->len - (sizeof(*req) + mtask->done); - err = read(fd, mtask->buf + mtask->done, len); + len = mtask->req_bsize - mtask->done; + err = read(fd, mtask->req_buf + mtask->done, len); if (err > 0) { mtask->done += err; - if (mtask->done == req->len - (sizeof(*req))) { - tgt_mgmt(mtask); - mtask->mtask_state = MTASK_STATE_RSP_SEND; - if (tgt_event_modify(fd, EPOLLOUT)) - eprintf("failed to modify\n"); - - mtask->done = 0; + if (mtask->done == mtask->req_bsize) { + err = mtask_received(mtask, fd); + if (err) + goto out; } } else if (errno != EAGAIN) @@ -535,7 +599,7 @@ static void mtask_handler(int fd, int events, void *data) p = (char *)rsp + mtask->done; len = sizeof(*rsp) - mtask->done; } else { - p = mtask->buf + (mtask->done - sizeof(*rsp)); + p = mtask->rsp_buf + (mtask->done - sizeof(*rsp)); len = rsp->len - mtask->done; } @@ -562,13 +626,10 @@ static void mtask_handler(int fd, int events, void *data) return; out: tgt_event_del(fd); - free(mtask->buf); - free(mtask); close(fd); + mtask_free(mtask); } -#define BUFSIZE 1024 - static void mgmt_event_handler(int accept_fd, int events, void *data) { int fd, err; @@ -592,26 +653,14 @@ static void mgmt_event_handler(int accept_fd, int events, void *data) goto out; } - mtask = zalloc(sizeof(*mtask)); - if (!mtask) { - eprintf("can't allocate mtask\n"); - goto out; - } - - mtask->buf = zalloc(BUFSIZE); - if (!mtask->buf) { - eprintf("can't allocate mtask buffer\n"); - free(mtask); + mtask = mtask_alloc(); + if (!mtask) goto out; - } - mtask->bsize = BUFSIZE; - mtask->mtask_state = MTASK_STATE_HDR_RECV; err = tgt_event_add(fd, EPOLLIN, mtask_handler, mtask); if (err) { eprintf("failed to add a socket to epoll %d\n", fd); - free(mtask->buf); - free(mtask); + mtask_free(mtask); goto out; } -- 1.7.3.2 -- To unsubscribe from this list: send the line "unsubscribe stgt" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html