[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