Commit 3b64b188 authored by Yi Zou's avatar Yi Zou Committed by James Bottomley
Browse files

[SCSI] libfc: fix lun reset failure bugs in fc_fcp_resp handling of FCP_RSP_INFO



In LUN RESET testing involving NetApp targets, it is observed that LUN
RESET is failing. The fc_fcp_resp() is not completing the completion
for the LUN RESET task since fc_fcp_resp assumes that the FCP_RSP_INFO
is 8 bytes with the 4 byte reserved field, where in case of NetApp targets
the FCP_RSP to LUN RESET only has 4 bytes of FCP_RSP_INFO. This leads
fc_fcp_resp to error out w/o completing the task completion, eventually
causing LUN RESET to be escalated to host reset, which is not very nice.

Per FCP-3 r04, clause 9.5.15 and Table 23, the FCP_RSP_INFO field can be either
4 bytes or 8 bytes, with the last 4 bytes as "Reserved (if any)". Therefore it
is valid to have 4 bytes FCP_RSP_INFO like some of the NetApp targets behave.
Fixing this by validating the FCP_RSP_INFO against both the two spec allowed
length.

Reported-by: default avatarFrank Zhang <frank_1.zhang@intel.com>
Signed-off-by: default avatarYi Zou <yi.zou@intel.com>
Tested-by: default avatarRoss Brattain <ross.b.brattain@intel.com>
Signed-off-by: default avatarRobert Love <robert.w.love@intel.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 31c37a6f
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -851,7 +851,8 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
			fc_rp_info = (struct fcp_resp_rsp_info *)(rp_ex + 1);
			if (flags & FCP_RSP_LEN_VAL) {
				respl = ntohl(rp_ex->fr_rsp_len);
				if (respl != sizeof(*fc_rp_info))
				if ((respl != FCP_RESP_RSP_INFO_LEN4) &&
				    (respl != FCP_RESP_RSP_INFO_LEN8))
					goto len_err;
				if (fsp->wait_for_comp) {
					/* Abuse cdb_status for rsp code */
+6 −0
Original line number Diff line number Diff line
@@ -127,6 +127,9 @@ struct fcp_txrdy {
 *
 * All response frames will always contain the fcp_resp template.  Some
 * will also include the fcp_resp_len template.
 *
 * From Table 23, the FCP_RSP_INFO can either be 4 bytes or 8 bytes, both
 * are valid length.
 */
struct fcp_resp {
	__u8		_fr_resvd[8];	/* reserved */
@@ -156,6 +159,9 @@ struct fcp_resp_rsp_info {
    __u8      _fr_resvd2[4];      /* reserved */
};

#define FCP_RESP_RSP_INFO_LEN4    4 /* without reserved field */
#define FCP_RESP_RSP_INFO_LEN8    8 /* with reserved field */

struct fcp_resp_with_ext {
	struct fcp_resp resp;
	struct fcp_resp_ext ext;