[libiscsi/f20] Improved patch 18 to cover write side too
bonzini
bonzini at fedoraproject.org
Mon Aug 26 21:37:14 UTC 2013
commit f622d55d8fa4b195e118e533241c768d84f65b91
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Mon Aug 26 23:34:05 2013 +0200
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 <pbonzini at redhat.com>
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 <pbonzini at redhat.com> - 1.9.0-3
+- Improved patch 18 to cover write side too
+
* Mon Aug 26 2013 Paolo Bonzini <pbonzini at redhat.com> - 1.9.0-2
- Add patch 18 to fix QEMU's scsi-generic mode
More information about the scm-commits
mailing list