[libiscsi/f20] Add patch 18 to fix QEMU's scsi-generic mode

bonzini bonzini at fedoraproject.org
Mon Aug 26 15:58:49 UTC 2013


commit 617a50a9c9a10e07adf50dd05c1ecd5d6a7643e2
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Aug 26 17:58:00 2013 +0200

    Add patch 18 to fix QEMU's scsi-generic mode

 0018-fix-iovec-short-reads.patch |  119 ++++++++++++++++++++++++++++++++++++++
 libiscsi.spec                    |    7 ++-
 2 files changed, 125 insertions(+), 1 deletions(-)
---
diff --git a/0018-fix-iovec-short-reads.patch b/0018-fix-iovec-short-reads.patch
new file mode 100644
index 0000000..c03b148
--- /dev/null
+++ b/0018-fix-iovec-short-reads.patch
@@ -0,0 +1,119 @@
+From: Paolo Bonzini <pbonzini at redhat.com>
+Subject: [PATCH] Ignore padding when an iovector is supplied
+
+The iSCSI protocol adds padding to a data packet if the data size is not
+a multiple of four.  The iovector provided by QEMU does not include such
+padding, and libiscsi then complains that there was a protocol error.
+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.
+
+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 <pbonzini at redhat.com>
+
+diff --git a/include/iscsi-private.h b/include/iscsi-private.h
+index 9345b09..a787127 100644
+--- a/include/iscsi-private.h
++++ b/include/iscsi-private.h
+@@ -258,6 +258,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);
++int iscsi_get_pdu_padding_size(const unsigned char *hdr);
+ int iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in);
+ 
+ int iscsi_process_login_reply(struct iscsi_context *iscsi,
+diff --git a/lib/pdu.c b/lib/pdu.c
+index b5e57fe..61abdd6 100644
+--- a/lib/pdu.c
++++ b/lib/pdu.c
+@@ -207,11 +207,22 @@ iscsi_get_pdu_data_size(const unsigned char *hdr)
+ 	int size;
+ 
+ 	size = scsi_get_uint32(&hdr[4]) & 0x00ffffff;
+-	size = (size+3) & 0xfffffffc;
+ 
+ 	return size;
+ }
+ 
++
++int
++iscsi_get_pdu_padding_size(const unsigned char *hdr)
++{
++	int data_size, padded_size;
++
++	data_size = scsi_get_uint32(&hdr[4]) & 0x00ffffff;
++	padded_size = (data_size+3) & 0xfffffffc;
++
++	return padded_size - data_size;
++}
++
+ enum iscsi_reject_reason {
+ 	ISCSI_REJECT_RESERVED                 = 0x01,
+ 	ISCSI_REJECT_DATA_DIGEST_ERROR        = 0x02,
+diff --git a/lib/socket.c b/lib/socket.c
+index edf2ec5..9055452 100644
+--- a/lib/socket.c
++++ b/lib/socket.c
+@@ -461,7 +461,7 @@ static int
+ iscsi_read_from_socket(struct iscsi_context *iscsi)
+ {
+ 	struct iscsi_in_pdu *in;
+-	ssize_t data_size, count;
++	ssize_t data_size, count, padding_size;
+ 
+ 	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)
+ 	}
+ 
+ 	data_size = iscsi_get_pdu_data_size(&in->hdr[0]);
++	padding_size = iscsi_get_pdu_padding_size(&in->hdr[0]);
++
+ 	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) {
+ 			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;
++			}
+ 		} else {
+ 			if (in->data == NULL) {
+-				in->data = iscsi_malloc(iscsi, data_size);
++				in->data = iscsi_malloc(iscsi, data_size + padding_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];
+-			count = recv(iscsi->fd, buf, count, 0);
++			count = recv(iscsi->fd, buf, count + padding_size, 0);
+ 		}
+ 		
+ 		if (count == 0) {
+@@ -541,7 +555,7 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
+ 		in->data_pos += count;
+ 	}
+ 
+-	if (in->data_pos < data_size) {
++	if (in->data_pos < data_size + padding_size) {
+ 		return 0;
+ 	}
+ 
+
diff --git a/libiscsi.spec b/libiscsi.spec
index 1cbe98f..6ce5d6e 100644
--- a/libiscsi.spec
+++ b/libiscsi.spec
@@ -1,7 +1,7 @@
 Name: libiscsi
 Summary: iSCSI client library
 Version: 1.9.0
-Release: 1%{?dist}
+Release: 2%{?dist}
 License: LGPLv2+
 Group: System Environment/Libraries
 URL: https://github.com/sahlberg/%{name}
@@ -25,6 +25,7 @@ Patch14: 0014-fix-another-aliasing-problem.patch
 Patch15: 0015-fix-arm-aliasing-problem.patch
 Patch16: 0016-avoid-casting-struct-sockaddr.patch
 Patch17: 0017-use-scsi_get-set_uint16-32-64-in-tests.patch
+Patch18: 0018-fix-iovec-short-reads.patch
 
 BuildRequires: autoconf
 BuildRequires: automake
@@ -65,6 +66,7 @@ a network.
 %patch15 -p1
 %patch16 -p1
 %patch17 -p1
+%patch18 -p1
 
 %build
 sh autogen.sh
@@ -125,6 +127,9 @@ The libiscsi-devel package includes the header files for libiscsi.
 %{_libdir}/pkgconfig/libiscsi.pc
 
 %changelog
+* Mon Aug 26 2013 Paolo Bonzini <pbonzini at redhat.com> - 1.9.0-2
+- Add patch 18 to fix QEMU's scsi-generic mode
+
 * Fri Aug 2 2013 Paolo Bonzini <pbonzini at redhat.com> - 1.9.0-1
 - Rebase to 1.9.0
 - Cherry-pick selected patches from upstream


More information about the scm-commits mailing list