1 From: Mike Christie <michaelc@cs.wisc.edu>
2 Subject: Open-iSCSI updates
3 References: FATE#304283
5 This patch updates the open-iscsi stack to include the required
6 support for bnx2i driver.
8 Signed-off-by: Hannes Reinecke <hare@suse.de>
11 drivers/infiniband/ulp/iser/iscsi_iser.c | 1
12 drivers/scsi/iscsi_tcp.c | 1
13 drivers/scsi/libiscsi.c | 72 +++++++++++++++++++++++++++----
14 include/scsi/iscsi_if.h | 1
15 include/scsi/libiscsi.h | 7 +++
16 5 files changed, 75 insertions(+), 7 deletions(-)
18 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c
19 +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
20 @@ -378,6 +378,7 @@ static void iscsi_iser_session_destroy(s
22 struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
24 + iscsi_session_teardown(cls_session);
25 iscsi_host_remove(shost);
26 iscsi_host_free(shost);
28 --- a/drivers/scsi/iscsi_tcp.c
29 +++ b/drivers/scsi/iscsi_tcp.c
30 @@ -1904,6 +1904,7 @@ static void iscsi_tcp_session_destroy(st
31 struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
33 iscsi_r2tpool_free(cls_session->dd_data);
34 + iscsi_session_teardown(cls_session);
36 iscsi_host_remove(shost);
37 iscsi_host_free(shost);
38 --- a/drivers/scsi/libiscsi.c
39 +++ b/drivers/scsi/libiscsi.c
40 @@ -368,11 +368,12 @@ void __iscsi_get_task(struct iscsi_task
42 EXPORT_SYMBOL_GPL(__iscsi_get_task);
44 -static void __iscsi_put_task(struct iscsi_task *task)
45 +void __iscsi_put_task(struct iscsi_task *task)
47 if (atomic_dec_and_test(&task->refcount))
48 iscsi_complete_command(task);
50 +EXPORT_SYMBOL_GPL(__iscsi_put_task);
52 void iscsi_put_task(struct iscsi_task *task)
54 @@ -711,7 +712,7 @@ static int iscsi_handle_reject(struct is
56 * The session lock must be held.
58 -static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt)
59 +struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt)
61 struct iscsi_session *session = conn->session;
63 @@ -725,6 +726,7 @@ static struct iscsi_task *iscsi_itt_to_t
65 return session->cmds[i];
67 +EXPORT_SYMBOL_GPL(iscsi_itt_to_task);
70 * __iscsi_complete_pdu - complete pdu
71 @@ -954,6 +956,38 @@ struct iscsi_task *iscsi_itt_to_ctask(st
73 EXPORT_SYMBOL_GPL(iscsi_itt_to_ctask);
75 +void iscsi_session_failure(struct iscsi_cls_session *cls_session,
78 + struct iscsi_session *session = cls_session->dd_data;
79 + struct iscsi_conn *conn;
81 + unsigned long flags;
83 + spin_lock_irqsave(&session->lock, flags);
84 + conn = session->leadconn;
85 + if (session->state == ISCSI_STATE_TERMINATE || !conn) {
86 + spin_unlock_irqrestore(&session->lock, flags);
90 + dev = get_device(&conn->cls_conn->dev);
91 + spin_unlock_irqrestore(&session->lock, flags);
95 + * if the host is being removed bypass the connection
96 + * recovery initialization because we are going to kill
99 + if (err == ISCSI_ERR_INVALID_HOST)
100 + iscsi_conn_error(conn->cls_conn, err);
102 + iscsi_conn_failure(conn, err);
105 +EXPORT_SYMBOL_GPL(iscsi_session_failure);
107 void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
109 struct iscsi_session *session = conn->session;
110 @@ -968,6 +1002,7 @@ void iscsi_conn_failure(struct iscsi_con
111 if (conn->stop_stage == 0)
112 session->state = ISCSI_STATE_FAILED;
113 spin_unlock_irqrestore(&session->lock, flags);
115 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
116 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
117 iscsi_conn_error(conn->cls_conn, err);
118 @@ -1878,6 +1913,7 @@ struct Scsi_Host *iscsi_host_alloc(struc
119 int dd_data_size, uint16_t qdepth)
121 struct Scsi_Host *shost;
122 + struct iscsi_host *ihost;
124 shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size);
126 @@ -1892,22 +1928,36 @@ struct Scsi_Host *iscsi_host_alloc(struc
127 qdepth = ISCSI_DEF_CMD_PER_LUN;
129 shost->cmd_per_lun = qdepth;
131 + ihost = shost_priv(shost);
132 + atomic_set(&ihost->num_sessions, 0);
133 + init_waitqueue_head(&ihost->session_removal_wq);
136 EXPORT_SYMBOL_GPL(iscsi_host_alloc);
138 +static void iscsi_kill_session(struct iscsi_cls_session *cls_session)
140 + iscsi_session_failure(cls_session, ISCSI_ERR_INVALID_HOST);
144 * iscsi_host_remove - remove host and sessions
147 - * This will also remove any sessions attached to the host, but if userspace
148 - * is managing the session at the same time this will break. TODO: add
149 - * refcounting to the netlink iscsi interface so a rmmod or host hot unplug
150 - * does not remove the memory from under us.
151 + * If there are any sessions left, this will initiate the removal and wait
152 + * for the completion.
154 void iscsi_host_remove(struct Scsi_Host *shost)
156 - iscsi_host_for_each_session(shost, iscsi_session_teardown);
157 + struct iscsi_host *ihost = shost_priv(shost);
159 + iscsi_host_for_each_session(shost, iscsi_kill_session);
160 + wait_event_interruptible(ihost->session_removal_wq,
161 + atomic_read(&ihost->num_sessions) == 0);
162 + if (signal_pending(current))
163 + flush_signals(current);
165 scsi_remove_host(shost);
167 EXPORT_SYMBOL_GPL(iscsi_host_remove);
168 @@ -1943,6 +1993,7 @@ iscsi_session_setup(struct iscsi_transpo
169 uint16_t cmds_max, int cmd_task_size,
170 uint32_t initial_cmdsn, unsigned int id)
172 + struct iscsi_host *ihost = shost_priv(shost);
173 struct iscsi_session *session;
174 struct iscsi_cls_session *cls_session;
175 int cmd_i, scsi_cmds, total_cmds = cmds_max;
176 @@ -2021,6 +2072,8 @@ iscsi_session_setup(struct iscsi_transpo
178 if (iscsi_add_session(cls_session, id))
179 goto cls_session_fail;
181 + atomic_inc(&ihost->num_sessions);
185 @@ -2043,6 +2096,7 @@ EXPORT_SYMBOL_GPL(iscsi_session_setup);
186 void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
188 struct iscsi_session *session = cls_session->dd_data;
189 + struct iscsi_host *ihost = shost_priv(session->host);
190 struct module *owner = cls_session->transport->owner;
192 iscsi_pool_free(&session->cmdpool);
193 @@ -2056,6 +2110,10 @@ void iscsi_session_teardown(struct iscsi
194 kfree(session->ifacename);
196 iscsi_destroy_session(cls_session);
198 + atomic_dec(&ihost->num_sessions);
199 + wake_up(&ihost->session_removal_wq);
203 EXPORT_SYMBOL_GPL(iscsi_session_teardown);
204 --- a/include/scsi/iscsi_if.h
205 +++ b/include/scsi/iscsi_if.h
206 @@ -213,6 +213,7 @@ enum iscsi_err {
207 ISCSI_ERR_DATA_DGST = ISCSI_ERR_BASE + 15,
208 ISCSI_ERR_PARAM_NOT_FOUND = ISCSI_ERR_BASE + 16,
209 ISCSI_ERR_NO_SCSI_CMD = ISCSI_ERR_BASE + 17,
210 + ISCSI_ERR_INVALID_HOST = ISCSI_ERR_BASE + 18,
214 --- a/include/scsi/libiscsi.h
215 +++ b/include/scsi/libiscsi.h
216 @@ -295,6 +295,9 @@ struct iscsi_host {
219 char local_address[ISCSI_ADDRESS_BUF_LEN];
221 + wait_queue_head_t session_removal_wq;
222 + atomic_t num_sessions;
226 @@ -351,6 +354,8 @@ extern void iscsi_conn_stop(struct iscsi
227 extern int iscsi_conn_bind(struct iscsi_cls_session *, struct iscsi_cls_conn *,
229 extern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err);
230 +extern void iscsi_session_failure(struct iscsi_cls_session *cls_session,
231 + enum iscsi_err err);
232 extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
233 enum iscsi_param param, char *buf);
234 extern void iscsi_suspend_tx(struct iscsi_conn *conn);
235 @@ -373,8 +378,10 @@ extern int __iscsi_complete_pdu(struct i
237 extern int iscsi_verify_itt(struct iscsi_conn *, itt_t);
238 extern struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *, itt_t);
239 +extern struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *, itt_t);
240 extern void iscsi_requeue_task(struct iscsi_task *task);
241 extern void iscsi_put_task(struct iscsi_task *task);
242 +extern void __iscsi_put_task(struct iscsi_task *task);
243 extern void __iscsi_get_task(struct iscsi_task *task);