summaryrefslogtreecommitdiffstats
path: root/usr.sbin/iscsid
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2014-04-21 12:24:58 +0000
committerclaudio <claudio@openbsd.org>2014-04-21 12:24:58 +0000
commita557b68ec1b7256c44ea5cd4760b7e6936cd1e49 (patch)
tree6cba91dd1d3f5e61933119b727281a264f38ee72 /usr.sbin/iscsid
parentip_output() using varargs always struck me as bizarre, esp since it's only (diff)
downloadwireguard-openbsd-a557b68ec1b7256c44ea5cd4760b7e6936cd1e49.tar.xz
wireguard-openbsd-a557b68ec1b7256c44ea5cd4760b7e6936cd1e49.zip
It is possible that we can't burst all of the data in the immediate data
part of the write request. In that case R2T requests with be sent for the rest of the data. The amount of data we can send is defined by MaxRecvDataSegmentLength which is per connection and so a bit hackish to read out. In the long run the min() of all connection MaxRecvDataSegmentLength should be stored in the session struct.
Diffstat (limited to 'usr.sbin/iscsid')
-rw-r--r--usr.sbin/iscsid/vscsi.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/usr.sbin/iscsid/vscsi.c b/usr.sbin/iscsid/vscsi.c
index 4f796eb3845..5606358fd9d 100644
--- a/usr.sbin/iscsid/vscsi.c
+++ b/usr.sbin/iscsid/vscsi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vscsi.c,v 1.11 2014/04/21 09:48:31 claudio Exp $ */
+/* $OpenBSD: vscsi.c,v 1.12 2014/04/21 12:24:58 claudio Exp $ */
/*
* Copyright (c) 2009 Claudio Jeker <claudio@openbsd.org>
@@ -49,9 +49,10 @@ struct scsi_task {
size_t datalen;
};
-void vscsi_callback(struct connection *, void *, struct pdu *);
-void vscsi_fail(void *arg);
-void vscsi_dataout(struct connection *, struct scsi_task *, u_int32_t, size_t);
+void vscsi_callback(struct connection *, void *, struct pdu *);
+void vscsi_fail(void *arg);
+void vscsi_dataout(struct connection *, struct scsi_task *, u_int32_t,
+ size_t, size_t);
void
vscsi_open(char *dev)
@@ -118,14 +119,20 @@ vscsi_dispatch(int fd, short event, void *arg)
memcpy(sreq->cdb, &i2t.cmd, i2t.cmdlen);
/* include immediate data of up to FirstBurstLength bytes if allowed */
- if (i2t.direction == VSCSI_DIR_WRITE &&
- s->active.ImmediateData) {
+ if (i2t.direction == VSCSI_DIR_WRITE && s->active.ImmediateData) {
+ struct connection *c;
char *buf;
u_int32_t t32;
size_t size;
size = i2t.datalen > s->active.FirstBurstLength ?
s->active.FirstBurstLength : i2t.datalen;
+
+ /* XXX assumes all connections have same settings */
+ c = TAILQ_FIRST(&s->connections);
+ if (c && size > c->active.MaxRecvDataSegmentLength)
+ size = c->active.MaxRecvDataSegmentLength;
+
if (!(buf = pdu_alloc(size)))
fatal("vscsi_dispatch");
t32 = htonl(size);
@@ -207,7 +214,7 @@ vscsi_callback(struct connection *c, void *arg, struct pdu *p)
struct iscsi_pdu_rt2 *r2t;
int status = VSCSI_STAT_DONE;
u_char *buf = NULL;
- size_t size = 0, n;
+ size_t size, off, n;
int tag;
sresp = pdu_getbuf(p, NULL, PDU_HEADER);
@@ -223,6 +230,7 @@ vscsi_callback(struct connection *c, void *arg, struct pdu *p)
conn_fail(c);
break;
}
+ size = 0;
/* XXX handle the various serial numbers */
if (sresp->response) {
status = VSCSI_STAT_ERR;
@@ -263,11 +271,10 @@ send_status:
case ISCSI_OP_R2T:
conn_task_cleanup(c, &t->task);
r2t = (struct iscsi_pdu_rt2 *)sresp;
- if (ntohl(r2t->buffer_offs))
- fatalx("vscsi: r2t bummer failure");
+ off = ntohl(r2t->buffer_offs);
size = ntohl(r2t->desired_datalen);
- vscsi_dataout(c, t, r2t->ttt, size);
+ vscsi_dataout(c, t, r2t->ttt, size, off);
break;
default:
log_debug("scsi task: tag %d, target %d lun %d", t->tag,
@@ -291,7 +298,7 @@ vscsi_fail(void *arg)
void
vscsi_dataout(struct connection *c, struct scsi_task *t, u_int32_t ttt,
- size_t len)
+ size_t len, size_t buffer_off)
{
struct pdu *p;
struct iscsi_pdu_data_out *dout;
@@ -318,7 +325,7 @@ vscsi_dataout(struct connection *c, struct scsi_task *t, u_int32_t ttt,
t32 = htonl(size);
memcpy(&dout->ahslen, &t32, sizeof(t32));
- dout->buffer_offs = htonl(off);
+ dout->buffer_offs = htonl(buffer_off + off);
if (!(buf = pdu_alloc(size)))
fatal("vscsi_r2t");