diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
| -rw-r--r-- | drivers/scsi/libiscsi.c | 23 | 
1 files changed, 15 insertions, 8 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 1e9c3171fa9f..f9314f1393fb 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -533,8 +533,8 @@ static void iscsi_complete_task(struct iscsi_task *task, int state)  	if (conn->task == task)  		conn->task = NULL; -	if (conn->ping_task == task) -		conn->ping_task = NULL; +	if (READ_ONCE(conn->ping_task) == task) +		WRITE_ONCE(conn->ping_task, NULL);  	/* release get from queueing */  	__iscsi_put_task(task); @@ -738,6 +738,9 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,  						   task->conn->session->age);  	} +	if (unlikely(READ_ONCE(conn->ping_task) == INVALID_SCSI_TASK)) +		WRITE_ONCE(conn->ping_task, task); +  	if (!ihost->workq) {  		if (iscsi_prep_mgmt_task(conn, task))  			goto free_task; @@ -941,8 +944,11 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)          struct iscsi_nopout hdr;  	struct iscsi_task *task; -	if (!rhdr && conn->ping_task) -		return -EINVAL; +	if (!rhdr) { +		if (READ_ONCE(conn->ping_task)) +			return -EINVAL; +		WRITE_ONCE(conn->ping_task, INVALID_SCSI_TASK); +	}  	memset(&hdr, 0, sizeof(struct iscsi_nopout));  	hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE; @@ -957,11 +963,12 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)  	task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);  	if (!task) { +		if (!rhdr) +			WRITE_ONCE(conn->ping_task, NULL);  		iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");  		return -EIO;  	} else if (!rhdr) {  		/* only track our nops */ -		conn->ping_task = task;  		conn->last_ping = jiffies;  	} @@ -984,7 +991,7 @@ static int iscsi_nop_out_rsp(struct iscsi_task *task,  	struct iscsi_conn *conn = task->conn;  	int rc = 0; -	if (conn->ping_task != task) { +	if (READ_ONCE(conn->ping_task) != task) {  		/*  		 * If this is not in response to one of our  		 * nops then it must be from userspace. @@ -1923,7 +1930,7 @@ static void iscsi_start_tx(struct iscsi_conn *conn)   */  static int iscsi_has_ping_timed_out(struct iscsi_conn *conn)  { -	if (conn->ping_task && +	if (READ_ONCE(conn->ping_task) &&  	    time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) +  			   (conn->ping_timeout * HZ), jiffies))  		return 1; @@ -2058,7 +2065,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)  	 * Checking the transport already or nop from a cmd timeout still  	 * running  	 */ -	if (conn->ping_task) { +	if (READ_ONCE(conn->ping_task)) {  		task->have_checked_conn = true;  		rc = BLK_EH_RESET_TIMER;  		goto done;  |