From: claudio Date: Mon, 21 Apr 2014 12:24:58 +0000 (+0000) Subject: It is possible that we can't burst all of the data in the immediate data X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=a557b68ec1b7256c44ea5cd4760b7e6936cd1e49;p=openbsd 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. --- 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 @@ -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");