[stgt] [PATCH 3/5 RESEND] mgmt and concat_buf: using concat_buf in mgmt.c
Alexander Nezhinsky
alexandern at mellanox.com
Wed Feb 1 14:45:55 CET 2012
Using concat_buf in mgmt.c.
The changes influence mainly the SHOW commands (those producing some
output). Upon concat_buf finalization the dynamically alloctaed buffer
is stored directly to the mtask response descriptor. No need to worry
about memory re-allocation anymore, it is taken care of by concat_buf
mechanism. Concatenated buffer descriptor is stored within struct concat_buf,
and is used transparently to write to a file through concat_write().
Using concat_buf api highlights a problem pre-existing in the mgmt code:
a mix of the regular linux error codes (like ENOMEM) and enum tgtadm_errno
(like TGTADM_NOMEM). Sometimes positive values returned correspond to
tgtadm_errno, sometimes to the number of bytes written.
Use enum tgtadm_errno explicitly in all related functions.
A new function errno2tgtadm() converts regular errno to tgtadm_errno.
A separate patch will address this problem in a more fundamental manner.
Signed-off-by: Alexander Nezhinsky <alexandern at mellanox.com>
---
usr/mgmt.c | 498 ++++++++++++++++++++++++++++++++----------------------------
1 files changed, 266 insertions(+), 232 deletions(-)
diff --git a/usr/mgmt.c b/usr/mgmt.c
index 26a360d..8b62d13 100644
--- a/usr/mgmt.c
+++ b/usr/mgmt.c
@@ -44,208 +44,229 @@
enum mgmt_task_state {
MTASK_STATE_HDR_RECV,
MTASK_STATE_PDU_RECV,
- MTASK_STATE_RSP_SEND,
+ MTASK_STATE_HDR_SEND,
+ MTASK_STATE_PDU_SEND,
};
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;
+ struct concat_buf rsp_concat;
/* 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 void set_show_results(struct tgtadm_rsp *rsp, int *err)
+static struct mgmt_task *mtask_alloc(void);
+static void mtask_free(struct mgmt_task *mtask);
+
+static tgtadm_err errno2tgtadm(int err)
{
- if (*err < 0)
- rsp->err = -*err;
- else {
- rsp->err = 0;
- rsp->len = *err + sizeof(*rsp);
- *err = 0;
+ if (err >= 0)
+ return TGTADM_SUCCESS;
+ else if (err == -ENOMEM)
+ return TGTADM_NOMEM;
+ else
+ return TGTADM_UNKNOWN_ERR;
+}
+
+static void set_mtask_result(struct mgmt_task *mtask, tgtadm_err adm_err)
+{
+ if (adm_err == TGTADM_SUCCESS && mtask->rsp_concat.err)
+ adm_err = errno2tgtadm(mtask->rsp_concat.err);
+
+ mtask->rsp.len = sizeof(mtask->rsp);
+ if (adm_err == TGTADM_SUCCESS) {
+ mtask->rsp.len += mtask->rsp_concat.size;
+ mtask->rsp.err = 0;
}
+ else
+ mtask->rsp.err = (uint32_t)adm_err;
}
-static int target_mgmt(int lld_no, struct mgmt_task *mtask)
+static tgtadm_err target_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;
+ tgtadm_err adm_err = TGTADM_INVALID_REQUEST;
switch (req->op) {
case OP_NEW:
- err = tgt_target_create(lld_no, req->tid, mtask->buf);
+ adm_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);
+ adm_err = tgt_target_destroy(lld_no, req->tid, req->force);
break;
case OP_BIND:
/* FIXME */
if (req->len == sizeof(*req))
- err = tgt_bind_host_to_target(req->tid, req->host_no);
+ adm_err = tgt_bind_host_to_target(req->tid, req->host_no);
else {
char *p;
- p = strstr(mtask->buf, "initiator-address=");
- if (p)
- err = acl_add(req->tid, p + strlen("initiator-address="));
+ 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->buf, "initiator-name=");
- if (p)
- err = iqn_acl_add(req->tid, p + strlen("initiator-name="));
+ 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))
- err = tgt_unbind_host_to_target(req->tid, req->host_no);
+ adm_err = tgt_unbind_host_to_target(req->tid, req->host_no);
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 += 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->buf, "initiator-name=");
+ p = strstr(mtask->req_buf, "initiator-name=");
if (p) {
- err = iqn_acl_del(req->tid, p + strlen("initiator-name="));
+ p += strlen("initiator-name=");
+ adm_err = iqn_acl_del(req->tid, p + strlen("initiator-name="));
+ if (adm_err != TGTADM_SUCCESS) {
+ eprintf("Failed to unbind by name: %s\n", p);
+ break;
+ }
}
}
break;
case OP_UPDATE:
{
char *p;
- err = TGTADM_UNSUPPORTED_OPERATION;
+ adm_err = TGTADM_UNSUPPORTED_OPERATION;
- p = strchr(mtask->buf, '=');
+ p = strchr(mtask->req_buf, '=');
if (!p)
break;
*p++ = '\0';
- if (!strcmp(mtask->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,
+ 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->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) {
- char *p;
- mtask->bsize <<= 1;
- p = realloc(mtask->buf, mtask->bsize);
- if (p) {
- mtask->buf = p;
- goto retry;
- } else {
- eprintf("out of memory\n");
- err = TGTADM_NOMEM;
- }
- }
- } else if (tgt_drivers[lld_no]->show)
- err = tgt_drivers[lld_no]->show(req->mode,
+ {
+ 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->buf, mtask->bsize);
+ &mtask->rsp_concat);
+ concat_buf_finish(&mtask->rsp_concat);
break;
+ }
default:
break;
}
- if (req->op == OP_SHOW)
- set_show_results(rsp, &err);
- else {
- rsp->err = err;
- rsp->len = sizeof(*rsp);
- }
- return err;
+ set_mtask_result(mtask, adm_err);
+ return adm_err;
}
-static int portal_mgmt(int lld_no, struct mgmt_task *mtask,
- struct tgtadm_req *req,
- struct tgtadm_rsp *rsp)
+static tgtadm_err portal_mgmt(int lld_no, struct mgmt_task *mtask)
{
- int err = TGTADM_INVALID_REQUEST;
+ 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) {
- err = tgt_drivers[lld_no]->show(req->mode,
+ concat_buf_init(&mtask->rsp_concat);
+ adm_err = tgt_drivers[lld_no]->show(req->mode,
req->tid, req->sid,
req->cid, req->lun,
- mtask->buf,
- mtask->bsize);
-
- set_show_results(rsp, &err);
- return err;
+ &mtask->rsp_concat);
+ concat_buf_finish(&mtask->rsp_concat);
}
break;
case OP_NEW:
- err = tgt_portal_create(lld_no, mtask->buf);
+ adm_err = tgt_portal_create(lld_no, mtask->req_buf);
break;
case OP_DELETE:
- err = tgt_portal_destroy(lld_no, mtask->buf);
+ adm_err = tgt_portal_destroy(lld_no, mtask->req_buf);
break;
default:
break;
}
- rsp->err = err;
- rsp->len = sizeof(*rsp);
-
- return err;
+ set_mtask_result(mtask, adm_err);
+ return adm_err;
}
-static int device_mgmt(int lld_no, struct tgtadm_req *req, char *params,
- struct tgtadm_rsp *rsp, int *rlen)
+static tgtadm_err device_mgmt(int lld_no, struct mgmt_task *mtask)
{
- int err = TGTADM_UNSUPPORTED_OPERATION;
+ struct tgtadm_req *req = &mtask->req;
+ char *params = mtask->req_buf;
+ tgtadm_err adm_err = TGTADM_UNSUPPORTED_OPERATION;
switch (req->op) {
case OP_NEW:
- err = tgt_device_create(req->tid, req->device_type, req->lun,
- params, 1);
+ 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:
- err = tgt_device_destroy(req->tid, req->lun, 0);
+ adm_err = tgt_device_destroy(req->tid, req->lun, 0);
break;
case OP_UPDATE:
- err = tgt_device_update(req->tid, req->lun, params);
+ adm_err = tgt_device_update(req->tid, req->lun, params);
break;
default:
break;
}
- rsp->err = err;
- rsp->len = sizeof(*rsp);
-
- return err;
+ set_mtask_result(mtask, adm_err);
+ return adm_err;
}
-static int account_mgmt(int lld_no, struct mgmt_task *mtask)
+static tgtadm_err account_mgmt(int lld_no, struct mgmt_task *mtask)
{
struct tgtadm_req *req = &mtask->req;
- struct tgtadm_rsp *rsp = &mtask->rsp;
- int err = TGTADM_UNSUPPORTED_OPERATION;
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->buf, "user=");
+ user = strstr(mtask->req_buf, "user=");
if (!user)
goto out;
user += 5;
@@ -258,130 +279,109 @@ static int account_mgmt(int lld_no, struct mgmt_task *mtask)
*password++ = '\0';
password += strlen("password=");
- err = account_add(user, password);
+ adm_err = account_add(user, password);
} else {
if (req->op == OP_DELETE) {
- err = account_del(user);
+ adm_err = account_del(user);
} else
- err = account_ctl(req->tid, req->ac_dir,
- user, req->op == OP_BIND);
+ adm_err = account_ctl(req->tid, req->ac_dir,
+ user, req->op == OP_BIND);
}
break;
case OP_SHOW:
- retry:
- err = account_show(mtask->buf, mtask->bsize);
- if (err == mtask->bsize) {
- char *p;
- mtask->bsize <<= 1;
- p = realloc(mtask->buf, mtask->bsize);
- if (p) {
- mtask->buf = p;
- goto retry;
- } else
- err = TGTADM_NOMEM;
- }
+ concat_buf_init(&mtask->rsp_concat);
+ adm_err = account_show(&mtask->rsp_concat);
+ concat_buf_finish(&mtask->rsp_concat);
break;
default:
break;
}
out:
- if (req->op == OP_SHOW)
- set_show_results(rsp, &err);
- else {
- rsp->err = err;
- rsp->len = sizeof(*rsp);
- }
- return err;
+ set_mtask_result(mtask, adm_err);
+ return adm_err;
}
-static int sys_mgmt(int lld_no, struct mgmt_task *mtask)
+static tgtadm_err 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;
+ tgtadm_err adm_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)) {
+ adm_err = TGTADM_SUCCESS;
+ } else if (!strncmp(mtask->req_buf+6, "off", 3)) {
is_debug = 0;
- err = 0;
+ adm_err = TGTADM_SUCCESS;
}
- if (!err)
+ if (adm_err == TGTADM_SUCCESS)
eprintf("set debug to: %d\n", is_debug);
} else if (tgt_drivers[lld_no]->update)
- err = tgt_drivers[lld_no]->update(req->mode, req->op,
+ adm_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);
- 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);
- }
- set_show_results(rsp, &err);
+ 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_DELETE:
if (is_system_inactive())
- err = 0;
-
- rsp->err = err;
- rsp->len = sizeof(*rsp);
+ adm_err = TGTADM_SUCCESS;
break;
default:
break;
}
- return err;
+ set_mtask_result(mtask, adm_err);
+ return adm_err;
}
-static int connection_mgmt(int lld_no, struct mgmt_task *mtask,
- struct tgtadm_req *req,
- struct tgtadm_rsp *rsp)
+static tgtadm_err connection_mgmt(int lld_no, struct mgmt_task *mtask)
{
- int err = TGTADM_INVALID_REQUEST;
+ 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) {
- err = tgt_drivers[lld_no]->show(req->mode,
- req->tid, req->sid,
- req->cid, req->lun,
- mtask->buf,
- mtask->bsize);
- set_show_results(rsp, &err);
- return err;
+ 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;
}
break;
default:
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);
- rsp->err = err;
- rsp->len = sizeof(*rsp);
+ adm_err = tgt_drivers[lld_no]->update(req->mode, req->op,
+ req->tid,
+ req->sid, req->lun,
+ req->cid, mtask->req_buf);
break;
}
- return err;
+ set_mtask_result(mtask, adm_err);
+ return adm_err;
}
-static int tgt_mgmt(struct mgmt_task *mtask)
+static tgtadm_err 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;
+ tgtadm_err adm_err = TGTADM_INVALID_REQUEST;
if (!strlen(req->lld))
lld_no = 0;
@@ -393,51 +393,48 @@ static int tgt_mgmt(struct mgmt_task *mtask)
else
eprintf("driver %s is in state: %s\n",
req->lld, driver_state_name(tgt_drivers[lld_no]));
- rsp->err = TGTADM_NO_DRIVER;
- rsp->len = sizeof(*rsp);
+ set_mtask_result(mtask, TGTADM_NO_DRIVER);
return 0;
}
}
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:
- err = sys_mgmt(lld_no, mtask);
+ adm_err = sys_mgmt(lld_no, mtask);
break;
case MODE_TARGET:
- err = target_mgmt(lld_no, mtask);
+ adm_err = target_mgmt(lld_no, mtask);
break;
case MODE_PORTAL:
- err = portal_mgmt(lld_no, mtask, req, rsp);
+ adm_err = portal_mgmt(lld_no, mtask);
break;
case MODE_DEVICE:
- err = device_mgmt(lld_no, req, mtask->buf, rsp, &len);
+ adm_err = device_mgmt(lld_no, mtask);
break;
case MODE_ACCOUNT:
- err = account_mgmt(lld_no, mtask);
+ adm_err = account_mgmt(lld_no, mtask);
break;
case MODE_CONNECTION:
- err = connection_mgmt(lld_no, mtask, req, rsp);
+ adm_err = connection_mgmt(lld_no, mtask);
break;
default:
if (req->op == OP_SHOW && tgt_drivers[lld_no]->show) {
- err = tgt_drivers[lld_no]->show(req->mode,
- req->tid, req->sid,
- req->cid, req->lun,
- mtask->buf, len);
-
- set_show_results(rsp, &err);
- } else {
- rsp->err = err;
- rsp->len = sizeof(*rsp);
+ 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;
}
- return err;
+ set_mtask_result(mtask, adm_err);
+ return adm_err;
}
static int ipc_accept(int accept_fd)
@@ -472,7 +469,49 @@ static int ipc_perm(int fd)
return 0;
}
-static void mtask_handler(int fd, int events, void *data)
+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);
+ concat_buf_release(&mtask->rsp_concat);
+ free(mtask);
+}
+
+static int mtask_received(struct mgmt_task *mtask, int fd)
+{
+ tgtadm_err adm_err;
+ int err;
+
+ adm_err = mtask_execute(mtask);
+ if (adm_err != TGTADM_SUCCESS)
+ eprintf("mgmt task processing failed, err: %d\n", adm_err);
+
+ mtask->mtask_state = MTASK_STATE_HDR_SEND;
+ mtask->done = 0;
+ err = tgt_event_modify(fd, EPOLLOUT);
+ if (err)
+ eprintf("failed to modify mgmt task event out\n");
+ return err;
+}
+
+static void mtask_recv_send_handler(int fd, int events, void *data)
{
int err, len;
char *p;
@@ -487,24 +526,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,47 +556,53 @@ 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)
goto out;
break;
- case MTASK_STATE_RSP_SEND:
- if (mtask->done < sizeof(*rsp)) {
- p = (char *)rsp + mtask->done;
- len = sizeof(*rsp) - mtask->done;
- } else {
- p = mtask->buf + (mtask->done - sizeof(*rsp));
- len = rsp->len - mtask->done;
- }
+ case MTASK_STATE_HDR_SEND:
+ p = (char *)rsp + mtask->done;
+ len = sizeof(*rsp) - mtask->done;
err = write(fd, p, len);
if (err > 0) {
mtask->done += err;
+ if (mtask->done == sizeof(*rsp)) {
+ if (rsp->len == sizeof(*rsp))
+ goto out;
+ mtask->done = 0;
+ mtask->mtask_state = MTASK_STATE_PDU_SEND;
+ }
+ } else
+ if (errno != EAGAIN)
+ goto out;
+ break;
+ case MTASK_STATE_PDU_SEND:
+ err = concat_write(&mtask->rsp_concat, fd, mtask->done);
+ if (err > 0) {
+ mtask->done += err;
if (mtask->done == rsp->len) {
if (req->mode == MODE_SYSTEM &&
req->op == OP_DELETE &&
!rsp->err)
system_active = 0;
-
goto out;
}
} else
if (errno != EAGAIN)
goto out;
+
break;
default:
eprintf("unknown state %d\n", mtask->mtask_state);
@@ -562,13 +611,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 +638,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);
+ err = tgt_event_add(fd, EPOLLIN, mtask_recv_send_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.1
--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
More information about the stgt
mailing list