summaryrefslogtreecommitdiffstats
path: root/usr.sbin/iscsid/task.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/iscsid/task.c')
-rw-r--r--usr.sbin/iscsid/task.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/usr.sbin/iscsid/task.c b/usr.sbin/iscsid/task.c
new file mode 100644
index 00000000000..70a4c85534c
--- /dev/null
+++ b/usr.sbin/iscsid/task.c
@@ -0,0 +1,124 @@
+/* $OpenBSD: task.c,v 1.1 2010/09/24 09:43:19 claudio Exp $ */
+
+/*
+ * Copyright (c) 2009 Claudio Jeker <claudio@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <scsi/iscsi.h>
+
+#include <errno.h>
+#include <event.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include "iscsid.h"
+#include "log.h"
+
+/*
+ * Task handling, PDU are attached to tasks and task are scheduled accross
+ * all connections of a session.
+ */
+
+void
+task_init(struct task *t, struct session *s, int immediate, void *carg,
+ void (*c)(struct connection *, void *, struct pdu *))
+{
+ TAILQ_INIT(&t->sendq);
+ TAILQ_INIT(&t->recvq);
+ t->callback = c;
+ t->callarg = carg;
+ t->itt = s->itt++; /* XXX we could do better here */
+ t->cmdseqnum = s->cmdseqnum;
+ if (!immediate)
+ s->cmdseqnum++;
+}
+
+void
+task_cleanup(struct task *t, struct connection *c)
+{
+/* XXX THIS FEELS WRONG FOR NOW */
+ pdu_free_queue(&t->sendq);
+ pdu_free_queue(&t->recvq);
+ /* XXX need some state to know if queued or not */
+ TAILQ_REMOVE(&c->tasks, t, entry);
+}
+
+void
+task_pdu_add(struct task *t, struct pdu *p)
+{
+ struct iscsi_pdu *ipdu;
+
+ /* fixup the pdu by setting the itt and seqnum if needed */
+ ipdu = pdu_getbuf(p, NULL, PDU_HEADER);
+ ipdu->itt = ntohl(t->itt);
+ switch (ISCSI_PDU_OPCODE(ipdu->opcode)) {
+ case ISCSI_OP_I_NOP:
+ case ISCSI_OP_SCSI_REQUEST:
+ case ISCSI_OP_TASK_REQUEST:
+ case ISCSI_OP_LOGIN_REQUEST:
+ case ISCSI_OP_TEXT_REQUEST:
+ case ISCSI_OP_LOGOUT_REQUEST:
+ ipdu->cmdsn = ntohl(t->cmdseqnum);
+ break;
+ }
+
+ TAILQ_INSERT_TAIL(&t->sendq, p, entry);
+}
+
+void
+task_pdu_cb(struct connection *c, struct pdu *p)
+{
+ struct task *t;
+ struct iscsi_pdu *ipdu;
+ u_int32_t itt;
+
+ ipdu = pdu_getbuf(p, NULL, PDU_HEADER);
+ switch (ISCSI_PDU_OPCODE(ipdu->opcode)) {
+ case ISCSI_OP_T_NOP:
+ case ISCSI_OP_LOGIN_RESPONSE:
+ case ISCSI_OP_TEXT_RESPONSE:
+ case ISCSI_OP_LOGOUT_RESPONSE:
+ case ISCSI_OP_SCSI_RESPONSE:
+ case ISCSI_OP_R2T:
+ case ISCSI_OP_DATA_IN:
+ itt = ntohl(ipdu->itt);
+ c->expstatsn = ntohl(ipdu->cmdsn) + 1;
+
+ /* XXX for now search the task on the connection queue
+ later on this should be moved to a per session RB tree but
+ now I do the quick ugly thing. */
+ TAILQ_FOREACH(t, &c->tasks, entry) {
+ if (itt == t->itt)
+ break;
+ }
+ if (t)
+ t->callback(c, t->callarg, p);
+ else {
+ log_debug("no task for PDU found");
+ pdu_free(p);
+ }
+ break;
+ default:
+log_pdu(p, 1);
+ log_warnx("not handled yet. fix me");
+ pdu_free(p);
+ }
+}