[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