]>
Commit | Line | Data |
---|---|---|
82094b55 AF |
1 | From: Hannes Reinecke <hare@suse.de> |
2 | Date: Tue, 18 Aug 2009 10:26:50 +0200 | |
3 | Subject: libiscsi: check suspend bit before each call to xmit_task | |
4 | References: bnc#472432 | |
5 | X-Git: 70b31c152dc49ef70bd2b34ad53ccbd9bb4116d4 | |
6 | ||
7 | If we had multiple tasks on the cmd or requeue lists, and iscsi_tcp | |
8 | returns a error, the write_space function can still run and queue | |
9 | iscsi_data_xmit. If it was a legetimate problem and iscsi_conn_failure | |
10 | was run but we raced and iscsi_data_xmit was run first it could miss | |
11 | the suspend bit checks, and start trying to send data again and hit | |
12 | another timeout. A similar problem is present when using cxgb3i. | |
13 | ||
14 | This has libiscsi check the suspend bit before calling the xmit | |
15 | task callout, so we at least do not try sending multiple tasks | |
16 | (one could be sent). | |
17 | ||
18 | It also adds a check in iscsi_tcp before calling | |
19 | the send function. The extra call in iscsi_tcp is needed because | |
20 | we can call sendpage/sendmsg multiple times for the same pdu | |
21 | and between each call iscsi_conn_failure could be called. | |
22 | ||
23 | Backported to SLES11. | |
24 | ||
25 | Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> | |
26 | Signed-off-by: Hannes Reinecke <hare@suse.de> | |
27 | --- | |
28 | drivers/scsi/libiscsi.c | 19 ++++++++++--------- | |
29 | 1 files changed, 10 insertions(+), 9 deletions(-) | |
30 | ||
31 | diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c | |
32 | index 0611558..95720cc 100644 | |
33 | --- a/drivers/scsi/libiscsi.c | |
34 | +++ b/drivers/scsi/libiscsi.c | |
35 | @@ -1150,6 +1150,9 @@ static int iscsi_xmit_task(struct iscsi_conn *conn) | |
36 | struct iscsi_task *task = conn->task; | |
37 | int rc; | |
38 | ||
39 | + if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) | |
40 | + return -ENODATA; | |
41 | + | |
42 | __iscsi_get_task(task); | |
43 | spin_unlock_bh(&conn->session->lock); | |
44 | rc = conn->session->tt->xmit_task(task); | |
45 | @@ -1192,7 +1195,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) | |
46 | int rc = 0; | |
47 | ||
48 | spin_lock_bh(&conn->session->lock); | |
49 | - if (unlikely(conn->suspend_tx)) { | |
50 | + if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) { | |
51 | debug_scsi("conn %d Tx suspended!\n", conn->id); | |
52 | spin_unlock_bh(&conn->session->lock); | |
53 | return -ENODATA; | |
54 | @@ -1200,8 +1203,8 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) | |
55 | ||
56 | if (conn->task) { | |
57 | rc = iscsi_xmit_task(conn); | |
58 | - if (rc) | |
59 | - goto again; | |
60 | + if (rc) | |
61 | + goto done; | |
62 | } | |
63 | ||
64 | /* | |
65 | @@ -1220,7 +1223,7 @@ check_mgmt: | |
66 | } | |
67 | rc = iscsi_xmit_task(conn); | |
68 | if (rc) | |
69 | - goto again; | |
70 | + goto done; | |
71 | } | |
72 | ||
73 | /* process pending command queue */ | |
74 | @@ -1240,7 +1243,7 @@ check_mgmt: | |
75 | } | |
76 | rc = iscsi_xmit_task(conn); | |
77 | if (rc) | |
78 | - goto again; | |
79 | + goto done; | |
80 | /* | |
81 | * we could continuously get new task requests so | |
82 | * we need to check the mgmt queue for nops that need to | |
83 | @@ -1266,16 +1269,14 @@ check_mgmt: | |
84 | list_move_tail(conn->requeue.next, &conn->run_list); | |
85 | rc = iscsi_xmit_task(conn); | |
86 | if (rc) | |
87 | - goto again; | |
88 | + goto done; | |
89 | if (!list_empty(&conn->mgmtqueue)) | |
90 | goto check_mgmt; | |
91 | } | |
92 | spin_unlock_bh(&conn->session->lock); | |
93 | return -ENODATA; | |
94 | ||
95 | -again: | |
96 | - if (unlikely(conn->suspend_tx)) | |
97 | - rc = -ENODATA; | |
98 | +done: | |
99 | spin_unlock_bh(&conn->session->lock); | |
100 | return rc; | |
101 | } | |
102 | -- | |
103 | 1.6.0.2 | |
104 |