[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