]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.fixes/open-iscsi-git-update
Merge branch 'master' of git://git.ipfire.org/ipfire-2.x
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.fixes / open-iscsi-git-update
1 From: Mike Christie <michaelc@cs.wisc.edu>
2 Subject: Open-iSCSI updates
3 References: FATE#304283
4
5 This patch updates the open-iscsi stack to include the required
6 support for bnx2i driver.
7
8 Signed-off-by: Hannes Reinecke <hare@suse.de>
9
10 ---
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(-)
17
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
21 {
22 struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
23
24 + iscsi_session_teardown(cls_session);
25 iscsi_host_remove(shost);
26 iscsi_host_free(shost);
27 }
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);
32
33 iscsi_r2tpool_free(cls_session->dd_data);
34 + iscsi_session_teardown(cls_session);
35
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
41 }
42 EXPORT_SYMBOL_GPL(__iscsi_get_task);
43
44 -static void __iscsi_put_task(struct iscsi_task *task)
45 +void __iscsi_put_task(struct iscsi_task *task)
46 {
47 if (atomic_dec_and_test(&task->refcount))
48 iscsi_complete_command(task);
49 }
50 +EXPORT_SYMBOL_GPL(__iscsi_put_task);
51
52 void iscsi_put_task(struct iscsi_task *task)
53 {
54 @@ -711,7 +712,7 @@ static int iscsi_handle_reject(struct is
55 *
56 * The session lock must be held.
57 */
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)
60 {
61 struct iscsi_session *session = conn->session;
62 uint32_t i;
63 @@ -725,6 +726,7 @@ static struct iscsi_task *iscsi_itt_to_t
64
65 return session->cmds[i];
66 }
67 +EXPORT_SYMBOL_GPL(iscsi_itt_to_task);
68
69 /**
70 * __iscsi_complete_pdu - complete pdu
71 @@ -954,6 +956,38 @@ struct iscsi_task *iscsi_itt_to_ctask(st
72 }
73 EXPORT_SYMBOL_GPL(iscsi_itt_to_ctask);
74
75 +void iscsi_session_failure(struct iscsi_cls_session *cls_session,
76 + enum iscsi_err err)
77 +{
78 + struct iscsi_session *session = cls_session->dd_data;
79 + struct iscsi_conn *conn;
80 + struct device *dev;
81 + unsigned long flags;
82 +
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);
87 + return;
88 + }
89 +
90 + dev = get_device(&conn->cls_conn->dev);
91 + spin_unlock_irqrestore(&session->lock, flags);
92 + if (!dev)
93 + return;
94 + /*
95 + * if the host is being removed bypass the connection
96 + * recovery initialization because we are going to kill
97 + * the session.
98 + */
99 + if (err == ISCSI_ERR_INVALID_HOST)
100 + iscsi_conn_error(conn->cls_conn, err);
101 + else
102 + iscsi_conn_failure(conn, err);
103 + put_device(dev);
104 +}
105 +EXPORT_SYMBOL_GPL(iscsi_session_failure);
106 +
107 void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
108 {
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);
114 +
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)
120 {
121 struct Scsi_Host *shost;
122 + struct iscsi_host *ihost;
123
124 shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size);
125 if (!shost)
126 @@ -1892,22 +1928,36 @@ struct Scsi_Host *iscsi_host_alloc(struc
127 qdepth = ISCSI_DEF_CMD_PER_LUN;
128 }
129 shost->cmd_per_lun = qdepth;
130 +
131 + ihost = shost_priv(shost);
132 + atomic_set(&ihost->num_sessions, 0);
133 + init_waitqueue_head(&ihost->session_removal_wq);
134 return shost;
135 }
136 EXPORT_SYMBOL_GPL(iscsi_host_alloc);
137
138 +static void iscsi_kill_session(struct iscsi_cls_session *cls_session)
139 +{
140 + iscsi_session_failure(cls_session, ISCSI_ERR_INVALID_HOST);
141 +}
142 +
143 /**
144 * iscsi_host_remove - remove host and sessions
145 * @shost: scsi host
146 *
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.
153 */
154 void iscsi_host_remove(struct Scsi_Host *shost)
155 {
156 - iscsi_host_for_each_session(shost, iscsi_session_teardown);
157 + struct iscsi_host *ihost = shost_priv(shost);
158 +
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);
164 +
165 scsi_remove_host(shost);
166 }
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)
171 {
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
177
178 if (iscsi_add_session(cls_session, id))
179 goto cls_session_fail;
180 +
181 + atomic_inc(&ihost->num_sessions);
182 return cls_session;
183
184 cls_session_fail:
185 @@ -2043,6 +2096,7 @@ EXPORT_SYMBOL_GPL(iscsi_session_setup);
186 void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
187 {
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;
191
192 iscsi_pool_free(&session->cmdpool);
193 @@ -2056,6 +2110,10 @@ void iscsi_session_teardown(struct iscsi
194 kfree(session->ifacename);
195
196 iscsi_destroy_session(cls_session);
197 +
198 + atomic_dec(&ihost->num_sessions);
199 + wake_up(&ihost->session_removal_wq);
200 +
201 module_put(owner);
202 }
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,
211 };
212
213 /*
214 --- a/include/scsi/libiscsi.h
215 +++ b/include/scsi/libiscsi.h
216 @@ -295,6 +295,9 @@ struct iscsi_host {
217 /* local address */
218 int local_port;
219 char local_address[ISCSI_ADDRESS_BUF_LEN];
220 +
221 + wait_queue_head_t session_removal_wq;
222 + atomic_t num_sessions;
223 };
224
225 /*
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 *,
228 int);
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
236 char *, int);
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);
244
245 /*