- Add full support for header / data digests.
- Increase target limit from 4 to 64; this limit will be removed entirely at a later time. - Improve recovery from lost network connections. - Fix some potential deadlocks and a serious memory leak. - Fix incorrect use of MH_ALIGN (instead of M_ALIGN), which makes no practical difference, but triggers a KASSERT with INVARIANTS. - Fix some warnings in iscontrol(8) and improve the man page somewhat. Submitted by: Daniel Braniss <danny@cs.huji.ac.il> Sponsored by: Dansk Scanning A/S, Data Robotics Inc.
This commit is contained in:
parent
1dd592007a
commit
c201d4532c
@ -4,9 +4,10 @@ SRCS= iscontrol.c pdu.c fsm.c config.c login.c auth_subr.c misc.c
|
||||
PROG= iscontrol
|
||||
DPADD= ${LIBCAM} ${LIBMD}
|
||||
LDADD= -lcam -lmd
|
||||
S= ${.CURDIR}/../../sys
|
||||
|
||||
WARNS?= 2
|
||||
CFLAGS += -I${.CURDIR}/../../sys/dev/iscsi/initiator
|
||||
WARNS?= 3
|
||||
CFLAGS += -I$S
|
||||
#CFLAGS += -g -DDEBUG
|
||||
|
||||
MAN= iscsi.conf.5 iscontrol.8
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -52,7 +52,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <md5.h>
|
||||
#include <sha.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include <dev/iscsi/initiator/iscsi.h>
|
||||
#include "iscontrol.h"
|
||||
|
||||
static int
|
||||
@ -152,7 +152,7 @@ chapDigest(char *ap, char id, char *cp, char *chapSecret)
|
||||
}
|
||||
|
||||
char *
|
||||
genChapChallenge(char *encoding, int len)
|
||||
genChapChallenge(char *encoding, uint len)
|
||||
{
|
||||
int fd;
|
||||
unsigned char tmp[1024];
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* Copyright (c) 2005-2009 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -41,7 +41,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <ctype.h>
|
||||
#include <camlib.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include <dev/iscsi/initiator/iscsi.h>
|
||||
#include "iscontrol.h"
|
||||
|
||||
/*
|
||||
@ -94,6 +94,11 @@ __FBSDID("$FreeBSD$");
|
||||
#define OPT_iqn 34
|
||||
#define OPT_sockbufsize 35
|
||||
|
||||
/*
|
||||
| sentinel
|
||||
*/
|
||||
#define OPT_end 0
|
||||
|
||||
#define _OFF(v) ((int)&((isc_opt_t *)NULL)->v)
|
||||
#define _E(u, s, v) {.usage=u, .scope=s, .name=#v, .tokenID=OPT_##v}
|
||||
|
||||
@ -145,7 +150,7 @@ textkey_t keyMap[] = {
|
||||
|
||||
_E(U_LO, S_SW, sessionType),
|
||||
|
||||
{0}
|
||||
_E(0, 0, end)
|
||||
};
|
||||
|
||||
#define _OPT_INT(w) strtol((char *)w, NULL, 0)
|
||||
@ -154,7 +159,7 @@ textkey_t keyMap[] = {
|
||||
static __inline int
|
||||
_OPT_BOOL(char *w)
|
||||
{
|
||||
if(isalpha(*w))
|
||||
if(isalpha((unsigned char)*w))
|
||||
return strcasecmp(w, "TRUE") == 0;
|
||||
else
|
||||
return _OPT_INT(w);
|
||||
@ -244,12 +249,12 @@ getConfig(FILE *fd, char *key, char **Ar, int *nargs)
|
||||
len = 0;
|
||||
state = 0;
|
||||
while((lp = getline(fd)) != NULL) {
|
||||
for(; isspace(*lp); lp++)
|
||||
for(; isspace((unsigned char)*lp); lp++)
|
||||
;
|
||||
switch(state) {
|
||||
case 0:
|
||||
if((p = strchr(lp, '{')) != NULL) {
|
||||
while((--p > lp) && *p && isspace(*p));
|
||||
while((--p > lp) && *p && isspace((unsigned char)*p));
|
||||
n = p - lp;
|
||||
if(len && strncmp(lp, key, MAX(n, len)) == 0)
|
||||
state = 2;
|
||||
@ -272,7 +277,7 @@ getConfig(FILE *fd, char *key, char **Ar, int *nargs)
|
||||
}
|
||||
|
||||
|
||||
for(p = &lp[strlen(lp)-1]; isspace(*p); p--)
|
||||
for(p = &lp[strlen(lp)-1]; isspace((unsigned char)*p); p--)
|
||||
*p = 0;
|
||||
if((*nargs)-- > 0)
|
||||
*ar++ = strdup(lp);
|
||||
@ -351,9 +356,9 @@ parseArgs(int nargs, char **args, isc_opt_t *op)
|
||||
continue;
|
||||
*p = 0;
|
||||
v = p + 1;
|
||||
while(isspace(*--p))
|
||||
while(isspace((unsigned char)*--p))
|
||||
*p = 0;
|
||||
while(isspace(*v))
|
||||
while(isspace((unsigned char)*v))
|
||||
v++;
|
||||
if((tk = keyLookup(*ar)) == NULL)
|
||||
continue;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -56,7 +56,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <stdarg.h>
|
||||
#include <camlib.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include <dev/iscsi/initiator/iscsi.h>
|
||||
#include "iscontrol.h"
|
||||
|
||||
typedef enum {
|
||||
@ -99,26 +99,26 @@ tcpConnect(isess_t *sess)
|
||||
#ifdef notyet
|
||||
{
|
||||
time_t sec;
|
||||
// make sure we are not in a loop
|
||||
// XXX: this code has to be tested
|
||||
sec = time(0) - sess->reconnect_time;
|
||||
if(sec > (5*60)) {
|
||||
// if we've been connected for more that 5 minutes
|
||||
// then just reconnect
|
||||
sess->reconnect_time = sec;
|
||||
sess->reconnect_cnt1 = 0;
|
||||
}
|
||||
else {
|
||||
//
|
||||
sess->reconnect_cnt1++;
|
||||
if((sec / sess->reconnect_cnt1) < 2) {
|
||||
// if less that 2 seconds from the last reconnect
|
||||
// we are most probably looping
|
||||
syslog(LOG_CRIT, "too many reconnects %d", sess->reconnect_cnt1);
|
||||
return 0;
|
||||
// make sure we are not in a loop
|
||||
// XXX: this code has to be tested
|
||||
sec = time(0) - sess->reconnect_time;
|
||||
if(sec > (5*60)) {
|
||||
// if we've been connected for more that 5 minutes
|
||||
// then just reconnect
|
||||
sess->reconnect_time = sec;
|
||||
sess->reconnect_cnt1 = 0;
|
||||
}
|
||||
else {
|
||||
//
|
||||
sess->reconnect_cnt1++;
|
||||
if((sec / sess->reconnect_cnt1) < 2) {
|
||||
// if less that 2 seconds from the last reconnect
|
||||
// we are most probably looping
|
||||
syslog(LOG_CRIT, "too many reconnects %d", sess->reconnect_cnt1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
sess->reconnect_cnt++;
|
||||
}
|
||||
@ -140,13 +140,13 @@ tcpConnect(isess_t *sess)
|
||||
if (soc == -1)
|
||||
continue;
|
||||
|
||||
// from Patrick.Guelat@imp.ch:
|
||||
// iscontrol can be called without waiting for the socket entry to time out
|
||||
val = 1;
|
||||
// from Patrick.Guelat@imp.ch:
|
||||
// iscontrol can be called without waiting for the socket entry to time out
|
||||
val = 1;
|
||||
if(setsockopt(soc, SOL_SOCKET, SO_REUSEADDR, &val, (socklen_t)sizeof(val)) < 0) {
|
||||
fprintf(stderr, "Cannot set socket SO_REUSEADDR %d: %s\n\n",
|
||||
errno, strerror(errno));
|
||||
}
|
||||
fprintf(stderr, "Cannot set socket SO_REUSEADDR %d: %s\n\n",
|
||||
errno, strerror(errno));
|
||||
}
|
||||
|
||||
if(connect(soc, res->ai_addr, res->ai_addrlen) == 0)
|
||||
break;
|
||||
@ -196,7 +196,7 @@ tcpConnect(isess_t *sess)
|
||||
}
|
||||
sess->flags |= SESS_CONNECTED;
|
||||
return T1;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "errno=%d\n", sv_errno);
|
||||
perror("connect");
|
||||
@ -289,7 +289,7 @@ startSession(isess_t *sess)
|
||||
// XXX: this has to go
|
||||
size_t n;
|
||||
n = sizeof(sess->isid);
|
||||
if(sysctlbyname("net.iscsi.isid", (void *)sess->isid, (size_t *)&n, 0, 0) != 0)
|
||||
if(sysctlbyname("net.iscsi_initiator.isid", (void *)sess->isid, (size_t *)&n, 0, 0) != 0)
|
||||
perror("sysctlbyname");
|
||||
}
|
||||
if(ioctl(fd, ISCSISETSES, &n)) {
|
||||
@ -343,29 +343,29 @@ trap(int sig)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
doCAM(isess_t *sess)
|
||||
{
|
||||
char pathstr[1024];
|
||||
union ccb *ccb;
|
||||
int i;
|
||||
int i, n;
|
||||
|
||||
if(ioctl(sess->fd, ISCSIGETCAM, &sess->cam) != 0) {
|
||||
syslog(LOG_WARNING, "ISCSIGETCAM failed: %d", errno);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
debug(2, "nluns=%d", sess->cam.target_nluns);
|
||||
debug(1, "nluns=%d", sess->cam.target_nluns);
|
||||
/*
|
||||
| for now will do this for each lun ...
|
||||
*/
|
||||
for(i = 0; i < sess->cam.target_nluns; i++) {
|
||||
for(n = i = 0; i < sess->cam.target_nluns; i++) {
|
||||
debug(2, "CAM path_id=%d target_id=%d target_lun=%d",
|
||||
sess->cam.path_id, sess->cam.target_id, sess->cam.target_lun[i]);
|
||||
|
||||
sess->camdev = cam_open_btl(sess->cam.path_id, sess->cam.target_id,
|
||||
sess->cam.target_lun[i], O_RDWR, NULL);
|
||||
i, O_RDWR, NULL);
|
||||
if(sess->camdev == NULL) {
|
||||
syslog(LOG_WARNING, "%s", cam_errbuf);
|
||||
//syslog(LOG_WARNING, "%s", cam_errbuf);
|
||||
debug(3, "%s", cam_errbuf);
|
||||
continue;
|
||||
}
|
||||
@ -378,20 +378,21 @@ doCAM(isess_t *sess)
|
||||
ccb->ccb_h.func_code = XPT_REL_SIMQ;
|
||||
ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
|
||||
ccb->crs.openings = sess->op->tags;
|
||||
|
||||
if(cam_send_ccb(sess->camdev, ccb) < 0)
|
||||
syslog(LOG_WARNING, "%s", cam_errbuf);
|
||||
debug(2, "%s", cam_errbuf);
|
||||
else
|
||||
if((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
||||
syslog(LOG_WARNING, "XPT_REL_SIMQ CCB failed");
|
||||
// cam_error_print(sess->camdev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
|
||||
}
|
||||
else
|
||||
else {
|
||||
n++;
|
||||
syslog(LOG_INFO, "%s tagged openings now %d\n", pathstr, ccb->crs.openings);
|
||||
|
||||
}
|
||||
cam_freeccb(ccb);
|
||||
cam_close_device(sess->camdev);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static trans_t
|
||||
@ -417,7 +418,15 @@ supervise(isess_t *sess)
|
||||
perror("daemon");
|
||||
exit(1);
|
||||
}
|
||||
if(sess->op->pidfile != NULL) {
|
||||
FILE *pidf;
|
||||
|
||||
pidf = fopen(sess->op->pidfile, "w");
|
||||
if(pidf != NULL) {
|
||||
fprintf(pidf, "%d\n", getpid());
|
||||
fclose(pidf);
|
||||
}
|
||||
}
|
||||
openlog("iscontrol", LOG_CONS|LOG_PERROR|LOG_PID|LOG_NDELAY, LOG_KERN);
|
||||
syslog(LOG_INFO, "running");
|
||||
|
||||
@ -426,7 +435,11 @@ supervise(isess_t *sess)
|
||||
perror("ISCSISTART");
|
||||
return -1;
|
||||
}
|
||||
doCAM(sess);
|
||||
if(doCAM(sess) == 0) {
|
||||
syslog(LOG_WARNING, "no device found");
|
||||
ioctl(sess->fd, ISCSISTOP);
|
||||
return T15;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
@ -449,7 +462,8 @@ supervise(isess_t *sess)
|
||||
sess->flags |= SESS_FULLFEATURE;
|
||||
|
||||
sess->flags &= ~(SESS_REDIRECT | SESS_RECONNECT);
|
||||
printf("iscontrol: supervise starting main loop\n");
|
||||
if(vflag)
|
||||
printf("iscontrol: supervise starting main loop\n");
|
||||
/*
|
||||
| the main loop - actually do nothing
|
||||
| all the work is done inside the kernel
|
||||
@ -468,14 +482,14 @@ supervise(isess_t *sess)
|
||||
}
|
||||
|
||||
if(sess->flags & SESS_DISCONNECT) {
|
||||
val = 0;
|
||||
if(ioctl(sess->fd, ISCSISTOP, &val)) {
|
||||
perror("ISCSISTOP");
|
||||
}
|
||||
sess->flags &= ~SESS_FULLFEATURE;
|
||||
return T9;
|
||||
}
|
||||
else {
|
||||
val = 0;
|
||||
if(ioctl(sess->fd, ISCSISTOP, &val)) {
|
||||
perror("ISCSISTOP");
|
||||
}
|
||||
sess->flags |= SESS_INITIALLOGIN1;
|
||||
}
|
||||
return T8;
|
||||
@ -490,7 +504,7 @@ handledDiscoveryResp(isess_t *sess, pdu_t *pp)
|
||||
debug_called(3);
|
||||
|
||||
len = pp->ds_len;
|
||||
ptr = pp->ds;
|
||||
ptr = pp->ds_addr;
|
||||
while(len > 0) {
|
||||
if(*ptr != 0)
|
||||
printf("%s\n", ptr);
|
||||
@ -579,8 +593,13 @@ doLogin(isess_t *sess)
|
||||
static int
|
||||
handleLogoutResp(isess_t *sess, pdu_t *pp)
|
||||
{
|
||||
if(sess->flags & SESS_DISCONNECT)
|
||||
if(sess->flags & SESS_DISCONNECT) {
|
||||
int val = 0;
|
||||
if(ioctl(sess->fd, ISCSISTOP, &val)) {
|
||||
perror("ISCSISTOP");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return T13;
|
||||
}
|
||||
|
||||
@ -610,7 +629,7 @@ typedef enum {
|
||||
S1, S2, /*S3,*/ S4, S5, S6, S7, S8
|
||||
} state_t;
|
||||
|
||||
#if 0
|
||||
/**
|
||||
S1: FREE
|
||||
S2: XPT_WAIT
|
||||
S4: IN_LOGIN
|
||||
@ -652,7 +671,7 @@ typedef enum {
|
||||
| +-----\ /--->\ / T14 |
|
||||
| ------- --+----+------+T17
|
||||
+---------------------------+
|
||||
#endif
|
||||
*/
|
||||
|
||||
int
|
||||
fsm(isc_opt_t *op)
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" Copyright (c) 2007-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
.\" Copyright (c) 2007-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
@ -32,11 +32,12 @@
|
||||
.Nd login/negotiator/control for an iSCSI initiator session
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl vd
|
||||
.Op Fl dv
|
||||
.Oo
|
||||
.Op Fl c Ar file
|
||||
.Fl c Ar file
|
||||
.Op Fl n Ar nickname
|
||||
.Oc
|
||||
.Op Fl p Ar pidfile
|
||||
.Op Fl t Ar target
|
||||
.Op Ar variable Ns = Ns Ar value
|
||||
.Sh DESCRIPTION
|
||||
@ -57,26 +58,29 @@ It will terminate/logout the session
|
||||
when a SIGHUP signal is received.
|
||||
The flags are as follows:
|
||||
.Bl -tag -width variable=value
|
||||
.It Fl v
|
||||
verbose mode.
|
||||
.It Fl d
|
||||
do a
|
||||
.Em discovery session
|
||||
and exit.
|
||||
.It Fl c Ar file
|
||||
a file containing configuration
|
||||
.Em key-options ,
|
||||
see
|
||||
.Xr iscsi.conf 5
|
||||
.Xr iscsi.conf 5 .
|
||||
.It Fl d
|
||||
do a
|
||||
.Em discovery session
|
||||
and exit.
|
||||
.It Fl n Ar nickname
|
||||
if
|
||||
.Sy -c file
|
||||
is specified, then search for the block named
|
||||
.Em nickname
|
||||
in that file, see
|
||||
.Xr iscsi.conf 5
|
||||
.Xr iscsi.conf 5 .
|
||||
.It Fl p Ar pidfile
|
||||
will write the process ID of the session to the specified
|
||||
.Em pidfile
|
||||
.It Fl t Ar target
|
||||
is the target's IP address or name
|
||||
the target's IP address or name.
|
||||
.It Fl v
|
||||
verbose mode.
|
||||
.It Ar variable Ns = Ns Ar value
|
||||
see
|
||||
.Xr iscsi.conf 5
|
||||
@ -86,13 +90,13 @@ possible values.
|
||||
.Sh EXAMPLES
|
||||
.Dl iscontrol -dt myiscsitarget
|
||||
.Pp
|
||||
will start a
|
||||
will start a
|
||||
.Em discovery session
|
||||
with the target and
|
||||
print to stdout the list of available targetnames/targetadresses.
|
||||
Note: this listing does not necessarily mean availability, since
|
||||
depending on the target configuration, a discovery session might
|
||||
not need login/access permission, but a
|
||||
not need login/access permission, but a
|
||||
.Em full session
|
||||
certainly does.
|
||||
.sp
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -53,15 +53,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include <time.h>
|
||||
#include <camlib.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include <dev/iscsi/initiator/iscsi.h>
|
||||
#include "iscontrol.h"
|
||||
|
||||
#define USAGE "[-v] [-d] [-c config] [-n name] [-t target] "
|
||||
#define OPTIONS "vdc:t:n:"
|
||||
|
||||
#ifndef DEBUG
|
||||
//int vflag;
|
||||
#endif
|
||||
#define USAGE "[-v] [-d] [-c config] [-n name] [-t target] [-p pidfile]"
|
||||
#define OPTIONS "vdc:t:n:p:"
|
||||
|
||||
token_t AuthMethods[] = {
|
||||
{"None", NONE},
|
||||
@ -70,14 +66,14 @@ token_t AuthMethods[] = {
|
||||
{"SPKM2", SPKM2},
|
||||
{"SRP", SRP},
|
||||
{"CHAP", CHAP},
|
||||
{0}
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
token_t DigestMethods[] = {
|
||||
{"None", 0},
|
||||
{"CRC32", 1},
|
||||
{"CRC32C", 1},
|
||||
{0}
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
u_char isid[6 + 6];
|
||||
@ -128,7 +124,7 @@ int
|
||||
main(int cc, char **vv)
|
||||
{
|
||||
int ch, disco;
|
||||
char *pname, *p, *q, *ta, *kw;
|
||||
char *pname, *pidfile, *p, *q, *ta, *kw;
|
||||
isc_opt_t *op;
|
||||
FILE *fd;
|
||||
|
||||
@ -141,6 +137,7 @@ main(int cc, char **vv)
|
||||
|
||||
kw = ta = 0;
|
||||
disco = 0;
|
||||
pidfile = NULL;
|
||||
|
||||
while((ch = getopt(cc, vv, OPTIONS)) != -1) {
|
||||
switch(ch) {
|
||||
@ -163,6 +160,9 @@ main(int cc, char **vv)
|
||||
case 'n':
|
||||
kw = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
pidfile = optarg;
|
||||
break;
|
||||
default:
|
||||
badu:
|
||||
fprintf(stderr, "Usage: %s %s\n", pname, USAGE);
|
||||
@ -225,7 +225,7 @@ main(int cc, char **vv)
|
||||
op->sessionType = "Discovery";
|
||||
op->targetName = 0;
|
||||
}
|
||||
|
||||
op->pidfile = pidfile;
|
||||
fsm(op);
|
||||
|
||||
exit(0);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -154,7 +154,7 @@ void parseArgs(int nargs, char **args, isc_opt_t *op);
|
||||
void parseConfig(FILE *fd, char *key, isc_opt_t *op);
|
||||
|
||||
char *chapDigest(char *ap, char id, char *cp, char *chapSecret);
|
||||
char *genChapChallenge(char *encoding, int len);
|
||||
char *genChapChallenge(char *encoding, uint len);
|
||||
|
||||
int str2bin(char *str, char **rsp);
|
||||
char *bin2str(char *fmt, unsigned char *md, int blen);
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" Copyright (c) 2007-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
.\" Copyright (c) 2007-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
@ -68,6 +68,7 @@ Only CRC32C is implemented.
|
||||
Default is none.
|
||||
.It Cm DataDigest
|
||||
same as for HeaderDigest, but on the data part of the iSCSI PDU.
|
||||
(not yet tested)
|
||||
.It Cm MaxConnections
|
||||
is the number of simultaneous connections per session,
|
||||
currently only 1.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -47,7 +47,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include <dev/iscsi/initiator/iscsi.h>
|
||||
#include "iscontrol.h"
|
||||
|
||||
static char *status_class1[] = {
|
||||
@ -107,7 +107,7 @@ getkeyval(char *key, pdu_t *pp)
|
||||
debug_called(3);
|
||||
|
||||
len = pp->ds_len;
|
||||
ptr = (char *)pp->ds;
|
||||
ptr = (char *)pp->ds_addr;
|
||||
klen = strlen(key);
|
||||
while(len > klen) {
|
||||
if(strncmp(key, ptr, klen) == 0)
|
||||
@ -163,7 +163,7 @@ processParams(isess_t *sess, pdu_t *pp)
|
||||
debug_called(3);
|
||||
|
||||
len = pp->ds_len;
|
||||
ptr = (char *)pp->ds;
|
||||
ptr = (char *)pp->ds_addr;
|
||||
while(len > 0) {
|
||||
if(vflag > 1)
|
||||
printf("got: len=%d %s\n", len, ptr);
|
||||
@ -233,7 +233,7 @@ handleLoginResp(isess_t *sess, pdu_t *pp)
|
||||
|
||||
st_class = status >> 8;
|
||||
if(status) {
|
||||
int st_detail = status & 0xff;
|
||||
uint st_detail = status & 0xff;
|
||||
|
||||
switch(st_class) {
|
||||
case 1: // Redirect
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -47,6 +47,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dev/iscsi/initiator/iscsi.h>
|
||||
#include "iscontrol.h"
|
||||
|
||||
static inline char
|
||||
c2b(unsigned char c)
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -43,7 +43,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <stdarg.h>
|
||||
#include <camlib.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include <dev/iscsi/initiator/iscsi.h>
|
||||
#include "iscontrol.h"
|
||||
|
||||
static void pukeText(char *it, pdu_t *pp);
|
||||
@ -85,7 +85,7 @@ sendPDU(isess_t *sess, pdu_t *pp, handler_t *hdlr)
|
||||
int res;
|
||||
|
||||
pp->ahs_size = 8 * 1024;
|
||||
if((pp->ahs = malloc(pp->ahs_size)) == NULL) {
|
||||
if((pp->ahs_addr = malloc(pp->ahs_size)) == NULL) {
|
||||
fprintf(stderr, "out of mem!");
|
||||
return -1;
|
||||
}
|
||||
@ -126,16 +126,16 @@ addText(pdu_t *pp, char *fmt, ...)
|
||||
if((pp->ds_len + len) > pp->ds_size) {
|
||||
u_char *np;
|
||||
|
||||
np = realloc(pp->ds, pp->ds_size + len + FUDGE);
|
||||
np = realloc(pp->ds_addr, pp->ds_size + len + FUDGE);
|
||||
if(np == NULL) {
|
||||
free(str);
|
||||
//XXX: out of memory!
|
||||
return -1;
|
||||
}
|
||||
pp->ds = np;
|
||||
pp->ds_addr = np;
|
||||
pp->ds_size += len + FUDGE;
|
||||
}
|
||||
memcpy(pp->ds + pp->ds_len, str, len);
|
||||
memcpy(pp->ds_addr + pp->ds_len, str, len);
|
||||
pp->ds_len += len;
|
||||
free(str);
|
||||
return len;
|
||||
@ -145,12 +145,12 @@ void
|
||||
freePDU(pdu_t *pp)
|
||||
{
|
||||
if(pp->ahs_size)
|
||||
free(pp->ahs);
|
||||
free(pp->ahs_addr);
|
||||
if(pp->ds_size)
|
||||
free(pp->ds);
|
||||
free(pp->ds_addr);
|
||||
bzero(&pp->ipdu, sizeof(union ipdu_u));
|
||||
pp->ahs = NULL;
|
||||
pp->ds = NULL;
|
||||
pp->ahs_addr = NULL;
|
||||
pp->ds_addr = NULL;
|
||||
pp->ahs_size = 0;
|
||||
pp->ds_size = pp->ds_len = 0;
|
||||
}
|
||||
@ -163,7 +163,7 @@ pukeText(char *it, pdu_t *pp)
|
||||
size_t len, n;
|
||||
|
||||
len = pp->ds_len;
|
||||
ptr = (char *)pp->ds;
|
||||
ptr = (char *)pp->ds_addr;
|
||||
cmd = pp->ipdu.bhs.opcode;
|
||||
|
||||
printf("%s: cmd=0x%x len=%d\n", it, cmd, (int)len);
|
||||
|
@ -1,134 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2005 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
/*
|
||||
| $Id: pdu.h,v 2.1 2006/11/12 08:06:51 danny Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
| keep in BIG endian order (network byte order).
|
||||
*/
|
||||
|
||||
typedef struct login_req {
|
||||
char cmd; // 0x03
|
||||
|
||||
u_char NSG:2;
|
||||
u_char CSG:2;
|
||||
u_char _:2;
|
||||
u_char C:1;
|
||||
u_char T:1;
|
||||
|
||||
char v_max;
|
||||
char v_min;
|
||||
|
||||
int len; // remapped via standard bhs
|
||||
char isid[6];
|
||||
short tsih;
|
||||
int itt; // Initiator Task Tag;
|
||||
|
||||
int CID:16;
|
||||
int rsv:16;
|
||||
|
||||
int cmdSN;
|
||||
int expStatSN;
|
||||
int unused[4];
|
||||
} login_req_t;
|
||||
|
||||
typedef struct login_rsp {
|
||||
char cmd; // 0x23
|
||||
u_char NSG:2;
|
||||
u_char CSG:2;
|
||||
u_char _1:2;
|
||||
u_char C:1;
|
||||
u_char T:1;
|
||||
|
||||
char v_max;
|
||||
char v_act;
|
||||
|
||||
int len; // remapped via standard bhs
|
||||
char isid[6];
|
||||
short tsih;
|
||||
int itt; // Initiator Task Tag;
|
||||
int _2;
|
||||
rsp_sn_t sn;
|
||||
int status:16;
|
||||
int _3:16;
|
||||
int _4[2];
|
||||
} login_rsp_t;
|
||||
|
||||
typedef struct text_req {
|
||||
char cmd; // 0x04
|
||||
|
||||
u_char _1:6;
|
||||
u_char C:1; // Continuation
|
||||
u_char F:1; // Final
|
||||
char _2[2];
|
||||
|
||||
int len;
|
||||
int itt; // Initiator Task Tag
|
||||
int LUN[2];
|
||||
int ttt; // Target Transfer Tag
|
||||
int cmdSN;
|
||||
int expStatSN;
|
||||
int unused[4];
|
||||
} text_req_t;
|
||||
|
||||
/*
|
||||
| Responses
|
||||
*/
|
||||
typedef struct logout_req {
|
||||
char cmd; // 0x06
|
||||
char reason; // 0 - close session
|
||||
// 1 - close connection
|
||||
// 2 - remove the connection for recovery
|
||||
char _2[2];
|
||||
|
||||
int len;
|
||||
int _r[2];
|
||||
int itt; // Initiator Task Tag;
|
||||
|
||||
u_int CID:16;
|
||||
u_int rsv:16;
|
||||
|
||||
int cmdSN;
|
||||
int expStatSN;
|
||||
int unused[4];
|
||||
} logout_req_t;
|
||||
|
||||
typedef struct logout_rsp {
|
||||
char cmd; // 0x26
|
||||
char cbits;
|
||||
char _1[2];
|
||||
int len;
|
||||
int _2[2];
|
||||
int itt;
|
||||
int _3;
|
||||
rsp_sn_t sn;
|
||||
short time2wait;
|
||||
short time2retain;
|
||||
int _4;
|
||||
} logout_rsp_t;
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -24,7 +24,9 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
| $Id: isc_cam.c 998 2009-12-20 10:32:45Z danny $
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
@ -43,6 +45,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/sx.h>
|
||||
|
||||
#include <cam/cam.h>
|
||||
#include <cam/cam_ccb.h>
|
||||
@ -53,146 +56,34 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/iscsi/initiator/iscsi.h>
|
||||
#include <dev/iscsi/initiator/iscsivar.h>
|
||||
|
||||
// XXX: untested/incomplete
|
||||
void
|
||||
ic_freeze(isc_session_t *sp)
|
||||
{
|
||||
debug_called(8);
|
||||
#if 0
|
||||
sdebug(2, "freezing path=%p", sp->cam_path == NULL? 0: sp->cam_path);
|
||||
if((sp->cam_path != NULL) && !(sp->flags & ISC_FROZEN)) {
|
||||
xpt_freeze_devq(sp->cam_path, 1);
|
||||
}
|
||||
#endif
|
||||
sp->flags |= ISC_FROZEN;
|
||||
}
|
||||
|
||||
// XXX: untested/incomplete
|
||||
void
|
||||
ic_release(isc_session_t *sp)
|
||||
{
|
||||
debug_called(8);
|
||||
#if 0
|
||||
sdebug(2, "release path=%p", sp->cam_path == NULL? 0: sp->cam_path);
|
||||
if((sp->cam_path != NULL) && (sp->flags & ISC_FROZEN)) {
|
||||
xpt_release_devq(sp->cam_path, 1, TRUE);
|
||||
}
|
||||
#endif
|
||||
sp->flags &= ~ISC_FROZEN;
|
||||
}
|
||||
|
||||
void
|
||||
ic_lost_target(isc_session_t *sp, int target)
|
||||
{
|
||||
struct isc_softc *isp = sp->isc;
|
||||
|
||||
debug_called(8);
|
||||
sdebug(2, "target=%d", target);
|
||||
if(sp->cam_path != NULL) {
|
||||
mtx_lock(&isp->cam_mtx);
|
||||
xpt_async(AC_LOST_DEVICE, sp->cam_path, NULL);
|
||||
xpt_free_path(sp->cam_path);
|
||||
mtx_unlock(&isp->cam_mtx);
|
||||
sp->cam_path = 0; // XXX
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_scan_callback(struct cam_periph *periph, union ccb *ccb)
|
||||
{
|
||||
isc_session_t *sp = (isc_session_t *)ccb->ccb_h.spriv_ptr0;
|
||||
|
||||
debug_called(8);
|
||||
|
||||
free(ccb, M_TEMP);
|
||||
|
||||
if(sp->flags & ISC_FFPWAIT) {
|
||||
sp->flags &= ~ISC_FFPWAIT;
|
||||
wakeup(sp);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_scan_target(isc_session_t *sp, int target)
|
||||
{
|
||||
union ccb *ccb;
|
||||
|
||||
debug_called(8);
|
||||
sdebug(2, "target=%d", target);
|
||||
|
||||
if((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO)) == NULL) {
|
||||
xdebug("scan failed (can't allocate CCB)");
|
||||
return;
|
||||
}
|
||||
CAM_LOCK(sp->isc);
|
||||
xpt_setup_ccb(&ccb->ccb_h, sp->cam_path, 5/*priority (low)*/);
|
||||
ccb->ccb_h.func_code = XPT_SCAN_BUS;
|
||||
ccb->ccb_h.cbfcnp = _scan_callback;
|
||||
ccb->crcn.flags = CAM_FLAG_NONE;
|
||||
ccb->ccb_h.spriv_ptr0 = sp;
|
||||
|
||||
xpt_action(ccb);
|
||||
CAM_UNLOCK(sp->isc);
|
||||
}
|
||||
|
||||
int
|
||||
ic_fullfeature(struct cdev *dev)
|
||||
{
|
||||
struct isc_softc *isp = dev->si_drv1;
|
||||
isc_session_t *sp = (isc_session_t *)dev->si_drv2;
|
||||
|
||||
debug_called(8);
|
||||
sdebug(3, "dev=%d sc=%p", dev2unit(dev), isp);
|
||||
|
||||
sp->flags &= ~ISC_FFPHASE;
|
||||
sp->flags |= ISC_FFPWAIT;
|
||||
|
||||
CAM_LOCK(isp);
|
||||
if(xpt_create_path(&sp->cam_path, xpt_periph, cam_sim_path(sp->isc->cam_sim),
|
||||
sp->sid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
xdebug("can't create cam path");
|
||||
CAM_UNLOCK(isp);
|
||||
return ENODEV; // XXX
|
||||
}
|
||||
CAM_UNLOCK(isp);
|
||||
|
||||
_scan_target(sp, sp->sid);
|
||||
|
||||
while(sp->flags & ISC_FFPWAIT)
|
||||
tsleep(sp, PRIBIO, "ffp", 5*hz); // the timeout time should
|
||||
// be configurable
|
||||
if(sp->target_nluns > 0) {
|
||||
sp->flags |= ISC_FFPHASE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
static void
|
||||
_inq(struct cam_sim *sim, union ccb *ccb, int maxluns)
|
||||
_inq(struct cam_sim *sim, union ccb *ccb)
|
||||
{
|
||||
struct ccb_pathinq *cpi = &ccb->cpi;
|
||||
isc_session_t *sp = cam_sim_softc(sim);
|
||||
|
||||
debug_called(4);
|
||||
debug_called(8);
|
||||
debug(3, "sid=%d target=%d lun=%d", sp->sid, ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
|
||||
|
||||
cpi->version_num = 1; /* XXX??? */
|
||||
cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE | PI_WIDE_32;
|
||||
cpi->target_sprt = 0;
|
||||
cpi->hba_misc = 0;
|
||||
cpi->hba_eng_cnt = 0;
|
||||
cpi->max_target = ISCSI_MAX_TARGETS - 1;
|
||||
cpi->max_target = 0; //ISCSI_MAX_TARGETS - 1;
|
||||
cpi->initiator_id = ISCSI_MAX_TARGETS;
|
||||
cpi->max_lun = maxluns;
|
||||
cpi->max_lun = sp->opt.maxluns - 1;
|
||||
cpi->bus_id = cam_sim_bus(sim);
|
||||
cpi->base_transfer_speed = 3300;
|
||||
cpi->base_transfer_speed = 3300; // 40000; // XXX:
|
||||
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
|
||||
strncpy(cpi->hba_vid, "iSCSI", HBA_IDLEN);
|
||||
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
|
||||
cpi->unit_number = cam_sim_unit(sim);
|
||||
cpi->ccb_h.status = CAM_REQ_CMP;
|
||||
#if defined(KNOB_VALID_ADDRESS)
|
||||
cpi->transport = XPORT_ISCSI;
|
||||
cpi->transport_version = 0;
|
||||
cpi->ccb_h.status = CAM_REQ_CMP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline int
|
||||
@ -203,77 +94,111 @@ _scsi_encap(struct cam_sim *sim, union ccb *ccb)
|
||||
#if __FreeBSD_version < 700000
|
||||
ret = scsi_encap(sim, ccb);
|
||||
#else
|
||||
struct isc_softc *isp = (struct isc_softc *)cam_sim_softc(sim);
|
||||
isc_session_t *sp = cam_sim_softc(sim);
|
||||
|
||||
mtx_unlock(&isp->cam_mtx);
|
||||
mtx_unlock(&sp->cam_mtx);
|
||||
ret = scsi_encap(sim, ccb);
|
||||
mtx_lock(&isp->cam_mtx);
|
||||
mtx_lock(&sp->cam_mtx);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
ic_lost_target(isc_session_t *sp, int target)
|
||||
{
|
||||
debug_called(8);
|
||||
sdebug(2, "lost target=%d", target);
|
||||
|
||||
if(sp->cam_path != NULL) {
|
||||
mtx_lock(&sp->cam_mtx);
|
||||
xpt_async(AC_LOST_DEVICE, sp->cam_path, NULL);
|
||||
xpt_free_path(sp->cam_path);
|
||||
mtx_unlock(&sp->cam_mtx);
|
||||
sp->cam_path = 0; // XXX
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
scan_callback(struct cam_periph *periph, union ccb *ccb)
|
||||
{
|
||||
isc_session_t *sp = (isc_session_t *)ccb->ccb_h.spriv_ptr0;
|
||||
|
||||
debug_called(8);
|
||||
|
||||
free(ccb, M_TEMP);
|
||||
|
||||
if(sp->flags & ISC_SCANWAIT) {
|
||||
sp->flags &= ~ISC_SCANWAIT;
|
||||
wakeup(sp);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ic_scan(isc_session_t *sp)
|
||||
{
|
||||
union ccb *ccb;
|
||||
|
||||
debug_called(8);
|
||||
sdebug(2, "scanning sid=%d", sp->sid);
|
||||
|
||||
if((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO)) == NULL) {
|
||||
xdebug("scan failed (can't allocate CCB)");
|
||||
return ENOMEM; // XXX
|
||||
}
|
||||
|
||||
sp->flags &= ~ISC_CAMDEVS;
|
||||
sp->flags |= ISC_SCANWAIT;
|
||||
|
||||
CAM_LOCK(sp);
|
||||
if(xpt_create_path(&sp->cam_path, xpt_periph, cam_sim_path(sp->cam_sim),
|
||||
0, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
xdebug("can't create cam path");
|
||||
CAM_UNLOCK(sp);
|
||||
free(ccb, M_TEMP);
|
||||
return ENODEV; // XXX
|
||||
}
|
||||
xpt_setup_ccb(&ccb->ccb_h, sp->cam_path, 5/*priority (low)*/);
|
||||
ccb->ccb_h.func_code = XPT_SCAN_BUS;
|
||||
ccb->ccb_h.cbfcnp = scan_callback;
|
||||
ccb->crcn.flags = CAM_FLAG_NONE;
|
||||
ccb->ccb_h.spriv_ptr0 = sp;
|
||||
|
||||
xpt_action(ccb);
|
||||
CAM_UNLOCK(sp);
|
||||
|
||||
while(sp->flags & ISC_SCANWAIT)
|
||||
tsleep(sp, PRIBIO, "ffp", 5*hz); // the timeout time should
|
||||
// be configurable
|
||||
sdebug(2, "# of luns=%d", sp->target_nluns);
|
||||
|
||||
if(sp->target_nluns > 0) {
|
||||
sp->flags |= ISC_CAMDEVS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
static void
|
||||
ic_action(struct cam_sim *sim, union ccb *ccb)
|
||||
{
|
||||
isc_session_t *sp = cam_sim_softc(sim);
|
||||
struct ccb_hdr *ccb_h = &ccb->ccb_h;
|
||||
struct isc_softc *isp = (struct isc_softc *)cam_sim_softc(sim);
|
||||
isc_session_t *sp;
|
||||
|
||||
debug_called(8);
|
||||
|
||||
if((ccb_h->target_id != CAM_TARGET_WILDCARD) && (ccb_h->target_id < MAX_SESSIONS))
|
||||
sp = isp->sessions[ccb_h->target_id];
|
||||
else
|
||||
sp = NULL;
|
||||
|
||||
ccb_h->spriv_ptr0 = sp;
|
||||
|
||||
debug(4, "func_code=0x%x flags=0x%x status=0x%x target=%d lun=%d retry_count=%d timeout=%d",
|
||||
sdebug(4, "func_code=0x%x flags=0x%x status=0x%x target=%d lun=%d retry_count=%d timeout=%d",
|
||||
ccb_h->func_code, ccb->ccb_h.flags, ccb->ccb_h.status,
|
||||
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
|
||||
ccb->ccb_h.retry_count, ccb_h->timeout);
|
||||
/*
|
||||
| first quick check
|
||||
*/
|
||||
if(sp == NULL) {
|
||||
xdebug("sp == NULL! cannot happen");
|
||||
return;
|
||||
}
|
||||
switch(ccb_h->func_code) {
|
||||
default:
|
||||
// XXX: maybe check something else?
|
||||
break;
|
||||
|
||||
case XPT_SCSI_IO:
|
||||
case XPT_RESET_DEV:
|
||||
case XPT_GET_TRAN_SETTINGS:
|
||||
case XPT_SET_TRAN_SETTINGS:
|
||||
case XPT_CALC_GEOMETRY:
|
||||
if(sp == NULL) {
|
||||
ccb->ccb_h.status = CAM_DEV_NOT_THERE;
|
||||
#if __FreeBSD_version < 700000
|
||||
XPT_DONE(isp, ccb);
|
||||
#else
|
||||
xpt_done(ccb);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case XPT_PATH_INQ:
|
||||
case XPT_NOOP:
|
||||
if(sp == NULL && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
|
||||
ccb->ccb_h.status = CAM_DEV_NOT_THERE;
|
||||
#if __FreeBSD_version < 700000
|
||||
XPT_DONE(isp, ccb);
|
||||
#else
|
||||
xpt_done(ccb);
|
||||
#endif
|
||||
debug(4, "status = CAM_DEV_NOT_THERE");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch(ccb_h->func_code) {
|
||||
|
||||
case XPT_PATH_INQ:
|
||||
_inq(sim, ccb, (sp? sp->opt.maxluns: ISCSI_MAX_LUNS) - 1);
|
||||
_inq(sim, ccb);
|
||||
break;
|
||||
|
||||
case XPT_RESET_BUS: // (can just be a stub that does nothing and completes)
|
||||
@ -310,14 +235,35 @@ ic_action(struct cam_sim *sim, union ccb *ccb)
|
||||
struct ccb_calc_geometry *ccg;
|
||||
|
||||
ccg = &ccb->ccg;
|
||||
debug(6, "XPT_CALC_GEOMETRY vsize=%jd bsize=%d", ccg->volume_size, ccg->block_size);
|
||||
debug(4, "sid=%d target=%d lun=%d XPT_CALC_GEOMETRY vsize=%jd bsize=%d",
|
||||
sp->sid, ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
|
||||
ccg->volume_size, ccg->block_size);
|
||||
if(ccg->block_size == 0 ||
|
||||
(ccg->volume_size < ccg->block_size)) {
|
||||
// print error message ...
|
||||
/* XXX: what error is appropiate? */
|
||||
break;
|
||||
} else
|
||||
}
|
||||
else {
|
||||
int lun, *off, boff;
|
||||
|
||||
lun = ccb->ccb_h.target_lun;
|
||||
if(lun > ISCSI_MAX_LUNS) {
|
||||
// XXX:
|
||||
xdebug("lun %d > ISCSI_MAX_LUNS!\n", lun);
|
||||
lun %= ISCSI_MAX_LUNS;
|
||||
}
|
||||
off = &sp->target_lun[lun / (sizeof(int)*8)];
|
||||
boff = BIT(lun % (sizeof(int)*8));
|
||||
debug(4, "sp->target_nluns=%d *off=%x boff=%x",
|
||||
sp->target_nluns, *off, boff);
|
||||
|
||||
if((*off & boff) == 0) {
|
||||
sp->target_nluns++;
|
||||
*off |= boff;
|
||||
}
|
||||
cam_calc_geometry(ccg, /*extended*/1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -327,7 +273,7 @@ ic_action(struct cam_sim *sim, union ccb *ccb)
|
||||
break;
|
||||
}
|
||||
#if __FreeBSD_version < 700000
|
||||
XPT_DONE(isp, ccb);
|
||||
XPT_DONE(sp, ccb);
|
||||
#else
|
||||
xpt_done(ccb);
|
||||
#endif
|
||||
@ -337,102 +283,102 @@ ic_action(struct cam_sim *sim, union ccb *ccb)
|
||||
static void
|
||||
ic_poll(struct cam_sim *sim)
|
||||
{
|
||||
debug_called(8);
|
||||
debug_called(4);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
ic_getCamVals(isc_session_t *sp, iscsi_cam_t *cp)
|
||||
{
|
||||
int i;
|
||||
|
||||
debug_called(8);
|
||||
|
||||
if(sp && sp->isc->cam_sim) {
|
||||
cp->path_id = cam_sim_path(sp->isc->cam_sim);
|
||||
cp->target_id = sp->sid;
|
||||
cp->target_nluns = sp->target_nluns; // XXX: -1?
|
||||
for(i = 0; i < cp->target_nluns; i++)
|
||||
cp->target_lun[i] = sp->target_lun[i];
|
||||
if(sp && sp->cam_sim) {
|
||||
cp->path_id = cam_sim_path(sp->cam_sim);
|
||||
cp->target_id = 0;
|
||||
cp->target_nluns = ISCSI_MAX_LUNS; // XXX: -1?
|
||||
return 0;
|
||||
}
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
void
|
||||
ic_destroy(struct isc_softc *isp)
|
||||
ic_destroy(isc_session_t *sp )
|
||||
{
|
||||
debug_called(8);
|
||||
|
||||
CAM_LOCK(isp); // can't harm :-)
|
||||
if(sp->cam_path != NULL) {
|
||||
sdebug(2, "name=%s unit=%d",
|
||||
cam_sim_name(sp->cam_sim), cam_sim_unit(sp->cam_sim));
|
||||
CAM_LOCK(sp);
|
||||
#if 0
|
||||
xpt_async(AC_LOST_DEVICE, sp->cam_path, NULL);
|
||||
#else
|
||||
xpt_async(XPT_RESET_BUS, sp->cam_path, NULL);
|
||||
#endif
|
||||
xpt_free_path(sp->cam_path);
|
||||
xpt_bus_deregister(cam_sim_path(sp->cam_sim));
|
||||
cam_sim_free(sp->cam_sim, TRUE /*free_devq*/);
|
||||
|
||||
xpt_async(AC_LOST_DEVICE, isp->cam_path, NULL);
|
||||
xpt_free_path(isp->cam_path);
|
||||
|
||||
xpt_bus_deregister(cam_sim_path(isp->cam_sim));
|
||||
cam_sim_free(isp->cam_sim, TRUE /*free_devq*/);
|
||||
|
||||
CAM_UNLOCK(isp);
|
||||
CAM_UNLOCK(sp);
|
||||
sdebug(2, "done");
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ic_init(struct isc_softc *isp)
|
||||
ic_init(isc_session_t *sp)
|
||||
{
|
||||
struct cam_sim *sim;
|
||||
struct cam_devq *devq;
|
||||
struct cam_path *path;
|
||||
|
||||
debug_called(8);
|
||||
|
||||
if((devq = cam_simq_alloc(256)) == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
#if __FreeBSD_version >= 700000
|
||||
mtx_init(&isp->cam_mtx, "isc-cam", NULL, MTX_DEF);
|
||||
mtx_init(&sp->cam_mtx, "isc-cam", NULL, MTX_DEF);
|
||||
#else
|
||||
isp->cam_mtx = Giant;
|
||||
#endif
|
||||
sim = cam_sim_alloc(ic_action, ic_poll,
|
||||
"iscsi", isp, 0/*unit*/,
|
||||
sim = cam_sim_alloc(ic_action,
|
||||
ic_poll,
|
||||
"iscsi",
|
||||
sp,
|
||||
sp->sid, // unit
|
||||
#if __FreeBSD_version >= 700000
|
||||
&isp->cam_mtx,
|
||||
&sp->cam_mtx,
|
||||
#endif
|
||||
1/*max_dev_transactions*/,
|
||||
100/*max_tagged_dev_transactions*/,
|
||||
1, // max_dev_transactions
|
||||
0, // max_tagged_dev_transactions
|
||||
devq);
|
||||
if(sim == NULL) {
|
||||
cam_simq_free(devq);
|
||||
#if __FreeBSD_version >= 700000
|
||||
mtx_destroy(&isp->cam_mtx);
|
||||
mtx_destroy(&sp->cam_mtx);
|
||||
#endif
|
||||
return ENXIO;
|
||||
}
|
||||
CAM_LOCK(isp);
|
||||
|
||||
CAM_LOCK(sp);
|
||||
if(xpt_bus_register(sim,
|
||||
#if __FreeBSD_version >= 700000
|
||||
NULL,
|
||||
#endif
|
||||
0/*bus_number*/) != CAM_SUCCESS)
|
||||
goto bad;
|
||||
0/*bus_number*/) != CAM_SUCCESS) {
|
||||
|
||||
if(xpt_create_path(&path, xpt_periph, cam_sim_path(sim),
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
xpt_bus_deregister(cam_sim_path(sim));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
CAM_UNLOCK(isp);
|
||||
|
||||
isp->cam_sim = sim;
|
||||
isp->cam_path = path;
|
||||
|
||||
debug(2, "cam subsystem initialized"); // XXX: add dev ...
|
||||
debug(4, "sim=%p path=%p", sim, path);
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
cam_sim_free(sim, /*free_devq*/TRUE);
|
||||
CAM_UNLOCK(isp);
|
||||
cam_sim_free(sim, /*free_devq*/TRUE);
|
||||
CAM_UNLOCK(sp);
|
||||
#if __FreeBSD_version >= 700000
|
||||
mtx_destroy(&isp->cam_mtx);
|
||||
mtx_destroy(&sp->cam_mtx);
|
||||
#endif
|
||||
return ENXIO;
|
||||
return ENXIO;
|
||||
}
|
||||
sp->cam_sim = sim;
|
||||
CAM_UNLOCK(sp);
|
||||
|
||||
sdebug(1, "cam subsystem initialized");
|
||||
|
||||
ic_scan(sp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,7 +26,7 @@
|
||||
*/
|
||||
/*
|
||||
| iSCSI - Session Manager
|
||||
| $Id: isc_sm.c,v 1.30 2007/04/22 09:53:09 danny Exp danny $
|
||||
| $Id: isc_sm.c 743 2009-08-08 10:54:53Z danny $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/sx.h>
|
||||
|
||||
#include <cam/cam.h>
|
||||
#include <cam/cam_ccb.h>
|
||||
@ -131,8 +132,10 @@ _scsi_rsp(isc_session_t *sp, pduq_t *pq)
|
||||
debug_called(8);
|
||||
opq = i_search_hld(sp, pq->pdu.ipdu.bhs.itt, 0);
|
||||
debug(5, "itt=%x pq=%p opq=%p", ntohl(pq->pdu.ipdu.bhs.itt), pq, opq);
|
||||
if(opq != NULL)
|
||||
if(opq != NULL) {
|
||||
iscsi_done(sp, opq, pq);
|
||||
i_acked_hld(sp, &pq->pdu);
|
||||
}
|
||||
else
|
||||
xdebug("%d] we lost something itt=%x",
|
||||
sp->sid, ntohl(pq->pdu.ipdu.bhs.itt));
|
||||
@ -267,7 +270,7 @@ i_prepPDU(isc_session_t *sp, pduq_t *pq)
|
||||
len += pp->ahs_len;
|
||||
bhp->AHSLength = pp->ahs_len / 4;
|
||||
}
|
||||
if(sp->hdrDigest)
|
||||
if(ISOK2DIG(sp->hdrDigest, pp))
|
||||
len += 4;
|
||||
if(pp->ds_len) {
|
||||
n = pp->ds_len;
|
||||
@ -283,7 +286,7 @@ i_prepPDU(isc_session_t *sp, pduq_t *pq)
|
||||
n = 4 - (len & 03);
|
||||
len += n;
|
||||
}
|
||||
if(sp->dataDigest)
|
||||
if(ISOK2DIG(sp->dataDigest, pp))
|
||||
len += 4;
|
||||
}
|
||||
|
||||
@ -321,7 +324,7 @@ isc_qout(isc_session_t *sp, pduq_t *pq)
|
||||
mtx_lock(&sp->io_mtx);
|
||||
sp->flags |= ISC_OQNOTEMPTY;
|
||||
if(sp->flags & ISC_OWAITING)
|
||||
wakeup(&sp->flags);
|
||||
wakeup(&sp->flags);
|
||||
mtx_unlock(&sp->io_mtx);
|
||||
|
||||
return error;
|
||||
@ -329,7 +332,7 @@ isc_qout(isc_session_t *sp, pduq_t *pq)
|
||||
/*
|
||||
| called when a fullPhase is restarted
|
||||
*/
|
||||
static void
|
||||
void
|
||||
ism_restart(isc_session_t *sp)
|
||||
{
|
||||
int lastcmd;
|
||||
@ -348,30 +351,7 @@ ism_restart(isc_session_t *sp)
|
||||
}
|
||||
mtx_unlock(&sp->io_mtx);
|
||||
|
||||
sdebug(2, "restarted lastcmd=0x%x", lastcmd);
|
||||
}
|
||||
|
||||
int
|
||||
ism_fullfeature(struct cdev *dev, int flag)
|
||||
{
|
||||
isc_session_t *sp = (isc_session_t *)dev->si_drv2;
|
||||
int error;
|
||||
|
||||
sdebug(2, "flag=%d", flag);
|
||||
|
||||
error = 0;
|
||||
switch(flag) {
|
||||
case 0: // stop
|
||||
sp->flags &= ~ISC_FFPHASE;
|
||||
break;
|
||||
case 1: // start
|
||||
error = ic_fullfeature(dev);
|
||||
break;
|
||||
case 2: // restart
|
||||
ism_restart(sp);
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
sdebug(2, "restarted sn.cmd=0x%x lastcmd=0x%x", sp->sn.cmd, lastcmd);
|
||||
}
|
||||
|
||||
void
|
||||
@ -384,26 +364,6 @@ ism_recv(isc_session_t *sp, pduq_t *pq)
|
||||
|
||||
bhs = &pq->pdu.ipdu.bhs;
|
||||
statSN = ntohl(bhs->OpcodeSpecificFields[1]);
|
||||
#if 0
|
||||
{
|
||||
/*
|
||||
| this code is only for debugging.
|
||||
*/
|
||||
sn_t *sn = &sp->sn;
|
||||
if(sp->cws == 0) {
|
||||
if((sp->flags & ISC_STALLED) == 0) {
|
||||
sdebug(4, "window closed: max=0x%x exp=0x%x opcode=0x%x cmd=0x%x cws=%d.",
|
||||
sn->maxCmd, sn->expCmd, bhs->opcode, sn->cmd, sp->cws);
|
||||
sp->flags |= ISC_STALLED;
|
||||
} else
|
||||
if(sp->flags & ISC_STALLED) {
|
||||
sdebug(4, "window opened: max=0x%x exp=0x%x opcode=0x%x cmd=0x%x cws=%d.",
|
||||
sn->maxCmd, sn->expCmd, bhs->opcode, sn->cmd, sp->cws);
|
||||
sp->flags &= ~ISC_STALLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef notyet
|
||||
if(sp->sn.expCmd != sn->cmd) {
|
||||
@ -454,7 +414,7 @@ ism_recv(isc_session_t *sp, pduq_t *pq)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
| go through the out queues looking for work
|
||||
| if either nothing to do, or window is closed
|
||||
@ -465,11 +425,10 @@ proc_out(isc_session_t *sp)
|
||||
{
|
||||
sn_t *sn = &sp->sn;
|
||||
pduq_t *pq;
|
||||
int error, ndone;
|
||||
int which;
|
||||
int error, which;
|
||||
|
||||
debug_called(8);
|
||||
error = ndone = 0;
|
||||
error = 0;
|
||||
|
||||
while(sp->flags & ISC_LINK_UP) {
|
||||
pdu_t *pp;
|
||||
@ -508,7 +467,7 @@ proc_out(isc_session_t *sp)
|
||||
sn->cmd++;
|
||||
|
||||
case ISCSI_WRITE_DATA:
|
||||
bhs->ExpStSN = htonl(sn->stat);
|
||||
bhs->ExpStSN = htonl(sn->stat + 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -523,19 +482,21 @@ proc_out(isc_session_t *sp)
|
||||
bhs->opcode,
|
||||
sn->cmd, sn->expCmd, sn->maxCmd, sn->expStat, sn->itt);
|
||||
|
||||
if(pq->ccb)
|
||||
if(bhs->opcode != ISCSI_NOP_OUT)
|
||||
/*
|
||||
| enqued till ack is received
|
||||
| note: sosend(...) does not mean the packet left
|
||||
| the host so that freeing resources has to wait
|
||||
*/
|
||||
i_nqueue_hld(sp, pq);
|
||||
|
||||
if((error = isc_sendPDU(sp, pq)) == 0) {
|
||||
ndone++;
|
||||
if(pq->ccb == NULL)
|
||||
pdu_free(sp->isc, pq);
|
||||
}
|
||||
else {
|
||||
xdebug("error=%d ndone=%d opcode=0x%x ccb=%p itt=%x",
|
||||
error, ndone, bhs->opcode, pq->ccb, ntohl(bhs->itt));
|
||||
if(pq->ccb)
|
||||
i_remove_hld(sp, pq);
|
||||
error = isc_sendPDU(sp, pq);
|
||||
if(bhs->opcode == ISCSI_NOP_OUT)
|
||||
pdu_free(sp->isc, pq);
|
||||
if(error) {
|
||||
xdebug("error=%d opcode=0x%x ccb=%p itt=%x",
|
||||
error, bhs->opcode, pq->ccb, ntohl(bhs->itt));
|
||||
i_remove_hld(sp, pq);
|
||||
switch(error) {
|
||||
case EPIPE:
|
||||
sp->flags &= ~ISC_LINK_UP;
|
||||
@ -546,12 +507,12 @@ proc_out(isc_session_t *sp)
|
||||
break;
|
||||
|
||||
default:
|
||||
if(pq->ccb) {
|
||||
if(pq->ccb) {
|
||||
xdebug("back to cam");
|
||||
pq->ccb->ccb_h.status |= CAM_REQUEUE_REQ; // some better error?
|
||||
XPT_DONE(sp->isc, pq->ccb);
|
||||
XPT_DONE(sp, pq->ccb);
|
||||
pdu_free(sp->isc, pq);
|
||||
}
|
||||
}
|
||||
else
|
||||
xdebug("we lost it!");
|
||||
}
|
||||
@ -559,12 +520,12 @@ proc_out(isc_session_t *sp)
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
| survives link breakdowns.
|
||||
*/
|
||||
static void
|
||||
ism_proc(void *vp)
|
||||
ism_out(void *vp)
|
||||
{
|
||||
isc_session_t *sp = (isc_session_t *)vp;
|
||||
int error;
|
||||
@ -580,8 +541,11 @@ ism_proc(void *vp)
|
||||
sdebug(3, "error=%d", error);
|
||||
}
|
||||
}
|
||||
mtx_lock(&sp->io_mtx);
|
||||
mtx_lock(&sp->io_mtx);
|
||||
if((sp->flags & ISC_LINK_UP) == 0) {
|
||||
sdebug(3, "ISC_LINK_UP==0, sp->flags=%x ", sp->flags);
|
||||
if(sp->soc != NULL)
|
||||
sdebug(3, "so_state=%x", sp->soc->so_state);
|
||||
wakeup(&sp->soc);
|
||||
}
|
||||
|
||||
@ -589,7 +553,7 @@ ism_proc(void *vp)
|
||||
sp->flags |= ISC_OWAITING;
|
||||
if(msleep(&sp->flags, &sp->io_mtx, PRIBIO, "isc_proc", hz*30) == EWOULDBLOCK) {
|
||||
if(sp->flags & ISC_CON_RUNNING)
|
||||
_nop_out(sp);
|
||||
_nop_out(sp);
|
||||
}
|
||||
sp->flags &= ~ISC_OWAITING;
|
||||
}
|
||||
@ -600,14 +564,20 @@ ism_proc(void *vp)
|
||||
sp->flags &= ~ISC_SM_RUNNING;
|
||||
sdebug(3, "dropped ISC_SM_RUNNING");
|
||||
|
||||
wakeup(&sp->soc);
|
||||
wakeup(sp); // XXX: do we need this one?
|
||||
|
||||
#if __FreeBSD_version >= 700000
|
||||
destroy_dev(sp->dev);
|
||||
#endif
|
||||
wakeup(sp);
|
||||
|
||||
debug(3, "terminated sp=%p sp->sid=%d", sp, sp->sid);
|
||||
|
||||
#if __FreeBSD_version >= 800000
|
||||
kproc_exit(0);
|
||||
#else
|
||||
kthread_exit(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -753,12 +723,16 @@ ism_stop(isc_session_t *sp)
|
||||
|
||||
(void)i_pdu_flush(sp);
|
||||
|
||||
ic_lost_target(sp, sp->sid);
|
||||
ic_destroy(sp);
|
||||
|
||||
mtx_lock(&sc->mtx);
|
||||
sx_xlock(&sc->unit_sx);
|
||||
free_unr(sc->unit, sp->sid);
|
||||
sx_xunlock(&sc->unit_sx);
|
||||
|
||||
mtx_lock(&sc->isc_mtx);
|
||||
TAILQ_REMOVE(&sc->isc_sess, sp, sp_link);
|
||||
sc->nsess--;
|
||||
mtx_unlock(&sc->mtx);
|
||||
mtx_unlock(&sc->isc_mtx);
|
||||
|
||||
#if __FreeBSD_version < 700000
|
||||
destroy_dev(sp->dev);
|
||||
@ -771,7 +745,6 @@ ism_stop(isc_session_t *sp)
|
||||
mtx_destroy(&sp->io_mtx);
|
||||
|
||||
i_freeopt(&sp->opt);
|
||||
sc->sessions[sp->sid] = NULL;
|
||||
|
||||
if(sysctl_ctx_free(&sp->clist))
|
||||
xdebug("sysctl_ctx_free failed");
|
||||
@ -792,17 +765,11 @@ ism_start(isc_session_t *sp)
|
||||
TAILQ_INIT(&sp->isnd);
|
||||
TAILQ_INIT(&sp->wsnd);
|
||||
TAILQ_INIT(&sp->hld);
|
||||
#if 1
|
||||
|
||||
mtx_init(&sp->rsv_mtx, "iscsi-rsv", NULL, MTX_DEF);
|
||||
mtx_init(&sp->rsp_mtx, "iscsi-rsp", NULL, MTX_DEF);
|
||||
mtx_init(&sp->snd_mtx, "iscsi-snd", NULL, MTX_DEF);
|
||||
mtx_init(&sp->hld_mtx, "iscsi-hld", NULL, MTX_DEF);
|
||||
#else
|
||||
mtx_init(&sp->rsv_mtx, "iscsi-rsv", NULL, MTX_SPIN);
|
||||
mtx_init(&sp->rsp_mtx, "iscsi-rsp", NULL, MTX_SPIN);
|
||||
mtx_init(&sp->snd_mtx, "iscsi-snd", NULL, MTX_SPIN);
|
||||
mtx_init(&sp->hld_mtx, "iscsi-hld", NULL, MTX_SPIN);
|
||||
#endif
|
||||
mtx_init(&sp->io_mtx, "iscsi-io", NULL, MTX_DEF);
|
||||
|
||||
isc_add_sysctls(sp);
|
||||
@ -810,5 +777,10 @@ ism_start(isc_session_t *sp)
|
||||
sp->flags |= ISC_SM_RUN;
|
||||
|
||||
debug(4, "starting ism_proc: sp->sid=%d", sp->sid);
|
||||
return kproc_create(ism_proc, sp, &sp->stp, 0, 0, "ism_%d", sp->sid);
|
||||
|
||||
#if __FreeBSD_version >= 800000
|
||||
return kproc_create(ism_out, sp, &sp->stp, 0, 0, "isc_out %d", sp->sid);
|
||||
#else
|
||||
return kthread_create(ism_out, sp, &sp->stp, 0, 0, "isc_out %d", sp->sid);
|
||||
#endif
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -25,10 +25,8 @@
|
||||
*
|
||||
*/
|
||||
/*
|
||||
| iSCSI
|
||||
| $Id: isc_soc.c,v 1.26 2007/05/19 06:09:01 danny Exp danny $
|
||||
| $Id: isc_soc.c 998 2009-12-20 10:32:45Z danny $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
@ -66,9 +64,7 @@ __FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
|
||||
#ifdef USE_MBUF
|
||||
|
||||
static int ou_refcnt = 0;
|
||||
|
||||
/*
|
||||
| function for freeing external storage for mbuf
|
||||
*/
|
||||
@ -79,7 +75,7 @@ ext_free(void *a, void *b)
|
||||
|
||||
if(pq->buf != NULL) {
|
||||
debug(3, "ou_refcnt=%d a=%p b=%p", ou_refcnt, a, pq->buf);
|
||||
free(pq->buf, M_ISCSI);
|
||||
free(pq->buf, M_ISCSIBUF);
|
||||
pq->buf = NULL;
|
||||
}
|
||||
}
|
||||
@ -88,84 +84,96 @@ int
|
||||
isc_sendPDU(isc_session_t *sp, pduq_t *pq)
|
||||
{
|
||||
struct mbuf *mh, **mp;
|
||||
pdu_t *pp = &pq->pdu;
|
||||
int len, error;
|
||||
pdu_t *pp = &pq->pdu;
|
||||
int len, error;
|
||||
|
||||
debug_called(8);
|
||||
/*
|
||||
| mbuf for the iSCSI header
|
||||
*/
|
||||
MGETHDR(mh, M_TRYWAIT, MT_DATA);
|
||||
mh->m_len = mh->m_pkthdr.len = sizeof(union ipdu_u);
|
||||
mh->m_pkthdr.rcvif = NULL;
|
||||
MH_ALIGN(mh, sizeof(union ipdu_u));
|
||||
bcopy(&pp->ipdu, mh->m_data, sizeof(union ipdu_u));
|
||||
mh->m_next = NULL;
|
||||
mh->m_len = sizeof(union ipdu_u);
|
||||
|
||||
if(sp->hdrDigest)
|
||||
pq->pdu.hdr_dig = sp->hdrDigest(&pp->ipdu, sizeof(union ipdu_u), 0);
|
||||
if(ISOK2DIG(sp->hdrDigest, pp)) {
|
||||
pp->hdr_dig = sp->hdrDigest(&pp->ipdu, sizeof(union ipdu_u), 0);
|
||||
mh->m_len += sizeof(pp->hdr_dig);
|
||||
if(pp->ahs_len) {
|
||||
debug(2, "ahs_len=%d", pp->ahs_len);
|
||||
pp->hdr_dig = sp->hdrDigest(&pp->ahs_addr, pp->ahs_len, pp->hdr_dig);
|
||||
}
|
||||
debug(3, "pp->hdr_dig=%04x", htonl(pp->hdr_dig));
|
||||
}
|
||||
if(pp->ahs_len) {
|
||||
/*
|
||||
| Add any AHS to the iSCSI hdr mbuf
|
||||
| XXX Assert: (mh->m_pkthdr.len + pp->ahs_len) < MHLEN
|
||||
*/
|
||||
bcopy(pp->ahs, (mh->m_data + mh->m_len), pp->ahs_len);
|
||||
mh->m_len += pp->ahs_len;
|
||||
mh->m_pkthdr.len += pp->ahs_len;
|
||||
|
||||
if(sp->hdrDigest)
|
||||
pq->pdu.hdr_dig = sp->hdrDigest(&pp->ahs, pp->ahs_len, pq->pdu.hdr_dig);
|
||||
if((mh->m_len + pp->ahs_len) < MHLEN) {
|
||||
MH_ALIGN(mh, mh->m_len + pp->ahs_len);
|
||||
bcopy(&pp->ipdu, mh->m_data, mh->m_len);
|
||||
bcopy(pp->ahs_addr, mh->m_data + mh->m_len, pp->ahs_len);
|
||||
mh->m_len += pp->ahs_len;
|
||||
}
|
||||
else
|
||||
panic("len AHS=%d too big, not impleneted yet", pp->ahs_len);
|
||||
}
|
||||
if(sp->hdrDigest) {
|
||||
debug(2, "hdr_dig=%x", pq->pdu.hdr_dig);
|
||||
/*
|
||||
| Add header digest to the iSCSI hdr mbuf
|
||||
| XXX Assert: (mh->m_pkthdr.len + 4) < MHLEN
|
||||
*/
|
||||
bcopy(&pp->hdr_dig, (mh->m_data + mh->m_len), sizeof(int));
|
||||
mh->m_len += sizeof(int);
|
||||
mh->m_pkthdr.len += sizeof(int);
|
||||
else {
|
||||
MH_ALIGN(mh, mh->m_len);
|
||||
bcopy(&pp->ipdu, mh->m_data, mh->m_len);
|
||||
}
|
||||
mh->m_pkthdr.len = mh->m_len;
|
||||
mp = &mh->m_next;
|
||||
if(pq->pdu.ds) {
|
||||
struct mbuf *md;
|
||||
int off = 0;
|
||||
if(pp->ds_len && pq->pdu.ds_addr) {
|
||||
struct mbuf *md;
|
||||
int off = 0;
|
||||
|
||||
len = pp->ds_len;
|
||||
while(len & 03) // the specs say it must be int alligned
|
||||
len++;
|
||||
while(len > 0) {
|
||||
int l;
|
||||
|
||||
int l;
|
||||
|
||||
MGET(md, M_TRYWAIT, MT_DATA);
|
||||
md->m_ext.ref_cnt = &ou_refcnt;
|
||||
l = min(MCLBYTES, len);
|
||||
debug(5, "setting ext_free(arg=%p len/l=%d/%d)", pq->buf, len, l);
|
||||
MEXTADD(md, pp->ds + off, l, ext_free, pp->ds + off, pq, 0, EXT_EXTREF);
|
||||
md->m_len = l;
|
||||
md->m_next = NULL;
|
||||
mh->m_pkthdr.len += l;
|
||||
*mp = md;
|
||||
mp = &md->m_next;
|
||||
len -= l;
|
||||
off += l;
|
||||
}
|
||||
}
|
||||
if(sp->dataDigest) {
|
||||
struct mbuf *me;
|
||||
|
||||
pp->ds_dig = sp->dataDigest(pp->ds, pp->ds_len, 0);
|
||||
|
||||
MGET(me, M_TRYWAIT, MT_DATA);
|
||||
me->m_len = sizeof(int);
|
||||
MH_ALIGN(mh, sizeof(int));
|
||||
bcopy(&pp->ds_dig, me->m_data, sizeof(int));
|
||||
me->m_next = NULL;
|
||||
mh->m_pkthdr.len += sizeof(int);
|
||||
*mp = me;
|
||||
l = min(MCLBYTES, len);
|
||||
debug(4, "setting ext_free(arg=%p len/l=%d/%d)", pq->buf, len, l);
|
||||
MEXTADD(md, pp->ds_addr + off, l, ext_free,
|
||||
#if __FreeBSD_version >= 800000
|
||||
pp->ds_addr + off,
|
||||
#endif
|
||||
pq, 0, EXT_EXTREF);
|
||||
md->m_len = l;
|
||||
md->m_next = NULL;
|
||||
mh->m_pkthdr.len += l;
|
||||
*mp = md;
|
||||
mp = &md->m_next;
|
||||
len -= l;
|
||||
off += l;
|
||||
}
|
||||
if(((pp->ds_len & 03) != 0) || ISOK2DIG(sp->dataDigest, pp)) {
|
||||
MGET(md, M_TRYWAIT, MT_DATA);
|
||||
if(pp->ds_len & 03)
|
||||
len = 4 - (pp->ds_len & 03);
|
||||
else
|
||||
len = 0;
|
||||
md->m_len = len;
|
||||
if(ISOK2DIG(sp->dataDigest, pp))
|
||||
md->m_len += sizeof(pp->ds_dig);
|
||||
M_ALIGN(md, md->m_len);
|
||||
if(ISOK2DIG(sp->dataDigest, pp)) {
|
||||
pp->ds_dig = sp->dataDigest(pp->ds_addr, pp->ds_len, 0);
|
||||
if(len) {
|
||||
bzero(md->m_data, len); // RFC says SHOULD be 0
|
||||
pp->ds_dig = sp->dataDigest(md->m_data, len, pp->ds_dig);
|
||||
}
|
||||
bcopy(&pp->ds_dig, md->m_data+len, sizeof(pp->ds_dig));
|
||||
}
|
||||
md->m_next = NULL;
|
||||
mh->m_pkthdr.len += md->m_len;
|
||||
*mp = md;
|
||||
}
|
||||
}
|
||||
if((error = sosend(sp->soc, NULL, NULL, mh, 0, 0, sp->td)) != 0) {
|
||||
sdebug(3, "error=%d", error);
|
||||
sdebug(2, "error=%d", error);
|
||||
return error;
|
||||
}
|
||||
sp->stats.nsent++;
|
||||
@ -191,39 +199,46 @@ isc_sendPDU(isc_session_t *sp, pduq_t *pq)
|
||||
|
||||
iv->iov_base = &pp->ipdu;
|
||||
iv->iov_len = sizeof(union ipdu_u);
|
||||
uio->uio_resid = pq->len;
|
||||
uio->uio_resid = iv->iov_len;
|
||||
iv++;
|
||||
if(sp->hdrDigest)
|
||||
if(ISOK2DIG(sp->hdrDigest, pp))
|
||||
pq->pdu.hdr_dig = sp->hdrDigest(&pp->ipdu, sizeof(union ipdu_u), 0);
|
||||
if(pp->ahs_len) {
|
||||
iv->iov_base = pp->ahs;
|
||||
iv->iov_base = pp->ahs_addr;
|
||||
iv->iov_len = pp->ahs_len;
|
||||
uio->uio_resid += iv->iov_len;
|
||||
iv++;
|
||||
|
||||
if(sp->hdrDigest)
|
||||
pq->pdu.hdr_dig = sp->hdrDigest(&pp->ahs, pp->ahs_len, pq->pdu.hdr_dig);
|
||||
if(ISOK2DIG(sp->hdrDigest, pp))
|
||||
pp->hdr_dig = sp->hdrDigest(&pp->ahs_addr, pp->ahs_len, pp->hdr_dig);
|
||||
}
|
||||
if(sp->hdrDigest) {
|
||||
debug(2, "hdr_dig=%x", pq->pdu.hdr_dig);
|
||||
if(ISOK2DIG(sp->hdrDigest, pp)) {
|
||||
debug(3, "hdr_dig=%04x", htonl(pp->hdr_dig));
|
||||
iv->iov_base = &pp->hdr_dig;
|
||||
iv->iov_len = sizeof(int);
|
||||
uio->uio_resid += iv->iov_len ;
|
||||
iv++;
|
||||
}
|
||||
if(pq->pdu.ds) {
|
||||
iv->iov_base = pp->ds;
|
||||
if(pq->pdu.ds_addr && pp->ds_len) {
|
||||
iv->iov_base = pp->ds_addr;
|
||||
iv->iov_len = pp->ds_len;
|
||||
while(iv->iov_len & 03) // the specs say it must be int alligned
|
||||
iv->iov_len++;
|
||||
uio->uio_resid += iv->iov_len ;
|
||||
iv++;
|
||||
if(ISOK2DIG(sp->dataDigest, pp)) {
|
||||
pp->ds_dig = sp->dataDigest(pp->ds, pp->ds_len, 0);
|
||||
iv->iov_base = &pp->ds_dig;
|
||||
iv->iov_len = sizeof(pp->ds_dig);
|
||||
uio->uio_resid += iv->iov_len ;
|
||||
iv++;
|
||||
}
|
||||
}
|
||||
if(sp->dataDigest) {
|
||||
pp->ds_dig = sp->dataDigest(pp->ds, pp->ds_len, 0);
|
||||
iv->iov_base = &pp->ds_dig;
|
||||
iv->iov_len = sizeof(int);
|
||||
iv++;
|
||||
}
|
||||
uio->uio_iovcnt = iv - pq->iov;
|
||||
sdebug(5, "opcode=%x iovcnt=%d uio_resid=%d itt=%x",
|
||||
uio->uio_iovcnt = iv - pq->iov;
|
||||
sdebug(4, "pq->len=%d uio->uio_resid=%d uio->uio_iovcnt=%d", pq->len,
|
||||
uio->uio_resid,
|
||||
uio->uio_iovcnt);
|
||||
|
||||
sdebug(4, "opcode=%x iovcnt=%d uio_resid=%d itt=%x",
|
||||
pp->ipdu.bhs.opcode, uio->uio_iovcnt, uio->uio_resid,
|
||||
ntohl(pp->ipdu.bhs.itt));
|
||||
sdebug(5, "sp=%p sp->soc=%p uio=%p sp->td=%p",
|
||||
@ -244,12 +259,12 @@ isc_sendPDU(isc_session_t *sp, pduq_t *pq)
|
||||
| XXX: untested code
|
||||
*/
|
||||
sdebug(1, "uio->uio_resid=%d uio->uio_iovcnt=%d",
|
||||
uio->uio_resid, uio->uio_iovcnt);
|
||||
uio->uio_resid, uio->uio_iovcnt);
|
||||
iv = uio->uio_iov;
|
||||
len -= uio->uio_resid;
|
||||
while(uio->uio_iovcnt > 0) {
|
||||
if(iv->iov_len > len) {
|
||||
caddr_t bp = (caddr_t)iv->iov_base;
|
||||
caddr_t bp = (caddr_t)iv->iov_base;
|
||||
|
||||
iv->iov_len -= len;
|
||||
iv->iov_base = (void *)&bp[len];
|
||||
@ -265,7 +280,6 @@ isc_sendPDU(isc_session_t *sp, pduq_t *pq)
|
||||
if(error == 0) {
|
||||
sp->stats.nsent++;
|
||||
getbintime(&sp->stats.t_sent);
|
||||
|
||||
}
|
||||
|
||||
return error;
|
||||
@ -322,159 +336,197 @@ so_getbhs(isc_session_t *sp)
|
||||
error = soreceive(sp->soc, NULL, uio, 0, 0, &flags);
|
||||
|
||||
if(error)
|
||||
debug(2, "error=%d so_error=%d uio->uio_resid=%zd iov.iov_len=%zd",
|
||||
debug(2,
|
||||
#if __FreeBSD_version > 800000
|
||||
"error=%d so_error=%d uio->uio_resid=%zd iov.iov_len=%zd",
|
||||
#else
|
||||
"error=%d so_error=%d uio->uio_resid=%d iov.iov_len=%zd",
|
||||
#endif
|
||||
error,
|
||||
sp->soc->so_error, uio->uio_resid, iov->iov_len);
|
||||
if(!error && (uio->uio_resid > 0)) {
|
||||
error = EPIPE; // was EAGAIN
|
||||
debug(2, "error=%d so_error=%d uio->uio_resid=%zd iov.iov_len=%zd so_state=%x",
|
||||
debug(2,
|
||||
#if __FreeBSD_version > 800000
|
||||
"error=%d so_error=%d uio->uio_resid=%zd iov.iov_len=%zd so_state=%x",
|
||||
#else
|
||||
"error=%d so_error=%d uio->uio_resid=%d iov.iov_len=%zd so_state=%x",
|
||||
#endif
|
||||
error,
|
||||
sp->soc->so_error, uio->uio_resid, iov->iov_len, sp->soc->so_state);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
| so_recv gets called when there is at least
|
||||
| an iSCSI header in the queue
|
||||
| so_recv gets called when
|
||||
| an iSCSI header has been received.
|
||||
| Note: the designers had no intentions
|
||||
| in making programmer's life easy.
|
||||
*/
|
||||
static int
|
||||
so_recv(isc_session_t *sp, pduq_t *pq)
|
||||
{
|
||||
struct socket *so = sp->soc;
|
||||
sn_t *sn = &sp->sn;
|
||||
struct uio *uio = &pq->uio;
|
||||
pdu_t *pp;
|
||||
pdu_t *pp = &pq->pdu;
|
||||
bhs_t *bhs = &pp->ipdu.bhs;
|
||||
struct iovec *iov = pq->iov;
|
||||
int error;
|
||||
size_t n, len;
|
||||
bhs_t *bhs;
|
||||
u_int len;
|
||||
u_int max, exp;
|
||||
int flags = MSG_WAITALL;
|
||||
|
||||
debug_called(8);
|
||||
/*
|
||||
| now calculate how much data should be in the buffer
|
||||
| NOTE: digest is not verified/calculated - yet
|
||||
*/
|
||||
pp = &pq->pdu;
|
||||
bhs = &pp->ipdu.bhs;
|
||||
|
||||
uio->uio_iov = iov;
|
||||
uio->uio_iovcnt = 0;
|
||||
len = 0;
|
||||
if(bhs->AHSLength) {
|
||||
debug(2, "bhs->AHSLength=%d", bhs->AHSLength);
|
||||
pp->ahs_len = bhs->AHSLength * 4;
|
||||
len += pp->ahs_len;
|
||||
pp->ahs_addr = malloc(pp->ahs_len, M_TEMP, M_WAITOK); // XXX: could get stuck here
|
||||
iov->iov_base = pp->ahs_addr;
|
||||
iov->iov_len = pp->ahs_len;
|
||||
uio->uio_iovcnt++;
|
||||
iov++;
|
||||
}
|
||||
if(sp->hdrDigest)
|
||||
len += 4;
|
||||
if(bhs->DSLength) {
|
||||
n = bhs->DSLength;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
pp->ds_len = ((n & 0x00ff0000) >> 16)
|
||||
| (n & 0x0000ff00)
|
||||
| ((n & 0x000000ff) << 16);
|
||||
#else
|
||||
pp->ds_len = n;
|
||||
#endif
|
||||
len += pp->ds_len;
|
||||
while(len & 03)
|
||||
len++;
|
||||
if(sp->dataDigest)
|
||||
len += 4;
|
||||
}
|
||||
|
||||
if((sp->opt.maxRecvDataSegmentLength > 0) && (len > sp->opt.maxRecvDataSegmentLength)) {
|
||||
#if 0
|
||||
xdebug("impossible PDU length(%d) opt.maxRecvDataSegmentLength=%d",
|
||||
len, sp->opt.maxRecvDataSegmentLength);
|
||||
// deep trouble here, probably all we can do is
|
||||
// force a disconnect, XXX: check RFC ...
|
||||
log(LOG_ERR,
|
||||
"so_recv: impossible PDU length(%ld) from iSCSI %s/%s\n",
|
||||
len, sp->opt.targetAddress, sp->opt.targetName);
|
||||
#endif
|
||||
/*
|
||||
| XXX: this will really screwup the stream.
|
||||
| should clear up the buffer till a valid header
|
||||
| is found, or just close connection ...
|
||||
| should read the RFC.
|
||||
*/
|
||||
error = E2BIG;
|
||||
goto out;
|
||||
if(ISOK2DIG(sp->hdrDigest, pp)) {
|
||||
len += sizeof(pp->hdr_dig);
|
||||
iov->iov_base = &pp->hdr_dig;
|
||||
iov->iov_len = sizeof(pp->hdr_dig);
|
||||
uio->uio_iovcnt++;
|
||||
}
|
||||
if(len) {
|
||||
int flags = MSG_WAITALL;
|
||||
struct mbuf **mp;
|
||||
|
||||
mp = &pq->mp;
|
||||
|
||||
uio->uio_resid = len;
|
||||
uio->uio_td = curthread; // why ...
|
||||
if(sp->douio) {
|
||||
// it's more efficient to use mbufs -- why?
|
||||
if(bhs->opcode == ISCSI_READ_DATA) {
|
||||
pduq_t *opq;
|
||||
|
||||
opq = i_search_hld(sp, pq->pdu.ipdu.bhs.itt, 1);
|
||||
if(opq != NULL) {
|
||||
union ccb *ccb = opq->ccb;
|
||||
struct ccb_scsiio *csio = &ccb->csio;
|
||||
pdu_t *opp = &opq->pdu;
|
||||
scsi_req_t *cmd = &opp->ipdu.scsi_req;
|
||||
data_in_t *rcmd = &pq->pdu.ipdu.data_in;
|
||||
bhs_t *bhp = &opp->ipdu.bhs;
|
||||
int r;
|
||||
|
||||
if(bhp->opcode == ISCSI_SCSI_CMD
|
||||
&& cmd->R
|
||||
&& (ntohl(cmd->edtlen) >= pq->pdu.ds_len)) {
|
||||
struct iovec *iov = pq->iov;
|
||||
iov->iov_base = csio->data_ptr + ntohl(rcmd->bo);
|
||||
iov->iov_len = pq->pdu.ds_len;
|
||||
|
||||
uio->uio_rw = UIO_READ;
|
||||
uio->uio_segflg = UIO_SYSSPACE;
|
||||
uio->uio_iov = iov;
|
||||
uio->uio_iovcnt = 1;
|
||||
if(len > pq->pdu.ds_len) {
|
||||
pq->iov[1].iov_base = &r;
|
||||
pq->iov[1].iov_len = len - pq->pdu.ds_len;
|
||||
uio->uio_iovcnt++;
|
||||
}
|
||||
mp = NULL;
|
||||
|
||||
sdebug(4, "uio_resid=0x%zx itt=0x%x bp=%p bo=%x len=%x/%x",
|
||||
uio->uio_resid,
|
||||
ntohl(pq->pdu.ipdu.bhs.itt),
|
||||
csio->data_ptr, ntohl(rcmd->bo), ntohl(cmd->edtlen), pq->pdu.ds_len);
|
||||
}
|
||||
}
|
||||
uio->uio_rw = UIO_READ;
|
||||
uio->uio_segflg = UIO_SYSSPACE;
|
||||
uio->uio_resid = len;
|
||||
uio->uio_td = sp->td; // why ...
|
||||
error = soreceive(sp->soc, NULL, uio, NULL, NULL, &flags);
|
||||
//if(error == EAGAIN)
|
||||
// XXX: this needs work! it hangs iscontrol
|
||||
if(error || uio->uio_resid) {
|
||||
debug(2,
|
||||
#if __FreeBSD_version > 800000
|
||||
"len=%d error=%d uio->uio_resid=%zd",
|
||||
#else
|
||||
"len=%d error=%d uio->uio_resid=%d",
|
||||
#endif
|
||||
len, error, uio->uio_resid);
|
||||
goto out;
|
||||
}
|
||||
if(ISOK2DIG(sp->hdrDigest, pp)) {
|
||||
bhs_t *bhs;
|
||||
u_int digest;
|
||||
|
||||
bhs = (bhs_t *)&pp->ipdu;
|
||||
digest = sp->hdrDigest(bhs, sizeof(bhs_t), 0);
|
||||
if(pp->ahs_len)
|
||||
digest = sp->hdrDigest(pp->ahs_addr, pp->ahs_len, digest);
|
||||
if(pp->hdr_dig != digest) {
|
||||
debug(2, "bad header digest: received=%x calculated=%x", pp->hdr_dig, digest);
|
||||
// XXX: now what?
|
||||
error = EIO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
error = soreceive(so, NULL, uio, mp, NULL, &flags);
|
||||
if(pp->ahs_len) {
|
||||
debug(2, "ahs len=%x type=%x spec=%x",
|
||||
pp->ahs_addr->len, pp->ahs_addr->type, pp->ahs_addr->spec);
|
||||
// XXX: till I figure out what to do with this
|
||||
free(pp->ahs_addr, M_TEMP);
|
||||
}
|
||||
pq->len += len; // XXX: who needs this?
|
||||
bzero(uio, sizeof(struct uio));
|
||||
len = 0;
|
||||
}
|
||||
|
||||
if(bhs->DSLength) {
|
||||
len = bhs->DSLength;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
len = ((len & 0x00ff0000) >> 16)
|
||||
| (len & 0x0000ff00)
|
||||
| ((len & 0x000000ff) << 16);
|
||||
#endif
|
||||
pp->ds_len = len;
|
||||
if((sp->opt.maxRecvDataSegmentLength > 0) && (len > sp->opt.maxRecvDataSegmentLength)) {
|
||||
xdebug("impossible PDU length(%d) opt.maxRecvDataSegmentLength=%d",
|
||||
len, sp->opt.maxRecvDataSegmentLength);
|
||||
log(LOG_ERR,
|
||||
"so_recv: impossible PDU length(%d) from iSCSI %s/%s\n",
|
||||
len, sp->opt.targetAddress, sp->opt.targetName);
|
||||
/*
|
||||
| XXX: this will really screwup the stream.
|
||||
| should clear up the buffer till a valid header
|
||||
| is found, or just close connection ...
|
||||
| should read the RFC.
|
||||
*/
|
||||
error = E2BIG;
|
||||
goto out;
|
||||
}
|
||||
while(len & 03)
|
||||
len++;
|
||||
if(ISOK2DIG(sp->dataDigest, pp))
|
||||
len += 4;
|
||||
uio->uio_resid = len;
|
||||
uio->uio_td = sp->td; // why ...
|
||||
pq->len += len; // XXX: do we need this?
|
||||
error = soreceive(sp->soc, NULL, uio, &pq->mp, NULL, &flags);
|
||||
//if(error == EAGAIN)
|
||||
// XXX: this needs work! it hangs iscontrol
|
||||
if(error || uio->uio_resid)
|
||||
goto out;
|
||||
if(ISOK2DIG(sp->dataDigest, pp)) {
|
||||
struct mbuf *m;
|
||||
u_int digest, ds_len, cnt;
|
||||
|
||||
// get the received digest
|
||||
m_copydata(pq->mp,
|
||||
len - sizeof(pp->ds_dig),
|
||||
sizeof(pp->ds_dig),
|
||||
(caddr_t)&pp->ds_dig);
|
||||
// calculate all mbufs
|
||||
digest = 0;
|
||||
ds_len = len - sizeof(pp->ds_dig);
|
||||
for(m = pq->mp; m != NULL; m = m->m_next) {
|
||||
cnt = MIN(ds_len, m->m_len);
|
||||
digest = sp->dataDigest(mtod(m, char *), cnt, digest);
|
||||
ds_len -= cnt;
|
||||
if(ds_len == 0)
|
||||
break;
|
||||
}
|
||||
if(digest != pp->ds_dig) {
|
||||
sdebug(1, "bad data digest: received=%x calculated=%x", pp->ds_dig, digest);
|
||||
error = EIO; // XXX: find a better error
|
||||
goto out;
|
||||
}
|
||||
KASSERT(ds_len == 0, ("ds_len not zero"));
|
||||
}
|
||||
}
|
||||
pq->len += len;
|
||||
sdebug(6, "len=%d] opcode=0x%x ahs_len=0x%x ds_len=0x%x",
|
||||
pq->len, bhs->opcode, pp->ahs_len, pp->ds_len);
|
||||
|
||||
max = ntohl(bhs->MaxCmdSN);
|
||||
exp = ntohl(bhs->ExpStSN);
|
||||
|
||||
if(max < exp - 1 &&
|
||||
max > exp - _MAXINCR) {
|
||||
sdebug(2, "bad cmd window size");
|
||||
error = EIO; // XXX: for now;
|
||||
goto out; // error
|
||||
}
|
||||
|
||||
if(SNA_GT(max, sn->maxCmd))
|
||||
sn->maxCmd = max;
|
||||
|
||||
if(SNA_GT(exp, sn->expCmd))
|
||||
sn->expCmd = exp;
|
||||
/*
|
||||
| remove from the holding queue packets
|
||||
| that have been acked and don't need
|
||||
| further processing.
|
||||
*/
|
||||
i_acked_hld(sp, NULL);
|
||||
|
||||
sp->cws = sn->maxCmd - sn->expCmd + 1;
|
||||
|
||||
@ -482,6 +534,10 @@ so_recv(isc_session_t *sp, pduq_t *pq)
|
||||
|
||||
out:
|
||||
// XXX: need some work here
|
||||
if(pp->ahs_len) {
|
||||
// XXX: till I figure out what to do with this
|
||||
free(pp->ahs_addr, M_TEMP);
|
||||
}
|
||||
xdebug("have a problem, error=%d", error);
|
||||
pdu_free(sp->isc, pq);
|
||||
if(!error && uio->uio_resid > 0)
|
||||
@ -510,8 +566,8 @@ so_input(isc_session_t *sp)
|
||||
*/
|
||||
pq = pdu_alloc(sp->isc, M_NOWAIT);
|
||||
if(pq == NULL) { // XXX: might cause a deadlock ...
|
||||
debug(3, "out of pdus, wait");
|
||||
pq = pdu_alloc(sp->isc, M_NOWAIT); // OK to WAIT
|
||||
debug(2, "out of pdus, wait");
|
||||
pq = pdu_alloc(sp->isc, M_WAITOK); // OK to WAIT
|
||||
}
|
||||
pq->pdu.ipdu.bhs = sp->bhs;
|
||||
pq->len = sizeof(bhs_t); // so far only the header was read
|
||||
@ -536,7 +592,7 @@ so_input(isc_session_t *sp)
|
||||
| in packets from the target.
|
||||
*/
|
||||
static void
|
||||
isc_soc(void *vp)
|
||||
isc_in(void *vp)
|
||||
{
|
||||
isc_session_t *sp = (isc_session_t *)vp;
|
||||
struct socket *so = sp->soc;
|
||||
@ -545,9 +601,6 @@ isc_soc(void *vp)
|
||||
debug_called(8);
|
||||
|
||||
sp->flags |= ISC_CON_RUNNING;
|
||||
if(sp->cam_path)
|
||||
ic_release(sp);
|
||||
|
||||
error = 0;
|
||||
while((sp->flags & (ISC_CON_RUN | ISC_LINK_UP)) == (ISC_CON_RUN | ISC_LINK_UP)) {
|
||||
// XXX: hunting ...
|
||||
@ -559,7 +612,7 @@ isc_soc(void *vp)
|
||||
if(error == 0) {
|
||||
mtx_lock(&sp->io_mtx);
|
||||
if(sp->flags & ISC_OWAITING) {
|
||||
wakeup(&sp->flags);
|
||||
wakeup(&sp->flags);
|
||||
}
|
||||
mtx_unlock(&sp->io_mtx);
|
||||
} else if(error == EPIPE) {
|
||||
@ -594,8 +647,11 @@ isc_soc(void *vp)
|
||||
mtx_unlock(&sp->io_mtx);
|
||||
|
||||
sdebug(2, "dropped ISC_CON_RUNNING");
|
||||
|
||||
#if __FreeBSD_version >= 800000
|
||||
kproc_exit(0);
|
||||
#else
|
||||
kthread_exit(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@ -621,7 +677,6 @@ isc_stop_receiver(isc_session_t *sp)
|
||||
}
|
||||
mtx_unlock(&sp->io_mtx);
|
||||
|
||||
|
||||
if(sp->fp != NULL)
|
||||
fdrop(sp->fp, sp->td);
|
||||
fputsock(sp->soc);
|
||||
@ -637,6 +692,10 @@ isc_start_receiver(isc_session_t *sp)
|
||||
debug_called(8);
|
||||
|
||||
sp->flags |= ISC_CON_RUN | ISC_LINK_UP;
|
||||
|
||||
kproc_create(isc_soc, sp, &sp->soc_proc, 0, 0, "iscsi%d", sp->sid);
|
||||
#if __FreeBSD_version >= 800000
|
||||
kproc_create
|
||||
#else
|
||||
kthread_create
|
||||
#endif
|
||||
(isc_in, sp, &sp->soc_proc, 0, 0, "isc_in %d", sp->sid);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,7 +26,7 @@
|
||||
*/
|
||||
/*
|
||||
| iSCSI
|
||||
| $Id: isc_subr.c,v 1.20 2006/12/01 09:10:17 danny Exp danny $
|
||||
| $Id: isc_subr.c 560 2009-05-07 07:37:49Z danny $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
@ -58,20 +58,22 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/iscsi/initiator/iscsi.h>
|
||||
#include <dev/iscsi/initiator/iscsivar.h>
|
||||
|
||||
MALLOC_DEFINE(M_ISC, "iSC", "iSCSI driver options");
|
||||
|
||||
static char *
|
||||
i_strdupin(char *s, size_t maxlen)
|
||||
{
|
||||
size_t len;
|
||||
char *p, *q;
|
||||
|
||||
p = malloc(maxlen, M_ISCSI, M_WAITOK);
|
||||
p = malloc(maxlen, M_ISC, M_WAITOK);
|
||||
if(copyinstr(s, p, maxlen, &len)) {
|
||||
free(p, M_ISCSI);
|
||||
free(p, M_ISC);
|
||||
return NULL;
|
||||
}
|
||||
q = malloc(len, M_ISCSI, M_WAITOK);
|
||||
q = malloc(len, M_ISC, M_WAITOK);
|
||||
bcopy(p, q, len);
|
||||
free(p, M_ISCSI);
|
||||
free(p, M_ISC);
|
||||
|
||||
return q;
|
||||
}
|
||||
@ -98,50 +100,51 @@ i_setopt(isc_session_t *sp, isc_opt_t *opt)
|
||||
if(opt->maxXmitDataSegmentLength > 0) {
|
||||
// danny's RFC
|
||||
sp->opt.maxXmitDataSegmentLength = opt->maxXmitDataSegmentLength;
|
||||
sdebug(2, "maXmitDataSegmentLength=%d", sp->opt.maxXmitDataSegmentLength);
|
||||
sdebug(2, "opt.maXmitDataSegmentLength=%d", sp->opt.maxXmitDataSegmentLength);
|
||||
}
|
||||
if(opt->maxBurstLength != 0) {
|
||||
sp->opt.maxBurstLength = opt->maxBurstLength;
|
||||
sdebug(2, "maxBurstLength=%d", sp->opt.maxBurstLength);
|
||||
sdebug(2, "opt.maxBurstLength=%d", sp->opt.maxBurstLength);
|
||||
}
|
||||
|
||||
if(opt->targetAddress != NULL) {
|
||||
if(sp->opt.targetAddress != NULL)
|
||||
free(sp->opt.targetAddress, M_ISCSI);
|
||||
free(sp->opt.targetAddress, M_ISC);
|
||||
sp->opt.targetAddress = i_strdupin(opt->targetAddress, 128);
|
||||
sdebug(4, "opt.targetAddress='%s'", sp->opt.targetAddress);
|
||||
sdebug(2, "opt.targetAddress='%s'", sp->opt.targetAddress);
|
||||
}
|
||||
if(opt->targetName != NULL) {
|
||||
if(sp->opt.targetName != NULL)
|
||||
free(sp->opt.targetName, M_ISCSI);
|
||||
free(sp->opt.targetName, M_ISC);
|
||||
sp->opt.targetName = i_strdupin(opt->targetName, 128);
|
||||
sdebug(4, "opt.targetName='%s'", sp->opt.targetName);
|
||||
sdebug(2, "opt.targetName='%s'", sp->opt.targetName);
|
||||
}
|
||||
if(opt->initiatorName != NULL) {
|
||||
if(sp->opt.initiatorName != NULL)
|
||||
free(sp->opt.initiatorName, M_ISCSI);
|
||||
free(sp->opt.initiatorName, M_ISC);
|
||||
sp->opt.initiatorName = i_strdupin(opt->initiatorName, 128);
|
||||
sdebug(4, "opt.initiatorName='%s'", sp->opt.initiatorName);
|
||||
sdebug(2, "opt.initiatorName='%s'", sp->opt.initiatorName);
|
||||
}
|
||||
|
||||
if(opt->maxluns > 0) {
|
||||
if(opt->maxluns > ISCSI_MAX_LUNS)
|
||||
sp->opt.maxluns = ISCSI_MAX_LUNS; // silently chop it down ...
|
||||
sp->opt.maxluns = opt->maxluns;
|
||||
sdebug(4, "opt.maxluns=%d", sp->opt.maxluns);
|
||||
sdebug(2, "opt.maxluns=%d", sp->opt.maxluns);
|
||||
}
|
||||
|
||||
if(opt->headerDigest != NULL) {
|
||||
sdebug(2, "opt.headerDigest='%s'", opt->headerDigest);
|
||||
if(strcmp(opt->headerDigest, "CRC32C") == 0) {
|
||||
sp->hdrDigest = (digest_t *)i_crc32c;
|
||||
sdebug(2, "headerDigest set");
|
||||
sdebug(2, "opt.headerDigest set");
|
||||
}
|
||||
}
|
||||
if(opt->dataDigest != NULL) {
|
||||
sdebug(2, "opt.dataDigest='%s'", opt->headerDigest);
|
||||
if(strcmp(opt->dataDigest, "CRC32C") == 0) {
|
||||
sp->dataDigest = (digest_t *)i_crc32c;
|
||||
sdebug(2, "dataDigest set");
|
||||
sdebug(2, "opt.dataDigest set");
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,16 +154,18 @@ i_setopt(isc_session_t *sp, isc_opt_t *opt)
|
||||
void
|
||||
i_freeopt(isc_opt_t *opt)
|
||||
{
|
||||
debug_called(8);
|
||||
|
||||
if(opt->targetAddress != NULL) {
|
||||
free(opt->targetAddress, M_ISCSI);
|
||||
free(opt->targetAddress, M_ISC);
|
||||
opt->targetAddress = NULL;
|
||||
}
|
||||
if(opt->targetName != NULL) {
|
||||
free(opt->targetName, M_ISCSI);
|
||||
free(opt->targetName, M_ISC);
|
||||
opt->targetName = NULL;
|
||||
}
|
||||
if(opt->initiatorName != NULL) {
|
||||
free(opt->initiatorName, M_ISCSI);
|
||||
free(opt->initiatorName, M_ISC);
|
||||
opt->initiatorName = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -25,8 +25,7 @@
|
||||
*
|
||||
*/
|
||||
/*
|
||||
| iSCSI
|
||||
| $Id: iscsi.c,v 1.35 2007/04/22 08:58:29 danny Exp danny $
|
||||
| $Id: iscsi.c 752 2009-08-20 11:23:28Z danny $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
@ -56,15 +55,17 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <vm/uma.h>
|
||||
#include <sys/sx.h>
|
||||
|
||||
#include <dev/iscsi/initiator/iscsi.h>
|
||||
#include <dev/iscsi/initiator/iscsivar.h>
|
||||
static char *iscsi_driver_version = "2.2.4.2";
|
||||
|
||||
static char *iscsi_driver_version = "2.1.0";
|
||||
|
||||
static struct isc_softc isc;
|
||||
static struct isc_softc *isc;
|
||||
|
||||
MALLOC_DEFINE(M_ISCSI, "iSCSI", "iSCSI driver");
|
||||
MALLOC_DEFINE(M_ISCSIBUF, "iSCbuf", "iSCSI buffers");
|
||||
MALLOC_DEFINE(M_TMP, "iSCtmp", "iSCSI tmp");
|
||||
|
||||
#ifdef ISCSI_INITIATOR_DEBUG
|
||||
int iscsi_debug = ISCSI_INITIATOR_DEBUG;
|
||||
@ -74,6 +75,12 @@ SYSCTL_INT(_debug, OID_AUTO, iscsi_initiator, CTLFLAG_RW, &iscsi_debug, 0,
|
||||
struct mtx iscsi_dbg_mtx;
|
||||
#endif
|
||||
|
||||
static int max_sessions = MAX_SESSIONS;
|
||||
SYSCTL_INT(_net, OID_AUTO, iscsi_initiator_max_sessions, CTLFLAG_RDTUN, &max_sessions, MAX_SESSIONS,
|
||||
"Max sessions allowed");
|
||||
static int max_pdus = MAX_PDUS;
|
||||
SYSCTL_INT(_net, OID_AUTO, iscsi_initiator_max_pdus, CTLFLAG_RDTUN, &max_pdus, MAX_PDUS,
|
||||
"Max pdu pool");
|
||||
|
||||
static char isid[6+1] = {
|
||||
0x80,
|
||||
@ -91,6 +98,7 @@ static int i_ping(struct cdev *dev);
|
||||
static int i_send(struct cdev *dev, caddr_t arg, struct thread *td);
|
||||
static int i_recv(struct cdev *dev, caddr_t arg, struct thread *td);
|
||||
static int i_setsoc(isc_session_t *sp, int fd, struct thread *td);
|
||||
static int i_fullfeature(struct cdev *dev, int flag);
|
||||
|
||||
static d_open_t iscsi_open;
|
||||
static d_close_t iscsi_close;
|
||||
@ -117,39 +125,28 @@ iscsi_open(struct cdev *dev, int flags, int otype, struct thread *td)
|
||||
|
||||
debug(7, "dev=%d", dev2unit(dev));
|
||||
|
||||
if(dev2unit(dev) > MAX_SESSIONS) {
|
||||
if(dev2unit(dev) > max_sessions) {
|
||||
// should not happen
|
||||
return ENODEV;
|
||||
}
|
||||
if(dev2unit(dev) == MAX_SESSIONS) {
|
||||
#if 1
|
||||
struct isc_softc *sc = (struct isc_softc *)dev->si_drv1;
|
||||
|
||||
// this should be in iscsi_start
|
||||
if(sc->cam_sim == NULL)
|
||||
ic_init(sc);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iscsi_close(struct cdev *dev, int flag, int otyp, struct thread *td)
|
||||
{
|
||||
struct isc *sc;
|
||||
isc_session_t *sp;
|
||||
|
||||
debug_called(8);
|
||||
|
||||
debug(3, "flag=%x", flag);
|
||||
debug(3, "session=%d flag=%x", dev2unit(dev), flag);
|
||||
|
||||
sc = (struct isc *)dev->si_drv1;
|
||||
if(dev2unit(dev) == MAX_SESSIONS) {
|
||||
if(dev2unit(dev) == max_sessions) {
|
||||
return 0;
|
||||
}
|
||||
sp = (isc_session_t *)dev->si_drv2;
|
||||
sp = dev->si_drv2;
|
||||
if(sp != NULL) {
|
||||
sdebug(2, "session=%d flags=%x", dev2unit(dev), sp->flags );
|
||||
sdebug(3, "sp->flags=%x", sp->flags );
|
||||
/*
|
||||
| if still in full phase, this probably means
|
||||
| that something went realy bad.
|
||||
@ -170,19 +167,19 @@ iscsi_close(struct cdev *dev, int flag, int otyp, struct thread *td)
|
||||
static int
|
||||
iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
{
|
||||
struct isc *sc;
|
||||
struct isc_softc *sc;
|
||||
isc_session_t *sp;
|
||||
isc_opt_t *opt;
|
||||
int error;
|
||||
|
||||
sc = (struct isc *)dev->si_drv1;
|
||||
debug_called(8);
|
||||
|
||||
error = 0;
|
||||
if(dev2unit(dev) == MAX_SESSIONS) {
|
||||
if(dev2unit(dev) == max_sessions) {
|
||||
/*
|
||||
| non Session commands
|
||||
*/
|
||||
sc = dev->si_drv1;
|
||||
if(sc == NULL)
|
||||
return ENXIO;
|
||||
|
||||
@ -190,18 +187,17 @@ iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode, struct thread *
|
||||
case ISCSISETSES:
|
||||
error = i_create_session(dev, (int *)arg);
|
||||
if(error == 0)
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
error = ENXIO; // XXX:
|
||||
error = ENXIO;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
sp = (isc_session_t *)dev->si_drv2;
|
||||
/*
|
||||
| session commands
|
||||
*/
|
||||
sp = dev->si_drv2;
|
||||
if(sp == NULL)
|
||||
return ENXIO;
|
||||
|
||||
@ -230,7 +226,7 @@ iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode, struct thread *
|
||||
break;
|
||||
|
||||
case ISCSISTART:
|
||||
error = sp->soc == NULL? ENOTCONN: ism_fullfeature(dev, 1);
|
||||
error = sp->soc == NULL? ENOTCONN: i_fullfeature(dev, 1);
|
||||
if(error == 0) {
|
||||
sp->proc = td->td_proc;
|
||||
SYSCTL_ADD_UINT(&sp->clist,
|
||||
@ -243,11 +239,11 @@ iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode, struct thread *
|
||||
break;
|
||||
|
||||
case ISCSIRESTART:
|
||||
error = sp->soc == NULL? ENOTCONN: ism_fullfeature(dev, 2);
|
||||
error = sp->soc == NULL? ENOTCONN: i_fullfeature(dev, 2);
|
||||
break;
|
||||
|
||||
case ISCSISTOP:
|
||||
error = ism_fullfeature(dev, 0);
|
||||
error = i_fullfeature(dev, 0);
|
||||
break;
|
||||
|
||||
case ISCSISIGNAL: {
|
||||
@ -283,9 +279,9 @@ iscsi_read(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
pduq_t *pq;
|
||||
char buf[1024];
|
||||
|
||||
sc = (struct isc_softc *)dev->si_drv1;
|
||||
sp = (isc_session_t *)dev->si_drv2;
|
||||
if(dev2unit(dev) == MAX_SESSIONS) {
|
||||
sc = dev->si_drv1;
|
||||
sp = dev->si_drv2;
|
||||
if(dev2unit(dev) == max_sessions) {
|
||||
sprintf(buf, "/----- Session ------/\n");
|
||||
uiomove(buf, strlen(buf), uio);
|
||||
int i = 0;
|
||||
@ -310,10 +306,11 @@ iscsi_read(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
int i = 0;
|
||||
struct socket *so = sp->soc;
|
||||
#define pukeit(i, pq) do {\
|
||||
sprintf(buf, "%03d] %06x %02x %x %ld %jd\n",\
|
||||
i, ntohl( pq->pdu.ipdu.bhs.CmdSN), \
|
||||
sprintf(buf, "%03d] %06x %02x %06x %06x %zd\n",\
|
||||
i, ntohl(pq->pdu.ipdu.bhs.CmdSN),\
|
||||
pq->pdu.ipdu.bhs.opcode, ntohl(pq->pdu.ipdu.bhs.itt),\
|
||||
(long)pq->ts.sec, pq->ts.frac);\
|
||||
ntohl(pq->pdu.ipdu.bhs.ExpStSN),\
|
||||
pq->ts.sec);\
|
||||
} while(0)
|
||||
|
||||
sprintf(buf, "%d/%d /---- hld -----/\n", sp->stats.nhld, sp->stats.max_hld);
|
||||
@ -418,8 +415,7 @@ i_setsoc(isc_session_t *sp, int fd, struct thread *td)
|
||||
static int
|
||||
i_send(struct cdev *dev, caddr_t arg, struct thread *td)
|
||||
{
|
||||
isc_session_t *sp = (isc_session_t *)dev->si_drv2;
|
||||
struct isc_softc *sc = (struct isc_softc *)dev->si_drv1;
|
||||
isc_session_t *sp = dev->si_drv2;
|
||||
caddr_t bp;
|
||||
pduq_t *pq;
|
||||
pdu_t *pp;
|
||||
@ -430,38 +426,46 @@ i_send(struct cdev *dev, caddr_t arg, struct thread *td)
|
||||
if(sp->soc == NULL)
|
||||
return ENOTCONN;
|
||||
|
||||
if((pq = pdu_alloc(sc, M_NOWAIT)) == NULL)
|
||||
if((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL)
|
||||
return EAGAIN;
|
||||
pp = &pq->pdu;
|
||||
pq->pdu = *(pdu_t *)arg;
|
||||
if((error = i_prepPDU(sp, pq)) != 0)
|
||||
goto out;
|
||||
|
||||
sdebug(3, "len=%d ahs_len=%d ds_len=%d", pq->len, pp->ahs_len, pp->ds_len);
|
||||
|
||||
pq->buf = bp = malloc(pq->len - sizeof(union ipdu_u), M_ISCSI, M_NOWAIT);
|
||||
if(pq->buf == NULL) {
|
||||
error = EAGAIN;
|
||||
goto out;
|
||||
bp = NULL;
|
||||
if((pq->len - sizeof(union ipdu_u)) > 0) {
|
||||
pq->buf = bp = malloc(pq->len - sizeof(union ipdu_u), M_ISCSIBUF, M_NOWAIT);
|
||||
if(pq->buf == NULL) {
|
||||
error = EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else
|
||||
pq->buf = NULL; // just in case?
|
||||
|
||||
sdebug(2, "len=%d ahs_len=%d ds_len=%d buf=%zu@%p",
|
||||
pq->len, pp->ahs_len, pp->ds_len, pq->len - sizeof(union ipdu_u), bp);
|
||||
|
||||
if(pp->ahs_len) {
|
||||
// XXX: never tested, looks suspicious
|
||||
n = pp->ahs_len;
|
||||
error = copyin(pp->ahs, bp, n);
|
||||
error = copyin(pp->ahs_addr, bp, n);
|
||||
if(error != 0) {
|
||||
sdebug(3, "copyin ahs: error=%d", error);
|
||||
goto out;
|
||||
}
|
||||
pp->ahs = (ahs_t *)bp;
|
||||
pp->ahs_addr = (ahs_t *)bp;
|
||||
bp += n;
|
||||
}
|
||||
if(pp->ds_len) {
|
||||
n = pp->ds_len;
|
||||
error = copyin(pp->ds, bp, n);
|
||||
error = copyin(pp->ds_addr, bp, n);
|
||||
if(error != 0) {
|
||||
sdebug(3, "copyin ds: error=%d", error);
|
||||
goto out;
|
||||
}
|
||||
pp->ds = bp;
|
||||
pp->ds_addr = bp;
|
||||
bp += n;
|
||||
while(n & 03) {
|
||||
n++;
|
||||
@ -470,24 +474,19 @@ i_send(struct cdev *dev, caddr_t arg, struct thread *td)
|
||||
}
|
||||
|
||||
error = isc_qout(sp, pq);
|
||||
#if 1
|
||||
if(error == 0)
|
||||
wakeup(&sp->flags); // XXX: to 'push' proc_out ...
|
||||
#endif
|
||||
out:
|
||||
if(error)
|
||||
pdu_free(sc, pq);
|
||||
pdu_free(sp->isc, pq);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
| NOTE: must calculate digest if requiered.
|
||||
*/
|
||||
static int
|
||||
i_recv(struct cdev *dev, caddr_t arg, struct thread *td)
|
||||
{
|
||||
isc_session_t *sp = (isc_session_t *)dev->si_drv2;
|
||||
isc_session_t *sp = dev->si_drv2;
|
||||
pduq_t *pq;
|
||||
pdu_t *pp, *up;
|
||||
caddr_t bp;
|
||||
@ -501,7 +500,6 @@ i_recv(struct cdev *dev, caddr_t arg, struct thread *td)
|
||||
|
||||
if(sp->soc == NULL)
|
||||
return ENOTCONN;
|
||||
sdebug(3, "");
|
||||
cnt = 6; // XXX: maybe the user can request a time out?
|
||||
mtx_lock(&sp->rsp_mtx);
|
||||
while((pq = TAILQ_FIRST(&sp->rsp)) == NULL) {
|
||||
@ -514,7 +512,7 @@ i_recv(struct cdev *dev, caddr_t arg, struct thread *td)
|
||||
}
|
||||
mtx_unlock(&sp->rsp_mtx);
|
||||
|
||||
sdebug(4, "cnt=%d", cnt);
|
||||
sdebug(6, "cnt=%d", cnt);
|
||||
|
||||
if(pq == NULL) {
|
||||
error = ENOTCONN;
|
||||
@ -536,19 +534,15 @@ i_recv(struct cdev *dev, caddr_t arg, struct thread *td)
|
||||
len = 0;
|
||||
if(pp->ahs_len) {
|
||||
len += pp->ahs_len;
|
||||
if(sp->hdrDigest)
|
||||
len += 4;
|
||||
}
|
||||
if(pp->ds_len) {
|
||||
len += pp->ds_len;
|
||||
if(sp->hdrDigest)
|
||||
len += 4;
|
||||
}
|
||||
|
||||
mustfree = 0;
|
||||
if(len > pq->mp->m_len) {
|
||||
mustfree++;
|
||||
bp = malloc(len, M_ISCSI, M_WAITOK);
|
||||
bp = malloc(len, M_TMP, M_WAITOK);
|
||||
sdebug(4, "need mbufcopy: %d", len);
|
||||
i_mbufcopy(pq->mp, bp, len);
|
||||
}
|
||||
@ -557,28 +551,24 @@ i_recv(struct cdev *dev, caddr_t arg, struct thread *td)
|
||||
|
||||
if(pp->ahs_len) {
|
||||
need = pp->ahs_len;
|
||||
if(sp->hdrDigest)
|
||||
need += 4;
|
||||
n = MIN(up->ahs_size, need);
|
||||
error = copyout(bp, (caddr_t)up->ahs, n);
|
||||
error = copyout(bp, (caddr_t)up->ahs_addr, n);
|
||||
up->ahs_len = n;
|
||||
bp += need;
|
||||
}
|
||||
if(!error && pp->ds_len) {
|
||||
need = pp->ds_len;
|
||||
if(sp->hdrDigest)
|
||||
need += 4;
|
||||
if((have = up->ds_size) == 0) {
|
||||
have = up->ahs_size - n;
|
||||
up->ds = (caddr_t)up->ahs + n;
|
||||
up->ds_addr = (caddr_t)up->ahs_addr + n;
|
||||
}
|
||||
n = MIN(have, need);
|
||||
error = copyout(bp, (caddr_t)up->ds, n);
|
||||
error = copyout(bp, (caddr_t)up->ds_addr, n);
|
||||
up->ds_len = n;
|
||||
}
|
||||
|
||||
if(mustfree)
|
||||
free(bp, M_ISCSI);
|
||||
free(bp, M_TMP);
|
||||
}
|
||||
|
||||
sdebug(6, "len=%d ahs_len=%d ds_len=%d", pq->len, pp->ahs_len, pp->ds_len);
|
||||
@ -588,34 +578,58 @@ i_recv(struct cdev *dev, caddr_t arg, struct thread *td)
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
i_fullfeature(struct cdev *dev, int flag)
|
||||
{
|
||||
isc_session_t *sp = dev->si_drv2;
|
||||
int error;
|
||||
|
||||
sdebug(2, "flag=%d", flag);
|
||||
|
||||
error = 0;
|
||||
switch(flag) {
|
||||
case 0: // stop
|
||||
sp->flags &= ~ISC_FFPHASE;
|
||||
break;
|
||||
case 1: // start
|
||||
sp->flags |= ISC_FFPHASE;
|
||||
error = ic_init(sp);
|
||||
break;
|
||||
case 2: // restart
|
||||
sp->flags |= ISC_FFPHASE;
|
||||
ism_restart(sp);
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
i_create_session(struct cdev *dev, int *ndev)
|
||||
{
|
||||
struct isc_softc *sc = (struct isc_softc *)dev->si_drv1;
|
||||
struct isc_softc *sc = dev->si_drv1;
|
||||
isc_session_t *sp;
|
||||
int error, n;
|
||||
|
||||
debug_called(8);
|
||||
sp = (isc_session_t *)malloc(sizeof *sp, M_ISCSI, M_WAITOK | M_ZERO);
|
||||
|
||||
sp = malloc(sizeof(isc_session_t), M_ISCSI, M_WAITOK | M_ZERO);
|
||||
if(sp == NULL)
|
||||
return ENOMEM;
|
||||
mtx_lock(&sc->mtx);
|
||||
/*
|
||||
| search for the lowest unused sid
|
||||
*/
|
||||
for(n = 0; n < MAX_SESSIONS; n++)
|
||||
if(sc->sessions[n] == NULL)
|
||||
break;
|
||||
if(n == MAX_SESSIONS) {
|
||||
mtx_unlock(&sc->mtx);
|
||||
|
||||
sx_xlock(&sc->unit_sx);
|
||||
if((n = alloc_unr(sc->unit)) < 0) {
|
||||
sx_unlock(&sc->unit_sx);
|
||||
free(sp, M_ISCSI);
|
||||
xdebug("too many sessions!");
|
||||
return EPERM;
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&sc->isc_sess, sp, sp_link);
|
||||
sc->nsess++;
|
||||
mtx_unlock(&sc->mtx);
|
||||
sx_unlock(&sc->unit_sx);
|
||||
|
||||
mtx_lock(&sc->isc_mtx);
|
||||
TAILQ_INSERT_TAIL(&sc->isc_sess, sp, sp_link);
|
||||
isc->nsess++;
|
||||
mtx_unlock(&sc->isc_mtx);
|
||||
|
||||
sc->sessions[n] = sp;
|
||||
sp->dev = make_dev(&iscsi_cdevsw, n, UID_ROOT, GID_WHEEL, 0600, "iscsi%d", n);
|
||||
*ndev = sp->sid = n;
|
||||
sp->isc = sc;
|
||||
@ -624,10 +638,9 @@ i_create_session(struct cdev *dev, int *ndev)
|
||||
|
||||
sp->opt.maxRecvDataSegmentLength = 8192;
|
||||
sp->opt.maxXmitDataSegmentLength = 8192;
|
||||
|
||||
sp->opt.maxBurstLength = 65536; // 64k
|
||||
sp->opt.maxluns = ISCSI_MAX_LUNS;
|
||||
|
||||
sdebug(2, "sessionID=%d sp=%p", n, sp);
|
||||
error = ism_start(sp);
|
||||
|
||||
return error;
|
||||
@ -663,7 +676,7 @@ iscsi_counters(isc_session_t *sp)
|
||||
static void
|
||||
iscsi_shutdown(void *v)
|
||||
{
|
||||
struct isc_softc *sc = (struct isc_softc *)v;
|
||||
struct isc_softc *sc = v;
|
||||
isc_session_t *sp;
|
||||
int n;
|
||||
|
||||
@ -672,12 +685,14 @@ iscsi_shutdown(void *v)
|
||||
xdebug("sc is NULL!");
|
||||
return;
|
||||
}
|
||||
#ifdef DO_EVENTHANDLER
|
||||
if(sc->eh == NULL)
|
||||
debug(2, "sc->eh is NULL");
|
||||
else {
|
||||
EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->eh);
|
||||
debug(2, "done n=%d", sc->nsess);
|
||||
}
|
||||
#endif
|
||||
n = 0;
|
||||
TAILQ_FOREACH(sp, &sc->isc_sess, sp_link) {
|
||||
debug(2, "%2d] sp->flags=0x%08x", n, sp->flags);
|
||||
@ -686,24 +701,6 @@ iscsi_shutdown(void *v)
|
||||
debug(2, "done");
|
||||
}
|
||||
|
||||
static int
|
||||
init_pdus(struct isc_softc *sc)
|
||||
{
|
||||
debug_called(8);
|
||||
|
||||
sc->pdu_zone = uma_zcreate("pdu", sizeof(pduq_t),
|
||||
NULL, NULL, NULL, NULL,
|
||||
0, 0);
|
||||
if(sc->pdu_zone == NULL) {
|
||||
printf("iscsi_initiator: uma_zcreate failed");
|
||||
return -1;
|
||||
}
|
||||
uma_zone_set_max(sc->pdu_zone, MAX_PDUS);
|
||||
TAILQ_INIT(&sc->freepdu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
free_pdus(struct isc_softc *sc)
|
||||
{
|
||||
@ -724,50 +721,52 @@ free_pdus(struct isc_softc *sc)
|
||||
static void
|
||||
iscsi_start(void)
|
||||
{
|
||||
struct isc_softc *sc = &isc;
|
||||
|
||||
debug_called(8);
|
||||
|
||||
memset(sc, 0, sizeof(struct isc_softc));
|
||||
TUNABLE_INT_FETCH("net.iscsi_initiator.max_sessions", &max_sessions);
|
||||
TUNABLE_INT_FETCH("net.iscsi_initiator.max_pdus", &max_pdus);
|
||||
|
||||
sc->dev = make_dev(&iscsi_cdevsw, MAX_SESSIONS, UID_ROOT, GID_WHEEL, 0600, "iscsi");
|
||||
sc->dev->si_drv1 = sc;
|
||||
isc = malloc(sizeof(struct isc_softc), M_ISCSI, M_ZERO|M_WAITOK);
|
||||
isc->dev = make_dev(&iscsi_cdevsw, max_sessions, UID_ROOT, GID_WHEEL, 0600, "iscsi");
|
||||
isc->dev->si_drv1 = isc;
|
||||
mtx_init(&isc->isc_mtx, "iscsi", NULL, MTX_DEF);
|
||||
mtx_init(&isc->pdu_mtx, "iscsi pdu pool", NULL, MTX_DEF);
|
||||
|
||||
TAILQ_INIT(&sc->isc_sess);
|
||||
if(init_pdus(sc) != 0)
|
||||
xdebug("pdu zone init failed!"); // XXX: should cause terminal failure ...
|
||||
|
||||
mtx_init(&sc->mtx, "iscsi", NULL, MTX_DEF);
|
||||
mtx_init(&sc->pdu_mtx, "iscsi pdu pool", NULL, MTX_DEF);
|
||||
|
||||
#if 0
|
||||
// XXX: this will cause a panic if the
|
||||
// module is loaded too early
|
||||
if(ic_init(sc) != 0)
|
||||
return;
|
||||
#else
|
||||
sc->cam_sim = NULL;
|
||||
#endif
|
||||
TAILQ_INIT(&isc->isc_sess);
|
||||
/*
|
||||
| now init the free pdu list
|
||||
*/
|
||||
isc->pdu_zone = uma_zcreate("pdu", sizeof(pduq_t),
|
||||
NULL, NULL, NULL, NULL,
|
||||
0, 0);
|
||||
if(isc->pdu_zone == NULL) {
|
||||
xdebug("iscsi_initiator: uma_zcreate failed");
|
||||
// XXX: should fail...
|
||||
}
|
||||
uma_zone_set_max(isc->pdu_zone, max_pdus);
|
||||
TAILQ_INIT(&isc->freepdu);
|
||||
isc->unit = new_unrhdr(0, max_sessions-1, NULL);
|
||||
sx_init(&isc->unit_sx, "iscsi sx");
|
||||
|
||||
#ifdef DO_EVENTHANDLER
|
||||
if((sc->eh = EVENTHANDLER_REGISTER(shutdown_pre_sync, iscsi_shutdown,
|
||||
if((isc->eh = EVENTHANDLER_REGISTER(shutdown_pre_sync, iscsi_shutdown,
|
||||
sc, SHUTDOWN_PRI_DEFAULT-1)) == NULL)
|
||||
xdebug("shutdown event registration failed\n");
|
||||
#endif
|
||||
/*
|
||||
| sysctl stuff
|
||||
*/
|
||||
sysctl_ctx_init(&sc->clist);
|
||||
sc->oid = SYSCTL_ADD_NODE(&sc->clist,
|
||||
sysctl_ctx_init(&isc->clist);
|
||||
isc->oid = SYSCTL_ADD_NODE(&isc->clist,
|
||||
SYSCTL_STATIC_CHILDREN(_net),
|
||||
OID_AUTO,
|
||||
"iscsi",
|
||||
"iscsi_initiator",
|
||||
CTLFLAG_RD,
|
||||
0,
|
||||
"iSCSI Subsystem");
|
||||
|
||||
SYSCTL_ADD_STRING(&sc->clist,
|
||||
SYSCTL_CHILDREN(sc->oid),
|
||||
SYSCTL_ADD_STRING(&isc->clist,
|
||||
SYSCTL_CHILDREN(isc->oid),
|
||||
OID_AUTO,
|
||||
"driver_version",
|
||||
CTLFLAG_RD,
|
||||
@ -775,8 +774,8 @@ iscsi_start(void)
|
||||
0,
|
||||
"iscsi driver version");
|
||||
|
||||
SYSCTL_ADD_STRING(&sc->clist,
|
||||
SYSCTL_CHILDREN(sc->oid),
|
||||
SYSCTL_ADD_STRING(&isc->clist,
|
||||
SYSCTL_CHILDREN(isc->oid),
|
||||
OID_AUTO,
|
||||
"isid",
|
||||
CTLFLAG_RW,
|
||||
@ -784,13 +783,13 @@ iscsi_start(void)
|
||||
6+1,
|
||||
"initiator part of the Session Identifier");
|
||||
|
||||
SYSCTL_ADD_INT(&sc->clist,
|
||||
SYSCTL_CHILDREN(sc->oid),
|
||||
SYSCTL_ADD_INT(&isc->clist,
|
||||
SYSCTL_CHILDREN(isc->oid),
|
||||
OID_AUTO,
|
||||
"sessions",
|
||||
CTLFLAG_RD,
|
||||
&sc->nsess,
|
||||
sizeof(sc->nsess),
|
||||
&isc->nsess,
|
||||
sizeof(isc->nsess),
|
||||
"number of active session");
|
||||
|
||||
printf("iscsi: version %s\n", iscsi_driver_version);
|
||||
@ -804,7 +803,6 @@ iscsi_start(void)
|
||||
static void
|
||||
iscsi_stop(void)
|
||||
{
|
||||
struct isc_softc *sc = &isc;
|
||||
isc_session_t *sp, *sp_tmp;
|
||||
|
||||
debug_called(8);
|
||||
@ -813,24 +811,26 @@ iscsi_stop(void)
|
||||
| go through all the sessions
|
||||
| Note: close should have done this ...
|
||||
*/
|
||||
TAILQ_FOREACH_SAFE(sp, &sc->isc_sess, sp_link, sp_tmp) {
|
||||
TAILQ_FOREACH_SAFE(sp, &isc->isc_sess, sp_link, sp_tmp) {
|
||||
//XXX: check for activity ...
|
||||
ism_stop(sp);
|
||||
if(sp->cam_sim != NULL)
|
||||
ic_destroy(sp);
|
||||
}
|
||||
if(sc->cam_sim != NULL)
|
||||
ic_destroy(sc);
|
||||
mtx_destroy(&isc->isc_mtx);
|
||||
mtx_destroy(&isc->pdu_mtx);
|
||||
sx_destroy(&isc->unit_sx);
|
||||
|
||||
mtx_destroy(&sc->mtx);
|
||||
mtx_destroy(&sc->pdu_mtx);
|
||||
free_pdus(sc);
|
||||
free_pdus(isc);
|
||||
|
||||
if(sc->dev)
|
||||
destroy_dev(sc->dev);
|
||||
if(isc->dev)
|
||||
destroy_dev(isc->dev);
|
||||
|
||||
if(sysctl_ctx_free(&sc->clist))
|
||||
if(sysctl_ctx_free(&isc->clist))
|
||||
xdebug("sysctl_ctx_free failed");
|
||||
|
||||
iscsi_shutdown(sc); // XXX: check EVENTHANDLER_ ...
|
||||
iscsi_shutdown(isc); // XXX: check EVENTHANDLER_ ...
|
||||
free(isc, M_ISCSI);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -844,13 +844,12 @@ iscsi_modevent(module_t mod, int what, void *arg)
|
||||
break;
|
||||
|
||||
case MOD_QUIESCE:
|
||||
#if 1
|
||||
if(isc.nsess) {
|
||||
xdebug("iscsi module busy(nsess=%d), cannot unload", isc.nsess);
|
||||
if(isc->nsess) {
|
||||
xdebug("iscsi module busy(nsess=%d), cannot unload", isc->nsess);
|
||||
log(LOG_ERR, "iscsi module busy, cannot unload");
|
||||
}
|
||||
return isc.nsess;
|
||||
#endif
|
||||
return isc->nsess;
|
||||
|
||||
case MOD_SHUTDOWN:
|
||||
break;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,7 +26,7 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
/*
|
||||
| $Id: iscsi.h,v 1.17 2006/12/01 09:10:17 danny Exp danny $
|
||||
| $Id: iscsi.h 743 2009-08-08 10:54:53Z danny $
|
||||
*/
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
@ -37,11 +37,7 @@ typedef int boolean_t;
|
||||
#include <cam/cam.h>
|
||||
|
||||
#define ISCSIDEV "iscsi"
|
||||
|
||||
#define ISCSI_MAX_TARGETS 4 //64
|
||||
|
||||
#define ISCSI_MAX_LUNS 4
|
||||
|
||||
#define ISCSI_MAX_TARGETS 64
|
||||
/*
|
||||
| iSCSI commands
|
||||
*/
|
||||
@ -422,13 +418,13 @@ typedef struct {
|
||||
*/
|
||||
typedef struct {
|
||||
union ipdu_u ipdu;
|
||||
|
||||
ahs_t *ahs;
|
||||
u_int ahs_len;
|
||||
u_int ahs_size; // the allocated size
|
||||
u_int hdr_dig; // header digest
|
||||
|
||||
u_char *ds;
|
||||
ahs_t *ahs_addr;
|
||||
u_int ahs_len;
|
||||
u_int ahs_size; // the allocated size
|
||||
|
||||
u_char *ds_addr;
|
||||
u_int ds_len;
|
||||
u_int ds_size; // the allocated size
|
||||
u_int ds_dig; // data digest
|
||||
@ -474,6 +470,7 @@ typedef struct opvals {
|
||||
u_char tgtChapID;
|
||||
char *tgtChapDigest;
|
||||
char *iqn;
|
||||
char *pidfile;
|
||||
} isc_opt_t;
|
||||
|
||||
/*
|
||||
@ -498,7 +495,6 @@ typedef struct iscsi_cam {
|
||||
path_id_t path_id;
|
||||
target_id_t target_id;
|
||||
int target_nluns;
|
||||
lun_id_t target_lun[ISCSI_MAX_LUNS];
|
||||
} iscsi_cam_t;
|
||||
|
||||
#define ISCSIGETCAM _IOR('i', 33, iscsi_cam_t)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -25,7 +25,7 @@
|
||||
*
|
||||
*/
|
||||
/*
|
||||
| $Id: iscsi_subr.c,v 1.17 2006/11/26 14:50:43 danny Exp danny $
|
||||
| $Id: iscsi_subr.c 743 2009-08-08 10:54:53Z danny $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/sx.h>
|
||||
|
||||
#include <cam/cam.h>
|
||||
#include <cam/cam_ccb.h>
|
||||
@ -122,7 +123,7 @@ iscsi_r2t(isc_session_t *sp, pduq_t *opq, pduq_t *pq)
|
||||
bs = MIN(bs, bleft);
|
||||
|
||||
wpq->pdu.ds_len = bs;
|
||||
wpq->pdu.ds = bp;
|
||||
wpq->pdu.ds_addr = bp;
|
||||
|
||||
error = isc_qout(sp, wpq);
|
||||
sdebug(6, "bs=%x bo=%x bp=%p dsn=%x error=%d", bs, bo, bp, dsn, error);
|
||||
@ -188,16 +189,16 @@ getSenseData(u_int status, union ccb *ccb, pduq_t *pq)
|
||||
| Some information is from SAM draft.
|
||||
*/
|
||||
static void
|
||||
_scsi_done(struct isc_softc *isp, u_int response, u_int status, union ccb *ccb, pduq_t *pq)
|
||||
_scsi_done(isc_session_t *sp, u_int response, u_int status, union ccb *ccb, pduq_t *pq)
|
||||
{
|
||||
struct ccb_hdr *ccb_h = &ccb->ccb_h;
|
||||
|
||||
debug_called(8);
|
||||
|
||||
if(status || response) {
|
||||
debug(3, "response=%x status=%x ccb=%p pq=%p", response, status, ccb, pq);
|
||||
sdebug(3, "response=%x status=%x ccb=%p pq=%p", response, status, ccb, pq);
|
||||
if(pq != NULL)
|
||||
debug(3, "mp=%p buf=%p len=%d", pq->mp, pq->buf, pq->len);
|
||||
sdebug(3, "mp=%p buf=%p len=%d", pq->mp, pq->buf, pq->len);
|
||||
}
|
||||
ccb_h->status = 0;
|
||||
switch(response) {
|
||||
@ -241,9 +242,9 @@ _scsi_done(struct isc_softc *isp, u_int response, u_int status, union ccb *ccb,
|
||||
ccb_h->status = CAM_REQ_CMP_ERR; //CAM_REQ_ABORTED;
|
||||
break;
|
||||
}
|
||||
debug(5, "ccb_h->status=%x", ccb_h->status);
|
||||
sdebug(5, "ccb_h->status=%x", ccb_h->status);
|
||||
|
||||
XPT_DONE(isp, ccb);
|
||||
XPT_DONE(sp, ccb);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -256,16 +257,17 @@ iscsi_requeue(isc_session_t *sp)
|
||||
u_int i, n, last;
|
||||
|
||||
debug_called(8);
|
||||
last = -1;
|
||||
i = 0;
|
||||
i = last = 0;
|
||||
sp->flags |= ISC_HOLD;
|
||||
while((pq = i_dqueue_hld(sp)) != NULL) {
|
||||
i++;
|
||||
_scsi_done(sp->isc, 0, 0x28, pq->ccb, NULL);
|
||||
n = ntohl(pq->pdu.ipdu.bhs.CmdSN);
|
||||
if(last > n)
|
||||
last = n;
|
||||
sdebug(2, "last=%x n=%x", last, n);
|
||||
if(pq->ccb != NULL) {
|
||||
_scsi_done(sp, 0, 0x28, pq->ccb, NULL);
|
||||
n = ntohl(pq->pdu.ipdu.bhs.CmdSN);
|
||||
if(last==0 || (last > n))
|
||||
last = n;
|
||||
sdebug(2, "last=%x n=%x", last, n);
|
||||
}
|
||||
pdu_free(sp->isc, pq);
|
||||
}
|
||||
sp->flags &= ~ISC_HOLD;
|
||||
@ -316,14 +318,22 @@ iscsi_cleanup(isc_session_t *sp)
|
||||
TAILQ_FOREACH_SAFE(pq, &sp->hld, pq_link, pqtmp) {
|
||||
sdebug(3, "hld pq=%p", pq);
|
||||
if(pq->ccb)
|
||||
_scsi_done(sp->isc, 1, 0x40, pq->ccb, NULL);
|
||||
_scsi_done(sp, 1, 0x40, pq->ccb, NULL);
|
||||
TAILQ_REMOVE(&sp->hld, pq, pq_link);
|
||||
if(pq->buf) {
|
||||
free(pq->buf, M_ISCSIBUF);
|
||||
pq->buf = NULL;
|
||||
}
|
||||
pdu_free(sp->isc, pq);
|
||||
}
|
||||
while((pq = i_dqueue_snd(sp, BIT(0)|BIT(1)|BIT(2))) != NULL) {
|
||||
sdebug(3, "pq=%p", pq);
|
||||
if(pq->ccb)
|
||||
_scsi_done(sp->isc, 1, 0x40, pq->ccb, NULL);
|
||||
_scsi_done(sp, 1, 0x40, pq->ccb, NULL);
|
||||
if(pq->buf) {
|
||||
free(pq->buf, M_ISCSIBUF);
|
||||
pq->buf = NULL;
|
||||
}
|
||||
pdu_free(sp->isc, pq);
|
||||
}
|
||||
|
||||
@ -338,7 +348,7 @@ iscsi_done(isc_session_t *sp, pduq_t *opq, pduq_t *pq)
|
||||
|
||||
debug_called(8);
|
||||
|
||||
_scsi_done(sp->isc, cmd->response, cmd->status, opq->ccb, pq);
|
||||
_scsi_done(sp, cmd->response, cmd->status, opq->ccb, pq);
|
||||
|
||||
pdu_free(sp->isc, opq);
|
||||
}
|
||||
@ -394,7 +404,7 @@ iscsi_reject(isc_session_t *sp, pduq_t *opq, pduq_t *pq)
|
||||
debug_called(8);
|
||||
//XXX: check RFC 10.17.1 (page 176)
|
||||
ccb->ccb_h.status = CAM_REQ_ABORTED;
|
||||
XPT_DONE(sp->isc, ccb);
|
||||
XPT_DONE(sp, ccb);
|
||||
|
||||
pdu_free(sp->isc, opq);
|
||||
}
|
||||
@ -405,10 +415,8 @@ iscsi_reject(isc_session_t *sp, pduq_t *opq, pduq_t *pq)
|
||||
static int
|
||||
dwl(isc_session_t *sp, int lun, u_char *lp)
|
||||
{
|
||||
int i;
|
||||
|
||||
debug_called(8);
|
||||
|
||||
sdebug(4, "lun=%d", lun);
|
||||
/*
|
||||
| mapping LUN to iSCSI LUN
|
||||
| check the SAM-2 specs
|
||||
@ -429,14 +437,6 @@ dwl(isc_session_t *sp, int lun, u_char *lp)
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i = 0; i < sp->target_nluns; i++)
|
||||
if(sp->target_lun[i] == lun)
|
||||
return 0;
|
||||
if(sp->target_nluns < ISCSI_MAX_LUNS)
|
||||
sp->target_lun[sp->target_nluns++] = lun;
|
||||
|
||||
sdebug(3, "nluns=%d lun=%d", sp->target_nluns, lun);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -446,8 +446,7 @@ dwl(isc_session_t *sp, int lun, u_char *lp)
|
||||
int
|
||||
scsi_encap(struct cam_sim *sim, union ccb *ccb)
|
||||
{
|
||||
struct isc_softc *isp = (struct isc_softc *)cam_sim_softc(sim);
|
||||
isc_session_t *sp;
|
||||
isc_session_t *sp = cam_sim_softc(sim);
|
||||
struct ccb_scsiio *csio = &ccb->csio;
|
||||
struct ccb_hdr *ccb_h = &ccb->ccb_h;
|
||||
pduq_t *pq;
|
||||
@ -458,33 +457,19 @@ scsi_encap(struct cam_sim *sim, union ccb *ccb)
|
||||
debug(4, "ccb->sp=%p", ccb_h->spriv_ptr0);
|
||||
sp = ccb_h->spriv_ptr0;
|
||||
|
||||
if((pq = pdu_alloc(isp, M_NOWAIT)) == NULL) {
|
||||
if((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL) {
|
||||
debug(2, "ccb->sp=%p", ccb_h->spriv_ptr0);
|
||||
sdebug(1, "pdu_alloc failed sc->npdu_max=%d npdu_alloc=%d",
|
||||
sp->isc->npdu_max, sp->isc->npdu_alloc);
|
||||
while((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL) {
|
||||
sdebug(3, "waiting...");
|
||||
sdebug(2, "waiting...");
|
||||
#if __FreeBSD_version >= 700000
|
||||
pause("isc_encap", 5*hz);
|
||||
#else
|
||||
tsleep(sp->isc, 0, "isc_encap", 5*hz);
|
||||
#endif
|
||||
}
|
||||
#if 0
|
||||
sdebug(3, "freezing");
|
||||
ccb->ccb_h.status = CAM_REQUEUE_REQ;
|
||||
ic_freeze(sp);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
if((sp->flags & ISC_FFPHASE) == 0) {
|
||||
ccb->ccb_h.status = CAM_DEV_NOT_THERE; // CAM_NO_NEXUS;
|
||||
sdebug(3, "no active session with target %d", ccb_h->target_id);
|
||||
goto bad;
|
||||
}
|
||||
#endif
|
||||
cmd = &pq->pdu.ipdu.scsi_req;
|
||||
cmd->opcode = ISCSI_SCSI_CMD;
|
||||
cmd->F = 1;
|
||||
@ -493,8 +478,8 @@ scsi_encap(struct cam_sim *sim, union ccb *ccb)
|
||||
*/
|
||||
switch(csio->tag_action) {
|
||||
case MSG_SIMPLE_Q_TAG: cmd->attr = iSCSI_TASK_SIMPLE; break;
|
||||
case MSG_HEAD_OF_Q_TAG: cmd->attr = iSCSI_TASK_ORDER; break;
|
||||
case MSG_ORDERED_Q_TAG: cmd->attr = iSCSI_TASK_HOFQ; break;
|
||||
case MSG_HEAD_OF_Q_TAG: cmd->attr = iSCSI_TASK_HOFQ; break;
|
||||
case MSG_ORDERED_Q_TAG: cmd->attr = iSCSI_TASK_ORDER; break;
|
||||
case MSG_ACA_TASK: cmd->attr = iSCSI_TASK_ACA; break;
|
||||
}
|
||||
|
||||
@ -532,7 +517,8 @@ scsi_encap(struct cam_sim *sim, union ccb *ccb)
|
||||
return 1;
|
||||
invalid:
|
||||
ccb->ccb_h.status = CAM_REQ_INVALID;
|
||||
pdu_free(isp, pq);
|
||||
pdu_free(sp->isc, pq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -573,15 +559,15 @@ scsi_decap(isc_session_t *sp, pduq_t *opq, pduq_t *pq)
|
||||
csio->data_ptr, bp? mtod(pq->mp, caddr_t): 0,
|
||||
ntohl(cmd->edtlen), pq->pdu.ds_len, pq->mp);
|
||||
if(ntohl(cmd->edtlen) >= pq->pdu.ds_len) {
|
||||
int offset, len = pq->pdu.ds_len;
|
||||
int offset, len = pq->pdu.ds_len;
|
||||
|
||||
if(pq->mp != NULL) {
|
||||
caddr_t dp;
|
||||
caddr_t dp;
|
||||
|
||||
offset = ntohl(rcmd->bo);
|
||||
dp = csio->data_ptr + offset;
|
||||
i_mbufcopy(pq->mp, dp, len);
|
||||
}
|
||||
offset = ntohl(rcmd->bo);
|
||||
dp = csio->data_ptr + offset;
|
||||
i_mbufcopy(pq->mp, dp, len);
|
||||
}
|
||||
}
|
||||
else {
|
||||
xdebug("edtlen=%d < ds_len=%d",
|
||||
@ -592,7 +578,7 @@ scsi_decap(isc_session_t *sp, pduq_t *opq, pduq_t *pq)
|
||||
/*
|
||||
| contains also the SCSI Status
|
||||
*/
|
||||
_scsi_done(sp->isc, 0, rcmd->status, opq->ccb, NULL);
|
||||
_scsi_done(sp, 0, rcmd->status, opq->ccb, NULL);
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -25,9 +25,18 @@
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
| $Id: iscsivar.h,v 1.30 2007/04/22 10:12:11 danny Exp danny $
|
||||
| $Id: iscsivar.h 743 2009-08-08 10:54:53Z danny $
|
||||
*/
|
||||
#define ISCSI_MAX_LUNS 128 // don't touch this
|
||||
#if ISCSI_MAX_LUNS > 8
|
||||
/*
|
||||
| for this to work
|
||||
| sysctl kern.cam.cam_srch_hi=1
|
||||
*/
|
||||
#endif
|
||||
|
||||
#ifndef ISCSI_INITIATOR_DEBUG
|
||||
#define ISCSI_INITIATOR_DEBUG 1
|
||||
#endif
|
||||
@ -48,13 +57,17 @@ extern int iscsi_debug;
|
||||
|
||||
#define xdebug(fmt, args...) printf(">>> %s: " fmt "\n", __func__ , ##args)
|
||||
|
||||
#define MAX_SESSIONS ISCSI_MAX_TARGETS
|
||||
#define MAX_SESSIONS ISCSI_MAX_TARGETS
|
||||
#define MAX_PDUS (MAX_SESSIONS*256) // XXX: at the moment this is arbitrary
|
||||
|
||||
typedef uint32_t digest_t(const void *, int len, uint32_t ocrc);
|
||||
|
||||
MALLOC_DECLARE(M_ISCSI);
|
||||
MALLOC_DECLARE(M_ISCSIBUF);
|
||||
MALLOC_DECLARE(M_PDU);
|
||||
|
||||
#define ISOK2DIG(dig, pp) ((dig != NULL) && ((pp->ipdu.bhs.opcode & 0x1f) != ISCSI_LOGIN_CMD))
|
||||
|
||||
#ifndef BIT
|
||||
#define BIT(n) (1 <<(n))
|
||||
#endif
|
||||
@ -69,15 +82,15 @@ MALLOC_DECLARE(M_PDU);
|
||||
#define ISC_OQNOTEMPTY BIT(6)
|
||||
#define ISC_OWAITING BIT(7)
|
||||
#define ISC_FFPHASE BIT(8)
|
||||
#define ISC_FFPWAIT BIT(9)
|
||||
|
||||
#define ISC_MEMWAIT BIT(10)
|
||||
#define ISC_SIGNALED BIT(11)
|
||||
#define ISC_FROZEN BIT(12)
|
||||
#define ISC_STALLED BIT(13)
|
||||
#define ISC_CAMDEVS BIT(9)
|
||||
#define ISC_SCANWAIT BIT(10)
|
||||
|
||||
#define ISC_HOLD BIT(14)
|
||||
#define ISC_HOLDED BIT(15)
|
||||
#define ISC_MEMWAIT BIT(11)
|
||||
#define ISC_SIGNALED BIT(12)
|
||||
|
||||
#define ISC_HOLD BIT(15)
|
||||
#define ISC_HOLDED BIT(16)
|
||||
|
||||
#define ISC_SHUTDOWN BIT(31)
|
||||
|
||||
@ -116,9 +129,7 @@ typedef struct isc_session {
|
||||
|
||||
struct proc *proc; // the userland process
|
||||
int signal;
|
||||
|
||||
struct proc *soc_proc;
|
||||
|
||||
struct proc *stp; // the sm thread
|
||||
|
||||
struct isc_softc *isc;
|
||||
@ -127,16 +138,13 @@ typedef struct isc_session {
|
||||
digest_t *dataDigest; // the digest alg. if any
|
||||
|
||||
int sid; // Session ID
|
||||
int targetid;
|
||||
// int cid; // Connection ID
|
||||
// int tsih; // target session identifier handle
|
||||
sn_t sn; // sequence number stuff;
|
||||
int cws; // current window size
|
||||
|
||||
int target_nluns; // this and target_lun are
|
||||
// hopefully temporal till I
|
||||
// figure out a better way.
|
||||
lun_id_t target_lun[ISCSI_MAX_LUNS];
|
||||
int target_lun[ISCSI_MAX_LUNS/(sizeof(int)*8) + 1];
|
||||
|
||||
struct mtx rsp_mtx;
|
||||
struct mtx rsv_mtx;
|
||||
@ -150,16 +158,18 @@ typedef struct isc_session {
|
||||
queue_t wsnd;
|
||||
queue_t hld;
|
||||
|
||||
/*
|
||||
| negotiable values
|
||||
*/
|
||||
isc_opt_t opt;
|
||||
isc_opt_t opt; // negotiable values
|
||||
|
||||
struct i_stats stats;
|
||||
struct cam_path *cam_path;
|
||||
bhs_t bhs;
|
||||
struct uio uio;
|
||||
struct iovec iov;
|
||||
/*
|
||||
| cam stuff
|
||||
*/
|
||||
struct cam_sim *cam_sim;
|
||||
struct cam_path *cam_path;
|
||||
struct mtx cam_mtx;
|
||||
/*
|
||||
| sysctl stuff
|
||||
*/
|
||||
@ -180,33 +190,29 @@ typedef struct pduq {
|
||||
struct iovec iov[5]; // XXX: careful ...
|
||||
struct mbuf *mp;
|
||||
struct bintime ts;
|
||||
queue_t *pduq;
|
||||
queue_t *pduq;
|
||||
} pduq_t;
|
||||
|
||||
/*
|
||||
*/
|
||||
struct isc_softc {
|
||||
//int state;
|
||||
struct cdev *dev;
|
||||
eventhandler_tag eh;
|
||||
char isid[6]; // Initiator Session ID (48 bits)
|
||||
struct mtx mtx;
|
||||
|
||||
int nsess;
|
||||
struct mtx isc_mtx;
|
||||
TAILQ_HEAD(,isc_session) isc_sess;
|
||||
isc_session_t *sessions[MAX_SESSIONS];
|
||||
int nsess;
|
||||
struct cdev *dev;
|
||||
char isid[6]; // Initiator Session ID (48 bits)
|
||||
struct unrhdr *unit;
|
||||
struct sx unit_sx;
|
||||
|
||||
struct mtx pdu_mtx;
|
||||
uma_zone_t pdu_zone; // pool of free pdu's
|
||||
TAILQ_HEAD(,pduq) freepdu;
|
||||
|
||||
struct mtx pdu_mtx;
|
||||
#ifdef ISCSI_INITIATOR_DEBUG
|
||||
int npdu_alloc, npdu_max; // for instrumentation
|
||||
int npdu_alloc, npdu_max; // for instrumentation
|
||||
#endif
|
||||
#ifdef DO_EVENTHANDLER
|
||||
eventhandler_tag eh;
|
||||
#endif
|
||||
#define MAX_PDUS (MAX_SESSIONS*256) // XXX: at the moment this is arbitrary
|
||||
uma_zone_t pdu_zone; // pool of free pdu's
|
||||
TAILQ_HEAD(,pduq) freepdu;
|
||||
/*
|
||||
| cam stuff
|
||||
*/
|
||||
struct cam_sim *cam_sim;
|
||||
struct cam_path *cam_path;
|
||||
struct mtx cam_mtx;
|
||||
/*
|
||||
| sysctl stuff
|
||||
*/
|
||||
@ -231,14 +237,14 @@ int i_pdu_flush(isc_session_t *sc);
|
||||
int i_setopt(isc_session_t *sp, isc_opt_t *opt);
|
||||
void i_freeopt(isc_opt_t *opt);
|
||||
|
||||
int ic_init(struct isc_softc *sc);
|
||||
void ic_destroy(struct isc_softc *sc);
|
||||
int ic_fullfeature(struct cdev *dev);
|
||||
int ic_init(isc_session_t *sp);
|
||||
void ic_destroy(isc_session_t *sp);
|
||||
void ic_lost_target(isc_session_t *sp, int target);
|
||||
int ic_getCamVals(isc_session_t *sp, iscsi_cam_t *cp);
|
||||
|
||||
void ism_recv(isc_session_t *sp, pduq_t *pq);
|
||||
int ism_start(isc_session_t *sp);
|
||||
void ism_restart(isc_session_t *sp);
|
||||
void ism_stop(isc_session_t *sp);
|
||||
|
||||
int scsi_encap(struct cam_sim *sim, union ccb *ccb);
|
||||
@ -250,9 +256,6 @@ void iscsi_async(isc_session_t *sp, pduq_t *pq);
|
||||
void iscsi_cleanup(isc_session_t *sp);
|
||||
int iscsi_requeue(isc_session_t *sp);
|
||||
|
||||
void ic_freeze(isc_session_t *sp);
|
||||
void ic_release(isc_session_t *sp);
|
||||
|
||||
// Serial Number Arithmetic
|
||||
#define _MAXINCR 0x7FFFFFFF // 2 ^ 31 - 1
|
||||
#define SNA_GT(i1, i2) ((i1 != i2) && (\
|
||||
@ -269,7 +272,7 @@ void ic_release(isc_session_t *sp);
|
||||
#define CAM_ULOCK(arg)
|
||||
|
||||
static __inline void
|
||||
XPT_DONE(struct isc_softc *isp, union ccb *ccb)
|
||||
XPT_DONE(isc_session_t *sp, union ccb *ccb)
|
||||
{
|
||||
mtx_lock(&Giant);
|
||||
xpt_done(ccb);
|
||||
@ -280,11 +283,11 @@ XPT_DONE(struct isc_softc *isp, union ccb *ccb)
|
||||
#define CAM_UNLOCK(arg) mtx_unlock(&arg->cam_mtx)
|
||||
|
||||
static __inline void
|
||||
XPT_DONE(struct isc_softc *isp, union ccb *ccb)
|
||||
XPT_DONE(isc_session_t *sp, union ccb *ccb)
|
||||
{
|
||||
CAM_LOCK(isp);
|
||||
CAM_LOCK(sp);
|
||||
xpt_done(ccb);
|
||||
CAM_UNLOCK(isp);
|
||||
CAM_UNLOCK(sp);
|
||||
}
|
||||
#else
|
||||
//__FreeBSD_version >= 600000
|
||||
@ -332,7 +335,7 @@ pdu_free(struct isc_softc *isc, pduq_t *pq)
|
||||
m_freem(pq->mp);
|
||||
#ifdef NO_USE_MBUF
|
||||
if(pq->buf != NULL)
|
||||
free(pq->buf, M_ISCSI);
|
||||
free(pq->buf, M_ISCSIBUF);
|
||||
#endif
|
||||
mtx_lock(&isc->pdu_mtx);
|
||||
TAILQ_INSERT_TAIL(&isc->freepdu, pq, pq_link);
|
||||
@ -564,6 +567,27 @@ i_search_hld(isc_session_t *sp, int itt, int keep)
|
||||
return pq;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
i_acked_hld(isc_session_t *sp, pdu_t *op)
|
||||
{
|
||||
pduq_t *pq, *tmp;
|
||||
u_int exp = sp->sn.expCmd;
|
||||
|
||||
pq = NULL;
|
||||
mtx_lock(&sp->hld_mtx);
|
||||
TAILQ_FOREACH_SAFE(pq, &sp->hld, pq_link, tmp) {
|
||||
if((op && op->ipdu.bhs.itt == pq->pdu.ipdu.bhs.itt)
|
||||
|| (pq->ccb == NULL
|
||||
&& (pq->pdu.ipdu.bhs.opcode != ISCSI_WRITE_DATA)
|
||||
&& SNA_GT(exp, ntohl(pq->pdu.ipdu.bhs.ExpStSN)))) {
|
||||
sp->stats.nhld--;
|
||||
TAILQ_REMOVE(&sp->hld, pq, pq_link);
|
||||
pdu_free(sp->isc, pq);
|
||||
}
|
||||
}
|
||||
mtx_unlock(&sp->hld_mtx);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
i_mbufcopy(struct mbuf *mp, caddr_t dp, int len)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user