diff options
Diffstat (limited to 'usr.sbin/iscsid/session.c')
-rw-r--r-- | usr.sbin/iscsid/session.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/usr.sbin/iscsid/session.c b/usr.sbin/iscsid/session.c new file mode 100644 index 00000000000..5527f9a2668 --- /dev/null +++ b/usr.sbin/iscsid/session.c @@ -0,0 +1,140 @@ +/* $OpenBSD: session.c,v 1.1 2011/04/05 18:26:19 claudio Exp $ */ + +/* + * Copyright (c) 2011 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/param.h> +#include <sys/types.h> +#include <sys/queue.h> +#include <sys/socket.h> +#include <sys/uio.h> + +#include <scsi/iscsi.h> + +#include <event.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "iscsid.h" +#include "log.h" + +struct session * +session_find(struct initiator *i, char *name) +{ + struct session *s; + + TAILQ_FOREACH(s, &i->sessions, entry) { + if (strcmp(s->config.SessionName, name) == 0) + return s; + } + return NULL; +} + +struct session * +session_new(struct initiator *i, u_int8_t st) +{ + struct session *s; + + if (!(s = calloc(1, sizeof(*s)))) + return NULL; + + /* use the same qualifier unless there is a conflict */ + s->isid_base = i->config.isid_base; + s->isid_qual = i->config.isid_qual; + s->cmdseqnum = arc4random(); + s->itt = arc4random(); + s->initiator = i; + s->state = SESS_FREE; + + if (st == SESSION_TYPE_DISCOVERY) + s->target = 0; + else + s->target = s->initiator->target++; + + TAILQ_INSERT_HEAD(&i->sessions, s, entry); + TAILQ_INIT(&s->connections); + TAILQ_INIT(&s->tasks); + + return s; +} + +void +session_close(struct session *s) +{ + struct connection *c; + + while ((c = TAILQ_FIRST(&s->connections)) != NULL) + conn_free(c); + + free(s->config.TargetName); + free(s->config.InitiatorName); + free(s); +} + +void +session_config(struct session *s, struct session_config *sc) +{ + if (s->config.TargetName) + free(s->config.TargetName); + s->config.TargetName = NULL; + if (s->config.InitiatorName) + free(s->config.InitiatorName); + s->config.InitiatorName = NULL; + + s->config = *sc; + + if (sc->TargetName) { + s->config.TargetName = strdup(sc->TargetName); + if (s->config.TargetName == NULL) + fatal("strdup"); + } + if (sc->InitiatorName) { + s->config.InitiatorName = strdup(sc->InitiatorName); + if (s->config.InitiatorName == NULL) + fatal("strdup"); + } else + s->config.InitiatorName = default_initiator_name(); +} + +void +session_task_issue(struct session *s, struct task *t) +{ + TAILQ_INSERT_TAIL(&s->tasks, t, entry); + session_schedule(s); +} + +void +session_schedule(struct session *s) +{ + struct task *t = TAILQ_FIRST(&s->tasks); + struct connection *c; + + if (!t) + return; + + /* XXX IMMEDIATE TASK NEED SPECIAL HANDLING !!!! */ + + /* wake up a idle connection or a not busy one */ + /* XXX this needs more work as it makes the daemon go wrooOOOMM */ + TAILQ_REMOVE(&s->tasks, t, entry); + TAILQ_FOREACH(c, &s->connections, entry) + if (conn_task_issue(c, t)) + return; + /* all connections are busy readd task to the head */ + TAILQ_INSERT_HEAD(&s->tasks, t, entry); +} |