Blame view

drivers/scsi/iscsi_tcp.c 27.5 KB
7ba247138   Alex Aizman   [SCSI] open-iscsi...
1
2
3
4
5
  /*
   * iSCSI Initiator over TCP/IP Data-Path
   *
   * Copyright (C) 2004 Dmitry Yusupov
   * Copyright (C) 2004 Alex Aizman
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
6
7
   * Copyright (C) 2005 - 2006 Mike Christie
   * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
7ba247138   Alex Aizman   [SCSI] open-iscsi...
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
   * maintained by open-iscsi@googlegroups.com
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published
   * by the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   * General Public License for more details.
   *
   * See the file COPYING included with this distribution for more details.
   *
   * Credits:
   *	Christoph Hellwig
   *	FUJITA Tomonori
   *	Arne Redlich
   *	Zhenyu Wang
   */
  
  #include <linux/types.h>
7ba247138   Alex Aizman   [SCSI] open-iscsi...
30
  #include <linux/inet.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
31
  #include <linux/slab.h>
4e7aba73f   Mike Christie   [SCSI] iscsi_tcp:...
32
  #include <linux/file.h>
7ba247138   Alex Aizman   [SCSI] open-iscsi...
33
34
35
36
37
  #include <linux/blkdev.h>
  #include <linux/crypto.h>
  #include <linux/delay.h>
  #include <linux/kfifo.h>
  #include <linux/scatterlist.h>
acf3368ff   Paul Gortmaker   scsi: Fix up file...
38
  #include <linux/module.h>
7ba247138   Alex Aizman   [SCSI] open-iscsi...
39
40
  #include <net/tcp.h>
  #include <scsi/scsi_cmnd.h>
d1d81c01f   Mike Christie   [SCSI] iscsi_tcp:...
41
  #include <scsi/scsi_device.h>
7ba247138   Alex Aizman   [SCSI] open-iscsi...
42
43
44
45
46
  #include <scsi/scsi_host.h>
  #include <scsi/scsi.h>
  #include <scsi/scsi_transport_iscsi.h>
  
  #include "iscsi_tcp.h"
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
47
48
  MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, "
  	      "Dmitry Yusupov <dmitry_yus@yahoo.com>, "
7ba247138   Alex Aizman   [SCSI] open-iscsi...
49
50
51
  	      "Alex Aizman <itn780@yahoo.com>");
  MODULE_DESCRIPTION("iSCSI/TCP data-path");
  MODULE_LICENSE("GPL");
7ba247138   Alex Aizman   [SCSI] open-iscsi...
52

38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
53
54
55
  static struct scsi_transport_template *iscsi_sw_tcp_scsi_transport;
  static struct scsi_host_template iscsi_sw_tcp_sht;
  static struct iscsi_transport iscsi_sw_tcp_transport;
756135215   Mike Christie   [SCSI] iscsi: rem...
56

7ba247138   Alex Aizman   [SCSI] open-iscsi...
57
58
  static unsigned int iscsi_max_lun = 512;
  module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
c93f87c72   Mike Christie   [SCSI] iscsi_tcp:...
59
60
61
62
63
64
65
66
67
68
69
70
71
  static int iscsi_sw_tcp_dbg;
  module_param_named(debug_iscsi_tcp, iscsi_sw_tcp_dbg, int,
  		   S_IRUGO | S_IWUSR);
  MODULE_PARM_DESC(debug_iscsi_tcp, "Turn on debugging for iscsi_tcp module "
  		 "Set to 1 to turn on, and zero to turn off. Default is off.");
  
  #define ISCSI_SW_TCP_DBG(_conn, dbg_fmt, arg...)		\
  	do {							\
  		if (iscsi_sw_tcp_dbg)				\
  			iscsi_conn_printk(KERN_INFO, _conn,	\
  					     "%s " dbg_fmt,	\
  					     __func__, ##arg);	\
  	} while (0);
da32dd681   Olaf Kirch   [SCSI] iscsi_tcp:...
72
  /**
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
73
   * iscsi_sw_tcp_recv - TCP receive in sendfile fashion
63c62f1cb   Mike Christie   [SCSI] iscsi_tcp:...
74
75
76
77
   * @rd_desc: read descriptor
   * @skb: socket buffer
   * @offset: offset in skb
   * @len: skb->len - offset
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
78
79
80
   */
  static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
  			     unsigned int offset, size_t len)
63c62f1cb   Mike Christie   [SCSI] iscsi_tcp:...
81
82
83
84
  {
  	struct iscsi_conn *conn = rd_desc->arg.data;
  	unsigned int consumed, total_consumed = 0;
  	int status;
c93f87c72   Mike Christie   [SCSI] iscsi_tcp:...
85
86
  	ISCSI_SW_TCP_DBG(conn, "in %d bytes
  ", skb->len - offset);
63c62f1cb   Mike Christie   [SCSI] iscsi_tcp:...
87
88
89
90
91
92
93
  
  	do {
  		status = 0;
  		consumed = iscsi_tcp_recv_skb(conn, skb, offset, 0, &status);
  		offset += consumed;
  		total_consumed += consumed;
  	} while (consumed != 0 && status != ISCSI_TCP_SKB_DONE);
c93f87c72   Mike Christie   [SCSI] iscsi_tcp:...
94
95
96
  	ISCSI_SW_TCP_DBG(conn, "read %d bytes status %d
  ",
  			 skb->len - offset, status);
63c62f1cb   Mike Christie   [SCSI] iscsi_tcp:...
97
  	return total_consumed;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
98
  }
523eeac67   Hannes Reinecke   [SCSI] iscsi_tcp:...
99
100
101
102
103
104
105
  /**
   * iscsi_sw_sk_state_check - check socket state
   * @sk: socket
   *
   * If the socket is in CLOSE or CLOSE_WAIT we should
   * not close the connection if there is still some
   * data pending.
03adb5f91   Mike Christie   [SCSI] iscsi_tcp:...
106
107
   *
   * Must be called with sk_callback_lock.
523eeac67   Hannes Reinecke   [SCSI] iscsi_tcp:...
108
109
110
   */
  static inline int iscsi_sw_sk_state_check(struct sock *sk)
  {
03adb5f91   Mike Christie   [SCSI] iscsi_tcp:...
111
  	struct iscsi_conn *conn = sk->sk_user_data;
523eeac67   Hannes Reinecke   [SCSI] iscsi_tcp:...
112

d1af8a328   Mike Christie   [SCSI] iscsi_tcp:...
113
114
115
116
117
118
119
  	if ((sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) &&
  	    !atomic_read(&sk->sk_rmem_alloc)) {
  		ISCSI_SW_TCP_DBG(conn, "TCP_CLOSE|TCP_CLOSE_WAIT
  ");
  		iscsi_conn_failure(conn, ISCSI_ERR_TCP_CONN_CLOSE);
  		return -ECONNRESET;
  	}
523eeac67   Hannes Reinecke   [SCSI] iscsi_tcp:...
120
121
  	return 0;
  }
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
122
  static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
123
  {
03adb5f91   Mike Christie   [SCSI] iscsi_tcp:...
124
125
  	struct iscsi_conn *conn;
  	struct iscsi_tcp_conn *tcp_conn;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
126
127
128
  	read_descriptor_t rd_desc;
  
  	read_lock(&sk->sk_callback_lock);
03adb5f91   Mike Christie   [SCSI] iscsi_tcp:...
129
130
131
132
133
134
  	conn = sk->sk_user_data;
  	if (!conn) {
  		read_unlock(&sk->sk_callback_lock);
  		return;
  	}
  	tcp_conn = conn->dd_data;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
135

665b44aee   Mike Christie   [SCSI] iscsi: deq...
136
  	/*
da32dd681   Olaf Kirch   [SCSI] iscsi_tcp:...
137
  	 * Use rd_desc to pass 'conn' to iscsi_tcp_recv.
665b44aee   Mike Christie   [SCSI] iscsi: deq...
138
  	 * We set count to 1 because we want the network layer to
da32dd681   Olaf Kirch   [SCSI] iscsi_tcp:...
139
  	 * hand us all the skbs that are available. iscsi_tcp_recv
665b44aee   Mike Christie   [SCSI] iscsi: deq...
140
141
  	 * handled pdus that cross buffers or pdus that still need data.
  	 */
7ba247138   Alex Aizman   [SCSI] open-iscsi...
142
  	rd_desc.arg.data = conn;
665b44aee   Mike Christie   [SCSI] iscsi: deq...
143
  	rd_desc.count = 1;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
144
  	tcp_read_sock(sk, &rd_desc, iscsi_sw_tcp_recv);
7ba247138   Alex Aizman   [SCSI] open-iscsi...
145

d1af8a328   Mike Christie   [SCSI] iscsi_tcp:...
146
  	iscsi_sw_sk_state_check(sk);
523eeac67   Hannes Reinecke   [SCSI] iscsi_tcp:...
147

da32dd681   Olaf Kirch   [SCSI] iscsi_tcp:...
148
149
  	/* If we had to (atomically) map a highmem page,
  	 * unmap it now. */
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
150
  	iscsi_tcp_segment_unmap(&tcp_conn->in.segment);
03adb5f91   Mike Christie   [SCSI] iscsi_tcp:...
151
  	read_unlock(&sk->sk_callback_lock);
7ba247138   Alex Aizman   [SCSI] open-iscsi...
152
  }
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
153
  static void iscsi_sw_tcp_state_change(struct sock *sk)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
154
  {
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
155
  	struct iscsi_tcp_conn *tcp_conn;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
156
  	struct iscsi_sw_tcp_conn *tcp_sw_conn;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
157
158
159
160
161
  	struct iscsi_conn *conn;
  	struct iscsi_session *session;
  	void (*old_state_change)(struct sock *);
  
  	read_lock(&sk->sk_callback_lock);
03adb5f91   Mike Christie   [SCSI] iscsi_tcp:...
162
163
164
165
166
  	conn = sk->sk_user_data;
  	if (!conn) {
  		read_unlock(&sk->sk_callback_lock);
  		return;
  	}
7ba247138   Alex Aizman   [SCSI] open-iscsi...
167
  	session = conn->session;
d1af8a328   Mike Christie   [SCSI] iscsi_tcp:...
168
  	iscsi_sw_sk_state_check(sk);
7ba247138   Alex Aizman   [SCSI] open-iscsi...
169

5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
170
  	tcp_conn = conn->dd_data;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
171
172
  	tcp_sw_conn = tcp_conn->dd_data;
  	old_state_change = tcp_sw_conn->old_state_change;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
173
174
175
176
177
178
179
180
181
182
  
  	read_unlock(&sk->sk_callback_lock);
  
  	old_state_change(sk);
  }
  
  /**
   * iscsi_write_space - Called when more output buffer space is available
   * @sk: socket space is available for
   **/
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
183
  static void iscsi_sw_tcp_write_space(struct sock *sk)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
184
  {
03adb5f91   Mike Christie   [SCSI] iscsi_tcp:...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
  	struct iscsi_conn *conn;
  	struct iscsi_tcp_conn *tcp_conn;
  	struct iscsi_sw_tcp_conn *tcp_sw_conn;
  	void (*old_write_space)(struct sock *);
  
  	read_lock_bh(&sk->sk_callback_lock);
  	conn = sk->sk_user_data;
  	if (!conn) {
  		read_unlock_bh(&sk->sk_callback_lock);
  		return;
  	}
  
  	tcp_conn = conn->dd_data;
  	tcp_sw_conn = tcp_conn->dd_data;
  	old_write_space = tcp_sw_conn->old_write_space;
  	read_unlock_bh(&sk->sk_callback_lock);
  
  	old_write_space(sk);
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
203

c93f87c72   Mike Christie   [SCSI] iscsi_tcp:...
204
205
  	ISCSI_SW_TCP_DBG(conn, "iscsi_write_space
  ");
32ae763e3   Mike Christie   [SCSI] iscsi lib:...
206
  	iscsi_conn_queue_work(conn);
7ba247138   Alex Aizman   [SCSI] open-iscsi...
207
  }
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
208
  static void iscsi_sw_tcp_conn_set_callbacks(struct iscsi_conn *conn)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
209
  {
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
210
  	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
211
212
  	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
  	struct sock *sk = tcp_sw_conn->sock->sk;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
213
214
215
216
  
  	/* assign new callbacks */
  	write_lock_bh(&sk->sk_callback_lock);
  	sk->sk_user_data = conn;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
217
218
219
220
221
222
  	tcp_sw_conn->old_data_ready = sk->sk_data_ready;
  	tcp_sw_conn->old_state_change = sk->sk_state_change;
  	tcp_sw_conn->old_write_space = sk->sk_write_space;
  	sk->sk_data_ready = iscsi_sw_tcp_data_ready;
  	sk->sk_state_change = iscsi_sw_tcp_state_change;
  	sk->sk_write_space = iscsi_sw_tcp_write_space;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
223
224
  	write_unlock_bh(&sk->sk_callback_lock);
  }
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
225
  static void
c484a50a4   Avi Kaplan   [SCSI] iscsi_tcp:...
226
  iscsi_sw_tcp_conn_restore_callbacks(struct iscsi_conn *conn)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
227
  {
c484a50a4   Avi Kaplan   [SCSI] iscsi_tcp:...
228
229
  	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
  	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
230
  	struct sock *sk = tcp_sw_conn->sock->sk;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
231
232
233
234
  
  	/* restore socket callbacks, see also: iscsi_conn_set_callbacks() */
  	write_lock_bh(&sk->sk_callback_lock);
  	sk->sk_user_data    = NULL;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
235
236
237
  	sk->sk_data_ready   = tcp_sw_conn->old_data_ready;
  	sk->sk_state_change = tcp_sw_conn->old_state_change;
  	sk->sk_write_space  = tcp_sw_conn->old_write_space;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
238
239
240
241
242
  	sk->sk_no_check	 = 0;
  	write_unlock_bh(&sk->sk_callback_lock);
  }
  
  /**
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
243
   * iscsi_sw_tcp_xmit_segment - transmit segment
6df19a791   Mike Christie   [SCSI] libiscsi_t...
244
   * @tcp_conn: the iSCSI TCP connection
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
245
246
247
248
249
250
251
252
253
254
   * @segment: the buffer to transmnit
   *
   * This function transmits as much of the buffer as
   * the network layer will accept, and returns the number of
   * bytes transmitted.
   *
   * If CRC hashing is enabled, the function will compute the
   * hash as it goes. When the entire segment has been transmitted,
   * it will retrieve the hash value and send it as well.
   */
6df19a791   Mike Christie   [SCSI] libiscsi_t...
255
  static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn,
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
256
257
  				     struct iscsi_segment *segment)
  {
6df19a791   Mike Christie   [SCSI] libiscsi_t...
258
  	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
259
260
261
  	struct socket *sk = tcp_sw_conn->sock;
  	unsigned int copied = 0;
  	int r = 0;
6df19a791   Mike Christie   [SCSI] libiscsi_t...
262
  	while (!iscsi_tcp_segment_done(tcp_conn, segment, 0, r)) {
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
  		struct scatterlist *sg;
  		unsigned int offset, copy;
  		int flags = 0;
  
  		r = 0;
  		offset = segment->copied;
  		copy = segment->size - offset;
  
  		if (segment->total_copied + segment->size < segment->total_size)
  			flags |= MSG_MORE;
  
  		/* Use sendpage if we can; else fall back to sendmsg */
  		if (!segment->data) {
  			sg = segment->sg;
  			offset += segment->sg_offset + sg->offset;
  			r = tcp_sw_conn->sendpage(sk, sg_page(sg), offset,
  						  copy, flags);
  		} else {
  			struct msghdr msg = { .msg_flags = flags };
  			struct kvec iov = {
  				.iov_base = segment->data + offset,
  				.iov_len = copy
  			};
  
  			r = kernel_sendmsg(sk, &msg, &iov, 1, copy);
  		}
  
  		if (r < 0) {
  			iscsi_tcp_segment_unmap(segment);
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
292
293
294
295
296
297
298
299
300
  			return r;
  		}
  		copied += r;
  	}
  	return copied;
  }
  
  /**
   * iscsi_sw_tcp_xmit - TCP transmit
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
301
   **/
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
302
  static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
303
  {
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
304
  	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
305
306
  	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
  	struct iscsi_segment *segment = &tcp_sw_conn->out.segment;
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
307
308
  	unsigned int consumed = 0;
  	int rc = 0;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
309

a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
310
  	while (1) {
6df19a791   Mike Christie   [SCSI] libiscsi_t...
311
  		rc = iscsi_sw_tcp_xmit_segment(tcp_conn, segment);
32382492e   Mike Christie   iscsi_tcp: propog...
312
313
  		/*
  		 * We may not have been able to send data because the conn
25985edce   Lucas De Marchi   Fix common misspe...
314
  		 * is getting stopped. libiscsi will know so propagate err
32382492e   Mike Christie   iscsi_tcp: propog...
315
316
317
318
319
  		 * for it to do the right thing.
  		 */
  		if (rc == -EAGAIN)
  			return rc;
  		else if (rc < 0) {
6f481e3ce   Mike Christie   [SCSI] iscsi_tcp:...
320
  			rc = ISCSI_ERR_XMIT_FAILED;
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
321
  			goto error;
32382492e   Mike Christie   iscsi_tcp: propog...
322
  		} else if (rc == 0)
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
323
324
325
326
327
328
329
  			break;
  
  		consumed += rc;
  
  		if (segment->total_copied >= segment->total_size) {
  			if (segment->done != NULL) {
  				rc = segment->done(tcp_conn, segment);
6f481e3ce   Mike Christie   [SCSI] iscsi_tcp:...
330
  				if (rc != 0)
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
331
332
333
  					goto error;
  			}
  		}
3219e5294   Mike Christie   [SCSI] iscsi: fix...
334
  	}
c93f87c72   Mike Christie   [SCSI] iscsi_tcp:...
335
336
  	ISCSI_SW_TCP_DBG(conn, "xmit %d bytes
  ", consumed);
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
337
338
339
340
341
342
343
  
  	conn->txdata_octets += consumed;
  	return consumed;
  
  error:
  	/* Transmit error. We could initiate error recovery
  	 * here. */
c93f87c72   Mike Christie   [SCSI] iscsi_tcp:...
344
345
  	ISCSI_SW_TCP_DBG(conn, "Error sending PDU, errno=%d
  ", rc);
6f481e3ce   Mike Christie   [SCSI] iscsi_tcp:...
346
347
  	iscsi_conn_failure(conn, rc);
  	return -EIO;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
348
349
350
  }
  
  /**
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
351
352
   * iscsi_tcp_xmit_qlen - return the number of bytes queued for xmit
   */
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
353
  static inline int iscsi_sw_tcp_xmit_qlen(struct iscsi_conn *conn)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
354
  {
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
355
  	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
356
357
  	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
  	struct iscsi_segment *segment = &tcp_sw_conn->out.segment;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
358

a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
359
  	return segment->total_copied - segment->total_size;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
360
  }
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
361
  static int iscsi_sw_tcp_pdu_xmit(struct iscsi_task *task)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
362
  {
e5a7efeff   Mike Christie   [SCSI] iscsi_tcp:...
363
  	struct iscsi_conn *conn = task->conn;
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
364
  	int rc;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
365
366
  	while (iscsi_sw_tcp_xmit_qlen(conn)) {
  		rc = iscsi_sw_tcp_xmit(conn);
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
367
  		if (rc == 0)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
368
  			return -EAGAIN;
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
369
370
  		if (rc < 0)
  			return rc;
3219e5294   Mike Christie   [SCSI] iscsi: fix...
371
  	}
7ba247138   Alex Aizman   [SCSI] open-iscsi...
372

a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
373
  	return 0;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
374
  }
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
375
376
377
378
  /*
   * This is called when we're done sending the header.
   * Simply copy the data_segment to the send segment, and return.
   */
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
379
380
  static int iscsi_sw_tcp_send_hdr_done(struct iscsi_tcp_conn *tcp_conn,
  				      struct iscsi_segment *segment)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
381
  {
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
382
383
384
  	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
  
  	tcp_sw_conn->out.segment = tcp_sw_conn->out.data_segment;
c93f87c72   Mike Christie   [SCSI] iscsi_tcp:...
385
386
387
388
389
  	ISCSI_SW_TCP_DBG(tcp_conn->iscsi_conn,
  			 "Header done. Next segment size %u total_size %u
  ",
  			 tcp_sw_conn->out.segment.size,
  			 tcp_sw_conn->out.segment.total_size);
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
390
391
  	return 0;
  }
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
392
393
  static void iscsi_sw_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr,
  				       size_t hdrlen)
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
394
395
  {
  	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
396
  	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
397

c93f87c72   Mike Christie   [SCSI] iscsi_tcp:...
398
399
400
  	ISCSI_SW_TCP_DBG(conn, "%s
  ", conn->hdrdgst_en ?
  			 "digest enabled" : "digest disabled");
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
401
402
403
  
  	/* Clear the data segment - needs to be filled in by the
  	 * caller using iscsi_tcp_send_data_prep() */
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
404
405
  	memset(&tcp_sw_conn->out.data_segment, 0,
  	       sizeof(struct iscsi_segment));
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
406
407
408
  
  	/* If header digest is enabled, compute the CRC and
  	 * place the digest into the same buffer. We make
135a8ad4e   Mike Christie   [SCSI] iscsi_tcp:...
409
  	 * sure that both iscsi_tcp_task and mtask have
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
410
411
412
  	 * sufficient room.
  	 */
  	if (conn->hdrdgst_en) {
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
413
  		iscsi_tcp_dgst_header(&tcp_sw_conn->tx_hash, hdr, hdrlen,
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
414
415
416
417
418
419
420
  				      hdr + hdrlen);
  		hdrlen += ISCSI_DIGEST_SIZE;
  	}
  
  	/* Remember header pointer for later, when we need
  	 * to decide whether there's a payload to go along
  	 * with the header. */
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
421
  	tcp_sw_conn->out.hdr = hdr;
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
422

38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
423
424
  	iscsi_segment_init_linear(&tcp_sw_conn->out.segment, hdr, hdrlen,
  				  iscsi_sw_tcp_send_hdr_done, NULL);
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
425
426
427
428
429
430
431
432
  }
  
  /*
   * Prepare the send buffer for the payload data.
   * Padding and checksumming will all be taken care
   * of by the iscsi_segment routines.
   */
  static int
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
433
434
435
  iscsi_sw_tcp_send_data_prep(struct iscsi_conn *conn, struct scatterlist *sg,
  			    unsigned int count, unsigned int offset,
  			    unsigned int len)
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
436
437
  {
  	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
438
  	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
439
440
  	struct hash_desc *tx_hash = NULL;
  	unsigned int hdr_spec_len;
c93f87c72   Mike Christie   [SCSI] iscsi_tcp:...
441
442
443
444
  	ISCSI_SW_TCP_DBG(conn, "offset=%d, datalen=%d %s
  ", offset, len,
  			 conn->datadgst_en ?
  			 "digest enabled" : "digest disabled");
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
445
446
447
  
  	/* Make sure the datalen matches what the caller
  	   said he would send. */
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
448
  	hdr_spec_len = ntoh24(tcp_sw_conn->out.hdr->dlength);
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
449
450
451
  	WARN_ON(iscsi_padded(len) != iscsi_padded(hdr_spec_len));
  
  	if (conn->datadgst_en)
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
452
  		tx_hash = &tcp_sw_conn->tx_hash;
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
453

38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
454
455
456
  	return iscsi_segment_seek_sg(&tcp_sw_conn->out.data_segment,
  				     sg, count, offset, len,
  				     NULL, tx_hash);
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
457
458
459
  }
  
  static void
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
460
  iscsi_sw_tcp_send_linear_data_prep(struct iscsi_conn *conn, void *data,
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
461
462
463
  				   size_t len)
  {
  	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
464
  	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
465
466
  	struct hash_desc *tx_hash = NULL;
  	unsigned int hdr_spec_len;
c93f87c72   Mike Christie   [SCSI] iscsi_tcp:...
467
468
469
  	ISCSI_SW_TCP_DBG(conn, "datalen=%zd %s
  ", len, conn->datadgst_en ?
  			 "digest enabled" : "digest disabled");
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
470
471
472
  
  	/* Make sure the datalen matches what the caller
  	   said he would send. */
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
473
  	hdr_spec_len = ntoh24(tcp_sw_conn->out.hdr->dlength);
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
474
475
476
  	WARN_ON(iscsi_padded(len) != iscsi_padded(hdr_spec_len));
  
  	if (conn->datadgst_en)
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
477
  		tx_hash = &tcp_sw_conn->tx_hash;
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
478

38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
479
  	iscsi_segment_init_linear(&tcp_sw_conn->out.data_segment,
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
480
  				data, len, NULL, tx_hash);
7ba247138   Alex Aizman   [SCSI] open-iscsi...
481
  }
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
482
483
  static int iscsi_sw_tcp_pdu_init(struct iscsi_task *task,
  				 unsigned int offset, unsigned int count)
e5a7efeff   Mike Christie   [SCSI] iscsi_tcp:...
484
485
486
  {
  	struct iscsi_conn *conn = task->conn;
  	int err = 0;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
487
  	iscsi_sw_tcp_send_hdr_prep(conn, task->hdr, task->hdr_len);
e5a7efeff   Mike Christie   [SCSI] iscsi_tcp:...
488
489
490
491
492
  
  	if (!count)
  		return 0;
  
  	if (!task->sc)
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
493
  		iscsi_sw_tcp_send_linear_data_prep(conn, task->data, count);
e5a7efeff   Mike Christie   [SCSI] iscsi_tcp:...
494
495
  	else {
  		struct scsi_data_buffer *sdb = scsi_out(task->sc);
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
496
497
498
  		err = iscsi_sw_tcp_send_data_prep(conn, sdb->table.sgl,
  						  sdb->table.nents, offset,
  						  count);
e5a7efeff   Mike Christie   [SCSI] iscsi_tcp:...
499
500
501
  	}
  
  	if (err) {
9a6510eb3   Mike Christie   [SCSI] iscsi_tcp:...
502
  		/* got invalid offset/len */
e5a7efeff   Mike Christie   [SCSI] iscsi_tcp:...
503
504
505
506
  		return -EIO;
  	}
  	return 0;
  }
2ff79d52d   Mike Christie   [SCSI] libiscsi: ...
507
  static int iscsi_sw_tcp_pdu_alloc(struct iscsi_task *task, uint8_t opcode)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
508
  {
135a8ad4e   Mike Christie   [SCSI] iscsi_tcp:...
509
  	struct iscsi_tcp_task *tcp_task = task->dd_data;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
510

38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
511
512
  	task->hdr = task->dd_data + sizeof(*tcp_task);
  	task->hdr_max = sizeof(struct iscsi_sw_tcp_hdrbuf) - ISCSI_DIGEST_SIZE;
a8ac6311c   Olaf Kirch   [SCSI] iscsi: con...
513
  	return 0;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
514
  }
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
515
  static struct iscsi_cls_conn *
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
516
517
  iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session,
  			 uint32_t conn_idx)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
518
  {
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
519
520
521
  	struct iscsi_conn *conn;
  	struct iscsi_cls_conn *cls_conn;
  	struct iscsi_tcp_conn *tcp_conn;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
522
  	struct iscsi_sw_tcp_conn *tcp_sw_conn;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
523

38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
524
525
  	cls_conn = iscsi_tcp_conn_setup(cls_session, sizeof(*tcp_sw_conn),
  					conn_idx);
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
526
527
528
  	if (!cls_conn)
  		return NULL;
  	conn = cls_conn->dd_data;
5d91e209f   Mike Christie   [SCSI] iscsi: rem...
529
  	tcp_conn = conn->dd_data;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
530
  	tcp_sw_conn = tcp_conn->dd_data;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
531

38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
532
533
534
535
  	tcp_sw_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
  						     CRYPTO_ALG_ASYNC);
  	tcp_sw_conn->tx_hash.flags = 0;
  	if (IS_ERR(tcp_sw_conn->tx_hash.tfm))
5d91e209f   Mike Christie   [SCSI] iscsi: rem...
536
  		goto free_conn;
dd8c0d958   Mike Christie   [SCSI] scsi_tcp: ...
537

38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
538
539
540
541
  	tcp_sw_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
  						     CRYPTO_ALG_ASYNC);
  	tcp_sw_conn->rx_hash.flags = 0;
  	if (IS_ERR(tcp_sw_conn->rx_hash.tfm))
dd8c0d958   Mike Christie   [SCSI] scsi_tcp: ...
542
  		goto free_tx_tfm;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
543
  	tcp_conn->rx_hash = &tcp_sw_conn->rx_hash;
dd8c0d958   Mike Christie   [SCSI] scsi_tcp: ...
544

5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
545
  	return cls_conn;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
546

dd8c0d958   Mike Christie   [SCSI] scsi_tcp: ...
547
  free_tx_tfm:
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
548
  	crypto_free_hash(tcp_sw_conn->tx_hash.tfm);
5d91e209f   Mike Christie   [SCSI] iscsi: rem...
549
  free_conn:
322d739da   Mike Christie   [SCSI] iscsi: fix...
550
551
552
553
554
555
  	iscsi_conn_printk(KERN_ERR, conn,
  			  "Could not create connection due to crc32c "
  			  "loading error. Make sure the crc32c "
  			  "module is built as a module or into the "
  			  "kernel
  ");
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
556
  	iscsi_tcp_conn_teardown(cls_conn);
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
557
  	return NULL;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
558
  }
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
559
  static void iscsi_sw_tcp_release_conn(struct iscsi_conn *conn)
1c83469d3   Mike Christie   [SCSI] iscsi bugf...
560
  {
222369619   Mike Christie   [SCSI] iscsi clas...
561
  	struct iscsi_session *session = conn->session;
1c83469d3   Mike Christie   [SCSI] iscsi bugf...
562
  	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
563
564
  	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
  	struct socket *sock = tcp_sw_conn->sock;
1c83469d3   Mike Christie   [SCSI] iscsi bugf...
565

222369619   Mike Christie   [SCSI] iscsi clas...
566
  	if (!sock)
1c83469d3   Mike Christie   [SCSI] iscsi bugf...
567
  		return;
222369619   Mike Christie   [SCSI] iscsi clas...
568
  	sock_hold(sock->sk);
c484a50a4   Avi Kaplan   [SCSI] iscsi_tcp:...
569
  	iscsi_sw_tcp_conn_restore_callbacks(conn);
222369619   Mike Christie   [SCSI] iscsi clas...
570
  	sock_put(sock->sk);
1c83469d3   Mike Christie   [SCSI] iscsi bugf...
571

222369619   Mike Christie   [SCSI] iscsi clas...
572
  	spin_lock_bh(&session->lock);
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
573
  	tcp_sw_conn->sock = NULL;
222369619   Mike Christie   [SCSI] iscsi clas...
574
575
  	spin_unlock_bh(&session->lock);
  	sockfd_put(sock);
1c83469d3   Mike Christie   [SCSI] iscsi bugf...
576
  }
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
577
  static void iscsi_sw_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
578
  {
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
579
580
  	struct iscsi_conn *conn = cls_conn->dd_data;
  	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
581
  	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
582

38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
583
  	iscsi_sw_tcp_release_conn(conn);
7ba247138   Alex Aizman   [SCSI] open-iscsi...
584

38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
585
586
587
588
  	if (tcp_sw_conn->tx_hash.tfm)
  		crypto_free_hash(tcp_sw_conn->tx_hash.tfm);
  	if (tcp_sw_conn->rx_hash.tfm)
  		crypto_free_hash(tcp_sw_conn->rx_hash.tfm);
7ba247138   Alex Aizman   [SCSI] open-iscsi...
589

38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
590
  	iscsi_tcp_conn_teardown(cls_conn);
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
591
  }
7ba247138   Alex Aizman   [SCSI] open-iscsi...
592

38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
593
  static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
1c83469d3   Mike Christie   [SCSI] iscsi bugf...
594
595
  {
  	struct iscsi_conn *conn = cls_conn->dd_data;
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
596
  	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
597
  	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
b64e77f70   Mike Christie   [SCSI] iscsi_tcp:...
598
  	struct socket *sock = tcp_sw_conn->sock;
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
599
600
  
  	/* userspace may have goofed up and not bound us */
b64e77f70   Mike Christie   [SCSI] iscsi_tcp:...
601
  	if (!sock)
913e5bf43   Mike Christie   [SCSI] libiscsi, ...
602
  		return;
1c83469d3   Mike Christie   [SCSI] iscsi bugf...
603

8c38a2951   Mike Christie   [SCSI] iscsi_tcp:...
604
605
  	sock->sk->sk_err = EIO;
  	wake_up_interruptible(sk_sleep(sock->sk));
b64e77f70   Mike Christie   [SCSI] iscsi_tcp:...
606

03adb5f91   Mike Christie   [SCSI] iscsi_tcp:...
607
608
609
610
  	/* stop xmit side */
  	iscsi_suspend_tx(conn);
  
  	/* stop recv side and release socket */
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
611
  	iscsi_sw_tcp_release_conn(conn);
03adb5f91   Mike Christie   [SCSI] iscsi_tcp:...
612
613
  
  	iscsi_conn_stop(cls_conn, flag);
1c83469d3   Mike Christie   [SCSI] iscsi bugf...
614
  }
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
615
  static int
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
616
617
618
  iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
  		       struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
  		       int is_leading)
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
619
  {
a79af8a64   Mike Christie   [SCSI] iscsi_tcp:...
620
  	struct iscsi_session *session = cls_session->dd_data;
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
621
622
  	struct iscsi_conn *conn = cls_conn->dd_data;
  	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
623
  	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
624
625
626
  	struct sock *sk;
  	struct socket *sock;
  	int err;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
627

5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
628
  	/* lookup for existing socket */
264faaaa1   Or Gerlitz   [SCSI] iscsi: add...
629
  	sock = sockfd_lookup((int)transport_eph, &err);
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
630
  	if (!sock) {
322d739da   Mike Christie   [SCSI] iscsi: fix...
631
632
633
  		iscsi_conn_printk(KERN_ERR, conn,
  				  "sockfd_lookup failed %d
  ", err);
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
634
  		return -EEXIST;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
635
  	}
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
636
637
  	err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
  	if (err)
222369619   Mike Christie   [SCSI] iscsi clas...
638
  		goto free_socket;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
639

a79af8a64   Mike Christie   [SCSI] iscsi_tcp:...
640
  	spin_lock_bh(&session->lock);
67a611149   Mike Christie   [SCSI] iscsi: don...
641
  	/* bind iSCSI connection and socket */
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
642
  	tcp_sw_conn->sock = sock;
a79af8a64   Mike Christie   [SCSI] iscsi_tcp:...
643
  	spin_unlock_bh(&session->lock);
7ba247138   Alex Aizman   [SCSI] open-iscsi...
644

67a611149   Mike Christie   [SCSI] iscsi: don...
645
646
647
648
649
  	/* setup Socket parameters */
  	sk = sock->sk;
  	sk->sk_reuse = 1;
  	sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */
  	sk->sk_allocation = GFP_ATOMIC;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
650

38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
651
652
  	iscsi_sw_tcp_conn_set_callbacks(conn);
  	tcp_sw_conn->sendpage = tcp_sw_conn->sock->ops->sendpage;
67a611149   Mike Christie   [SCSI] iscsi: don...
653
654
655
  	/*
  	 * set receive state machine into initial state
  	 */
da32dd681   Olaf Kirch   [SCSI] iscsi_tcp:...
656
  	iscsi_tcp_hdr_recv_prep(tcp_conn);
7ba247138   Alex Aizman   [SCSI] open-iscsi...
657
  	return 0;
222369619   Mike Christie   [SCSI] iscsi clas...
658
659
660
661
  
  free_socket:
  	sockfd_put(sock);
  	return err;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
662
  }
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
663
664
665
  static int iscsi_sw_tcp_conn_set_param(struct iscsi_cls_conn *cls_conn,
  				       enum iscsi_param param, char *buf,
  				       int buflen)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
666
  {
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
667
  	struct iscsi_conn *conn = cls_conn->dd_data;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
668
  	struct iscsi_session *session = conn->session;
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
669
  	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
670
  	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
5c75b7fcf   Mike Christie   [SCSI] iscsi: con...
671
  	int value;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
672

7ba247138   Alex Aizman   [SCSI] open-iscsi...
673
  	switch(param) {
7ba247138   Alex Aizman   [SCSI] open-iscsi...
674
  	case ISCSI_PARAM_HDRDGST_EN:
5c75b7fcf   Mike Christie   [SCSI] iscsi: con...
675
  		iscsi_set_param(cls_conn, param, buf, buflen);
7ba247138   Alex Aizman   [SCSI] open-iscsi...
676
677
  		break;
  	case ISCSI_PARAM_DATADGST_EN:
5c75b7fcf   Mike Christie   [SCSI] iscsi: con...
678
  		iscsi_set_param(cls_conn, param, buf, buflen);
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
679
680
  		tcp_sw_conn->sendpage = conn->datadgst_en ?
  			sock_no_sendpage : tcp_sw_conn->sock->ops->sendpage;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
681
  		break;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
682
  	case ISCSI_PARAM_MAX_R2T:
5c75b7fcf   Mike Christie   [SCSI] iscsi: con...
683
  		sscanf(buf, "%d", &value);
df93ffcd7   Mike Christie   [SCSI] iscsi_tcp:...
684
685
686
  		if (value <= 0 || !is_power_of_2(value))
  			return -EINVAL;
  		if (session->max_r2t == value)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
687
  			break;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
688
  		iscsi_tcp_r2tpool_free(session);
5c75b7fcf   Mike Christie   [SCSI] iscsi: con...
689
  		iscsi_set_param(cls_conn, param, buf, buflen);
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
690
  		if (iscsi_tcp_r2tpool_alloc(session))
7ba247138   Alex Aizman   [SCSI] open-iscsi...
691
692
  			return -ENOMEM;
  		break;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
693
  	default:
5c75b7fcf   Mike Christie   [SCSI] iscsi: con...
694
  		return iscsi_set_param(cls_conn, param, buf, buflen);
7ba247138   Alex Aizman   [SCSI] open-iscsi...
695
696
697
698
  	}
  
  	return 0;
  }
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
699
700
  static int iscsi_sw_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
  				       enum iscsi_param param, char *buf)
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
701
  {
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
702
  	struct iscsi_conn *conn = cls_conn->dd_data;
a79af8a64   Mike Christie   [SCSI] iscsi_tcp:...
703
704
705
706
  	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
  	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
  	struct sockaddr_in6 addr;
  	int rc, len;
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
707
708
  
  	switch(param) {
fd7255f51   Mike Christie   [SCSI] iscsi: add...
709
  	case ISCSI_PARAM_CONN_PORT:
fd7255f51   Mike Christie   [SCSI] iscsi: add...
710
  	case ISCSI_PARAM_CONN_ADDRESS:
222369619   Mike Christie   [SCSI] iscsi clas...
711
  		spin_lock_bh(&conn->session->lock);
a79af8a64   Mike Christie   [SCSI] iscsi_tcp:...
712
713
714
715
716
717
  		if (!tcp_sw_conn || !tcp_sw_conn->sock) {
  			spin_unlock_bh(&conn->session->lock);
  			return -ENOTCONN;
  		}
  		rc = kernel_getpeername(tcp_sw_conn->sock,
  					(struct sockaddr *)&addr, &len);
222369619   Mike Christie   [SCSI] iscsi clas...
718
  		spin_unlock_bh(&conn->session->lock);
a79af8a64   Mike Christie   [SCSI] iscsi_tcp:...
719
720
721
722
723
  		if (rc)
  			return rc;
  
  		return iscsi_conn_get_addr_param((struct sockaddr_storage *)
  						 &addr, param, buf);
fd7255f51   Mike Christie   [SCSI] iscsi: add...
724
  	default:
5c75b7fcf   Mike Christie   [SCSI] iscsi: con...
725
  		return iscsi_conn_get_param(cls_conn, param, buf);
fd7255f51   Mike Christie   [SCSI] iscsi: add...
726
  	}
a79af8a64   Mike Christie   [SCSI] iscsi_tcp:...
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
  	return 0;
  }
  
  static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost,
  				       enum iscsi_host_param param, char *buf)
  {
  	struct iscsi_sw_tcp_host *tcp_sw_host = iscsi_host_priv(shost);
  	struct iscsi_session *session = tcp_sw_host->session;
  	struct iscsi_conn *conn;
  	struct iscsi_tcp_conn *tcp_conn;
  	struct iscsi_sw_tcp_conn *tcp_sw_conn;
  	struct sockaddr_in6 addr;
  	int rc, len;
  
  	switch (param) {
  	case ISCSI_HOST_PARAM_IPADDRESS:
  		spin_lock_bh(&session->lock);
  		conn = session->leadconn;
  		if (!conn) {
  			spin_unlock_bh(&session->lock);
  			return -ENOTCONN;
  		}
  		tcp_conn = conn->dd_data;
  
  		tcp_sw_conn = tcp_conn->dd_data;
  		if (!tcp_sw_conn->sock) {
  			spin_unlock_bh(&session->lock);
  			return -ENOTCONN;
  		}
  
  		rc = kernel_getsockname(tcp_sw_conn->sock,
  					(struct sockaddr *)&addr, &len);
  		spin_unlock_bh(&session->lock);
  		if (rc)
  			return rc;
  
  		return iscsi_conn_get_addr_param((struct sockaddr_storage *)
  						 &addr, param, buf);
  	default:
  		return iscsi_host_get_param(shost, param, buf);
  	}
  
  	return 0;
fd7255f51   Mike Christie   [SCSI] iscsi: add...
770
  }
7ba247138   Alex Aizman   [SCSI] open-iscsi...
771
  static void
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
772
773
  iscsi_sw_tcp_conn_get_stats(struct iscsi_cls_conn *cls_conn,
  			    struct iscsi_stats *stats)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
774
  {
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
775
  	struct iscsi_conn *conn = cls_conn->dd_data;
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
776
  	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
777
  	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
778

7ba247138   Alex Aizman   [SCSI] open-iscsi...
779
780
  	stats->custom_length = 3;
  	strcpy(stats->custom[0].desc, "tx_sendpage_failures");
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
781
  	stats->custom[0].value = tcp_sw_conn->sendpage_failures_cnt;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
782
  	strcpy(stats->custom[1].desc, "rx_discontiguous_hdr");
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
783
  	stats->custom[1].value = tcp_sw_conn->discontiguous_hdr_cnt;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
784
785
  	strcpy(stats->custom[2].desc, "eh_abort_cnt");
  	stats->custom[2].value = conn->eh_abort_cnt;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
786
787
  
  	iscsi_tcp_conn_get_stats(cls_conn, stats);
7ba247138   Alex Aizman   [SCSI] open-iscsi...
788
  }
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
789
  static struct iscsi_cls_session *
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
790
  iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
5e7facb77   Mike Christie   [SCSI] iscsi clas...
791
  			    uint16_t qdepth, uint32_t initial_cmdsn)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
792
  {
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
793
794
  	struct iscsi_cls_session *cls_session;
  	struct iscsi_session *session;
a79af8a64   Mike Christie   [SCSI] iscsi_tcp:...
795
  	struct iscsi_sw_tcp_host *tcp_sw_host;
06520edea   Mike Christie   [SCSI] iscsi_tcp:...
796
  	struct Scsi_Host *shost;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
797

06520edea   Mike Christie   [SCSI] iscsi_tcp:...
798
799
800
  	if (ep) {
  		printk(KERN_ERR "iscsi_tcp: invalid ep %p.
  ", ep);
756135215   Mike Christie   [SCSI] iscsi: rem...
801
802
  		return NULL;
  	}
a79af8a64   Mike Christie   [SCSI] iscsi_tcp:...
803
804
  	shost = iscsi_host_alloc(&iscsi_sw_tcp_sht,
  				 sizeof(struct iscsi_sw_tcp_host), 1);
756135215   Mike Christie   [SCSI] iscsi: rem...
805
  	if (!shost)
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
806
  		return NULL;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
807
  	shost->transportt = iscsi_sw_tcp_scsi_transport;
4d1083509   Mike Christie   [SCSI] iscsi lib:...
808
  	shost->cmd_per_lun = qdepth;
756135215   Mike Christie   [SCSI] iscsi: rem...
809
810
811
  	shost->max_lun = iscsi_max_lun;
  	shost->max_id = 0;
  	shost->max_channel = 0;
30e9ba9f2   Boaz Harrosh   [SCSI] iscsi_tcp:...
812
  	shost->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE;
756135215   Mike Christie   [SCSI] iscsi: rem...
813

a4804cd6e   Mike Christie   [SCSI] iscsi: add...
814
  	if (iscsi_host_add(shost, NULL))
756135215   Mike Christie   [SCSI] iscsi: rem...
815
  		goto free_host;
756135215   Mike Christie   [SCSI] iscsi: rem...
816

38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
817
  	cls_session = iscsi_session_setup(&iscsi_sw_tcp_transport, shost,
b8b9e1b81   Jayamohan Kallickal   [SCSI] libiscsi: ...
818
  					  cmds_max, 0,
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
819
820
  					  sizeof(struct iscsi_tcp_task) +
  					  sizeof(struct iscsi_sw_tcp_hdrbuf),
7970634b8   Mike Christie   [SCSI] iscsi clas...
821
  					  initial_cmdsn, 0);
756135215   Mike Christie   [SCSI] iscsi: rem...
822
823
824
  	if (!cls_session)
  		goto remove_host;
  	session = cls_session->dd_data;
a79af8a64   Mike Christie   [SCSI] iscsi_tcp:...
825
826
  	tcp_sw_host = iscsi_host_priv(shost);
  	tcp_sw_host->session = session;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
827

fbc514b4e   Mike Christie   [SCSI] iscsi_tcp:...
828
  	shost->can_queue = session->scsi_cmds_max;
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
829
  	if (iscsi_tcp_r2tpool_alloc(session))
756135215   Mike Christie   [SCSI] iscsi: rem...
830
  		goto remove_session;
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
831
  	return cls_session;
756135215   Mike Christie   [SCSI] iscsi: rem...
832
  remove_session:
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
833
  	iscsi_session_teardown(cls_session);
756135215   Mike Christie   [SCSI] iscsi: rem...
834
  remove_host:
a4804cd6e   Mike Christie   [SCSI] iscsi: add...
835
  	iscsi_host_remove(shost);
756135215   Mike Christie   [SCSI] iscsi: rem...
836
  free_host:
a4804cd6e   Mike Christie   [SCSI] iscsi: add...
837
  	iscsi_host_free(shost);
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
838
839
  	return NULL;
  }
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
840
  static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session)
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
841
  {
756135215   Mike Christie   [SCSI] iscsi: rem...
842
  	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
843
  	iscsi_tcp_r2tpool_free(cls_session->dd_data);
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
844
  	iscsi_session_teardown(cls_session);
756135215   Mike Christie   [SCSI] iscsi: rem...
845

a4804cd6e   Mike Christie   [SCSI] iscsi: add...
846
847
  	iscsi_host_remove(shost);
  	iscsi_host_free(shost);
7ba247138   Alex Aizman   [SCSI] open-iscsi...
848
  }
587a1f165   Al Viro   switch ->is_visib...
849
  static umode_t iscsi_sw_tcp_attr_is_visible(int param_type, int param)
3128c6c73   Mike Christie   [SCSI] iscsi cls:...
850
851
  {
  	switch (param_type) {
f27fb2ef7   Mike Christie   [SCSI] iscsi clas...
852
853
854
855
856
857
858
859
860
861
  	case ISCSI_HOST_PARAM:
  		switch (param) {
  		case ISCSI_HOST_PARAM_NETDEV_NAME:
  		case ISCSI_HOST_PARAM_HWADDRESS:
  		case ISCSI_HOST_PARAM_IPADDRESS:
  		case ISCSI_HOST_PARAM_INITIATOR_NAME:
  			return S_IRUGO;
  		default:
  			return 0;
  		}
3128c6c73   Mike Christie   [SCSI] iscsi cls:...
862
863
864
865
866
867
868
869
870
871
872
873
874
  	case ISCSI_PARAM:
  		switch (param) {
  		case ISCSI_PARAM_MAX_RECV_DLENGTH:
  		case ISCSI_PARAM_MAX_XMIT_DLENGTH:
  		case ISCSI_PARAM_HDRDGST_EN:
  		case ISCSI_PARAM_DATADGST_EN:
  		case ISCSI_PARAM_CONN_ADDRESS:
  		case ISCSI_PARAM_CONN_PORT:
  		case ISCSI_PARAM_EXP_STATSN:
  		case ISCSI_PARAM_PERSISTENT_ADDRESS:
  		case ISCSI_PARAM_PERSISTENT_PORT:
  		case ISCSI_PARAM_PING_TMO:
  		case ISCSI_PARAM_RECV_TMO:
1d063c172   Mike Christie   [SCSI] iscsi clas...
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
  		case ISCSI_PARAM_INITIAL_R2T_EN:
  		case ISCSI_PARAM_MAX_R2T:
  		case ISCSI_PARAM_IMM_DATA_EN:
  		case ISCSI_PARAM_FIRST_BURST:
  		case ISCSI_PARAM_MAX_BURST:
  		case ISCSI_PARAM_PDU_INORDER_EN:
  		case ISCSI_PARAM_DATASEQ_INORDER_EN:
  		case ISCSI_PARAM_ERL:
  		case ISCSI_PARAM_TARGET_NAME:
  		case ISCSI_PARAM_TPGT:
  		case ISCSI_PARAM_USERNAME:
  		case ISCSI_PARAM_PASSWORD:
  		case ISCSI_PARAM_USERNAME_IN:
  		case ISCSI_PARAM_PASSWORD_IN:
  		case ISCSI_PARAM_FAST_ABORT:
  		case ISCSI_PARAM_ABORT_TMO:
  		case ISCSI_PARAM_LU_RESET_TMO:
  		case ISCSI_PARAM_TGT_RESET_TMO:
  		case ISCSI_PARAM_IFACE_NAME:
  		case ISCSI_PARAM_INITIATOR_NAME:
3128c6c73   Mike Christie   [SCSI] iscsi cls:...
895
896
897
898
899
900
901
902
  			return S_IRUGO;
  		default:
  			return 0;
  		}
  	}
  
  	return 0;
  }
091e6dbec   Pete Wyckoff   [SCSI] iscsi tcp:...
903
904
905
906
907
  static int iscsi_sw_tcp_slave_alloc(struct scsi_device *sdev)
  {
  	set_bit(QUEUE_FLAG_BIDI, &sdev->request_queue->queue_flags);
  	return 0;
  }
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
908
  static int iscsi_sw_tcp_slave_configure(struct scsi_device *sdev)
d1d81c01f   Mike Christie   [SCSI] iscsi_tcp:...
909
  {
b6d44fe95   Mike Christie   [SCSI] iscsi_tcp:...
910
  	blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_ANY);
d1d81c01f   Mike Christie   [SCSI] iscsi_tcp:...
911
912
913
  	blk_queue_dma_alignment(sdev->request_queue, 0);
  	return 0;
  }
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
914
  static struct scsi_host_template iscsi_sw_tcp_sht = {
7974392c0   Mike Christie   [SCSI] iscsi_tcp,...
915
  	.module			= THIS_MODULE,
f4246b33c   Mike Christie   [SCSI] iscsi bugf...
916
  	.name			= "iSCSI Initiator over TCP/IP",
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
917
918
  	.queuecommand           = iscsi_queuecommand,
  	.change_queue_depth	= iscsi_change_queue_depth,
1548271ec   Mike Christie   [SCSI] libiscsi: ...
919
  	.can_queue		= ISCSI_DEF_XMIT_CMDS_MAX - 1,
66bbe0ce1   Mike Christie   [SCSI] iscsi_tcp:...
920
  	.sg_tablesize		= 4096,
8231f0edd   Mike Christie   [SCSI] iscsi_tcp:...
921
  	.max_sectors		= 0xFFFF,
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
922
923
  	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
  	.eh_abort_handler       = iscsi_eh_abort,
843c0a8a7   Mike Christie   [SCSI] libiscsi, ...
924
  	.eh_device_reset_handler= iscsi_eh_device_reset,
309ce156a   Jayamohan Kallickal   [SCSI] libiscsi: ...
925
  	.eh_target_reset_handler = iscsi_eh_recover_target,
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
926
  	.use_clustering         = DISABLE_CLUSTERING,
091e6dbec   Pete Wyckoff   [SCSI] iscsi tcp:...
927
  	.slave_alloc            = iscsi_sw_tcp_slave_alloc,
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
928
  	.slave_configure        = iscsi_sw_tcp_slave_configure,
6b5d6c443   Mike Christie   [SCSI] cxgb3i, is...
929
  	.target_alloc		= iscsi_target_alloc,
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
930
931
932
  	.proc_name		= "iscsi_tcp",
  	.this_id		= -1,
  };
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
933
  static struct iscsi_transport iscsi_sw_tcp_transport = {
7ba247138   Alex Aizman   [SCSI] open-iscsi...
934
935
936
937
  	.owner			= THIS_MODULE,
  	.name			= "tcp",
  	.caps			= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
  				  | CAP_DATADGST,
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
938
  	/* session management */
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
939
940
  	.create_session		= iscsi_sw_tcp_session_create,
  	.destroy_session	= iscsi_sw_tcp_session_destroy,
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
941
  	/* connection management */
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
942
943
944
  	.create_conn		= iscsi_sw_tcp_conn_create,
  	.bind_conn		= iscsi_sw_tcp_conn_bind,
  	.destroy_conn		= iscsi_sw_tcp_conn_destroy,
3128c6c73   Mike Christie   [SCSI] iscsi cls:...
945
  	.attr_is_visible	= iscsi_sw_tcp_attr_is_visible,
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
946
947
  	.set_param		= iscsi_sw_tcp_conn_set_param,
  	.get_conn_param		= iscsi_sw_tcp_conn_get_param,
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
948
  	.get_session_param	= iscsi_session_get_param,
7ba247138   Alex Aizman   [SCSI] open-iscsi...
949
  	.start_conn		= iscsi_conn_start,
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
950
  	.stop_conn		= iscsi_sw_tcp_conn_stop,
0801c242a   Mike Christie   [SCSI] libiscsi, ...
951
  	/* iscsi host params */
a79af8a64   Mike Christie   [SCSI] iscsi_tcp:...
952
  	.get_host_param		= iscsi_sw_tcp_host_get_param,
0801c242a   Mike Christie   [SCSI] libiscsi, ...
953
  	.set_host_param		= iscsi_host_set_param,
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
954
  	/* IO */
7ba247138   Alex Aizman   [SCSI] open-iscsi...
955
  	.send_pdu		= iscsi_conn_send_pdu,
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
956
  	.get_stats		= iscsi_sw_tcp_conn_get_stats,
e5a7efeff   Mike Christie   [SCSI] iscsi_tcp:...
957
  	/* iscsi task/cmd helpers */
fbc514b4e   Mike Christie   [SCSI] iscsi_tcp:...
958
959
960
  	.init_task		= iscsi_tcp_task_init,
  	.xmit_task		= iscsi_tcp_task_xmit,
  	.cleanup_task		= iscsi_tcp_cleanup_task,
e5a7efeff   Mike Christie   [SCSI] iscsi_tcp:...
961
  	/* low level pdu helpers */
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
962
963
964
  	.xmit_pdu		= iscsi_sw_tcp_pdu_xmit,
  	.init_pdu		= iscsi_sw_tcp_pdu_init,
  	.alloc_pdu		= iscsi_sw_tcp_pdu_alloc,
5bb0b55a3   Mike Christie   [SCSI] iscsi: con...
965
  	/* recovery */
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
966
  	.session_recovery_timedout = iscsi_session_recovery_timedout,
7ba247138   Alex Aizman   [SCSI] open-iscsi...
967
  };
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
968
  static int __init iscsi_sw_tcp_init(void)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
969
  {
7ba247138   Alex Aizman   [SCSI] open-iscsi...
970
  	if (iscsi_max_lun < 1) {
be2df72e7   Or Gerlitz   [SCSI] iscsi: ali...
971
972
973
  		printk(KERN_ERR "iscsi_tcp: Invalid max_lun value of %u
  ",
  		       iscsi_max_lun);
7ba247138   Alex Aizman   [SCSI] open-iscsi...
974
975
  		return -EINVAL;
  	}
7ba247138   Alex Aizman   [SCSI] open-iscsi...
976

38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
977
978
979
  	iscsi_sw_tcp_scsi_transport = iscsi_register_transport(
  						&iscsi_sw_tcp_transport);
  	if (!iscsi_sw_tcp_scsi_transport)
ffbfe9253   Mike Christie   [SCSI] iscsi: kil...
980
  		return -ENODEV;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
981

7b8631b53   Mike Christie   [SCSI] iscsi: sep...
982
  	return 0;
7ba247138   Alex Aizman   [SCSI] open-iscsi...
983
  }
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
984
  static void __exit iscsi_sw_tcp_exit(void)
7ba247138   Alex Aizman   [SCSI] open-iscsi...
985
  {
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
986
  	iscsi_unregister_transport(&iscsi_sw_tcp_transport);
7ba247138   Alex Aizman   [SCSI] open-iscsi...
987
  }
38e1a8f54   Mike Christie   [SCSI] iscsi_tcp:...
988
989
  module_init(iscsi_sw_tcp_init);
  module_exit(iscsi_sw_tcp_exit);