[BACK]Return to task.c CVS log [TXT][DIR] Up to [local] / src / usr.sbin / iscsid

File: [local] / src / usr.sbin / iscsid / task.c (download)

Revision 1.10, Sat May 10 11:28:02 2014 UTC (10 years ago) by claudio
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, OPENBSD_7_3_BASE, OPENBSD_7_3, OPENBSD_7_2_BASE, OPENBSD_7_2, OPENBSD_7_1_BASE, OPENBSD_7_1, OPENBSD_7_0_BASE, OPENBSD_7_0, OPENBSD_6_9_BASE, OPENBSD_6_9, OPENBSD_6_8_BASE, OPENBSD_6_8, OPENBSD_6_7_BASE, OPENBSD_6_7, OPENBSD_6_6_BASE, OPENBSD_6_6, OPENBSD_6_5_BASE, OPENBSD_6_5, OPENBSD_6_4_BASE, OPENBSD_6_4, OPENBSD_6_3_BASE, OPENBSD_6_3, OPENBSD_6_2_BASE, OPENBSD_6_2, OPENBSD_6_1_BASE, OPENBSD_6_1, OPENBSD_6_0_BASE, OPENBSD_6_0, OPENBSD_5_9_BASE, OPENBSD_5_9, OPENBSD_5_8_BASE, OPENBSD_5_8, OPENBSD_5_7_BASE, OPENBSD_5_7, OPENBSD_5_6_BASE, OPENBSD_5_6, HEAD
Changes since 1.9: +3 -5 lines

Move the task cleanup from the task fail callback to taskq_cleanup.
This makes the one failure callback a lot simpler.

/*	$OpenBSD: task.c,v 1.10 2014/05/10 11:28:02 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 across
 * 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 *),
    void (*f)(void *))
{
	TAILQ_INIT(&t->sendq);
	TAILQ_INIT(&t->recvq);
	t->callback = c;
	t->failback = f;
	t->callarg = carg;
	/* skip reserved and maybe bad ITT values */
	if (s->itt == 0xffffffff || s->itt == 0)
		s->itt = 1;
	t->itt = s->itt++; /* XXX we could do better here */
	t->cmdseqnum = s->cmdseqnum;
	if (!immediate)
		s->cmdseqnum++;
}

void
taskq_cleanup(struct taskq *tq)
{
	struct task *t;

	while ((t = TAILQ_FIRST(tq))) {
		TAILQ_REMOVE(tq, t, entry);
		if (t->failback)
			t->failback(t->callarg);
		conn_task_cleanup(NULL, t);
		free(t);
	}
}

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:
		itt = ntohl(ipdu->itt);
		if (itt == 0xffffffff) {
			/* target issued a ping, must answer back immediately */
			c->expstatsn = ntohl(ipdu->cmdsn) + 1;
			initiator_nop_in_imm(c, p);
			break;
		}
		/* FALLTHROUGH */
	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");
			log_pdu(p, 1);
			pdu_free(p);
		}
		break;
	default:
		log_warnx("not handled yet. fix me");
		log_pdu(p, 1);
		pdu_free(p);
	}
}