From a5ec0e4f5124615877e7a67bb055bc5f11db7800 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Fri, 26 Sep 2008 15:59:47 +0000 Subject: [PATCH] Fixes broken NOP-Out with payload handling + minor fixed. Both problems derived from IET. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@498 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- iscsi-scst/kernel/iscsi.c | 36 +++++++++++++++++++++++++++++------ iscsi-scst/kernel/iscsi_hdr.h | 8 ++++---- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/iscsi-scst/kernel/iscsi.c b/iscsi-scst/kernel/iscsi.c index ab320e784..6d7ccd3f5 100644 --- a/iscsi-scst/kernel/iscsi.c +++ b/iscsi-scst/kernel/iscsi.c @@ -1221,21 +1221,30 @@ static int noop_out_start(struct iscsi_cmnd *cmnd) } size = cmnd->pdu.datasize; + if (size) { size = (size + 3) & -4; conn->read_msg.msg_iov = conn->read_iov; if (cmnd->pdu.bhs.itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { struct scatterlist *sg; - /* ToDo: __GFP_NOFAIL ?? */ - cmnd->sg = sg = scst_alloc(size, - GFP_KERNEL|__GFP_NOFAIL, &cmnd->sg_cnt); + cmnd->sg = sg = scst_alloc(size, GFP_KERNEL, + &cmnd->sg_cnt); if (sg == NULL) { - ;/* ToDo */; + TRACE(TRACE_OUT_OF_MEM, "Allocating buffer for " + "%d NOP-Out payload failed", size); + err = -ISCSI_REASON_OUT_OF_RESOURCES; + goto out; } if (cmnd->sg_cnt > ISCSI_CONN_IOV_MAX) { - ;/* ToDo */; + PRINT_ERROR("Too big NOP-Out payload: %d " + "segments, while only %lu allowed (size " + "%d)", cmnd->sg_cnt, ISCSI_CONN_IOV_MAX, + size); + err = -ISCSI_REASON_INVALID_PDU_FIELD; + goto out_free; } + cmnd->own_sg = 1; cmnd->bufflen = size; @@ -1247,6 +1256,7 @@ static int noop_out_start(struct iscsi_cmnd *cmnd) conn->read_size += tmp; size -= tmp; } + sBUG_ON(size != 0); } else { /* * There are no problems with the safety from concurrent @@ -1260,14 +1270,28 @@ static int noop_out_start(struct iscsi_cmnd *cmnd) conn->read_size += tmp; size -= tmp; } + + if (size != 0) { + PRINT_ERROR("Too big NOP-Out payload: %d " + "segments, while only %lu allowed (size " + "%d)", i, ISCSI_CONN_IOV_MAX, + size + sizeof(dummy_data) * i); + err = -ISCSI_REASON_INVALID_PDU_FIELD; + goto out; + } } - sBUG_ON(size == 0); + conn->read_msg.msg_iovlen = i; TRACE_DBG("msg_iov=%p, msg_iovlen=%zd", conn->read_msg.msg_iov, conn->read_msg.msg_iovlen); } + out: return err; + +out_free: + scst_free(cmnd->sg, cmnd->sg_cnt); + goto out; } static inline u32 get_next_ttt(struct iscsi_conn *conn) diff --git a/iscsi-scst/kernel/iscsi_hdr.h b/iscsi-scst/kernel/iscsi_hdr.h index 4910cd392..d279d4233 100644 --- a/iscsi-scst/kernel/iscsi_hdr.h +++ b/iscsi-scst/kernel/iscsi_hdr.h @@ -466,16 +466,16 @@ struct iscsi_reject_hdr { u32 rsvd4[2]; } __packed; -#define ISCSI_REASON_NO_FULL_FEATURE_PHASE 0x01 +#define ISCSI_REASON_RESERVED 0x01 #define ISCSI_REASON_DATA_DIGEST_ERROR 0x02 #define ISCSI_REASON_DATA_SNACK_REJECT 0x03 #define ISCSI_REASON_PROTOCOL_ERROR 0x04 #define ISCSI_REASON_UNSUPPORTED_COMMAND 0x05 #define ISCSI_REASON_IMMEDIATE_COMMAND_REJECT 0x06 #define ISCSI_REASON_TASK_IN_PROGRESS 0x07 -#define ISCSI_REASON_INVALID_SNACK 0x08 -#define ISCSI_REASON_NO_BOOKMARK 0x09 -#define ISCSI_REASON_BOOKMARK_REJECT 0x0a +#define ISCSI_REASON_INVALID_DATA_ACK 0x08 +#define ISCSI_REASON_INVALID_PDU_FIELD 0x09 +#define ISCSI_REASON_OUT_OF_RESOURCES 0x0a #define ISCSI_REASON_NEGOTIATION_RESET 0x0b #define ISCSI_REASON_WAITING_LOGOUT 0x0c