diff options
Diffstat (limited to 'usr.sbin/iscsid/task.c')
-rw-r--r-- | usr.sbin/iscsid/task.c | 124 |
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); + } +} |