Batch pdu read in function iscsi_read_from_socket()
iscsi_read_from_socket can currently only read one PDU in each iscsi_service invocation even if there is more data available on the socket. This patch reads all PDUs until the socket would block. It enqueues all complete read PDUs and then processes them in order of arrival. Signed-off-by: Peter Lieven <pl@kamp.de>
This commit is contained in:
@@ -119,6 +119,7 @@ struct iscsi_context {
|
|||||||
int tcp_keepintvl;
|
int tcp_keepintvl;
|
||||||
int tcp_keepidle;
|
int tcp_keepidle;
|
||||||
int tcp_syncnt;
|
int tcp_syncnt;
|
||||||
|
int tcp_nonblocking;
|
||||||
|
|
||||||
int current_phase;
|
int current_phase;
|
||||||
int next_phase;
|
int next_phase;
|
||||||
|
|||||||
22
lib/socket.c
22
lib/socket.c
@@ -126,15 +126,15 @@ void iscsi_decrement_iface_rr() {
|
|||||||
iface_rr--;
|
iface_rr--;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_nonblocking(int fd)
|
static int set_nonblocking(int fd)
|
||||||
{
|
{
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
unsigned long opt = 1;
|
unsigned long opt = 1;
|
||||||
ioctlsocket(fd, FIONBIO, &opt);
|
return ioctlsocket(fd, FIONBIO, &opt);
|
||||||
#else
|
#else
|
||||||
unsigned v;
|
unsigned v;
|
||||||
v = fcntl(fd, F_GETFL, 0);
|
v = fcntl(fd, F_GETFL, 0);
|
||||||
fcntl(fd, F_SETFL, v | O_NONBLOCK);
|
return fcntl(fd, F_SETFL, v | O_NONBLOCK);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +203,7 @@ static int iscsi_tcp_connect(struct iscsi_context *iscsi, union socket_address *
|
|||||||
iscsi->fd = iscsi->old_iscsi->fd;
|
iscsi->fd = iscsi->old_iscsi->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_nonblocking(iscsi->fd);
|
iscsi->tcp_nonblocking = !set_nonblocking(iscsi->fd);
|
||||||
|
|
||||||
iscsi_set_tcp_keepalive(iscsi, iscsi->tcp_keepidle, iscsi->tcp_keepcnt, iscsi->tcp_keepintvl);
|
iscsi_set_tcp_keepalive(iscsi, iscsi->tcp_keepidle, iscsi->tcp_keepcnt, iscsi->tcp_keepintvl);
|
||||||
|
|
||||||
@@ -568,6 +568,7 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
|
|||||||
struct iscsi_in_pdu *in;
|
struct iscsi_in_pdu *in;
|
||||||
ssize_t data_size, count, padding_size;
|
ssize_t data_size, count, padding_size;
|
||||||
|
|
||||||
|
do {
|
||||||
if (iscsi->incoming == NULL) {
|
if (iscsi->incoming == NULL) {
|
||||||
iscsi->incoming = iscsi_szmalloc(iscsi, sizeof(struct iscsi_in_pdu));
|
iscsi->incoming = iscsi_szmalloc(iscsi, sizeof(struct iscsi_in_pdu));
|
||||||
iscsi->incoming->hdr = iscsi_szmalloc(iscsi, ISCSI_RAW_HEADER_SIZE + ISCSI_DIGEST_SIZE);
|
iscsi->incoming->hdr = iscsi_szmalloc(iscsi, ISCSI_RAW_HEADER_SIZE + ISCSI_DIGEST_SIZE);
|
||||||
@@ -586,11 +587,12 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
|
|||||||
count = ISCSI_HEADER_SIZE - in->hdr_pos;
|
count = ISCSI_HEADER_SIZE - in->hdr_pos;
|
||||||
count = recv(iscsi->fd, &in->hdr[in->hdr_pos], count, 0);
|
count = recv(iscsi->fd, &in->hdr[in->hdr_pos], count, 0);
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
|
/* remote side has closed the socket. */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
if (errno == EINTR || errno == EAGAIN) {
|
if (errno == EINTR || errno == EAGAIN) {
|
||||||
return 0;
|
break;
|
||||||
}
|
}
|
||||||
iscsi_set_error(iscsi, "read from socket failed, "
|
iscsi_set_error(iscsi, "read from socket failed, "
|
||||||
"errno:%d", errno);
|
"errno:%d", errno);
|
||||||
@@ -601,7 +603,7 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
|
|||||||
|
|
||||||
if (in->hdr_pos < ISCSI_HEADER_SIZE) {
|
if (in->hdr_pos < ISCSI_HEADER_SIZE) {
|
||||||
/* we don't have the full header yet, so return */
|
/* we don't have the full header yet, so return */
|
||||||
return 0;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
padding_size = iscsi_get_pdu_padding_size(&in->hdr[0]);
|
padding_size = iscsi_get_pdu_padding_size(&in->hdr[0]);
|
||||||
@@ -638,11 +640,12 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
|
/* remote side has closed the socket. */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
if (errno == EINTR || errno == EAGAIN) {
|
if (errno == EINTR || errno == EAGAIN) {
|
||||||
return 0;
|
break;
|
||||||
}
|
}
|
||||||
iscsi_set_error(iscsi, "read from socket failed, "
|
iscsi_set_error(iscsi, "read from socket failed, "
|
||||||
"errno:%d %s", errno,
|
"errno:%d %s", errno,
|
||||||
@@ -654,12 +657,12 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (in->data_pos < data_size) {
|
if (in->data_pos < data_size) {
|
||||||
return 0;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ISCSI_LIST_ADD_END(&iscsi->inqueue, in);
|
ISCSI_LIST_ADD_END(&iscsi->inqueue, in);
|
||||||
iscsi->incoming = NULL;
|
iscsi->incoming = NULL;
|
||||||
|
} while (iscsi->is_loggedin && iscsi->tcp_nonblocking);
|
||||||
|
|
||||||
while (iscsi->inqueue != NULL) {
|
while (iscsi->inqueue != NULL) {
|
||||||
struct iscsi_in_pdu *current = iscsi->inqueue;
|
struct iscsi_in_pdu *current = iscsi->inqueue;
|
||||||
@@ -671,7 +674,6 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
|
|||||||
iscsi_free_iscsi_in_pdu(iscsi, current);
|
iscsi_free_iscsi_in_pdu(iscsi, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user