task.c revision 1.3
1/* $OpenBSD: task.c,v 1.3 2010/09/25 16:20:06 sobrado Exp $ */ 2 3/* 4 * Copyright (c) 2009 Claudio Jeker <claudio@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18#include <sys/types.h> 19#include <sys/queue.h> 20#include <sys/socket.h> 21#include <sys/uio.h> 22 23#include <scsi/iscsi.h> 24 25#include <errno.h> 26#include <event.h> 27#include <stdio.h> 28#include <stdlib.h> 29#include <strings.h> 30#include <unistd.h> 31 32#include "iscsid.h" 33#include "log.h" 34 35/* 36 * Task handling, PDU are attached to tasks and task are scheduled across 37 * all connections of a session. 38 */ 39 40void 41task_init(struct task *t, struct session *s, int immediate, void *carg, 42 void (*c)(struct connection *, void *, struct pdu *)) 43{ 44 TAILQ_INIT(&t->sendq); 45 TAILQ_INIT(&t->recvq); 46 t->callback = c; 47 t->callarg = carg; 48 t->itt = s->itt++; /* XXX we could do better here */ 49 t->cmdseqnum = s->cmdseqnum; 50 if (!immediate) 51 s->cmdseqnum++; 52} 53 54void 55task_cleanup(struct task *t, struct connection *c) 56{ 57/* XXX THIS FEELS WRONG FOR NOW */ 58 pdu_free_queue(&t->sendq); 59 pdu_free_queue(&t->recvq); 60 /* XXX need some state to know if queued or not */ 61 TAILQ_REMOVE(&c->tasks, t, entry); 62} 63 64void 65task_pdu_add(struct task *t, struct pdu *p) 66{ 67 struct iscsi_pdu *ipdu; 68 69 /* fixup the pdu by setting the itt and seqnum if needed */ 70 ipdu = pdu_getbuf(p, NULL, PDU_HEADER); 71 ipdu->itt = ntohl(t->itt); 72 switch (ISCSI_PDU_OPCODE(ipdu->opcode)) { 73 case ISCSI_OP_I_NOP: 74 case ISCSI_OP_SCSI_REQUEST: 75 case ISCSI_OP_TASK_REQUEST: 76 case ISCSI_OP_LOGIN_REQUEST: 77 case ISCSI_OP_TEXT_REQUEST: 78 case ISCSI_OP_LOGOUT_REQUEST: 79 ipdu->cmdsn = ntohl(t->cmdseqnum); 80 break; 81 } 82 83 TAILQ_INSERT_TAIL(&t->sendq, p, entry); 84} 85 86void 87task_pdu_cb(struct connection *c, struct pdu *p) 88{ 89 struct task *t; 90 struct iscsi_pdu *ipdu; 91 u_int32_t itt; 92 93 ipdu = pdu_getbuf(p, NULL, PDU_HEADER); 94 switch (ISCSI_PDU_OPCODE(ipdu->opcode)) { 95 case ISCSI_OP_T_NOP: 96 case ISCSI_OP_LOGIN_RESPONSE: 97 case ISCSI_OP_TEXT_RESPONSE: 98 case ISCSI_OP_LOGOUT_RESPONSE: 99 case ISCSI_OP_SCSI_RESPONSE: 100 case ISCSI_OP_R2T: 101 case ISCSI_OP_DATA_IN: 102 itt = ntohl(ipdu->itt); 103 c->expstatsn = ntohl(ipdu->cmdsn) + 1; 104 105 /* XXX for now search the task on the connection queue 106 later on this should be moved to a per session RB tree but 107 now I do the quick ugly thing. */ 108 TAILQ_FOREACH(t, &c->tasks, entry) { 109 if (itt == t->itt) 110 break; 111 } 112 if (t) 113 t->callback(c, t->callarg, p); 114 else { 115 log_debug("no task for PDU found"); 116 pdu_free(p); 117 } 118 break; 119 default: 120log_pdu(p, 1); 121 log_warnx("not handled yet. fix me"); 122 pdu_free(p); 123 } 124} 125