From f622d55d8fa4b195e118e533241c768d84f65b91 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 26 Aug 2013 23:34:05 +0200 Subject: [PATCH] Improved patch 18 to cover write side too --- 0018-fix-iovec-short-reads.patch | 113 ++++++++++++++++++++----------- libiscsi.spec | 5 +- 2 files changed, 77 insertions(+), 41 deletions(-) diff --git a/0018-fix-iovec-short-reads.patch b/0018-fix-iovec-short-reads.patch index c03b148..76d3204 100644 --- a/0018-fix-iovec-short-reads.patch +++ b/0018-fix-iovec-short-reads.patch @@ -8,16 +8,18 @@ This patch fixes this by reading the padding in a separate "recv" system call. These packets anyway do not happen in the data path, where the packet size is a multiple of 512. +Similarly, we need to write padding after an outgoing data packet. + This fixes QEMU's scsi-generic backend, which triggered the problem when the target sent a 66-byte INQUIRY response. Signed-off-by: Paolo Bonzini diff --git a/include/iscsi-private.h b/include/iscsi-private.h -index 9345b09..a787127 100644 +index e9b9e7e..6cc8a20 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h -@@ -258,6 +258,7 @@ struct scsi_task; +@@ -261,6 +261,7 @@ struct scsi_task; void iscsi_pdu_set_cdb(struct iscsi_pdu *pdu, struct scsi_task *task); int iscsi_get_pdu_data_size(const unsigned char *hdr); @@ -26,10 +28,10 @@ index 9345b09..a787127 100644 int iscsi_process_login_reply(struct iscsi_context *iscsi, diff --git a/lib/pdu.c b/lib/pdu.c -index b5e57fe..61abdd6 100644 +index f53490a..043a986 100644 --- a/lib/pdu.c +++ b/lib/pdu.c -@@ -207,11 +207,22 @@ iscsi_get_pdu_data_size(const unsigned char *hdr) +@@ -217,11 +217,22 @@ iscsi_get_pdu_data_size(const unsigned char *hdr) int size; size = scsi_get_uint32(&hdr[4]) & 0x00ffffff; @@ -54,10 +56,10 @@ index b5e57fe..61abdd6 100644 ISCSI_REJECT_RESERVED = 0x01, ISCSI_REJECT_DATA_DIGEST_ERROR = 0x02, diff --git a/lib/socket.c b/lib/socket.c -index edf2ec5..9055452 100644 +index 13020ee..7a668c2 100644 --- a/lib/socket.c +++ b/lib/socket.c -@@ -461,7 +461,7 @@ static int +@@ -479,7 +479,7 @@ static int iscsi_read_from_socket(struct iscsi_context *iscsi) { struct iscsi_in_pdu *in; @@ -66,54 +68,85 @@ index edf2ec5..9055452 100644 if (iscsi->incoming == NULL) { iscsi->incoming = iscsi_zmalloc(iscsi, sizeof(struct iscsi_in_pdu)); -@@ -499,6 +499,8 @@ iscsi_read_from_socket(struct iscsi_context *iscsi) +@@ -516,31 +516,36 @@ iscsi_read_from_socket(struct iscsi_context *iscsi) + return 0; } - data_size = iscsi_get_pdu_data_size(&in->hdr[0]); +- data_size = iscsi_get_pdu_data_size(&in->hdr[0]); + padding_size = iscsi_get_pdu_padding_size(&in->hdr[0]); ++ data_size = iscsi_get_pdu_data_size(&in->hdr[0]) + padding_size; + if (data_size < 0 || data_size > (ssize_t)iscsi->initiator_max_recv_data_segment_length) { iscsi_set_error(iscsi, "Invalid data size received from target (%d)", (int)data_size); return -1; -@@ -514,16 +516,29 @@ iscsi_read_from_socket(struct iscsi_context *iscsi) - if (iovector_in != NULL) { + } + if (data_size != 0) { +- unsigned char *buf = NULL; ++ unsigned char padding_buf[3]; ++ unsigned char *buf = padding_buf; + struct scsi_iovector * iovector_in; + + count = data_size - in->data_pos; + + /* first try to see if we already have a user buffer */ + iovector_in = iscsi_get_scsi_task_iovector_in(iscsi, in); +- if (iovector_in != NULL) { ++ if (iovector_in != NULL && count > padding_size) { uint32_t offset = scsi_get_uint32(&in->hdr[40]); - count = iscsi_iovector_readv_writev(iscsi, iovector_in, in->data_pos + offset, count, 0); -+ -+ /* This does not happen on the data path, so it does not need -+ * to be especially efficient. -+ */ -+ if (padding_size) { -+ char padding_buf[3]; -+ int count2; -+ count2 = recv(iscsi->fd, padding_buf, padding_size, 0); -+ if (count2 < 0) -+ count = count2; -+ else -+ count += count2; -+ } +- count = iscsi_iovector_readv_writev(iscsi, iovector_in, in->data_pos + offset, count, 0); ++ count = iscsi_iovector_readv_writev(iscsi, iovector_in, in->data_pos + offset, count - padding_size, 0); } else { - if (in->data == NULL) { +- if (in->data == NULL) { - in->data = iscsi_malloc(iscsi, data_size); -+ in->data = iscsi_malloc(iscsi, data_size + padding_size); ++ if (iovector_in == NULL) { if (in->data == NULL) { - iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu->data(%d)", (int)data_size); - return -1; +- iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu->data(%d)", (int)data_size); +- return -1; ++ in->data = iscsi_malloc(iscsi, data_size); ++ if (in->data == NULL) { ++ iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu->data(%d)", (int)data_size); ++ return -1; ++ } } ++ buf = &in->data[in->data_pos]; } - buf = &in->data[in->data_pos]; -- count = recv(iscsi->fd, buf, count, 0); -+ count = recv(iscsi->fd, buf, count + padding_size, 0); +- buf = &in->data[in->data_pos]; + count = recv(iscsi->fd, buf, count, 0); } - if (count == 0) { -@@ -541,7 +555,7 @@ iscsi_read_from_socket(struct iscsi_context *iscsi) - in->data_pos += count; - } +@@ -586,6 +591,7 @@ iscsi_write_to_socket(struct iscsi_context *iscsi) + { + ssize_t count; + struct iscsi_pdu *pdu; ++ static char padding_buf[3]; -- if (in->data_pos < data_size) { -+ if (in->data_pos < data_size + padding_size) { - return 0; - } + if (iscsi->fd == -1) { + iscsi_set_error(iscsi, "trying to write but not connected"); +@@ -663,6 +669,27 @@ iscsi_write_to_socket(struct iscsi_context *iscsi) + pdu->out_written += count; + } - ++ total = pdu->out_len; ++ total = (total + 3) & 0xfffffffc; ++ ++ /* Write padding */ ++ if (pdu->out_written < total) { ++ count = send(iscsi->fd, padding_buf, total - pdu->out_written, 0); ++ if (count == -1) { ++ if (errno == EAGAIN || errno == EWOULDBLOCK) { ++ return 0; ++ } ++ iscsi_set_error(iscsi, "Error when writing to " ++ "socket :%d", errno); ++ return -1; ++ } ++ pdu->out_written += count; ++ } ++ /* if we havent written the full padding yet. */ ++ if (pdu->out_written != total) { ++ return 0; ++ } ++ + if (pdu->flags & ISCSI_PDU_DELETE_WHEN_SENT) { + iscsi_free_pdu(iscsi, pdu); + } diff --git a/libiscsi.spec b/libiscsi.spec index 6ce5d6e..d6aef5c 100644 --- a/libiscsi.spec +++ b/libiscsi.spec @@ -1,7 +1,7 @@ Name: libiscsi Summary: iSCSI client library Version: 1.9.0 -Release: 2%{?dist} +Release: 3%{?dist} License: LGPLv2+ Group: System Environment/Libraries URL: https://github.com/sahlberg/%{name} @@ -127,6 +127,9 @@ The libiscsi-devel package includes the header files for libiscsi. %{_libdir}/pkgconfig/libiscsi.pc %changelog +* Mon Aug 26 2013 Paolo Bonzini - 1.9.0-3 +- Improved patch 18 to cover write side too + * Mon Aug 26 2013 Paolo Bonzini - 1.9.0-2 - Add patch 18 to fix QEMU's scsi-generic mode