PDU use serial32 arithmetic for cmdsn, maxcmdsn and expcmdsn.

RFC3720 says that cmdsn comparison must be done using
serial32 arithmetic. This will definetly avoid a deadlock
if cmdsn wraps from 2^32-1 to 0.

Signed-off-by: Peter Lieven <pl@kamp.de>
This commit is contained in:
Peter Lieven
2012-11-28 10:37:28 +01:00
parent 700d363a88
commit cd09c0f17d
6 changed files with 30 additions and 9 deletions

View File

@@ -325,6 +325,9 @@ iscsi_log_message(struct iscsi_context *iscsi, int level, const char *format, ..
void
iscsi_add_to_outqueue(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);
int
iscsi_serial32_compare(u_int32_t s1, u_int32_t s2);
#ifdef __cplusplus
}
#endif

View File

@@ -335,7 +335,7 @@ iscsi_process_scsi_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
}
maxcmdsn = scsi_get_uint32(&in->hdr[32]);
if (maxcmdsn > iscsi->maxcmdsn) {
if (iscsi_serial32_compare(maxcmdsn,iscsi->maxcmdsn) > 0) {
iscsi->maxcmdsn = maxcmdsn;
}
@@ -452,7 +452,7 @@ iscsi_process_scsi_data_in(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
}
maxcmdsn = scsi_get_uint32(&in->hdr[32]);
if (maxcmdsn > iscsi->maxcmdsn) {
if (iscsi_serial32_compare(maxcmdsn,iscsi->maxcmdsn) > 0) {
iscsi->maxcmdsn = maxcmdsn;
}
@@ -542,7 +542,7 @@ iscsi_process_r2t(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
len = scsi_get_uint32(&in->hdr[44]);
maxcmdsn = scsi_get_uint32(&in->hdr[32]);
if (maxcmdsn > iscsi->maxcmdsn) {
if (iscsi_serial32_compare(maxcmdsn,iscsi->maxcmdsn) > 0) {
iscsi->maxcmdsn = maxcmdsn;
}

View File

@@ -950,10 +950,10 @@ iscsi_process_login_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
iscsi->statsn = scsi_get_uint16(&in->hdr[24]);
maxcmdsn = scsi_get_uint32(&in->hdr[32]);
if (maxcmdsn > iscsi->maxcmdsn) {
if (iscsi_serial32_compare(maxcmdsn,iscsi->maxcmdsn) > 0) {
iscsi->maxcmdsn = maxcmdsn;
}
/* XXX here we should parse the data returned in case the target
* renegotiated some some parameters.
* we should also do proper handshaking if the target is not yet
@@ -1136,7 +1136,7 @@ struct iscsi_in_pdu *in)
uint32_t maxcmdsn;
maxcmdsn = scsi_get_uint32(&in->hdr[32]);
if (maxcmdsn > iscsi->maxcmdsn) {
if (iscsi_serial32_compare(maxcmdsn,iscsi->maxcmdsn) > 0) {
iscsi->maxcmdsn = maxcmdsn;
}

View File

@@ -30,6 +30,24 @@
#include "scsi-lowlevel.h"
#include "slist.h"
/* This adds 32-bit serial comparision as defined in RFC1982.
* It returns 0 for equality, 1 if s1 is greater than s2 and
* -1 if s1 is less than s2. According to RFC1982 section 3.2
* there are rare cases where the result of the comparision is
* undefined e.g. when s1 = 0 and s2=2^31. This cases should
* not happen in iSCSI protocol.
*/
int
iscsi_serial32_compare(u_int32_t s1, u_int32_t s2) {
if (s1 == s2) return 0;
if (s1 < s2 && s2-s1 < (u_int32_t)1<<31) return -1;
if (s1 > s2 && s1-s2 < (u_int32_t)1<<31) return 1;
if (s1 > s2 && s1-s2 > (u_int32_t)1<<31) return -1;
if (s1 < s2 && s2-s1 > (u_int32_t)1<<31) return 1;
/* undefined result */
return -1;
}
struct iscsi_pdu *
iscsi_allocate_pdu_with_itt_flags_size(struct iscsi_context *iscsi, enum iscsi_opcode opcode,
enum iscsi_opcode response_opcode, uint32_t itt, uint32_t flags, size_t payload_size)

View File

@@ -302,7 +302,7 @@ iscsi_which_events(struct iscsi_context *iscsi)
{
int events = iscsi->is_connected ? POLLIN : POLLOUT;
if (iscsi->outqueue && iscsi->outqueue->cmdsn <= iscsi->maxcmdsn) {
if (iscsi->outqueue && iscsi_serial32_compare(iscsi->outqueue->cmdsn,iscsi->maxcmdsn) <= 0) {
events |= POLLOUT;
}
return events;
@@ -442,7 +442,7 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
while (iscsi->outqueue) {
ssize_t total;
if (iscsi->outqueue->cmdsn > iscsi->maxcmdsn) {
if (iscsi_serial32_compare(iscsi->outqueue->cmdsn,iscsi->maxcmdsn) > 0) {
/* stop sending. maxcmdsn is reached */
return 0;
}

View File

@@ -88,7 +88,7 @@ iscsi_process_task_mgmt_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu
response = in->hdr[2];
maxcmdsn = scsi_get_uint32(&in->hdr[32]);
if (maxcmdsn > iscsi->maxcmdsn) {
if (iscsi_serial32_compare(maxcmdsn,iscsi->maxcmdsn) > 0) {
iscsi->maxcmdsn = maxcmdsn;
}