Blame view

drivers/scsi/scsi_transport_iscsi.c 76.3 KB
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
   * iSCSI transport class definitions
   *
   * Copyright (C) IBM Corporation, 2004
0896b7523   Alex Aizman   [SCSI] open-iscsi...
5
6
7
   * Copyright (C) Mike Christie, 2004 - 2005
   * Copyright (C) Dmitry Yusupov, 2004 - 2005
   * Copyright (C) Alex Aizman, 2004 - 2005
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   *
   * 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.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   */
  #include <linux/module.h>
0b9506723   Arjan van de Ven   [SCSI] turn most ...
24
  #include <linux/mutex.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
25
  #include <linux/slab.h>
90eeb01a0   Mike Christie   [SCSI] iscsi clas...
26
  #include <linux/bsg-lib.h>
8d4a690cd   Mike Christie   [SCSI] iscsi clas...
27
  #include <linux/idr.h>
0896b7523   Alex Aizman   [SCSI] open-iscsi...
28
  #include <net/tcp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
33
  #include <scsi/scsi.h>
  #include <scsi/scsi_host.h>
  #include <scsi/scsi_device.h>
  #include <scsi/scsi_transport.h>
  #include <scsi/scsi_transport_iscsi.h>
0896b7523   Alex Aizman   [SCSI] open-iscsi...
34
  #include <scsi/iscsi_if.h>
c01be6dcb   Mike Christie   [SCSI] iscsi_tran...
35
  #include <scsi/scsi_cmnd.h>
90eeb01a0   Mike Christie   [SCSI] iscsi clas...
36
  #include <scsi/scsi_bsg_iscsi.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37

4c2133c82   Mike Christie   [SCSI] iscsi clas...
38
  #define ISCSI_TRANSPORT_VERSION "2.0-870"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39

632248aab   Mike Christie   [SCSI] iscsi clas...
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  static int dbg_session;
  module_param_named(debug_session, dbg_session, int,
  		   S_IRUGO | S_IWUSR);
  MODULE_PARM_DESC(debug_session,
  		 "Turn on debugging for sessions in scsi_transport_iscsi "
  		 "module. Set to 1 to turn on, and zero to turn off. Default "
  		 "is off.");
  
  static int dbg_conn;
  module_param_named(debug_conn, dbg_conn, int,
  		   S_IRUGO | S_IWUSR);
  MODULE_PARM_DESC(debug_conn,
  		 "Turn on debugging for connections in scsi_transport_iscsi "
  		 "module. Set to 1 to turn on, and zero to turn off. Default "
  		 "is off.");
  
  #define ISCSI_DBG_TRANS_SESSION(_session, dbg_fmt, arg...)		\
  	do {								\
  		if (dbg_session)					\
  			iscsi_cls_session_printk(KERN_INFO, _session,	\
  						 "%s: " dbg_fmt,	\
  						 __func__, ##arg);	\
  	} while (0);
  
  #define ISCSI_DBG_TRANS_CONN(_conn, dbg_fmt, arg...)			\
  	do {								\
  		if (dbg_conn)						\
  			iscsi_cls_conn_printk(KERN_INFO, _conn,		\
  					      "%s: " dbg_fmt,		\
  					      __func__, ##arg);	\
  	} while (0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
  struct iscsi_internal {
  	struct scsi_transport_template t;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
73
74
  	struct iscsi_transport *iscsi_transport;
  	struct list_head list;
ee959b00c   Tony Jones   SCSI: convert str...
75
  	struct device dev;
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
76

0896b7523   Alex Aizman   [SCSI] open-iscsi...
77
  	struct transport_container conn_cont;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
78
  	struct transport_container session_cont;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
  };
41be14442   Mike Christie   [SCSI] iscsi tran...
80
  static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
d8bf541e6   Mike Christie   [SCSI] iscsi clas...
81
  static struct workqueue_struct *iscsi_eh_timer_workq;
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
82

8d4a690cd   Mike Christie   [SCSI] iscsi clas...
83
  static DEFINE_IDA(iscsi_sess_ida);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
84
85
86
  /*
   * list of registered transports and lock that must
   * be held while accessing list. The iscsi_transport_lock must
0b9506723   Arjan van de Ven   [SCSI] turn most ...
87
   * be acquired after the rx_queue_mutex.
0896b7523   Alex Aizman   [SCSI] open-iscsi...
88
89
90
91
92
93
   */
  static LIST_HEAD(iscsi_transports);
  static DEFINE_SPINLOCK(iscsi_transport_lock);
  
  #define to_iscsi_internal(tmpl) \
  	container_of(tmpl, struct iscsi_internal, t)
ee959b00c   Tony Jones   SCSI: convert str...
94
95
  #define dev_to_iscsi_internal(_dev) \
  	container_of(_dev, struct iscsi_internal, dev)
0896b7523   Alex Aizman   [SCSI] open-iscsi...
96

ee959b00c   Tony Jones   SCSI: convert str...
97
  static void iscsi_transport_release(struct device *dev)
0896b7523   Alex Aizman   [SCSI] open-iscsi...
98
  {
ee959b00c   Tony Jones   SCSI: convert str...
99
  	struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
100
101
  	kfree(priv);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102

0896b7523   Alex Aizman   [SCSI] open-iscsi...
103
104
105
106
107
108
  /*
   * iscsi_transport_class represents the iscsi_transports that are
   * registered.
   */
  static struct class iscsi_transport_class = {
  	.name = "iscsi_transport",
ee959b00c   Tony Jones   SCSI: convert str...
109
  	.dev_release = iscsi_transport_release,
0896b7523   Alex Aizman   [SCSI] open-iscsi...
110
111
112
  };
  
  static ssize_t
ee959b00c   Tony Jones   SCSI: convert str...
113
114
  show_transport_handle(struct device *dev, struct device_attribute *attr,
  		      char *buf)
0896b7523   Alex Aizman   [SCSI] open-iscsi...
115
  {
ee959b00c   Tony Jones   SCSI: convert str...
116
  	struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
762e2bfac   Mike Christie   [SCSI] iscsi: add...
117
118
  	return sprintf(buf, "%llu
  ", (unsigned long long)iscsi_handle(priv->iscsi_transport));
0896b7523   Alex Aizman   [SCSI] open-iscsi...
119
  }
ee959b00c   Tony Jones   SCSI: convert str...
120
  static DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
121
122
123
  
  #define show_transport_attr(name, format)				\
  static ssize_t								\
ee959b00c   Tony Jones   SCSI: convert str...
124
125
  show_transport_##name(struct device *dev, 				\
  		      struct device_attribute *attr,char *buf)		\
0896b7523   Alex Aizman   [SCSI] open-iscsi...
126
  {									\
ee959b00c   Tony Jones   SCSI: convert str...
127
  	struct iscsi_internal *priv = dev_to_iscsi_internal(dev);	\
0896b7523   Alex Aizman   [SCSI] open-iscsi...
128
129
130
  	return sprintf(buf, format"
  ", priv->iscsi_transport->name);	\
  }									\
ee959b00c   Tony Jones   SCSI: convert str...
131
  static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
132
133
  
  show_transport_attr(caps, "0x%x");
0896b7523   Alex Aizman   [SCSI] open-iscsi...
134
135
  
  static struct attribute *iscsi_transport_attrs[] = {
ee959b00c   Tony Jones   SCSI: convert str...
136
137
  	&dev_attr_handle.attr,
  	&dev_attr_caps.attr,
0896b7523   Alex Aizman   [SCSI] open-iscsi...
138
139
140
141
142
143
  	NULL,
  };
  
  static struct attribute_group iscsi_transport_group = {
  	.attrs = iscsi_transport_attrs,
  };
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
  /*
   * iSCSI endpoint attrs
   */
  #define iscsi_dev_to_endpoint(_dev) \
  	container_of(_dev, struct iscsi_endpoint, dev)
  
  #define ISCSI_ATTR(_prefix,_name,_mode,_show,_store)	\
  struct device_attribute dev_attr_##_prefix##_##_name =	\
          __ATTR(_name,_mode,_show,_store)
  
  static void iscsi_endpoint_release(struct device *dev)
  {
  	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
  	kfree(ep);
  }
  
  static struct class iscsi_endpoint_class = {
  	.name = "iscsi_endpoint",
  	.dev_release = iscsi_endpoint_release,
  };
  
  static ssize_t
  show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf)
  {
  	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
21536062d   Mike Christie   [SCSI] iscsi clas...
169
170
  	return sprintf(buf, "%llu
  ", (unsigned long long) ep->id);
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
  }
  static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);
  
  static struct attribute *iscsi_endpoint_attrs[] = {
  	&dev_attr_ep_handle.attr,
  	NULL,
  };
  
  static struct attribute_group iscsi_endpoint_group = {
  	.attrs = iscsi_endpoint_attrs,
  };
  
  #define ISCSI_MAX_EPID -1
  
  static int iscsi_match_epid(struct device *dev, void *data)
  {
  	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
21536062d   Mike Christie   [SCSI] iscsi clas...
188
  	uint64_t *epid = (uint64_t *) data;
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
189
190
191
192
193
194
195
196
197
  
  	return *epid == ep->id;
  }
  
  struct iscsi_endpoint *
  iscsi_create_endpoint(int dd_size)
  {
  	struct device *dev;
  	struct iscsi_endpoint *ep;
21536062d   Mike Christie   [SCSI] iscsi clas...
198
  	uint64_t id;
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
199
200
201
  	int err;
  
  	for (id = 1; id < ISCSI_MAX_EPID; id++) {
695794ae0   Greg Kroah-Hartman   Driver Core: add ...
202
  		dev = class_find_device(&iscsi_endpoint_class, NULL, &id,
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
  					iscsi_match_epid);
  		if (!dev)
  			break;
  	}
  	if (id == ISCSI_MAX_EPID) {
  		printk(KERN_ERR "Too many connections. Max supported %u
  ",
  		       ISCSI_MAX_EPID - 1);
  		return NULL;
  	}
  
  	ep = kzalloc(sizeof(*ep) + dd_size, GFP_KERNEL);
  	if (!ep)
  		return NULL;
  
  	ep->id = id;
  	ep->dev.class = &iscsi_endpoint_class;
71610f55f   Kay Sievers   [SCSI] struct dev...
220
  	dev_set_name(&ep->dev, "ep-%llu", (unsigned long long) id);
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
  	err = device_register(&ep->dev);
          if (err)
                  goto free_ep;
  
  	err = sysfs_create_group(&ep->dev.kobj, &iscsi_endpoint_group);
  	if (err)
  		goto unregister_dev;
  
  	if (dd_size)
  		ep->dd_data = &ep[1];
  	return ep;
  
  unregister_dev:
  	device_unregister(&ep->dev);
  	return NULL;
  
  free_ep:
  	kfree(ep);
  	return NULL;
  }
  EXPORT_SYMBOL_GPL(iscsi_create_endpoint);
  
  void iscsi_destroy_endpoint(struct iscsi_endpoint *ep)
  {
  	sysfs_remove_group(&ep->dev.kobj, &iscsi_endpoint_group);
  	device_unregister(&ep->dev);
  }
  EXPORT_SYMBOL_GPL(iscsi_destroy_endpoint);
  
  struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
  {
f80f868ec   Mike Christie   [SCSI] iscsi clas...
252
  	struct iscsi_endpoint *ep;
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
253
  	struct device *dev;
695794ae0   Greg Kroah-Hartman   Driver Core: add ...
254
  	dev = class_find_device(&iscsi_endpoint_class, NULL, &handle,
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
255
256
257
  				iscsi_match_epid);
  	if (!dev)
  		return NULL;
f80f868ec   Mike Christie   [SCSI] iscsi clas...
258
259
260
261
262
263
264
  	ep = iscsi_dev_to_endpoint(dev);
  	/*
  	 * we can drop this now because the interface will prevent
  	 * removals and lookups from racing.
  	 */
  	put_device(dev);
  	return ep;
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
265
266
  }
  EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
8d07913db   Mike Christie   [SCSI] iscsi clas...
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
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
  /*
   * Interface to display network param to sysfs
   */
  
  static void iscsi_iface_release(struct device *dev)
  {
  	struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
  	struct device *parent = iface->dev.parent;
  
  	kfree(iface);
  	put_device(parent);
  }
  
  
  static struct class iscsi_iface_class = {
  	.name = "iscsi_iface",
  	.dev_release = iscsi_iface_release,
  };
  
  #define ISCSI_IFACE_ATTR(_prefix, _name, _mode, _show, _store)	\
  struct device_attribute dev_attr_##_prefix##_##_name =		\
  	__ATTR(_name, _mode, _show, _store)
  
  /* iface attrs show */
  #define iscsi_iface_attr_show(type, name, param_type, param)		\
  static ssize_t								\
  show_##type##_##name(struct device *dev, struct device_attribute *attr,	\
  		     char *buf)						\
  {									\
  	struct iscsi_iface *iface = iscsi_dev_to_iface(dev);		\
  	struct iscsi_transport *t = iface->transport;			\
  	return t->get_iface_param(iface, param_type, param, buf);	\
  }									\
  
  #define iscsi_iface_net_attr(type, name, param)				\
  	iscsi_iface_attr_show(type, name, ISCSI_NET_PARAM, param)	\
  static ISCSI_IFACE_ATTR(type, name, S_IRUGO, show_##type##_##name, NULL);
  
  /* generic read only ipvi4 attribute */
  iscsi_iface_net_attr(ipv4_iface, ipaddress, ISCSI_NET_PARAM_IPV4_ADDR);
  iscsi_iface_net_attr(ipv4_iface, gateway, ISCSI_NET_PARAM_IPV4_GW);
  iscsi_iface_net_attr(ipv4_iface, subnet, ISCSI_NET_PARAM_IPV4_SUBNET);
  iscsi_iface_net_attr(ipv4_iface, bootproto, ISCSI_NET_PARAM_IPV4_BOOTPROTO);
  
  /* generic read only ipv6 attribute */
  iscsi_iface_net_attr(ipv6_iface, ipaddress, ISCSI_NET_PARAM_IPV6_ADDR);
  iscsi_iface_net_attr(ipv6_iface, link_local_addr, ISCSI_NET_PARAM_IPV6_LINKLOCAL);
  iscsi_iface_net_attr(ipv6_iface, router_addr, ISCSI_NET_PARAM_IPV6_ROUTER);
  iscsi_iface_net_attr(ipv6_iface, ipaddr_autocfg,
  		     ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG);
88f4f5170   Mike Christie   [SCSI] iscsi clas...
317
  iscsi_iface_net_attr(ipv6_iface, link_local_autocfg,
8d07913db   Mike Christie   [SCSI] iscsi clas...
318
319
320
321
  		     ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG);
  
  /* common read only iface attribute */
  iscsi_iface_net_attr(iface, enabled, ISCSI_NET_PARAM_IFACE_ENABLE);
2d63673b4   Mike Christie   [SCSI] iscsi clas...
322
  iscsi_iface_net_attr(iface, vlan_id, ISCSI_NET_PARAM_VLAN_ID);
4223b9e91   Mike Christie   [SCSI] iscsi clas...
323
324
  iscsi_iface_net_attr(iface, vlan_priority, ISCSI_NET_PARAM_VLAN_PRIORITY);
  iscsi_iface_net_attr(iface, vlan_enabled, ISCSI_NET_PARAM_VLAN_ENABLED);
8c7d40fb6   Vikas Chaudhary   [SCSI] scsi_trans...
325
  iscsi_iface_net_attr(iface, mtu, ISCSI_NET_PARAM_MTU);
fcb5124e0   Vikas Chaudhary   [SCSI] scsi_trans...
326
  iscsi_iface_net_attr(iface, port, ISCSI_NET_PARAM_PORT);
8d07913db   Mike Christie   [SCSI] iscsi clas...
327

587a1f165   Al Viro   switch ->is_visib...
328
  static umode_t iscsi_iface_attr_is_visible(struct kobject *kobj,
8d07913db   Mike Christie   [SCSI] iscsi clas...
329
330
331
332
333
  					  struct attribute *attr, int i)
  {
  	struct device *dev = container_of(kobj, struct device, kobj);
  	struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
  	struct iscsi_transport *t = iface->transport;
b78dbba00   Mike Christie   [SCSI] iscsi clas...
334
  	int param;
8d07913db   Mike Christie   [SCSI] iscsi clas...
335
336
  
  	if (attr == &dev_attr_iface_enabled.attr)
b78dbba00   Mike Christie   [SCSI] iscsi clas...
337
  		param = ISCSI_NET_PARAM_IFACE_ENABLE;
2d63673b4   Mike Christie   [SCSI] iscsi clas...
338
  	else if (attr == &dev_attr_iface_vlan_id.attr)
b78dbba00   Mike Christie   [SCSI] iscsi clas...
339
  		param = ISCSI_NET_PARAM_VLAN_ID;
4223b9e91   Mike Christie   [SCSI] iscsi clas...
340
341
342
343
  	else if (attr == &dev_attr_iface_vlan_priority.attr)
  		param = ISCSI_NET_PARAM_VLAN_PRIORITY;
  	else if (attr == &dev_attr_iface_vlan_enabled.attr)
  		param = ISCSI_NET_PARAM_VLAN_ENABLED;
8c7d40fb6   Vikas Chaudhary   [SCSI] scsi_trans...
344
345
  	else if (attr == &dev_attr_iface_mtu.attr)
  		param = ISCSI_NET_PARAM_MTU;
fcb5124e0   Vikas Chaudhary   [SCSI] scsi_trans...
346
347
  	else if (attr == &dev_attr_iface_port.attr)
  		param = ISCSI_NET_PARAM_PORT;
b78dbba00   Mike Christie   [SCSI] iscsi clas...
348
  	else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {
8d07913db   Mike Christie   [SCSI] iscsi clas...
349
  		if (attr == &dev_attr_ipv4_iface_ipaddress.attr)
b78dbba00   Mike Christie   [SCSI] iscsi clas...
350
  			param = ISCSI_NET_PARAM_IPV4_ADDR;
8d07913db   Mike Christie   [SCSI] iscsi clas...
351
  		else if (attr == &dev_attr_ipv4_iface_gateway.attr)
b78dbba00   Mike Christie   [SCSI] iscsi clas...
352
  			param = ISCSI_NET_PARAM_IPV4_GW;
8d07913db   Mike Christie   [SCSI] iscsi clas...
353
  		else if (attr == &dev_attr_ipv4_iface_subnet.attr)
b78dbba00   Mike Christie   [SCSI] iscsi clas...
354
  			param = ISCSI_NET_PARAM_IPV4_SUBNET;
8d07913db   Mike Christie   [SCSI] iscsi clas...
355
  		else if (attr == &dev_attr_ipv4_iface_bootproto.attr)
b78dbba00   Mike Christie   [SCSI] iscsi clas...
356
357
358
  			param = ISCSI_NET_PARAM_IPV4_BOOTPROTO;
  		else
  			return 0;
8d07913db   Mike Christie   [SCSI] iscsi clas...
359
360
  	} else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) {
  		if (attr == &dev_attr_ipv6_iface_ipaddress.attr)
b78dbba00   Mike Christie   [SCSI] iscsi clas...
361
  			param = ISCSI_NET_PARAM_IPV6_ADDR;
8d07913db   Mike Christie   [SCSI] iscsi clas...
362
  		else if (attr == &dev_attr_ipv6_iface_link_local_addr.attr)
b78dbba00   Mike Christie   [SCSI] iscsi clas...
363
  			param = ISCSI_NET_PARAM_IPV6_LINKLOCAL;
8d07913db   Mike Christie   [SCSI] iscsi clas...
364
  		else if (attr == &dev_attr_ipv6_iface_router_addr.attr)
b78dbba00   Mike Christie   [SCSI] iscsi clas...
365
  			param = ISCSI_NET_PARAM_IPV6_ROUTER;
8d07913db   Mike Christie   [SCSI] iscsi clas...
366
  		else if (attr == &dev_attr_ipv6_iface_ipaddr_autocfg.attr)
b78dbba00   Mike Christie   [SCSI] iscsi clas...
367
  			param = ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG;
88f4f5170   Mike Christie   [SCSI] iscsi clas...
368
  		else if (attr == &dev_attr_ipv6_iface_link_local_autocfg.attr)
b78dbba00   Mike Christie   [SCSI] iscsi clas...
369
370
371
372
373
374
  			param = ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG;
  		else
  			return 0;
  	} else {
  		WARN_ONCE(1, "Invalid iface attr");
  		return 0;
8d07913db   Mike Christie   [SCSI] iscsi clas...
375
  	}
b78dbba00   Mike Christie   [SCSI] iscsi clas...
376
  	return t->attr_is_visible(ISCSI_NET_PARAM, param);
8d07913db   Mike Christie   [SCSI] iscsi clas...
377
378
379
380
  }
  
  static struct attribute *iscsi_iface_attrs[] = {
  	&dev_attr_iface_enabled.attr,
2d63673b4   Mike Christie   [SCSI] iscsi clas...
381
  	&dev_attr_iface_vlan_id.attr,
4223b9e91   Mike Christie   [SCSI] iscsi clas...
382
383
  	&dev_attr_iface_vlan_priority.attr,
  	&dev_attr_iface_vlan_enabled.attr,
8d07913db   Mike Christie   [SCSI] iscsi clas...
384
385
386
387
388
389
390
391
  	&dev_attr_ipv4_iface_ipaddress.attr,
  	&dev_attr_ipv4_iface_gateway.attr,
  	&dev_attr_ipv4_iface_subnet.attr,
  	&dev_attr_ipv4_iface_bootproto.attr,
  	&dev_attr_ipv6_iface_ipaddress.attr,
  	&dev_attr_ipv6_iface_link_local_addr.attr,
  	&dev_attr_ipv6_iface_router_addr.attr,
  	&dev_attr_ipv6_iface_ipaddr_autocfg.attr,
88f4f5170   Mike Christie   [SCSI] iscsi clas...
392
  	&dev_attr_ipv6_iface_link_local_autocfg.attr,
8c7d40fb6   Vikas Chaudhary   [SCSI] scsi_trans...
393
  	&dev_attr_iface_mtu.attr,
fcb5124e0   Vikas Chaudhary   [SCSI] scsi_trans...
394
  	&dev_attr_iface_port.attr,
8d07913db   Mike Christie   [SCSI] iscsi clas...
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
  	NULL,
  };
  
  static struct attribute_group iscsi_iface_group = {
  	.attrs = iscsi_iface_attrs,
  	.is_visible = iscsi_iface_attr_is_visible,
  };
  
  struct iscsi_iface *
  iscsi_create_iface(struct Scsi_Host *shost, struct iscsi_transport *transport,
  		   uint32_t iface_type, uint32_t iface_num, int dd_size)
  {
  	struct iscsi_iface *iface;
  	int err;
  
  	iface = kzalloc(sizeof(*iface) + dd_size, GFP_KERNEL);
  	if (!iface)
  		return NULL;
  
  	iface->transport = transport;
  	iface->iface_type = iface_type;
  	iface->iface_num = iface_num;
  	iface->dev.release = iscsi_iface_release;
  	iface->dev.class = &iscsi_iface_class;
  	/* parent reference released in iscsi_iface_release */
  	iface->dev.parent = get_device(&shost->shost_gendev);
  	if (iface_type == ISCSI_IFACE_TYPE_IPV4)
  		dev_set_name(&iface->dev, "ipv4-iface-%u-%u", shost->host_no,
  			     iface_num);
  	else
  		dev_set_name(&iface->dev, "ipv6-iface-%u-%u", shost->host_no,
  			     iface_num);
  
  	err = device_register(&iface->dev);
  	if (err)
  		goto free_iface;
  
  	err = sysfs_create_group(&iface->dev.kobj, &iscsi_iface_group);
  	if (err)
  		goto unreg_iface;
  
  	if (dd_size)
  		iface->dd_data = &iface[1];
  	return iface;
  
  unreg_iface:
  	device_unregister(&iface->dev);
  	return NULL;
  
  free_iface:
  	put_device(iface->dev.parent);
  	kfree(iface);
  	return NULL;
  }
  EXPORT_SYMBOL_GPL(iscsi_create_iface);
  
  void iscsi_destroy_iface(struct iscsi_iface *iface)
  {
  	sysfs_remove_group(&iface->dev.kobj, &iscsi_iface_group);
  	device_unregister(&iface->dev);
  }
  EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
90eeb01a0   Mike Christie   [SCSI] iscsi clas...
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
  /*
   * BSG support
   */
  /**
   * iscsi_bsg_host_dispatch - Dispatch command to LLD.
   * @job: bsg job to be processed
   */
  static int iscsi_bsg_host_dispatch(struct bsg_job *job)
  {
  	struct Scsi_Host *shost = iscsi_job_to_shost(job);
  	struct iscsi_bsg_request *req = job->request;
  	struct iscsi_bsg_reply *reply = job->reply;
  	struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
  	int cmdlen = sizeof(uint32_t);	/* start with length of msgcode */
  	int ret;
  
  	/* check if we have the msgcode value at least */
  	if (job->request_len < sizeof(uint32_t)) {
  		ret = -ENOMSG;
  		goto fail_host_msg;
  	}
  
  	/* Validate the host command */
  	switch (req->msgcode) {
  	case ISCSI_BSG_HST_VENDOR:
  		cmdlen += sizeof(struct iscsi_bsg_host_vendor);
  		if ((shost->hostt->vendor_id == 0L) ||
  		    (req->rqst_data.h_vendor.vendor_id !=
  			shost->hostt->vendor_id)) {
  			ret = -ESRCH;
  			goto fail_host_msg;
  		}
  		break;
  	default:
  		ret = -EBADR;
  		goto fail_host_msg;
  	}
  
  	/* check if we really have all the request data needed */
  	if (job->request_len < cmdlen) {
  		ret = -ENOMSG;
  		goto fail_host_msg;
  	}
  
  	ret = i->iscsi_transport->bsg_request(job);
  	if (!ret)
  		return 0;
  
  fail_host_msg:
  	/* return the errno failure code as the only status */
  	BUG_ON(job->reply_len < sizeof(uint32_t));
  	reply->reply_payload_rcv_len = 0;
  	reply->result = ret;
  	job->reply_len = sizeof(uint32_t);
  	bsg_job_done(job, ret, 0);
  	return 0;
  }
  
  /**
   * iscsi_bsg_host_add - Create and add the bsg hooks to receive requests
   * @shost: shost for iscsi_host
eae627e4b   Marcos Paulo de Souza   [SCSI] scsi_trans...
518
   * @ihost: iscsi_cls_host adding the structures to
90eeb01a0   Mike Christie   [SCSI] iscsi clas...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
   */
  static int
  iscsi_bsg_host_add(struct Scsi_Host *shost, struct iscsi_cls_host *ihost)
  {
  	struct device *dev = &shost->shost_gendev;
  	struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
  	struct request_queue *q;
  	char bsg_name[20];
  	int ret;
  
  	if (!i->iscsi_transport->bsg_request)
  		return -ENOTSUPP;
  
  	snprintf(bsg_name, sizeof(bsg_name), "iscsi_host%d", shost->host_no);
  
  	q = __scsi_alloc_queue(shost, bsg_request_fn);
  	if (!q)
  		return -ENOMEM;
  
  	ret = bsg_setup_queue(dev, q, bsg_name, iscsi_bsg_host_dispatch, 0);
  	if (ret) {
  		shost_printk(KERN_ERR, shost, "bsg interface failed to "
  			     "initialize - no request queue
  ");
  		blk_cleanup_queue(q);
  		return ret;
  	}
  
  	ihost->bsg_q = q;
  	return 0;
  }
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
550
  static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
ee959b00c   Tony Jones   SCSI: convert str...
551
  			    struct device *cdev)
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
552
553
  {
  	struct Scsi_Host *shost = dev_to_shost(dev);
32c6e1b9a   Mike Christie   [SCSI] iscsi clas...
554
  	struct iscsi_cls_host *ihost = shost->shost_data;
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
555
556
  
  	memset(ihost, 0, sizeof(*ihost));
8aae18adb   Mike Christie   [SCSI] iscsi clas...
557
  	atomic_set(&ihost->nr_scans, 0);
7970634b8   Mike Christie   [SCSI] iscsi clas...
558
  	mutex_init(&ihost->mutex);
90eeb01a0   Mike Christie   [SCSI] iscsi clas...
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
  
  	iscsi_bsg_host_add(shost, ihost);
  	/* ignore any bsg add error - we just can't do sgio */
  
  	return 0;
  }
  
  static int iscsi_remove_host(struct transport_container *tc,
  			     struct device *dev, struct device *cdev)
  {
  	struct Scsi_Host *shost = dev_to_shost(dev);
  	struct iscsi_cls_host *ihost = shost->shost_data;
  
  	if (ihost->bsg_q) {
  		bsg_remove_queue(ihost->bsg_q);
  		blk_cleanup_queue(ihost->bsg_q);
  	}
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
576
577
578
579
580
581
  	return 0;
  }
  
  static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
  			       "iscsi_host",
  			       iscsi_setup_host,
90eeb01a0   Mike Christie   [SCSI] iscsi clas...
582
  			       iscsi_remove_host,
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
583
  			       NULL);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
584
585
  static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
  			       "iscsi_session",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
587
588
  			       NULL,
  			       NULL,
  			       NULL);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
589
590
  static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
  			       "iscsi_connection",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591
592
593
  			       NULL,
  			       NULL,
  			       NULL);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
594
595
  
  static struct sock *nls;
0b9506723   Arjan van de Ven   [SCSI] turn most ...
596
  static DEFINE_MUTEX(rx_queue_mutex);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
597

7b7232f3f   Mike Christie   [SCSI] iscsi upda...
598
599
  static LIST_HEAD(sesslist);
  static DEFINE_SPINLOCK(sesslock);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
600
601
  static LIST_HEAD(connlist);
  static DEFINE_SPINLOCK(connlock);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
602

b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
603
604
605
606
607
608
609
610
611
612
  static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn)
  {
  	struct iscsi_cls_session *sess = iscsi_dev_to_session(conn->dev.parent);
  	return sess->sid;
  }
  
  /*
   * Returns the matching session to a given sid
   */
  static struct iscsi_cls_session *iscsi_session_lookup(uint32_t sid)
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
613
614
615
616
617
618
  {
  	unsigned long flags;
  	struct iscsi_cls_session *sess;
  
  	spin_lock_irqsave(&sesslock, flags);
  	list_for_each_entry(sess, &sesslist, sess_list) {
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
619
  		if (sess->sid == sid) {
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
620
621
622
623
624
625
626
  			spin_unlock_irqrestore(&sesslock, flags);
  			return sess;
  		}
  	}
  	spin_unlock_irqrestore(&sesslock, flags);
  	return NULL;
  }
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
627
628
629
630
  /*
   * Returns the matching connection to a given sid / cid tuple
   */
  static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid)
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
631
632
633
634
635
636
  {
  	unsigned long flags;
  	struct iscsi_cls_conn *conn;
  
  	spin_lock_irqsave(&connlock, flags);
  	list_for_each_entry(conn, &connlist, conn_list) {
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
637
  		if ((conn->cid == cid) && (iscsi_conn_get_sid(conn) == sid)) {
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
638
639
640
641
642
643
644
  			spin_unlock_irqrestore(&connlock, flags);
  			return conn;
  		}
  	}
  	spin_unlock_irqrestore(&connlock, flags);
  	return NULL;
  }
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
645
646
647
648
  /*
   * The following functions can be used by LLDs that allocate
   * their own scsi_hosts or by software iscsi LLDs
   */
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
649
650
651
652
653
654
655
656
  static struct {
  	int value;
  	char *name;
  } iscsi_session_state_names[] = {
  	{ ISCSI_SESSION_LOGGED_IN,	"LOGGED_IN" },
  	{ ISCSI_SESSION_FAILED,		"FAILED" },
  	{ ISCSI_SESSION_FREE,		"FREE" },
  };
3b0f208a5   Adrian Bunk   [SCSI] iscsi tran...
657
  static const char *iscsi_session_state_name(int state)
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
  {
  	int i;
  	char *name = NULL;
  
  	for (i = 0; i < ARRAY_SIZE(iscsi_session_state_names); i++) {
  		if (iscsi_session_state_names[i].value == state) {
  			name = iscsi_session_state_names[i].name;
  			break;
  		}
  	}
  	return name;
  }
  
  int iscsi_session_chkready(struct iscsi_cls_session *session)
  {
  	unsigned long flags;
  	int err;
  
  	spin_lock_irqsave(&session->lock, flags);
  	switch (session->state) {
  	case ISCSI_SESSION_LOGGED_IN:
  		err = 0;
  		break;
  	case ISCSI_SESSION_FAILED:
9a1a69a1f   Andrew Vasquez   [SCSI] fc-transpo...
682
  		err = DID_IMM_RETRY << 16;
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
683
684
  		break;
  	case ISCSI_SESSION_FREE:
56d7fcfa8   Mike Christie   [SCSI] iscsi clas...
685
  		err = DID_TRANSPORT_FAILFAST << 16;
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
686
687
688
689
690
691
692
693
694
  		break;
  	default:
  		err = DID_NO_CONNECT << 16;
  		break;
  	}
  	spin_unlock_irqrestore(&session->lock, flags);
  	return err;
  }
  EXPORT_SYMBOL_GPL(iscsi_session_chkready);
17fa575ee   Manish Rangankar   [SCSI] scsi_trans...
695
696
697
698
699
700
701
702
703
704
705
706
  int iscsi_is_session_online(struct iscsi_cls_session *session)
  {
  	unsigned long flags;
  	int ret = 0;
  
  	spin_lock_irqsave(&session->lock, flags);
  	if (session->state == ISCSI_SESSION_LOGGED_IN)
  		ret = 1;
  	spin_unlock_irqrestore(&session->lock, flags);
  	return ret;
  }
  EXPORT_SYMBOL_GPL(iscsi_is_session_online);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
707
708
709
  static void iscsi_session_release(struct device *dev)
  {
  	struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
710
  	struct Scsi_Host *shost;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
711

7b8631b53   Mike Christie   [SCSI] iscsi: sep...
712
713
  	shost = iscsi_session_to_shost(session);
  	scsi_host_put(shost);
632248aab   Mike Christie   [SCSI] iscsi clas...
714
715
  	ISCSI_DBG_TRANS_SESSION(session, "Completing session release
  ");
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
716
  	kfree(session);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
717
  }
0896b7523   Alex Aizman   [SCSI] open-iscsi...
718

7b8631b53   Mike Christie   [SCSI] iscsi: sep...
719
720
721
722
  static int iscsi_is_session_dev(const struct device *dev)
  {
  	return dev->release == iscsi_session_release;
  }
0896b7523   Alex Aizman   [SCSI] open-iscsi...
723

a4804cd6e   Mike Christie   [SCSI] iscsi: add...
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
  static int iscsi_iter_session_fn(struct device *dev, void *data)
  {
  	void (* fn) (struct iscsi_cls_session *) = data;
  
  	if (!iscsi_is_session_dev(dev))
  		return 0;
  	fn(iscsi_dev_to_session(dev));
  	return 0;
  }
  
  void iscsi_host_for_each_session(struct Scsi_Host *shost,
  				 void (*fn)(struct iscsi_cls_session *))
  {
  	device_for_each_child(&shost->shost_gendev, fn,
  			      iscsi_iter_session_fn);
  }
  EXPORT_SYMBOL_GPL(iscsi_host_for_each_session);
8aae18adb   Mike Christie   [SCSI] iscsi clas...
741
742
743
744
745
746
747
748
749
750
  /**
   * iscsi_scan_finished - helper to report when running scans are done
   * @shost: scsi host
   * @time: scan run time
   *
   * This function can be used by drives like qla4xxx to report to the scsi
   * layer when the scans it kicked off at module load time are done.
   */
  int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time)
  {
32c6e1b9a   Mike Christie   [SCSI] iscsi clas...
751
  	struct iscsi_cls_host *ihost = shost->shost_data;
8aae18adb   Mike Christie   [SCSI] iscsi clas...
752
753
754
755
756
757
758
  	/*
  	 * qla4xxx will have kicked off some session unblocks before calling
  	 * scsi_scan_host, so just wait for them to complete.
  	 */
  	return !atomic_read(&ihost->nr_scans);
  }
  EXPORT_SYMBOL_GPL(iscsi_scan_finished);
7970634b8   Mike Christie   [SCSI] iscsi clas...
759
760
761
762
763
764
765
  struct iscsi_scan_data {
  	unsigned int channel;
  	unsigned int id;
  	unsigned int lun;
  };
  
  static int iscsi_user_scan_session(struct device *dev, void *data)
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
766
  {
7970634b8   Mike Christie   [SCSI] iscsi clas...
767
  	struct iscsi_scan_data *scan_data = data;
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
768
  	struct iscsi_cls_session *session;
7970634b8   Mike Christie   [SCSI] iscsi clas...
769
770
771
772
773
774
775
776
777
  	struct Scsi_Host *shost;
  	struct iscsi_cls_host *ihost;
  	unsigned long flags;
  	unsigned int id;
  
  	if (!iscsi_is_session_dev(dev))
  		return 0;
  
  	session = iscsi_dev_to_session(dev);
632248aab   Mike Christie   [SCSI] iscsi clas...
778
779
780
  
  	ISCSI_DBG_TRANS_SESSION(session, "Scanning session
  ");
7970634b8   Mike Christie   [SCSI] iscsi clas...
781
782
  	shost = iscsi_session_to_shost(session);
  	ihost = shost->shost_data;
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
783
784
  
  	mutex_lock(&ihost->mutex);
7970634b8   Mike Christie   [SCSI] iscsi clas...
785
786
787
  	spin_lock_irqsave(&session->lock, flags);
  	if (session->state != ISCSI_SESSION_LOGGED_IN) {
  		spin_unlock_irqrestore(&session->lock, flags);
632248aab   Mike Christie   [SCSI] iscsi clas...
788
  		goto user_scan_exit;
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
789
  	}
7970634b8   Mike Christie   [SCSI] iscsi clas...
790
791
  	id = session->target_id;
  	spin_unlock_irqrestore(&session->lock, flags);
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
792

7970634b8   Mike Christie   [SCSI] iscsi clas...
793
794
795
796
797
798
799
800
  	if (id != ISCSI_MAX_TARGET) {
  		if ((scan_data->channel == SCAN_WILD_CARD ||
  		     scan_data->channel == 0) &&
  		    (scan_data->id == SCAN_WILD_CARD ||
  		     scan_data->id == id))
  			scsi_scan_target(&session->dev, 0, id,
  					 scan_data->lun, 1);
  	}
632248aab   Mike Christie   [SCSI] iscsi clas...
801
802
  
  user_scan_exit:
7970634b8   Mike Christie   [SCSI] iscsi clas...
803
  	mutex_unlock(&ihost->mutex);
632248aab   Mike Christie   [SCSI] iscsi clas...
804
805
  	ISCSI_DBG_TRANS_SESSION(session, "Completed session scan
  ");
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
806
807
  	return 0;
  }
7970634b8   Mike Christie   [SCSI] iscsi clas...
808
809
810
811
812
813
814
815
816
817
818
819
  static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
  			   uint id, uint lun)
  {
  	struct iscsi_scan_data scan_data;
  
  	scan_data.channel = channel;
  	scan_data.id = id;
  	scan_data.lun = lun;
  
  	return device_for_each_child(&shost->shost_gendev, &scan_data,
  				     iscsi_user_scan_session);
  }
bd976f62c   Mike Christie   [SCSI] iscsi clas...
820
821
822
823
  static void iscsi_scan_session(struct work_struct *work)
  {
  	struct iscsi_cls_session *session =
  			container_of(work, struct iscsi_cls_session, scan_work);
8aae18adb   Mike Christie   [SCSI] iscsi clas...
824
  	struct Scsi_Host *shost = iscsi_session_to_shost(session);
32c6e1b9a   Mike Christie   [SCSI] iscsi clas...
825
  	struct iscsi_cls_host *ihost = shost->shost_data;
7970634b8   Mike Christie   [SCSI] iscsi clas...
826
  	struct iscsi_scan_data scan_data;
bd976f62c   Mike Christie   [SCSI] iscsi clas...
827

7970634b8   Mike Christie   [SCSI] iscsi clas...
828
829
830
  	scan_data.channel = 0;
  	scan_data.id = SCAN_WILD_CARD;
  	scan_data.lun = SCAN_WILD_CARD;
bd976f62c   Mike Christie   [SCSI] iscsi clas...
831

7970634b8   Mike Christie   [SCSI] iscsi clas...
832
  	iscsi_user_scan_session(&session->dev, &scan_data);
8aae18adb   Mike Christie   [SCSI] iscsi clas...
833
  	atomic_dec(&ihost->nr_scans);
bd976f62c   Mike Christie   [SCSI] iscsi clas...
834
  }
c01be6dcb   Mike Christie   [SCSI] iscsi_tran...
835
836
  /**
   * iscsi_block_scsi_eh - block scsi eh until session state has transistioned
e6d4ef450   Randy Dunlap   [SCSI] iscsi tran...
837
   * @cmd: scsi cmd passed to scsi eh handler
c01be6dcb   Mike Christie   [SCSI] iscsi_tran...
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
   *
   * If the session is down this function will wait for the recovery
   * timer to fire or for the session to be logged back in. If the
   * recovery timer fires then FAST_IO_FAIL is returned. The caller
   * should pass this error value to the scsi eh.
   */
  int iscsi_block_scsi_eh(struct scsi_cmnd *cmd)
  {
  	struct iscsi_cls_session *session =
  			starget_to_session(scsi_target(cmd->device));
  	unsigned long flags;
  	int ret = 0;
  
  	spin_lock_irqsave(&session->lock, flags);
  	while (session->state != ISCSI_SESSION_LOGGED_IN) {
  		if (session->state == ISCSI_SESSION_FREE) {
  			ret = FAST_IO_FAIL;
  			break;
  		}
  		spin_unlock_irqrestore(&session->lock, flags);
  		msleep(1000);
  		spin_lock_irqsave(&session->lock, flags);
  	}
  	spin_unlock_irqrestore(&session->lock, flags);
  	return ret;
  }
  EXPORT_SYMBOL_GPL(iscsi_block_scsi_eh);
c4028958b   David Howells   WorkStruct: make ...
865
  static void session_recovery_timedout(struct work_struct *work)
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
866
  {
c4028958b   David Howells   WorkStruct: make ...
867
868
869
  	struct iscsi_cls_session *session =
  		container_of(work, struct iscsi_cls_session,
  			     recovery_work.work);
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
870
  	unsigned long flags;
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
871

322d739da   Mike Christie   [SCSI] iscsi: fix...
872
873
874
875
  	iscsi_cls_session_printk(KERN_INFO, session,
  				 "session recovery timed out after %d secs
  ",
  				 session->recovery_tmo);
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
876

6eabafbe6   Mike Christie   [SCSI] iscsi clas...
877
878
879
880
881
882
883
884
885
886
887
888
  	spin_lock_irqsave(&session->lock, flags);
  	switch (session->state) {
  	case ISCSI_SESSION_FAILED:
  		session->state = ISCSI_SESSION_FREE;
  		break;
  	case ISCSI_SESSION_LOGGED_IN:
  	case ISCSI_SESSION_FREE:
  		/* we raced with the unblock's flush */
  		spin_unlock_irqrestore(&session->lock, flags);
  		return;
  	}
  	spin_unlock_irqrestore(&session->lock, flags);
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
889
890
  	if (session->transport->session_recovery_timedout)
  		session->transport->session_recovery_timedout(session);
632248aab   Mike Christie   [SCSI] iscsi clas...
891
892
  	ISCSI_DBG_TRANS_SESSION(session, "Unblocking SCSI target
  ");
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
893
  	scsi_target_unblock(&session->dev);
632248aab   Mike Christie   [SCSI] iscsi clas...
894
895
  	ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking SCSI target
  ");
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
896
  }
45ab33b6c   Mike Christie   [SCSI] iscsi clas...
897
  static void __iscsi_unblock_session(struct work_struct *work)
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
898
  {
45ab33b6c   Mike Christie   [SCSI] iscsi clas...
899
900
901
  	struct iscsi_cls_session *session =
  			container_of(work, struct iscsi_cls_session,
  				     unblock_work);
bd976f62c   Mike Christie   [SCSI] iscsi clas...
902
  	struct Scsi_Host *shost = iscsi_session_to_shost(session);
32c6e1b9a   Mike Christie   [SCSI] iscsi clas...
903
  	struct iscsi_cls_host *ihost = shost->shost_data;
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
904
  	unsigned long flags;
632248aab   Mike Christie   [SCSI] iscsi clas...
905
906
  	ISCSI_DBG_TRANS_SESSION(session, "Unblocking session
  ");
45ab33b6c   Mike Christie   [SCSI] iscsi clas...
907
908
909
910
911
  	/*
  	 * The recovery and unblock work get run from the same workqueue,
  	 * so try to cancel it if it was going to run after this unblock.
  	 */
  	cancel_delayed_work(&session->recovery_work);
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
912
913
914
  	spin_lock_irqsave(&session->lock, flags);
  	session->state = ISCSI_SESSION_LOGGED_IN;
  	spin_unlock_irqrestore(&session->lock, flags);
45ab33b6c   Mike Christie   [SCSI] iscsi clas...
915
916
  	/* start IO */
  	scsi_target_unblock(&session->dev);
8aae18adb   Mike Christie   [SCSI] iscsi clas...
917
918
919
920
921
922
  	/*
  	 * Only do kernel scanning if the driver is properly hooked into
  	 * the async scanning code (drivers like iscsi_tcp do login and
  	 * scanning from userspace).
  	 */
  	if (shost->hostt->scan_finished) {
06d25af4e   Mike Christie   [SCSI] iscsi clas...
923
  		if (scsi_queue_work(shost, &session->scan_work))
8aae18adb   Mike Christie   [SCSI] iscsi clas...
924
925
  			atomic_inc(&ihost->nr_scans);
  	}
632248aab   Mike Christie   [SCSI] iscsi clas...
926
927
  	ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking session
  ");
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
928
  }
45ab33b6c   Mike Christie   [SCSI] iscsi clas...
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
  
  /**
   * iscsi_unblock_session - set a session as logged in and start IO.
   * @session: iscsi session
   *
   * Mark a session as ready to accept IO.
   */
  void iscsi_unblock_session(struct iscsi_cls_session *session)
  {
  	queue_work(iscsi_eh_timer_workq, &session->unblock_work);
  	/*
  	 * make sure all the events have completed before tell the driver
  	 * it is safe
  	 */
  	flush_workqueue(iscsi_eh_timer_workq);
  }
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
945
  EXPORT_SYMBOL_GPL(iscsi_unblock_session);
45ab33b6c   Mike Christie   [SCSI] iscsi clas...
946
  static void __iscsi_block_session(struct work_struct *work)
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
947
  {
45ab33b6c   Mike Christie   [SCSI] iscsi clas...
948
949
950
  	struct iscsi_cls_session *session =
  			container_of(work, struct iscsi_cls_session,
  				     block_work);
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
951
  	unsigned long flags;
632248aab   Mike Christie   [SCSI] iscsi clas...
952
953
  	ISCSI_DBG_TRANS_SESSION(session, "Blocking session
  ");
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
954
955
956
  	spin_lock_irqsave(&session->lock, flags);
  	session->state = ISCSI_SESSION_FAILED;
  	spin_unlock_irqrestore(&session->lock, flags);
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
957
  	scsi_target_block(&session->dev);
632248aab   Mike Christie   [SCSI] iscsi clas...
958
959
  	ISCSI_DBG_TRANS_SESSION(session, "Completed SCSI target blocking
  ");
fdd46dcbe   Mike Christie   [SCSI] iscsi clas...
960
961
962
963
  	if (session->recovery_tmo >= 0)
  		queue_delayed_work(iscsi_eh_timer_workq,
  				   &session->recovery_work,
  				   session->recovery_tmo * HZ);
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
964
  }
45ab33b6c   Mike Christie   [SCSI] iscsi clas...
965
966
967
968
969
  
  void iscsi_block_session(struct iscsi_cls_session *session)
  {
  	queue_work(iscsi_eh_timer_workq, &session->block_work);
  }
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
970
  EXPORT_SYMBOL_GPL(iscsi_block_session);
269747890   Mike Christie   [SCSI] libiscsi: ...
971
972
973
974
975
976
  static void __iscsi_unbind_session(struct work_struct *work)
  {
  	struct iscsi_cls_session *session =
  			container_of(work, struct iscsi_cls_session,
  				     unbind_work);
  	struct Scsi_Host *shost = iscsi_session_to_shost(session);
32c6e1b9a   Mike Christie   [SCSI] iscsi clas...
977
  	struct iscsi_cls_host *ihost = shost->shost_data;
7970634b8   Mike Christie   [SCSI] iscsi clas...
978
  	unsigned long flags;
8d4a690cd   Mike Christie   [SCSI] iscsi clas...
979
  	unsigned int target_id;
269747890   Mike Christie   [SCSI] libiscsi: ...
980

632248aab   Mike Christie   [SCSI] iscsi clas...
981
982
  	ISCSI_DBG_TRANS_SESSION(session, "Unbinding session
  ");
269747890   Mike Christie   [SCSI] libiscsi: ...
983
984
  	/* Prevent new scans and make sure scanning is not in progress */
  	mutex_lock(&ihost->mutex);
7970634b8   Mike Christie   [SCSI] iscsi clas...
985
986
987
  	spin_lock_irqsave(&session->lock, flags);
  	if (session->target_id == ISCSI_MAX_TARGET) {
  		spin_unlock_irqrestore(&session->lock, flags);
269747890   Mike Christie   [SCSI] libiscsi: ...
988
989
990
  		mutex_unlock(&ihost->mutex);
  		return;
  	}
8d4a690cd   Mike Christie   [SCSI] iscsi clas...
991
992
  
  	target_id = session->target_id;
7970634b8   Mike Christie   [SCSI] iscsi clas...
993
994
  	session->target_id = ISCSI_MAX_TARGET;
  	spin_unlock_irqrestore(&session->lock, flags);
269747890   Mike Christie   [SCSI] libiscsi: ...
995
  	mutex_unlock(&ihost->mutex);
8d4a690cd   Mike Christie   [SCSI] iscsi clas...
996
997
  	if (session->ida_used)
  		ida_simple_remove(&iscsi_sess_ida, target_id);
269747890   Mike Christie   [SCSI] libiscsi: ...
998
999
  	scsi_remove_target(&session->dev);
  	iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
632248aab   Mike Christie   [SCSI] iscsi clas...
1000
1001
  	ISCSI_DBG_TRANS_SESSION(session, "Completed target removal
  ");
269747890   Mike Christie   [SCSI] libiscsi: ...
1002
  }
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1003
  struct iscsi_cls_session *
5d91e209f   Mike Christie   [SCSI] iscsi: rem...
1004
1005
  iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
  		    int dd_size)
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1006
1007
  {
  	struct iscsi_cls_session *session;
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1008

5d91e209f   Mike Christie   [SCSI] iscsi: rem...
1009
  	session = kzalloc(sizeof(*session) + dd_size,
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1010
  			  GFP_KERNEL);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1011
  	if (!session)
f53a88da1   Mike Christie   [SCSI] iscsi: fix...
1012
  		return NULL;
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1013
  	session->transport = transport;
0c70d84b7   Mike Christie   [SCSI] iscsi clas...
1014
  	session->creator = -1;
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
1015
  	session->recovery_tmo = 120;
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
1016
  	session->state = ISCSI_SESSION_FREE;
c4028958b   David Howells   WorkStruct: make ...
1017
  	INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
1018
  	INIT_LIST_HEAD(&session->sess_list);
45ab33b6c   Mike Christie   [SCSI] iscsi clas...
1019
1020
  	INIT_WORK(&session->unblock_work, __iscsi_unblock_session);
  	INIT_WORK(&session->block_work, __iscsi_block_session);
269747890   Mike Christie   [SCSI] libiscsi: ...
1021
  	INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
bd976f62c   Mike Christie   [SCSI] iscsi clas...
1022
  	INIT_WORK(&session->scan_work, iscsi_scan_session);
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
1023
  	spin_lock_init(&session->lock);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1024

6a8a0d362   Mike Christie   [SCSI] iscsi: pas...
1025
1026
  	/* this is released in the dev's release function */
  	scsi_host_get(shost);
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1027
1028
1029
  	session->dev.parent = &shost->shost_gendev;
  	session->dev.release = iscsi_session_release;
  	device_initialize(&session->dev);
5d91e209f   Mike Christie   [SCSI] iscsi: rem...
1030
  	if (dd_size)
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1031
  		session->dd_data = &session[1];
632248aab   Mike Christie   [SCSI] iscsi clas...
1032
1033
1034
  
  	ISCSI_DBG_TRANS_SESSION(session, "Completed session allocation
  ");
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1035
1036
1037
  	return session;
  }
  EXPORT_SYMBOL_GPL(iscsi_alloc_session);
6a8a0d362   Mike Christie   [SCSI] iscsi: pas...
1038
  int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1039
1040
  {
  	struct Scsi_Host *shost = iscsi_session_to_shost(session);
32c6e1b9a   Mike Christie   [SCSI] iscsi clas...
1041
  	struct iscsi_cls_host *ihost;
269747890   Mike Christie   [SCSI] libiscsi: ...
1042
  	unsigned long flags;
8d4a690cd   Mike Christie   [SCSI] iscsi clas...
1043
  	int id = 0;
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1044
  	int err;
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1045

30a6c6523   Mike Christie   [SCSI] iscsi: fix...
1046
  	ihost = shost->shost_data;
41be14442   Mike Christie   [SCSI] iscsi tran...
1047
  	session->sid = atomic_add_return(1, &iscsi_session_nr);
7970634b8   Mike Christie   [SCSI] iscsi clas...
1048

8d4a690cd   Mike Christie   [SCSI] iscsi clas...
1049
1050
  	if (target_id == ISCSI_MAX_TARGET) {
  		id = ida_simple_get(&iscsi_sess_ida, 0, 0, GFP_KERNEL);
7970634b8   Mike Christie   [SCSI] iscsi clas...
1051

8d4a690cd   Mike Christie   [SCSI] iscsi clas...
1052
  		if (id < 0) {
7970634b8   Mike Christie   [SCSI] iscsi clas...
1053
  			iscsi_cls_session_printk(KERN_ERR, session,
8d4a690cd   Mike Christie   [SCSI] iscsi clas...
1054
1055
1056
  					"Failure in Target ID Allocation
  ");
  			return id;
7970634b8   Mike Christie   [SCSI] iscsi clas...
1057
  		}
8d4a690cd   Mike Christie   [SCSI] iscsi clas...
1058
1059
1060
1061
  		session->target_id = (unsigned int)id;
  		session->ida_used = true;
  	} else
  		session->target_id = target_id;
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
1062

71610f55f   Kay Sievers   [SCSI] struct dev...
1063
  	dev_set_name(&session->dev, "session%u", session->sid);
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1064
  	err = device_add(&session->dev);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1065
  	if (err) {
322d739da   Mike Christie   [SCSI] iscsi: fix...
1066
1067
1068
  		iscsi_cls_session_printk(KERN_ERR, session,
  					 "could not register session's dev
  ");
8d4a690cd   Mike Christie   [SCSI] iscsi clas...
1069
  		goto release_ida;
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1070
1071
  	}
  	transport_register_device(&session->dev);
269747890   Mike Christie   [SCSI] libiscsi: ...
1072
1073
1074
  	spin_lock_irqsave(&sesslock, flags);
  	list_add(&session->sess_list, &sesslist);
  	spin_unlock_irqrestore(&sesslock, flags);
269747890   Mike Christie   [SCSI] libiscsi: ...
1075
  	iscsi_session_event(session, ISCSI_KEVENT_CREATE_SESSION);
632248aab   Mike Christie   [SCSI] iscsi clas...
1076
1077
  	ISCSI_DBG_TRANS_SESSION(session, "Completed session adding
  ");
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1078
  	return 0;
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
1079

8d4a690cd   Mike Christie   [SCSI] iscsi clas...
1080
1081
1082
  release_ida:
  	if (session->ida_used)
  		ida_simple_remove(&iscsi_sess_ida, session->target_id);
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1083
  	return err;
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1084
  }
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1085
  EXPORT_SYMBOL_GPL(iscsi_add_session);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1086
1087
  
  /**
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1088
1089
1090
   * iscsi_create_session - create iscsi class session
   * @shost: scsi host
   * @transport: iscsi transport
5d91e209f   Mike Christie   [SCSI] iscsi: rem...
1091
   * @dd_size: private driver data size
eb44820c2   Rob Landley   [SCSI] Add Docume...
1092
   * @target_id: which target
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1093
   *
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1094
   * This can be called from a LLD or iscsi_transport.
eb44820c2   Rob Landley   [SCSI] Add Docume...
1095
   */
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1096
  struct iscsi_cls_session *
5d91e209f   Mike Christie   [SCSI] iscsi: rem...
1097
1098
  iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
  		     int dd_size, unsigned int target_id)
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1099
1100
  {
  	struct iscsi_cls_session *session;
5d91e209f   Mike Christie   [SCSI] iscsi: rem...
1101
  	session = iscsi_alloc_session(shost, transport, dd_size);
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1102
1103
  	if (!session)
  		return NULL;
6a8a0d362   Mike Christie   [SCSI] iscsi: pas...
1104
  	if (iscsi_add_session(session, target_id)) {
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1105
1106
1107
1108
1109
1110
  		iscsi_free_session(session);
  		return NULL;
  	}
  	return session;
  }
  EXPORT_SYMBOL_GPL(iscsi_create_session);
269747890   Mike Christie   [SCSI] libiscsi: ...
1111
1112
1113
1114
  static void iscsi_conn_release(struct device *dev)
  {
  	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
  	struct device *parent = conn->dev.parent;
632248aab   Mike Christie   [SCSI] iscsi clas...
1115
1116
  	ISCSI_DBG_TRANS_CONN(conn, "Releasing conn
  ");
269747890   Mike Christie   [SCSI] libiscsi: ...
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
  	kfree(conn);
  	put_device(parent);
  }
  
  static int iscsi_is_conn_dev(const struct device *dev)
  {
  	return dev->release == iscsi_conn_release;
  }
  
  static int iscsi_iter_destroy_conn_fn(struct device *dev, void *data)
  {
  	if (!iscsi_is_conn_dev(dev))
  		return 0;
  	return iscsi_destroy_conn(iscsi_dev_to_conn(dev));
  }
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1132
  void iscsi_remove_session(struct iscsi_cls_session *session)
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1133
  {
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
1134
  	struct Scsi_Host *shost = iscsi_session_to_shost(session);
269747890   Mike Christie   [SCSI] libiscsi: ...
1135
1136
  	unsigned long flags;
  	int err;
632248aab   Mike Christie   [SCSI] iscsi clas...
1137
1138
  	ISCSI_DBG_TRANS_SESSION(session, "Removing session
  ");
269747890   Mike Christie   [SCSI] libiscsi: ...
1139
1140
1141
  	spin_lock_irqsave(&sesslock, flags);
  	list_del(&session->sess_list);
  	spin_unlock_irqrestore(&sesslock, flags);
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
1142

45ab33b6c   Mike Christie   [SCSI] iscsi clas...
1143
1144
1145
1146
1147
  	/* make sure there are no blocks/unblocks queued */
  	flush_workqueue(iscsi_eh_timer_workq);
  	/* make sure the timedout callout is not running */
  	if (!cancel_delayed_work(&session->recovery_work))
  		flush_workqueue(iscsi_eh_timer_workq);
269747890   Mike Christie   [SCSI] libiscsi: ...
1148
1149
1150
  	/*
  	 * If we are blocked let commands flow again. The lld or iscsi
  	 * layer should set up the queuecommand to fail commands.
45ab33b6c   Mike Christie   [SCSI] iscsi clas...
1151
1152
  	 * We assume that LLD will not be calling block/unblock while
  	 * removing the session.
269747890   Mike Christie   [SCSI] libiscsi: ...
1153
  	 */
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
1154
1155
1156
  	spin_lock_irqsave(&session->lock, flags);
  	session->state = ISCSI_SESSION_FREE;
  	spin_unlock_irqrestore(&session->lock, flags);
bd976f62c   Mike Christie   [SCSI] iscsi clas...
1157

45ab33b6c   Mike Christie   [SCSI] iscsi clas...
1158
1159
  	scsi_target_unblock(&session->dev);
  	/* flush running scans then delete devices */
06d25af4e   Mike Christie   [SCSI] iscsi clas...
1160
  	scsi_flush_work(shost);
45ab33b6c   Mike Christie   [SCSI] iscsi clas...
1161
  	__iscsi_unbind_session(&session->unbind_work);
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
1162

269747890   Mike Christie   [SCSI] libiscsi: ...
1163
1164
1165
1166
  	/* hw iscsi may not have removed all connections from session */
  	err = device_for_each_child(&session->dev, NULL,
  				    iscsi_iter_destroy_conn_fn);
  	if (err)
322d739da   Mike Christie   [SCSI] iscsi: fix...
1167
1168
1169
1170
  		iscsi_cls_session_printk(KERN_ERR, session,
  					 "Could not delete all connections "
  					 "for session. Error %d.
  ", err);
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1171

7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1172
  	transport_unregister_device(&session->dev);
632248aab   Mike Christie   [SCSI] iscsi clas...
1173
1174
1175
  
  	ISCSI_DBG_TRANS_SESSION(session, "Completing session removal
  ");
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1176
1177
1178
1179
1180
1181
  	device_del(&session->dev);
  }
  EXPORT_SYMBOL_GPL(iscsi_remove_session);
  
  void iscsi_free_session(struct iscsi_cls_session *session)
  {
632248aab   Mike Christie   [SCSI] iscsi clas...
1182
1183
  	ISCSI_DBG_TRANS_SESSION(session, "Freeing session
  ");
269747890   Mike Christie   [SCSI] libiscsi: ...
1184
  	iscsi_session_event(session, ISCSI_KEVENT_DESTROY_SESSION);
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1185
  	put_device(&session->dev);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1186
  }
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1187
1188
1189
1190
1191
1192
1193
1194
  EXPORT_SYMBOL_GPL(iscsi_free_session);
  
  /**
   * iscsi_destroy_session - destroy iscsi session
   * @session: iscsi_session
   *
   * Can be called by a LLD or iscsi_transport. There must not be
   * any running connections.
eb44820c2   Rob Landley   [SCSI] Add Docume...
1195
   */
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1196
1197
1198
  int iscsi_destroy_session(struct iscsi_cls_session *session)
  {
  	iscsi_remove_session(session);
632248aab   Mike Christie   [SCSI] iscsi clas...
1199
1200
  	ISCSI_DBG_TRANS_SESSION(session, "Completing session destruction
  ");
8434aa8b6   Mike Christie   [SCSI] iscsi: bre...
1201
1202
1203
  	iscsi_free_session(session);
  	return 0;
  }
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1204
  EXPORT_SYMBOL_GPL(iscsi_destroy_session);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1205
1206
1207
  /**
   * iscsi_create_conn - create iscsi class connection
   * @session: iscsi cls session
5d91e209f   Mike Christie   [SCSI] iscsi: rem...
1208
   * @dd_size: private driver data size
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1209
1210
1211
1212
1213
   * @cid: connection id
   *
   * This can be called from a LLD or iscsi_transport. The connection
   * is child of the session so cid must be unique for all connections
   * on the session.
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1214
1215
1216
1217
1218
   *
   * Since we do not support MCS, cid will normally be zero. In some cases
   * for software iscsi we could be trying to preallocate a connection struct
   * in which case there could be two connection structs and cid would be
   * non-zero.
eb44820c2   Rob Landley   [SCSI] Add Docume...
1219
   */
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1220
  struct iscsi_cls_conn *
5d91e209f   Mike Christie   [SCSI] iscsi: rem...
1221
  iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1222
1223
  {
  	struct iscsi_transport *transport = session->transport;
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1224
  	struct iscsi_cls_conn *conn;
269747890   Mike Christie   [SCSI] libiscsi: ...
1225
  	unsigned long flags;
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1226
  	int err;
5d91e209f   Mike Christie   [SCSI] iscsi: rem...
1227
  	conn = kzalloc(sizeof(*conn) + dd_size, GFP_KERNEL);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1228
1229
  	if (!conn)
  		return NULL;
5d91e209f   Mike Christie   [SCSI] iscsi: rem...
1230
  	if (dd_size)
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1231
  		conn->dd_data = &conn[1];
22a39fbbf   Mike Christie   [SCSI] iscsi: fix...
1232
  	mutex_init(&conn->ep_mutex);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1233
1234
  	INIT_LIST_HEAD(&conn->conn_list);
  	conn->transport = transport;
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1235
  	conn->cid = cid;
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1236
1237
1238
  
  	/* this is released in the dev's release function */
  	if (!get_device(&session->dev))
43a145a34   Mike Christie   [SCSI] iscsi clas...
1239
  		goto free_conn;
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1240

71610f55f   Kay Sievers   [SCSI] struct dev...
1241
  	dev_set_name(&conn->dev, "connection%d:%u", session->sid, cid);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1242
1243
1244
1245
  	conn->dev.parent = &session->dev;
  	conn->dev.release = iscsi_conn_release;
  	err = device_register(&conn->dev);
  	if (err) {
322d739da   Mike Christie   [SCSI] iscsi: fix...
1246
1247
1248
  		iscsi_cls_session_printk(KERN_ERR, session, "could not "
  					 "register connection's dev
  ");
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1249
1250
1251
  		goto release_parent_ref;
  	}
  	transport_register_device(&conn->dev);
269747890   Mike Christie   [SCSI] libiscsi: ...
1252
1253
1254
  
  	spin_lock_irqsave(&connlock, flags);
  	list_add(&conn->conn_list, &connlist);
269747890   Mike Christie   [SCSI] libiscsi: ...
1255
  	spin_unlock_irqrestore(&connlock, flags);
632248aab   Mike Christie   [SCSI] iscsi clas...
1256
1257
1258
  
  	ISCSI_DBG_TRANS_CONN(conn, "Completed conn creation
  ");
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
  	return conn;
  
  release_parent_ref:
  	put_device(&session->dev);
  free_conn:
  	kfree(conn);
  	return NULL;
  }
  
  EXPORT_SYMBOL_GPL(iscsi_create_conn);
  
  /**
   * iscsi_destroy_conn - destroy iscsi class connection
eb44820c2   Rob Landley   [SCSI] Add Docume...
1272
   * @conn: iscsi cls session
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1273
   *
269747890   Mike Christie   [SCSI] libiscsi: ...
1274
   * This can be called from a LLD or iscsi_transport.
eb44820c2   Rob Landley   [SCSI] Add Docume...
1275
   */
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1276
1277
  int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
  {
269747890   Mike Christie   [SCSI] libiscsi: ...
1278
1279
1280
  	unsigned long flags;
  
  	spin_lock_irqsave(&connlock, flags);
269747890   Mike Christie   [SCSI] libiscsi: ...
1281
1282
  	list_del(&conn->conn_list);
  	spin_unlock_irqrestore(&connlock, flags);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1283
  	transport_unregister_device(&conn->dev);
632248aab   Mike Christie   [SCSI] iscsi clas...
1284
1285
  	ISCSI_DBG_TRANS_CONN(conn, "Completing conn destruction
  ");
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1286
1287
1288
  	device_unregister(&conn->dev);
  	return 0;
  }
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1289
1290
1291
  EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
  
  /*
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1292
1293
   * iscsi interface functions
   */
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
  static struct iscsi_internal *
  iscsi_if_transport_lookup(struct iscsi_transport *tt)
  {
  	struct iscsi_internal *priv;
  	unsigned long flags;
  
  	spin_lock_irqsave(&iscsi_transport_lock, flags);
  	list_for_each_entry(priv, &iscsi_transports, list) {
  		if (tt == priv->iscsi_transport) {
  			spin_unlock_irqrestore(&iscsi_transport_lock, flags);
  			return priv;
  		}
  	}
  	spin_unlock_irqrestore(&iscsi_transport_lock, flags);
  	return NULL;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1310

0896b7523   Alex Aizman   [SCSI] open-iscsi...
1311
  static int
43514774f   Michael Chan   [SCSI] iscsi clas...
1312
  iscsi_multicast_skb(struct sk_buff *skb, uint32_t group, gfp_t gfp)
53cb8a1f4   Mike Christie   [SCSI] iscsi: add...
1313
  {
43514774f   Michael Chan   [SCSI] iscsi clas...
1314
  	return nlmsg_multicast(nls, skb, 0, group, gfp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1315
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1316

7b7232f3f   Mike Christie   [SCSI] iscsi upda...
1317
  int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1318
  		   char *data, uint32_t data_size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1319
  {
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1320
1321
1322
  	struct nlmsghdr	*nlh;
  	struct sk_buff *skb;
  	struct iscsi_uevent *ev;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1323
  	char *pdu;
790f39a2d   Mike Christie   [SCSI] iscsi: sup...
1324
  	struct iscsi_internal *priv;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1325
1326
  	int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
  			      data_size);
790f39a2d   Mike Christie   [SCSI] iscsi: sup...
1327
1328
1329
  	priv = iscsi_if_transport_lookup(conn->transport);
  	if (!priv)
  		return -EINVAL;
43a145a34   Mike Christie   [SCSI] iscsi clas...
1330
  	skb = alloc_skb(len, GFP_ATOMIC);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1331
  	if (!skb) {
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
1332
  		iscsi_conn_error_event(conn, ISCSI_ERR_CONN_FAILED);
322d739da   Mike Christie   [SCSI] iscsi: fix...
1333
1334
1335
  		iscsi_cls_conn_printk(KERN_ERR, conn, "can not deliver "
  				      "control PDU: OOM
  ");
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1336
1337
  		return -ENOMEM;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1338

43514774f   Michael Chan   [SCSI] iscsi clas...
1339
  	nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1340
1341
1342
1343
  	ev = NLMSG_DATA(nlh);
  	memset(ev, 0, sizeof(*ev));
  	ev->transport_handle = iscsi_handle(conn->transport);
  	ev->type = ISCSI_KEVENT_RECV_PDU;
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1344
1345
  	ev->r.recv_req.cid = conn->cid;
  	ev->r.recv_req.sid = iscsi_conn_get_sid(conn);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1346
1347
1348
  	pdu = (char*)ev + sizeof(*ev);
  	memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
  	memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1349

43514774f   Michael Chan   [SCSI] iscsi clas...
1350
  	return iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1351
  }
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1352
  EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353

43514774f   Michael Chan   [SCSI] iscsi clas...
1354
1355
1356
1357
1358
1359
1360
1361
  int iscsi_offload_mesg(struct Scsi_Host *shost,
  		       struct iscsi_transport *transport, uint32_t type,
  		       char *data, uint16_t data_size)
  {
  	struct nlmsghdr	*nlh;
  	struct sk_buff *skb;
  	struct iscsi_uevent *ev;
  	int len = NLMSG_SPACE(sizeof(*ev) + data_size);
a541f8401   Michael Chan   iscsi: Use GFP_AT...
1362
  	skb = alloc_skb(len, GFP_ATOMIC);
43514774f   Michael Chan   [SCSI] iscsi clas...
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
  	if (!skb) {
  		printk(KERN_ERR "can not deliver iscsi offload message:OOM
  ");
  		return -ENOMEM;
  	}
  
  	nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
  	ev = NLMSG_DATA(nlh);
  	memset(ev, 0, sizeof(*ev));
  	ev->type = type;
  	ev->transport_handle = iscsi_handle(transport);
  	switch (type) {
  	case ISCSI_KEVENT_PATH_REQ:
  		ev->r.req_path.host_no = shost->host_no;
  		break;
  	case ISCSI_KEVENT_IF_DOWN:
  		ev->r.notify_if_down.host_no = shost->host_no;
  		break;
  	}
  
  	memcpy((char *)ev + sizeof(*ev), data, data_size);
a541f8401   Michael Chan   iscsi: Use GFP_AT...
1384
  	return iscsi_multicast_skb(skb, ISCSI_NL_GRP_UIP, GFP_ATOMIC);
43514774f   Michael Chan   [SCSI] iscsi clas...
1385
1386
  }
  EXPORT_SYMBOL_GPL(iscsi_offload_mesg);
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
1387
  void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1388
  {
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1389
1390
1391
  	struct nlmsghdr	*nlh;
  	struct sk_buff	*skb;
  	struct iscsi_uevent *ev;
790f39a2d   Mike Christie   [SCSI] iscsi: sup...
1392
  	struct iscsi_internal *priv;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1393
  	int len = NLMSG_SPACE(sizeof(*ev));
790f39a2d   Mike Christie   [SCSI] iscsi: sup...
1394
1395
1396
  	priv = iscsi_if_transport_lookup(conn->transport);
  	if (!priv)
  		return;
43a145a34   Mike Christie   [SCSI] iscsi clas...
1397
  	skb = alloc_skb(len, GFP_ATOMIC);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1398
  	if (!skb) {
322d739da   Mike Christie   [SCSI] iscsi: fix...
1399
1400
1401
  		iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
  				      "conn error (%d)
  ", error);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1402
1403
  		return;
  	}
43514774f   Michael Chan   [SCSI] iscsi clas...
1404
  	nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1405
1406
1407
  	ev = NLMSG_DATA(nlh);
  	ev->transport_handle = iscsi_handle(conn->transport);
  	ev->type = ISCSI_KEVENT_CONN_ERROR;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1408
  	ev->r.connerror.error = error;
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1409
1410
  	ev->r.connerror.cid = conn->cid;
  	ev->r.connerror.sid = iscsi_conn_get_sid(conn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1411

43514774f   Michael Chan   [SCSI] iscsi clas...
1412
  	iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1413

322d739da   Mike Christie   [SCSI] iscsi: fix...
1414
1415
1416
  	iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn error (%d)
  ",
  			      error);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1417
  }
e5bd7b54e   Mike Christie   [SCSI] libiscsi: ...
1418
  EXPORT_SYMBOL_GPL(iscsi_conn_error_event);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1419

17fa575ee   Manish Rangankar   [SCSI] scsi_trans...
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
  void iscsi_conn_login_event(struct iscsi_cls_conn *conn,
  			    enum iscsi_conn_state state)
  {
  	struct nlmsghdr *nlh;
  	struct sk_buff  *skb;
  	struct iscsi_uevent *ev;
  	struct iscsi_internal *priv;
  	int len = NLMSG_SPACE(sizeof(*ev));
  
  	priv = iscsi_if_transport_lookup(conn->transport);
  	if (!priv)
  		return;
  
  	skb = alloc_skb(len, GFP_ATOMIC);
  	if (!skb) {
  		iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
  				      "conn login (%d)
  ", state);
  		return;
  	}
  
  	nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
  	ev = NLMSG_DATA(nlh);
  	ev->transport_handle = iscsi_handle(conn->transport);
  	ev->type = ISCSI_KEVENT_CONN_LOGIN_STATE;
  	ev->r.conn_login.state = state;
  	ev->r.conn_login.cid = conn->cid;
  	ev->r.conn_login.sid = iscsi_conn_get_sid(conn);
  	iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
  
  	iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn login (%d)
  ",
  			      state);
  }
  EXPORT_SYMBOL_GPL(iscsi_conn_login_event);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1455
  static int
43514774f   Michael Chan   [SCSI] iscsi clas...
1456
1457
  iscsi_if_send_reply(uint32_t group, int seq, int type, int done, int multi,
  		    void *payload, int size)
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1458
1459
1460
1461
1462
1463
  {
  	struct sk_buff	*skb;
  	struct nlmsghdr	*nlh;
  	int len = NLMSG_SPACE(size);
  	int flags = multi ? NLM_F_MULTI : 0;
  	int t = done ? NLMSG_DONE : type;
43a145a34   Mike Christie   [SCSI] iscsi clas...
1464
  	skb = alloc_skb(len, GFP_ATOMIC);
239a7dc2f   Mike Christie   [SCSI] iscsi_tran...
1465
1466
1467
1468
1469
  	if (!skb) {
  		printk(KERN_ERR "Could not allocate skb to send reply.
  ");
  		return -ENOMEM;
  	}
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1470

43514774f   Michael Chan   [SCSI] iscsi clas...
1471
  	nlh = __nlmsg_put(skb, 0, 0, t, (len - sizeof(*nlh)), 0);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1472
1473
  	nlh->nlmsg_flags = flags;
  	memcpy(NLMSG_DATA(nlh), payload, size);
43514774f   Michael Chan   [SCSI] iscsi clas...
1474
  	return iscsi_multicast_skb(skb, group, GFP_ATOMIC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1475
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1476

7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1477
  static int
5b940adf5   Mike Christie   [SCSI] iscsi upda...
1478
  iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1479
1480
1481
1482
1483
1484
1485
  {
  	struct iscsi_uevent *ev = NLMSG_DATA(nlh);
  	struct iscsi_stats *stats;
  	struct sk_buff *skbstat;
  	struct iscsi_cls_conn *conn;
  	struct nlmsghdr	*nlhstat;
  	struct iscsi_uevent *evstat;
790f39a2d   Mike Christie   [SCSI] iscsi: sup...
1486
  	struct iscsi_internal *priv;
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1487
1488
1489
1490
1491
  	int len = NLMSG_SPACE(sizeof(*ev) +
  			      sizeof(struct iscsi_stats) +
  			      sizeof(struct iscsi_stats_custom) *
  			      ISCSI_STATS_CUSTOM_MAX);
  	int err = 0;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1492

790f39a2d   Mike Christie   [SCSI] iscsi: sup...
1493
1494
1495
  	priv = iscsi_if_transport_lookup(transport);
  	if (!priv)
  		return -EINVAL;
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1496
  	conn = iscsi_conn_lookup(ev->u.get_stats.sid, ev->u.get_stats.cid);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1497
1498
  	if (!conn)
  		return -EEXIST;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1499

7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1500
1501
  	do {
  		int actual_size;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1502

43a145a34   Mike Christie   [SCSI] iscsi clas...
1503
  		skbstat = alloc_skb(len, GFP_ATOMIC);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1504
  		if (!skbstat) {
322d739da   Mike Christie   [SCSI] iscsi: fix...
1505
1506
1507
  			iscsi_cls_conn_printk(KERN_ERR, conn, "can not "
  					      "deliver stats: OOM
  ");
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1508
1509
  			return -ENOMEM;
  		}
43514774f   Michael Chan   [SCSI] iscsi clas...
1510
  		nlhstat = __nlmsg_put(skbstat, 0, 0, 0,
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1511
1512
1513
1514
1515
  				      (len - sizeof(*nlhstat)), 0);
  		evstat = NLMSG_DATA(nlhstat);
  		memset(evstat, 0, sizeof(*evstat));
  		evstat->transport_handle = iscsi_handle(conn->transport);
  		evstat->type = nlh->nlmsg_type;
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1516
1517
1518
1519
  		evstat->u.get_stats.cid =
  			ev->u.get_stats.cid;
  		evstat->u.get_stats.sid =
  			ev->u.get_stats.sid;
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1520
1521
1522
  		stats = (struct iscsi_stats *)
  			((char*)evstat + sizeof(*evstat));
  		memset(stats, 0, sizeof(*stats));
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
1523
  		transport->get_stats(conn, stats);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1524
1525
1526
1527
1528
1529
  		actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
  					  sizeof(struct iscsi_stats) +
  					  sizeof(struct iscsi_stats_custom) *
  					  stats->custom_length);
  		actual_size -= sizeof(*nlhstat);
  		actual_size = NLMSG_LENGTH(actual_size);
5b940adf5   Mike Christie   [SCSI] iscsi upda...
1530
  		skb_trim(skbstat, NLMSG_ALIGN(actual_size));
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1531
  		nlhstat->nlmsg_len = actual_size;
43514774f   Michael Chan   [SCSI] iscsi clas...
1532
1533
  		err = iscsi_multicast_skb(skbstat, ISCSI_NL_GRP_ISCSID,
  					  GFP_ATOMIC);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1534
1535
1536
  	} while (err < 0 && err != -ECONNREFUSED);
  
  	return err;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1537
  }
53cb8a1f4   Mike Christie   [SCSI] iscsi: add...
1538
  /**
269747890   Mike Christie   [SCSI] libiscsi: ...
1539
1540
1541
   * iscsi_session_event - send session destr. completion event
   * @session: iscsi class session
   * @event: type of event
eb44820c2   Rob Landley   [SCSI] Add Docume...
1542
   */
269747890   Mike Christie   [SCSI] libiscsi: ...
1543
1544
  int iscsi_session_event(struct iscsi_cls_session *session,
  			enum iscsi_uevent_e event)
53cb8a1f4   Mike Christie   [SCSI] iscsi: add...
1545
1546
  {
  	struct iscsi_internal *priv;
53cb8a1f4   Mike Christie   [SCSI] iscsi: add...
1547
1548
1549
1550
  	struct Scsi_Host *shost;
  	struct iscsi_uevent *ev;
  	struct sk_buff  *skb;
  	struct nlmsghdr *nlh;
53cb8a1f4   Mike Christie   [SCSI] iscsi: add...
1551
  	int rc, len = NLMSG_SPACE(sizeof(*ev));
269747890   Mike Christie   [SCSI] libiscsi: ...
1552
  	priv = iscsi_if_transport_lookup(session->transport);
53cb8a1f4   Mike Christie   [SCSI] iscsi: add...
1553
1554
  	if (!priv)
  		return -EINVAL;
53cb8a1f4   Mike Christie   [SCSI] iscsi: add...
1555
  	shost = iscsi_session_to_shost(session);
43a145a34   Mike Christie   [SCSI] iscsi clas...
1556
  	skb = alloc_skb(len, GFP_KERNEL);
53cb8a1f4   Mike Christie   [SCSI] iscsi: add...
1557
  	if (!skb) {
322d739da   Mike Christie   [SCSI] iscsi: fix...
1558
1559
1560
1561
  		iscsi_cls_session_printk(KERN_ERR, session,
  					 "Cannot notify userspace of session "
  					 "event %u
  ", event);
53cb8a1f4   Mike Christie   [SCSI] iscsi: add...
1562
1563
  		return -ENOMEM;
  	}
43514774f   Michael Chan   [SCSI] iscsi clas...
1564
  	nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
53cb8a1f4   Mike Christie   [SCSI] iscsi: add...
1565
  	ev = NLMSG_DATA(nlh);
269747890   Mike Christie   [SCSI] libiscsi: ...
1566
  	ev->transport_handle = iscsi_handle(session->transport);
53cb8a1f4   Mike Christie   [SCSI] iscsi: add...
1567

269747890   Mike Christie   [SCSI] libiscsi: ...
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
  	ev->type = event;
  	switch (event) {
  	case ISCSI_KEVENT_DESTROY_SESSION:
  		ev->r.d_session.host_no = shost->host_no;
  		ev->r.d_session.sid = session->sid;
  		break;
  	case ISCSI_KEVENT_CREATE_SESSION:
  		ev->r.c_session_ret.host_no = shost->host_no;
  		ev->r.c_session_ret.sid = session->sid;
  		break;
  	case ISCSI_KEVENT_UNBIND_SESSION:
  		ev->r.unbind_session.host_no = shost->host_no;
  		ev->r.unbind_session.sid = session->sid;
  		break;
  	default:
322d739da   Mike Christie   [SCSI] iscsi: fix...
1583
1584
1585
  		iscsi_cls_session_printk(KERN_ERR, session, "Invalid event "
  					 "%u.
  ", event);
269747890   Mike Christie   [SCSI] libiscsi: ...
1586
  		kfree_skb(skb);
53cb8a1f4   Mike Christie   [SCSI] iscsi: add...
1587
  		return -EINVAL;
53cb8a1f4   Mike Christie   [SCSI] iscsi: add...
1588
  	}
53cb8a1f4   Mike Christie   [SCSI] iscsi: add...
1589
1590
1591
1592
  	/*
  	 * this will occur if the daemon is not up, so we just warn
  	 * the user and when the daemon is restarted it will handle it
  	 */
43514774f   Michael Chan   [SCSI] iscsi clas...
1593
  	rc = iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_KERNEL);
ff491a733   Pablo Neira Ayuso   netlink: change r...
1594
  	if (rc == -ESRCH)
322d739da   Mike Christie   [SCSI] iscsi: fix...
1595
1596
1597
1598
1599
  		iscsi_cls_session_printk(KERN_ERR, session,
  					 "Cannot notify userspace of session "
  					 "event %u. Check iscsi daemon
  ",
  					 event);
632248aab   Mike Christie   [SCSI] iscsi clas...
1600
1601
1602
1603
  
  	ISCSI_DBG_TRANS_SESSION(session, "Completed handling event %d rc %d
  ",
  				event, rc);
53cb8a1f4   Mike Christie   [SCSI] iscsi: add...
1604
1605
  	return rc;
  }
269747890   Mike Christie   [SCSI] libiscsi: ...
1606
  EXPORT_SYMBOL_GPL(iscsi_session_event);
53cb8a1f4   Mike Christie   [SCSI] iscsi: add...
1607

0896b7523   Alex Aizman   [SCSI] open-iscsi...
1608
  static int
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
1609
  iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep,
0c70d84b7   Mike Christie   [SCSI] iscsi clas...
1610
1611
1612
  			struct iscsi_uevent *ev, pid_t pid,
  			uint32_t initial_cmdsn,	uint16_t cmds_max,
  			uint16_t queue_depth)
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1613
1614
  {
  	struct iscsi_transport *transport = priv->iscsi_transport;
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
1615
  	struct iscsi_cls_session *session;
5e7facb77   Mike Christie   [SCSI] iscsi clas...
1616
  	struct Scsi_Host *shost;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1617

d82ff9be7   Mike Christie   [SCSI] iscsi clas...
1618
  	session = transport->create_session(ep, cmds_max, queue_depth,
5e7facb77   Mike Christie   [SCSI] iscsi clas...
1619
  					    initial_cmdsn);
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
1620
  	if (!session)
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1621
  		return -ENOMEM;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1622

0c70d84b7   Mike Christie   [SCSI] iscsi clas...
1623
  	session->creator = pid;
5e7facb77   Mike Christie   [SCSI] iscsi clas...
1624
1625
  	shost = iscsi_session_to_shost(session);
  	ev->r.c_session_ret.host_no = shost->host_no;
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1626
  	ev->r.c_session_ret.sid = session->sid;
632248aab   Mike Christie   [SCSI] iscsi clas...
1627
1628
1629
  	ISCSI_DBG_TRANS_SESSION(session,
  				"Completed creating transport session
  ");
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1630
  	return 0;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1631
1632
1633
  }
  
  static int
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
1634
  iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1635
  {
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1636
  	struct iscsi_cls_conn *conn;
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
1637
  	struct iscsi_cls_session *session;
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1638

b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1639
1640
  	session = iscsi_session_lookup(ev->u.c_conn.sid);
  	if (!session) {
322d739da   Mike Christie   [SCSI] iscsi: fix...
1641
1642
  		printk(KERN_ERR "iscsi: invalid session %d.
  ",
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1643
  		       ev->u.c_conn.sid);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1644
  		return -EINVAL;
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1645
  	}
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1646

7b7232f3f   Mike Christie   [SCSI] iscsi upda...
1647
  	conn = transport->create_conn(session, ev->u.c_conn.cid);
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1648
  	if (!conn) {
322d739da   Mike Christie   [SCSI] iscsi: fix...
1649
1650
  		iscsi_cls_session_printk(KERN_ERR, session,
  					 "couldn't create a new connection.");
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
1651
  		return -ENOMEM;
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1652
  	}
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1653

b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1654
1655
  	ev->r.c_conn_ret.sid = session->sid;
  	ev->r.c_conn_ret.cid = conn->cid;
632248aab   Mike Christie   [SCSI] iscsi clas...
1656
1657
1658
  
  	ISCSI_DBG_TRANS_CONN(conn, "Completed creating transport conn
  ");
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1659
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1660
  }
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1661
1662
1663
  static int
  iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
  {
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1664
  	struct iscsi_cls_conn *conn;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1665

b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1666
  	conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1667
  	if (!conn)
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1668
  		return -EINVAL;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1669

632248aab   Mike Christie   [SCSI] iscsi clas...
1670
1671
  	ISCSI_DBG_TRANS_CONN(conn, "Destroying transport conn
  ");
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1672
1673
  	if (transport->destroy_conn)
  		transport->destroy_conn(conn);
632248aab   Mike Christie   [SCSI] iscsi clas...
1674

7b8631b53   Mike Christie   [SCSI] iscsi: sep...
1675
  	return 0;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1676
  }
fd7255f51   Mike Christie   [SCSI] iscsi: add...
1677
1678
1679
1680
1681
1682
  static int
  iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
  {
  	char *data = (char*)ev + sizeof(*ev);
  	struct iscsi_cls_conn *conn;
  	struct iscsi_cls_session *session;
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
1683
  	int err = 0, value = 0;
fd7255f51   Mike Christie   [SCSI] iscsi: add...
1684
1685
1686
1687
1688
1689
1690
  
  	session = iscsi_session_lookup(ev->u.set_param.sid);
  	conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
  	if (!conn || !session)
  		return -EINVAL;
  
  	switch (ev->u.set_param.param) {
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
1691
  	case ISCSI_PARAM_SESS_RECOVERY_TMO:
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
1692
  		sscanf(data, "%d", &value);
fdd46dcbe   Mike Christie   [SCSI] iscsi clas...
1693
  		session->recovery_tmo = value;
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
1694
  		break;
fd7255f51   Mike Christie   [SCSI] iscsi: add...
1695
  	default:
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
1696
1697
  		err = transport->set_param(conn, ev->u.set_param.param,
  					   data, ev->u.set_param.len);
fd7255f51   Mike Christie   [SCSI] iscsi: add...
1698
1699
1700
1701
  	}
  
  	return err;
  }
10eb0f013   Mike Christie   [SCSI] iscsi: pas...
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
  static int iscsi_if_ep_connect(struct iscsi_transport *transport,
  			       struct iscsi_uevent *ev, int msg_type)
  {
  	struct iscsi_endpoint *ep;
  	struct sockaddr *dst_addr;
  	struct Scsi_Host *shost = NULL;
  	int non_blocking, err = 0;
  
  	if (!transport->ep_connect)
  		return -EINVAL;
  
  	if (msg_type == ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST) {
  		shost = scsi_host_lookup(ev->u.ep_connect_through_host.host_no);
  		if (!shost) {
  			printk(KERN_ERR "ep connect failed. Could not find "
  			       "host no %u
  ",
  			       ev->u.ep_connect_through_host.host_no);
  			return -ENODEV;
  		}
  		non_blocking = ev->u.ep_connect_through_host.non_blocking;
  	} else
  		non_blocking = ev->u.ep_connect.non_blocking;
  
  	dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
  	ep = transport->ep_connect(shost, dst_addr, non_blocking);
  	if (IS_ERR(ep)) {
  		err = PTR_ERR(ep);
  		goto release_host;
  	}
  
  	ev->r.ep_connect_ret.handle = ep->id;
  release_host:
  	if (shost)
  		scsi_host_put(shost);
  	return err;
  }
22a39fbbf   Mike Christie   [SCSI] iscsi: fix...
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
  static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
  				  u64 ep_handle)
  {
  	struct iscsi_cls_conn *conn;
  	struct iscsi_endpoint *ep;
  
  	if (!transport->ep_disconnect)
  		return -EINVAL;
  
  	ep = iscsi_lookup_endpoint(ep_handle);
  	if (!ep)
  		return -EINVAL;
  	conn = ep->conn;
  	if (conn) {
  		mutex_lock(&conn->ep_mutex);
  		conn->ep = NULL;
  		mutex_unlock(&conn->ep_mutex);
  	}
  
  	transport->ep_disconnect(ep);
  	return 0;
  }
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1761
  static int
264faaaa1   Or Gerlitz   [SCSI] iscsi: add...
1762
1763
1764
  iscsi_if_transport_ep(struct iscsi_transport *transport,
  		      struct iscsi_uevent *ev, int msg_type)
  {
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
1765
  	struct iscsi_endpoint *ep;
264faaaa1   Or Gerlitz   [SCSI] iscsi: add...
1766
1767
1768
  	int rc = 0;
  
  	switch (msg_type) {
10eb0f013   Mike Christie   [SCSI] iscsi: pas...
1769
  	case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
264faaaa1   Or Gerlitz   [SCSI] iscsi: add...
1770
  	case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
10eb0f013   Mike Christie   [SCSI] iscsi: pas...
1771
  		rc = iscsi_if_ep_connect(transport, ev, msg_type);
264faaaa1   Or Gerlitz   [SCSI] iscsi: add...
1772
1773
1774
1775
  		break;
  	case ISCSI_UEVENT_TRANSPORT_EP_POLL:
  		if (!transport->ep_poll)
  			return -EINVAL;
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
1776
1777
1778
1779
1780
  		ep = iscsi_lookup_endpoint(ev->u.ep_poll.ep_handle);
  		if (!ep)
  			return -EINVAL;
  
  		ev->r.retcode = transport->ep_poll(ep,
264faaaa1   Or Gerlitz   [SCSI] iscsi: add...
1781
1782
1783
  						   ev->u.ep_poll.timeout_ms);
  		break;
  	case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
22a39fbbf   Mike Christie   [SCSI] iscsi: fix...
1784
1785
  		rc = iscsi_if_ep_disconnect(transport,
  					    ev->u.ep_disconnect.ep_handle);
264faaaa1   Or Gerlitz   [SCSI] iscsi: add...
1786
1787
1788
1789
1790
1791
  		break;
  	}
  	return rc;
  }
  
  static int
01cb225da   Mike Christie   [SCSI] iscsi: add...
1792
1793
1794
  iscsi_tgt_dscvr(struct iscsi_transport *transport,
  		struct iscsi_uevent *ev)
  {
2174a04ee   Mike Christie   [SCSI] iscsi_tran...
1795
  	struct Scsi_Host *shost;
01cb225da   Mike Christie   [SCSI] iscsi: add...
1796
  	struct sockaddr *dst_addr;
2174a04ee   Mike Christie   [SCSI] iscsi_tran...
1797
  	int err;
01cb225da   Mike Christie   [SCSI] iscsi: add...
1798
1799
1800
  
  	if (!transport->tgt_dscvr)
  		return -EINVAL;
2174a04ee   Mike Christie   [SCSI] iscsi_tran...
1801
  	shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no);
315cb0ad1   James Smart   [SCSI] scsi_host_...
1802
  	if (!shost) {
2174a04ee   Mike Christie   [SCSI] iscsi_tran...
1803
1804
1805
1806
1807
  		printk(KERN_ERR "target discovery could not find host no %u
  ",
  		       ev->u.tgt_dscvr.host_no);
  		return -ENODEV;
  	}
01cb225da   Mike Christie   [SCSI] iscsi: add...
1808
  	dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
2174a04ee   Mike Christie   [SCSI] iscsi_tran...
1809
1810
1811
1812
  	err = transport->tgt_dscvr(shost, ev->u.tgt_dscvr.type,
  				   ev->u.tgt_dscvr.enable, dst_addr);
  	scsi_host_put(shost);
  	return err;
01cb225da   Mike Christie   [SCSI] iscsi: add...
1813
1814
1815
  }
  
  static int
1d9bf13a9   Mike Christie   [SCSI] iscsi clas...
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
  iscsi_set_host_param(struct iscsi_transport *transport,
  		     struct iscsi_uevent *ev)
  {
  	char *data = (char*)ev + sizeof(*ev);
  	struct Scsi_Host *shost;
  	int err;
  
  	if (!transport->set_host_param)
  		return -ENOSYS;
  
  	shost = scsi_host_lookup(ev->u.set_host_param.host_no);
315cb0ad1   James Smart   [SCSI] scsi_host_...
1827
  	if (!shost) {
1d9bf13a9   Mike Christie   [SCSI] iscsi clas...
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
  		printk(KERN_ERR "set_host_param could not find host no %u
  ",
  		       ev->u.set_host_param.host_no);
  		return -ENODEV;
  	}
  
  	err = transport->set_host_param(shost, ev->u.set_host_param.param,
  					data, ev->u.set_host_param.len);
  	scsi_host_put(shost);
  	return err;
  }
  
  static int
43514774f   Michael Chan   [SCSI] iscsi clas...
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
  iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
  {
  	struct Scsi_Host *shost;
  	struct iscsi_path *params;
  	int err;
  
  	if (!transport->set_path)
  		return -ENOSYS;
  
  	shost = scsi_host_lookup(ev->u.set_path.host_no);
  	if (!shost) {
  		printk(KERN_ERR "set path could not find host no %u
  ",
  		       ev->u.set_path.host_no);
  		return -ENODEV;
  	}
  
  	params = (struct iscsi_path *)((char *)ev + sizeof(*ev));
  	err = transport->set_path(shost, params);
  
  	scsi_host_put(shost);
  	return err;
  }
  
  static int
56c155b5c   Mike Christie   [SCSI] iscsi_tran...
1866
  iscsi_set_iface_params(struct iscsi_transport *transport,
00c31889f   Mike Christie   [SCSI] qla4xxx: f...
1867
  		       struct iscsi_uevent *ev, uint32_t len)
56c155b5c   Mike Christie   [SCSI] iscsi_tran...
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
  {
  	char *data = (char *)ev + sizeof(*ev);
  	struct Scsi_Host *shost;
  	int err;
  
  	if (!transport->set_iface_param)
  		return -ENOSYS;
  
  	shost = scsi_host_lookup(ev->u.set_iface_params.host_no);
  	if (!shost) {
  		printk(KERN_ERR "set_iface_params could not find host no %u
  ",
  		       ev->u.set_iface_params.host_no);
  		return -ENODEV;
  	}
00c31889f   Mike Christie   [SCSI] qla4xxx: f...
1883
  	err = transport->set_iface_param(shost, data, len);
56c155b5c   Mike Christie   [SCSI] iscsi_tran...
1884
1885
1886
1887
1888
  	scsi_host_put(shost);
  	return err;
  }
  
  static int
43514774f   Michael Chan   [SCSI] iscsi clas...
1889
  iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1890
1891
1892
1893
1894
  {
  	int err = 0;
  	struct iscsi_uevent *ev = NLMSG_DATA(nlh);
  	struct iscsi_transport *transport = NULL;
  	struct iscsi_internal *priv;
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
1895
1896
  	struct iscsi_cls_session *session;
  	struct iscsi_cls_conn *conn;
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
1897
  	struct iscsi_endpoint *ep = NULL;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1898

43514774f   Michael Chan   [SCSI] iscsi clas...
1899
1900
1901
1902
  	if (nlh->nlmsg_type == ISCSI_UEVENT_PATH_UPDATE)
  		*group = ISCSI_NL_GRP_UIP;
  	else
  		*group = ISCSI_NL_GRP_ISCSID;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1903
1904
1905
1906
  	priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
  	if (!priv)
  		return -EINVAL;
  	transport = priv->iscsi_transport;
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
1907
1908
  	if (!try_module_get(transport->owner))
  		return -EINVAL;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1909
1910
  	switch (nlh->nlmsg_type) {
  	case ISCSI_UEVENT_CREATE_SESSION:
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
1911
  		err = iscsi_if_create_session(priv, ep, ev,
0c70d84b7   Mike Christie   [SCSI] iscsi clas...
1912
  					      NETLINK_CREDS(skb)->pid,
40753caa3   Mike Christie   [SCSI] iscsi clas...
1913
1914
1915
1916
1917
  					      ev->u.c_session.initial_cmdsn,
  					      ev->u.c_session.cmds_max,
  					      ev->u.c_session.queue_depth);
  		break;
  	case ISCSI_UEVENT_CREATE_BOUND_SESSION:
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
1918
  		ep = iscsi_lookup_endpoint(ev->u.c_bound_session.ep_handle);
c95fddc72   Mike Christie   [SCSI] iscsi clas...
1919
1920
1921
1922
  		if (!ep) {
  			err = -EINVAL;
  			break;
  		}
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
1923
1924
  
  		err = iscsi_if_create_session(priv, ep, ev,
0c70d84b7   Mike Christie   [SCSI] iscsi clas...
1925
  					NETLINK_CREDS(skb)->pid,
40753caa3   Mike Christie   [SCSI] iscsi clas...
1926
1927
1928
  					ev->u.c_bound_session.initial_cmdsn,
  					ev->u.c_bound_session.cmds_max,
  					ev->u.c_bound_session.queue_depth);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1929
1930
  		break;
  	case ISCSI_UEVENT_DESTROY_SESSION:
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1931
  		session = iscsi_session_lookup(ev->u.d_session.sid);
269747890   Mike Christie   [SCSI] libiscsi: ...
1932
  		if (session)
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
1933
  			transport->destroy_session(session);
269747890   Mike Christie   [SCSI] libiscsi: ...
1934
1935
1936
1937
1938
1939
  		else
  			err = -EINVAL;
  		break;
  	case ISCSI_UEVENT_UNBIND_SESSION:
  		session = iscsi_session_lookup(ev->u.d_session.sid);
  		if (session)
06d25af4e   Mike Christie   [SCSI] iscsi clas...
1940
1941
  			scsi_queue_work(iscsi_session_to_shost(session),
  					&session->unbind_work);
269747890   Mike Christie   [SCSI] libiscsi: ...
1942
  		else
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
1943
  			err = -EINVAL;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1944
1945
1946
1947
1948
1949
1950
1951
  		break;
  	case ISCSI_UEVENT_CREATE_CONN:
  		err = iscsi_if_create_conn(transport, ev);
  		break;
  	case ISCSI_UEVENT_DESTROY_CONN:
  		err = iscsi_if_destroy_conn(transport, ev);
  		break;
  	case ISCSI_UEVENT_BIND_CONN:
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1952
1953
  		session = iscsi_session_lookup(ev->u.b_conn.sid);
  		conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
1954

22a39fbbf   Mike Christie   [SCSI] iscsi: fix...
1955
1956
1957
1958
  		if (conn && conn->ep)
  			iscsi_if_ep_disconnect(transport, conn->ep->id);
  
  		if (!session || !conn) {
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
1959
  			err = -EINVAL;
22a39fbbf   Mike Christie   [SCSI] iscsi: fix...
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
  			break;
  		}
  
  		ev->r.retcode =	transport->bind_conn(session, conn,
  						ev->u.b_conn.transport_eph,
  						ev->u.b_conn.is_leading);
  		if (ev->r.retcode || !transport->ep_connect)
  			break;
  
  		ep = iscsi_lookup_endpoint(ev->u.b_conn.transport_eph);
  		if (ep) {
  			ep->conn = conn;
  
  			mutex_lock(&conn->ep_mutex);
  			conn->ep = ep;
  			mutex_unlock(&conn->ep_mutex);
  		} else
  			iscsi_cls_conn_printk(KERN_ERR, conn,
  					      "Could not set ep conn "
  					      "binding
  ");
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1981
1982
  		break;
  	case ISCSI_UEVENT_SET_PARAM:
fd7255f51   Mike Christie   [SCSI] iscsi: add...
1983
  		err = iscsi_set_param(transport, ev);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1984
1985
  		break;
  	case ISCSI_UEVENT_START_CONN:
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1986
  		conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid);
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
1987
1988
1989
1990
  		if (conn)
  			ev->r.retcode = transport->start_conn(conn);
  		else
  			err = -EINVAL;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1991
1992
  		break;
  	case ISCSI_UEVENT_STOP_CONN:
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
1993
  		conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
1994
1995
1996
1997
  		if (conn)
  			transport->stop_conn(conn, ev->u.stop_conn.flag);
  		else
  			err = -EINVAL;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
1998
1999
  		break;
  	case ISCSI_UEVENT_SEND_PDU:
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
2000
  		conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
2001
2002
2003
2004
2005
2006
2007
  		if (conn)
  			ev->r.retcode =	transport->send_pdu(conn,
  				(struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
  				(char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
  				ev->u.send_pdu.data_size);
  		else
  			err = -EINVAL;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2008
2009
  		break;
  	case ISCSI_UEVENT_GET_STATS:
5b940adf5   Mike Christie   [SCSI] iscsi upda...
2010
  		err = iscsi_if_get_stats(transport, nlh);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2011
  		break;
264faaaa1   Or Gerlitz   [SCSI] iscsi: add...
2012
2013
2014
  	case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
  	case ISCSI_UEVENT_TRANSPORT_EP_POLL:
  	case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
10eb0f013   Mike Christie   [SCSI] iscsi: pas...
2015
  	case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
264faaaa1   Or Gerlitz   [SCSI] iscsi: add...
2016
2017
  		err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
  		break;
01cb225da   Mike Christie   [SCSI] iscsi: add...
2018
2019
2020
  	case ISCSI_UEVENT_TGT_DSCVR:
  		err = iscsi_tgt_dscvr(transport, ev);
  		break;
1d9bf13a9   Mike Christie   [SCSI] iscsi clas...
2021
2022
2023
  	case ISCSI_UEVENT_SET_HOST_PARAM:
  		err = iscsi_set_host_param(transport, ev);
  		break;
43514774f   Michael Chan   [SCSI] iscsi clas...
2024
2025
2026
  	case ISCSI_UEVENT_PATH_UPDATE:
  		err = iscsi_set_path(transport, ev);
  		break;
56c155b5c   Mike Christie   [SCSI] iscsi_tran...
2027
  	case ISCSI_UEVENT_SET_IFACE_PARAMS:
00c31889f   Mike Christie   [SCSI] qla4xxx: f...
2028
2029
  		err = iscsi_set_iface_params(transport, ev,
  					     nlmsg_attrlen(nlh, sizeof(*ev)));
56c155b5c   Mike Christie   [SCSI] iscsi_tran...
2030
  		break;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2031
  	default:
1d9bf13a9   Mike Christie   [SCSI] iscsi clas...
2032
  		err = -ENOSYS;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2033
2034
  		break;
  	}
7b7232f3f   Mike Christie   [SCSI] iscsi upda...
2035
  	module_put(transport->owner);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2036
2037
  	return err;
  }
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
2038
  /*
cd40b7d39   Denis V. Lunev   [NET]: make netli...
2039
2040
   * Get message from skb.  Each message is processed by iscsi_if_recv_msg.
   * Malformed skbs with wrong lengths or invalid creds are not processed.
b5c7a12dc   Mike Christie   [SCSI] iscsi: rm ...
2041
   */
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2042
  static void
cd40b7d39   Denis V. Lunev   [NET]: make netli...
2043
  iscsi_if_rx(struct sk_buff *skb)
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2044
  {
0b9506723   Arjan van de Ven   [SCSI] turn most ...
2045
  	mutex_lock(&rx_queue_mutex);
cd40b7d39   Denis V. Lunev   [NET]: make netli...
2046
2047
2048
2049
2050
  	while (skb->len >= NLMSG_SPACE(0)) {
  		int err;
  		uint32_t rlen;
  		struct nlmsghdr	*nlh;
  		struct iscsi_uevent *ev;
43514774f   Michael Chan   [SCSI] iscsi clas...
2051
  		uint32_t group;
cd40b7d39   Denis V. Lunev   [NET]: make netli...
2052
2053
2054
2055
2056
  
  		nlh = nlmsg_hdr(skb);
  		if (nlh->nlmsg_len < sizeof(*nlh) ||
  		    skb->len < nlh->nlmsg_len) {
  			break;
ee7f8e405   Mike Christie   [SCSI] iscsi upda...
2057
  		}
ee7f8e405   Mike Christie   [SCSI] iscsi upda...
2058

cd40b7d39   Denis V. Lunev   [NET]: make netli...
2059
2060
2061
2062
  		ev = NLMSG_DATA(nlh);
  		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
  		if (rlen > skb->len)
  			rlen = skb->len;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2063

43514774f   Michael Chan   [SCSI] iscsi clas...
2064
  		err = iscsi_if_recv_msg(skb, nlh, &group);
cd40b7d39   Denis V. Lunev   [NET]: make netli...
2065
2066
2067
  		if (err) {
  			ev->type = ISCSI_KEVENT_IF_ERROR;
  			ev->iferror = err;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2068
  		}
cd40b7d39   Denis V. Lunev   [NET]: make netli...
2069
2070
2071
2072
2073
2074
2075
2076
2077
  		do {
  			/*
  			 * special case for GET_STATS:
  			 * on success - sending reply and stats from
  			 * inside of if_recv_msg(),
  			 * on error - fall through.
  			 */
  			if (ev->type == ISCSI_UEVENT_GET_STATS && !err)
  				break;
43514774f   Michael Chan   [SCSI] iscsi clas...
2078
  			err = iscsi_if_send_reply(group, nlh->nlmsg_seq,
cd40b7d39   Denis V. Lunev   [NET]: make netli...
2079
2080
2081
  				nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
  		} while (err < 0 && err != -ECONNREFUSED);
  		skb_pull(skb, rlen);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2082
  	}
0b9506723   Arjan van de Ven   [SCSI] turn most ...
2083
  	mutex_unlock(&rx_queue_mutex);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2084
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2085

fd7255f51   Mike Christie   [SCSI] iscsi: add...
2086
  #define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store)		\
ee959b00c   Tony Jones   SCSI: convert str...
2087
  struct device_attribute dev_attr_##_prefix##_##_name =	\
fd7255f51   Mike Christie   [SCSI] iscsi: add...
2088
  	__ATTR(_name,_mode,_show,_store)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2089
  /*
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2090
   * iSCSI connection attrs
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2091
   */
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
2092
  #define iscsi_conn_attr_show(param)					\
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2093
  static ssize_t								\
ee959b00c   Tony Jones   SCSI: convert str...
2094
2095
  show_conn_param_##param(struct device *dev, 				\
  			struct device_attribute *attr, char *buf)	\
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2096
  {									\
ee959b00c   Tony Jones   SCSI: convert str...
2097
  	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent);	\
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
2098
  	struct iscsi_transport *t = conn->transport;			\
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
2099
  	return t->get_conn_param(conn, param, buf);			\
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2100
  }
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
2101
2102
2103
  #define iscsi_conn_attr(field, param)					\
  	iscsi_conn_attr_show(param)					\
  static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_param_##param,	\
fd7255f51   Mike Christie   [SCSI] iscsi: add...
2104
  			NULL);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2105

a54a52caa   Mike Christie   [SCSI] iscsi: fix...
2106
2107
2108
2109
2110
2111
2112
  iscsi_conn_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH);
  iscsi_conn_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH);
  iscsi_conn_attr(header_digest, ISCSI_PARAM_HDRDGST_EN);
  iscsi_conn_attr(data_digest, ISCSI_PARAM_DATADGST_EN);
  iscsi_conn_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN);
  iscsi_conn_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN);
  iscsi_conn_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT);
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
2113
2114
  iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN);
  iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
f6d5180c7   Mike Christie   [SCSI] libiscsi: ...
2115
2116
  iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO);
  iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2117

289324b0c   Mike Christie   [SCSI] iscsi clas...
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
  #define iscsi_conn_ep_attr_show(param)					\
  static ssize_t show_conn_ep_param_##param(struct device *dev,		\
  					  struct device_attribute *attr,\
  					  char *buf)			\
  {									\
  	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent);	\
  	struct iscsi_transport *t = conn->transport;			\
  	struct iscsi_endpoint *ep;					\
  	ssize_t rc;							\
  									\
  	/*								\
  	 * Need to make sure ep_disconnect does not free the LLD's	\
  	 * interconnect resources while we are trying to read them.	\
  	 */								\
  	mutex_lock(&conn->ep_mutex);					\
  	ep = conn->ep;							\
  	if (!ep && t->ep_connect) {					\
  		mutex_unlock(&conn->ep_mutex);				\
  		return -ENOTCONN;					\
  	}								\
  									\
  	if (ep)								\
  		rc = t->get_ep_param(ep, param, buf);			\
  	else								\
  		rc = t->get_conn_param(conn, param, buf);		\
  	mutex_unlock(&conn->ep_mutex);					\
  	return rc;							\
  }
  
  #define iscsi_conn_ep_attr(field, param)				\
  	iscsi_conn_ep_attr_show(param)					\
  static ISCSI_CLASS_ATTR(conn, field, S_IRUGO,				\
  			show_conn_ep_param_##param, NULL);
  
  iscsi_conn_ep_attr(address, ISCSI_PARAM_CONN_ADDRESS);
  iscsi_conn_ep_attr(port, ISCSI_PARAM_CONN_PORT);
3128c6c73   Mike Christie   [SCSI] iscsi cls:...
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
  static struct attribute *iscsi_conn_attrs[] = {
  	&dev_attr_conn_max_recv_dlength.attr,
  	&dev_attr_conn_max_xmit_dlength.attr,
  	&dev_attr_conn_header_digest.attr,
  	&dev_attr_conn_data_digest.attr,
  	&dev_attr_conn_ifmarker.attr,
  	&dev_attr_conn_ofmarker.attr,
  	&dev_attr_conn_address.attr,
  	&dev_attr_conn_port.attr,
  	&dev_attr_conn_exp_statsn.attr,
  	&dev_attr_conn_persistent_address.attr,
  	&dev_attr_conn_persistent_port.attr,
  	&dev_attr_conn_ping_tmo.attr,
  	&dev_attr_conn_recv_tmo.attr,
  	NULL,
  };
587a1f165   Al Viro   switch ->is_visib...
2170
  static umode_t iscsi_conn_attr_is_visible(struct kobject *kobj,
3128c6c73   Mike Christie   [SCSI] iscsi cls:...
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
  					 struct attribute *attr, int i)
  {
  	struct device *cdev = container_of(kobj, struct device, kobj);
  	struct iscsi_cls_conn *conn = transport_class_to_conn(cdev);
  	struct iscsi_transport *t = conn->transport;
  	int param;
  
  	if (attr == &dev_attr_conn_max_recv_dlength.attr)
  		param = ISCSI_PARAM_MAX_RECV_DLENGTH;
  	else if (attr == &dev_attr_conn_max_xmit_dlength.attr)
  		param = ISCSI_PARAM_MAX_XMIT_DLENGTH;
  	else if (attr == &dev_attr_conn_header_digest.attr)
  		param = ISCSI_PARAM_HDRDGST_EN;
  	else if (attr == &dev_attr_conn_data_digest.attr)
  		param = ISCSI_PARAM_DATADGST_EN;
  	else if (attr == &dev_attr_conn_ifmarker.attr)
  		param = ISCSI_PARAM_IFMARKER_EN;
  	else if (attr == &dev_attr_conn_ofmarker.attr)
  		param = ISCSI_PARAM_OFMARKER_EN;
  	else if (attr == &dev_attr_conn_address.attr)
  		param = ISCSI_PARAM_CONN_ADDRESS;
  	else if (attr == &dev_attr_conn_port.attr)
  		param = ISCSI_PARAM_CONN_PORT;
  	else if (attr == &dev_attr_conn_exp_statsn.attr)
  		param = ISCSI_PARAM_EXP_STATSN;
  	else if (attr == &dev_attr_conn_persistent_address.attr)
  		param = ISCSI_PARAM_PERSISTENT_ADDRESS;
  	else if (attr == &dev_attr_conn_persistent_port.attr)
  		param = ISCSI_PARAM_PERSISTENT_PORT;
  	else if (attr == &dev_attr_conn_ping_tmo.attr)
  		param = ISCSI_PARAM_PING_TMO;
  	else if (attr == &dev_attr_conn_recv_tmo.attr)
  		param = ISCSI_PARAM_RECV_TMO;
  	else {
  		WARN_ONCE(1, "Invalid conn attr");
  		return 0;
  	}
  
  	return t->attr_is_visible(ISCSI_PARAM, param);
  }
  
  static struct attribute_group iscsi_conn_group = {
  	.attrs = iscsi_conn_attrs,
  	.is_visible = iscsi_conn_attr_is_visible,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2216
  /*
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2217
   * iSCSI session attrs
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2218
   */
b2c641673   Mike Christie   [SCSI] iscsi clas...
2219
  #define iscsi_session_attr_show(param, perm)				\
fd7255f51   Mike Christie   [SCSI] iscsi: add...
2220
  static ssize_t								\
ee959b00c   Tony Jones   SCSI: convert str...
2221
2222
  show_session_param_##param(struct device *dev,				\
  			   struct device_attribute *attr, char *buf)	\
fd7255f51   Mike Christie   [SCSI] iscsi: add...
2223
  {									\
ee959b00c   Tony Jones   SCSI: convert str...
2224
2225
  	struct iscsi_cls_session *session = 				\
  		iscsi_dev_to_session(dev->parent);			\
fd7255f51   Mike Christie   [SCSI] iscsi: add...
2226
  	struct iscsi_transport *t = session->transport;			\
b2c641673   Mike Christie   [SCSI] iscsi clas...
2227
2228
2229
  									\
  	if (perm && !capable(CAP_SYS_ADMIN))				\
  		return -EACCES;						\
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
2230
  	return t->get_session_param(session, param, buf);		\
fd7255f51   Mike Christie   [SCSI] iscsi: add...
2231
  }
b2c641673   Mike Christie   [SCSI] iscsi clas...
2232
2233
  #define iscsi_session_attr(field, param, perm)				\
  	iscsi_session_attr_show(param, perm)				\
a54a52caa   Mike Christie   [SCSI] iscsi: fix...
2234
  static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \
fd7255f51   Mike Christie   [SCSI] iscsi: add...
2235
  			NULL);
b2c641673   Mike Christie   [SCSI] iscsi clas...
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
  iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME, 0);
  iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, 0);
  iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, 0);
  iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN, 0);
  iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST, 0);
  iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, 0);
  iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, 0);
  iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, 0);
  iscsi_session_attr(erl, ISCSI_PARAM_ERL, 0);
  iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT, 0);
  iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
  iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
  iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
  iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
4cd49ea13   Mike Christie   [SCSI] libiscsi, ...
2250
2251
2252
  iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 0);
  iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
  iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0);
3fe5ae8b4   Mike Christie   [SCSI] libiscsi: ...
2253
  iscsi_session_attr(tgt_reset_tmo, ISCSI_PARAM_TGT_RESET_TMO, 0);
88dfd340b   Mike Christie   [SCSI] iscsi clas...
2254
  iscsi_session_attr(ifacename, ISCSI_PARAM_IFACE_NAME, 0);
3b2bef1fc   Vikas Chaudhary   [SCSI] iscsi_tran...
2255
2256
  iscsi_session_attr(initiatorname, ISCSI_PARAM_INITIATOR_NAME, 0);
  iscsi_session_attr(targetalias, ISCSI_PARAM_TARGET_ALIAS, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2257

6eabafbe6   Mike Christie   [SCSI] iscsi clas...
2258
  static ssize_t
ee959b00c   Tony Jones   SCSI: convert str...
2259
2260
  show_priv_session_state(struct device *dev, struct device_attribute *attr,
  			char *buf)
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
2261
  {
ee959b00c   Tony Jones   SCSI: convert str...
2262
  	struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
2263
2264
2265
2266
2267
  	return sprintf(buf, "%s
  ", iscsi_session_state_name(session->state));
  }
  static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
  			NULL);
0c70d84b7   Mike Christie   [SCSI] iscsi clas...
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
  static ssize_t
  show_priv_session_creator(struct device *dev, struct device_attribute *attr,
  			char *buf)
  {
  	struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
  	return sprintf(buf, "%d
  ", session->creator);
  }
  static ISCSI_CLASS_ATTR(priv_sess, creator, S_IRUGO, show_priv_session_creator,
  			NULL);
6eabafbe6   Mike Christie   [SCSI] iscsi clas...
2278

fd7255f51   Mike Christie   [SCSI] iscsi: add...
2279
2280
  #define iscsi_priv_session_attr_show(field, format)			\
  static ssize_t								\
ee959b00c   Tony Jones   SCSI: convert str...
2281
2282
  show_priv_session_##field(struct device *dev, 				\
  			  struct device_attribute *attr, char *buf)	\
fd7255f51   Mike Christie   [SCSI] iscsi: add...
2283
  {									\
ee959b00c   Tony Jones   SCSI: convert str...
2284
2285
  	struct iscsi_cls_session *session = 				\
  			iscsi_dev_to_session(dev->parent);		\
fe4f0bdee   Vikas Chaudhary   [SCSI] iscsi_tran...
2286
2287
2288
  	if (session->field == -1)					\
  		return sprintf(buf, "off
  ");				\
fd7255f51   Mike Christie   [SCSI] iscsi: add...
2289
2290
2291
  	return sprintf(buf, format"
  ", session->field);		\
  }
fe4f0bdee   Vikas Chaudhary   [SCSI] iscsi_tran...
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
  #define iscsi_priv_session_attr_store(field)				\
  static ssize_t								\
  store_priv_session_##field(struct device *dev,				\
  			   struct device_attribute *attr,		\
  			   const char *buf, size_t count)		\
  {									\
  	int val;							\
  	char *cp;							\
  	struct iscsi_cls_session *session =				\
  		iscsi_dev_to_session(dev->parent);			\
  	if ((session->state == ISCSI_SESSION_FREE) ||			\
  	    (session->state == ISCSI_SESSION_FAILED))			\
  		return -EBUSY;						\
  	if (strncmp(buf, "off", 3) == 0)				\
  		session->field = -1;					\
  	else {								\
  		val = simple_strtoul(buf, &cp, 0);			\
  		if (*cp != '\0' && *cp != '
  ')				\
  			return -EINVAL;					\
  		session->field = val;					\
  	}								\
  	return count;							\
  }
  
  #define iscsi_priv_session_rw_attr(field, format)			\
fd7255f51   Mike Christie   [SCSI] iscsi: add...
2318
  	iscsi_priv_session_attr_show(field, format)			\
fe4f0bdee   Vikas Chaudhary   [SCSI] iscsi_tran...
2319
  	iscsi_priv_session_attr_store(field)				\
523f3c80b   Vasiliy Kulikov   [SCSI] scsi_trans...
2320
  static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUSR,		\
fe4f0bdee   Vikas Chaudhary   [SCSI] iscsi_tran...
2321
2322
2323
  			show_priv_session_##field,			\
  			store_priv_session_##field)
  iscsi_priv_session_rw_attr(recovery_tmo, "%d");
fd7255f51   Mike Christie   [SCSI] iscsi: add...
2324

1d063c172   Mike Christie   [SCSI] iscsi clas...
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
  static struct attribute *iscsi_session_attrs[] = {
  	&dev_attr_sess_initial_r2t.attr,
  	&dev_attr_sess_max_outstanding_r2t.attr,
  	&dev_attr_sess_immediate_data.attr,
  	&dev_attr_sess_first_burst_len.attr,
  	&dev_attr_sess_max_burst_len.attr,
  	&dev_attr_sess_data_pdu_in_order.attr,
  	&dev_attr_sess_data_seq_in_order.attr,
  	&dev_attr_sess_erl.attr,
  	&dev_attr_sess_targetname.attr,
  	&dev_attr_sess_tpgt.attr,
  	&dev_attr_sess_password.attr,
  	&dev_attr_sess_password_in.attr,
  	&dev_attr_sess_username.attr,
  	&dev_attr_sess_username_in.attr,
  	&dev_attr_sess_fast_abort.attr,
  	&dev_attr_sess_abort_tmo.attr,
  	&dev_attr_sess_lu_reset_tmo.attr,
  	&dev_attr_sess_tgt_reset_tmo.attr,
  	&dev_attr_sess_ifacename.attr,
  	&dev_attr_sess_initiatorname.attr,
  	&dev_attr_sess_targetalias.attr,
  	&dev_attr_priv_sess_recovery_tmo.attr,
  	&dev_attr_priv_sess_state.attr,
0c70d84b7   Mike Christie   [SCSI] iscsi clas...
2349
  	&dev_attr_priv_sess_creator.attr,
1d063c172   Mike Christie   [SCSI] iscsi clas...
2350
2351
  	NULL,
  };
587a1f165   Al Viro   switch ->is_visib...
2352
  static umode_t iscsi_session_attr_is_visible(struct kobject *kobj,
1d063c172   Mike Christie   [SCSI] iscsi clas...
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
  					    struct attribute *attr, int i)
  {
  	struct device *cdev = container_of(kobj, struct device, kobj);
  	struct iscsi_cls_session *session = transport_class_to_session(cdev);
  	struct iscsi_transport *t = session->transport;
  	int param;
  
  	if (attr == &dev_attr_sess_initial_r2t.attr)
  		param = ISCSI_PARAM_INITIAL_R2T_EN;
  	else if (attr == &dev_attr_sess_max_outstanding_r2t.attr)
  		param = ISCSI_PARAM_MAX_R2T;
  	else if (attr == &dev_attr_sess_immediate_data.attr)
  		param = ISCSI_PARAM_IMM_DATA_EN;
  	else if (attr == &dev_attr_sess_first_burst_len.attr)
  		param = ISCSI_PARAM_FIRST_BURST;
  	else if (attr == &dev_attr_sess_max_burst_len.attr)
  		param = ISCSI_PARAM_MAX_BURST;
  	else if (attr == &dev_attr_sess_data_pdu_in_order.attr)
  		param = ISCSI_PARAM_PDU_INORDER_EN;
  	else if (attr == &dev_attr_sess_data_seq_in_order.attr)
  		param = ISCSI_PARAM_DATASEQ_INORDER_EN;
  	else if (attr == &dev_attr_sess_erl.attr)
  		param = ISCSI_PARAM_ERL;
  	else if (attr == &dev_attr_sess_targetname.attr)
  		param = ISCSI_PARAM_TARGET_NAME;
  	else if (attr == &dev_attr_sess_tpgt.attr)
  		param = ISCSI_PARAM_TPGT;
  	else if (attr == &dev_attr_sess_password.attr)
  		param = ISCSI_PARAM_USERNAME;
  	else if (attr == &dev_attr_sess_password_in.attr)
  		param = ISCSI_PARAM_USERNAME_IN;
  	else if (attr == &dev_attr_sess_username.attr)
  		param = ISCSI_PARAM_PASSWORD;
  	else if (attr == &dev_attr_sess_username_in.attr)
  		param = ISCSI_PARAM_PASSWORD_IN;
  	else if (attr == &dev_attr_sess_fast_abort.attr)
  		param = ISCSI_PARAM_FAST_ABORT;
  	else if (attr == &dev_attr_sess_abort_tmo.attr)
  		param = ISCSI_PARAM_ABORT_TMO;
  	else if (attr == &dev_attr_sess_lu_reset_tmo.attr)
  		param = ISCSI_PARAM_LU_RESET_TMO;
  	else if (attr == &dev_attr_sess_tgt_reset_tmo.attr)
  		param = ISCSI_PARAM_TGT_RESET_TMO;
  	else if (attr == &dev_attr_sess_ifacename.attr)
  		param = ISCSI_PARAM_IFACE_NAME;
  	else if (attr == &dev_attr_sess_initiatorname.attr)
  		param = ISCSI_PARAM_INITIATOR_NAME;
  	else if (attr == &dev_attr_sess_targetalias.attr)
  		param = ISCSI_PARAM_TARGET_ALIAS;
  	else if (attr == &dev_attr_priv_sess_recovery_tmo.attr)
  		return S_IRUGO | S_IWUSR;
  	else if (attr == &dev_attr_priv_sess_state.attr)
  		return S_IRUGO;
0c70d84b7   Mike Christie   [SCSI] iscsi clas...
2406
2407
  	else if (attr == &dev_attr_priv_sess_creator.attr)
  		return S_IRUGO;
1d063c172   Mike Christie   [SCSI] iscsi clas...
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
  	else {
  		WARN_ONCE(1, "Invalid session attr");
  		return 0;
  	}
  
  	return t->attr_is_visible(ISCSI_PARAM, param);
  }
  
  static struct attribute_group iscsi_session_group = {
  	.attrs = iscsi_session_attrs,
  	.is_visible = iscsi_session_attr_is_visible,
  };
1819dc814   Mike Christie   [SCSI] iscsi_tran...
2420
2421
2422
2423
2424
  /*
   * iSCSI host attrs
   */
  #define iscsi_host_attr_show(param)					\
  static ssize_t								\
ee959b00c   Tony Jones   SCSI: convert str...
2425
2426
  show_host_param_##param(struct device *dev, 				\
  			struct device_attribute *attr, char *buf)	\
1819dc814   Mike Christie   [SCSI] iscsi_tran...
2427
  {									\
ee959b00c   Tony Jones   SCSI: convert str...
2428
  	struct Scsi_Host *shost = transport_class_to_shost(dev);	\
1819dc814   Mike Christie   [SCSI] iscsi_tran...
2429
2430
2431
2432
2433
2434
2435
2436
  	struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
  	return priv->iscsi_transport->get_host_param(shost, param, buf); \
  }
  
  #define iscsi_host_attr(field, param)					\
  	iscsi_host_attr_show(param)					\
  static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param,	\
  			NULL);
d8196ed21   Mike Christie   [SCSI] iscsi clas...
2437
  iscsi_host_attr(netdev, ISCSI_HOST_PARAM_NETDEV_NAME);
1819dc814   Mike Christie   [SCSI] iscsi_tran...
2438
  iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
d8196ed21   Mike Christie   [SCSI] iscsi clas...
2439
  iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
8ad5781ae   Mike Christie   [SCSI] iscsi clas...
2440
  iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
1819dc814   Mike Christie   [SCSI] iscsi_tran...
2441

f27fb2ef7   Mike Christie   [SCSI] iscsi clas...
2442
2443
2444
2445
2446
2447
2448
  static struct attribute *iscsi_host_attrs[] = {
  	&dev_attr_host_netdev.attr,
  	&dev_attr_host_hwaddress.attr,
  	&dev_attr_host_ipaddress.attr,
  	&dev_attr_host_initiatorname.attr,
  	NULL,
  };
587a1f165   Al Viro   switch ->is_visib...
2449
  static umode_t iscsi_host_attr_is_visible(struct kobject *kobj,
f27fb2ef7   Mike Christie   [SCSI] iscsi clas...
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
  					 struct attribute *attr, int i)
  {
  	struct device *cdev = container_of(kobj, struct device, kobj);
  	struct Scsi_Host *shost = transport_class_to_shost(cdev);
  	struct iscsi_internal *priv = to_iscsi_internal(shost->transportt);
  	int param;
  
  	if (attr == &dev_attr_host_netdev.attr)
  		param = ISCSI_HOST_PARAM_NETDEV_NAME;
  	else if (attr == &dev_attr_host_hwaddress.attr)
  		param = ISCSI_HOST_PARAM_HWADDRESS;
  	else if (attr == &dev_attr_host_ipaddress.attr)
  		param = ISCSI_HOST_PARAM_IPADDRESS;
  	else if (attr == &dev_attr_host_initiatorname.attr)
  		param = ISCSI_HOST_PARAM_INITIATOR_NAME;
  	else {
  		WARN_ONCE(1, "Invalid host attr");
  		return 0;
  	}
  
  	return priv->iscsi_transport->attr_is_visible(ISCSI_HOST_PARAM, param);
  }
  
  static struct attribute_group iscsi_host_group = {
  	.attrs = iscsi_host_attrs,
  	.is_visible = iscsi_host_attr_is_visible,
  };
1819dc814   Mike Christie   [SCSI] iscsi_tran...
2477

0896b7523   Alex Aizman   [SCSI] open-iscsi...
2478
2479
  static int iscsi_session_match(struct attribute_container *cont,
  			   struct device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2480
  {
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
2481
  	struct iscsi_cls_session *session;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2482
  	struct Scsi_Host *shost;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2483
2484
2485
2486
  	struct iscsi_internal *priv;
  
  	if (!iscsi_is_session_dev(dev))
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2487

7b8631b53   Mike Christie   [SCSI] iscsi: sep...
2488
2489
  	session = iscsi_dev_to_session(dev);
  	shost = iscsi_session_to_shost(session);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2490
  	if (!shost->transportt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2491
  		return 0;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2492
2493
  	priv = to_iscsi_internal(shost->transportt);
  	if (priv->session_cont.ac.class != &iscsi_session_class.class)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2494
  		return 0;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2495
  	return &priv->session_cont.ac == cont;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2496
  }
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2497
2498
2499
  static int iscsi_conn_match(struct attribute_container *cont,
  			   struct device *dev)
  {
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
2500
2501
  	struct iscsi_cls_session *session;
  	struct iscsi_cls_conn *conn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2502
  	struct Scsi_Host *shost;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2503
  	struct iscsi_internal *priv;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2504

0896b7523   Alex Aizman   [SCSI] open-iscsi...
2505
  	if (!iscsi_is_conn_dev(dev))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2506
  		return 0;
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
2507
2508
2509
  	conn = iscsi_dev_to_conn(dev);
  	session = iscsi_dev_to_session(conn->dev.parent);
  	shost = iscsi_session_to_shost(session);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2510
  	if (!shost->transportt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2511
  		return 0;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2512
2513
2514
  	priv = to_iscsi_internal(shost->transportt);
  	if (priv->conn_cont.ac.class != &iscsi_connection_class.class)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2515

0896b7523   Alex Aizman   [SCSI] open-iscsi...
2516
2517
  	return &priv->conn_cont.ac == cont;
  }
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
  static int iscsi_host_match(struct attribute_container *cont,
  			    struct device *dev)
  {
  	struct Scsi_Host *shost;
  	struct iscsi_internal *priv;
  
  	if (!scsi_is_host_device(dev))
  		return 0;
  
  	shost = dev_to_shost(dev);
  	if (!shost->transportt  ||
  	    shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
  		return 0;
  
          priv = to_iscsi_internal(shost->transportt);
          return &priv->t.host_attrs.ac == cont;
  }
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
2535
2536
  struct scsi_transport_template *
  iscsi_register_transport(struct iscsi_transport *tt)
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2537
2538
2539
  {
  	struct iscsi_internal *priv;
  	unsigned long flags;
f27fb2ef7   Mike Christie   [SCSI] iscsi clas...
2540
  	int err;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2541
2542
2543
2544
2545
  
  	BUG_ON(!tt);
  
  	priv = iscsi_if_transport_lookup(tt);
  	if (priv)
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
2546
  		return NULL;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2547

24669f75a   Jes Sorensen   [SCSI] SCSI core ...
2548
  	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2549
  	if (!priv)
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
2550
  		return NULL;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2551
  	INIT_LIST_HEAD(&priv->list);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2552
  	priv->iscsi_transport = tt;
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
2553
  	priv->t.user_scan = iscsi_user_scan;
06d25af4e   Mike Christie   [SCSI] iscsi clas...
2554
  	priv->t.create_work_queue = 1;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2555

ee959b00c   Tony Jones   SCSI: convert str...
2556
  	priv->dev.class = &iscsi_transport_class;
71610f55f   Kay Sievers   [SCSI] struct dev...
2557
  	dev_set_name(&priv->dev, "%s", tt->name);
ee959b00c   Tony Jones   SCSI: convert str...
2558
  	err = device_register(&priv->dev);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2559
2560
  	if (err)
  		goto free_priv;
ee959b00c   Tony Jones   SCSI: convert str...
2561
  	err = sysfs_create_group(&priv->dev.kobj, &iscsi_transport_group);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2562
  	if (err)
ee959b00c   Tony Jones   SCSI: convert str...
2563
  		goto unregister_dev;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2564

30a6c6523   Mike Christie   [SCSI] iscsi: fix...
2565
  	/* host parameters */
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
2566
2567
  	priv->t.host_attrs.ac.class = &iscsi_host_class.class;
  	priv->t.host_attrs.ac.match = iscsi_host_match;
f27fb2ef7   Mike Christie   [SCSI] iscsi clas...
2568
  	priv->t.host_attrs.ac.grp = &iscsi_host_group;
32c6e1b9a   Mike Christie   [SCSI] iscsi clas...
2569
  	priv->t.host_size = sizeof(struct iscsi_cls_host);
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
2570
  	transport_container_register(&priv->t.host_attrs);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2571
  	/* connection parameters */
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2572
2573
  	priv->conn_cont.ac.class = &iscsi_connection_class.class;
  	priv->conn_cont.ac.match = iscsi_conn_match;
3128c6c73   Mike Christie   [SCSI] iscsi cls:...
2574
  	priv->conn_cont.ac.grp = &iscsi_conn_group;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2575
  	transport_container_register(&priv->conn_cont);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2576

0896b7523   Alex Aizman   [SCSI] open-iscsi...
2577
  	/* session parameters */
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2578
2579
  	priv->session_cont.ac.class = &iscsi_session_class.class;
  	priv->session_cont.ac.match = iscsi_session_match;
1d063c172   Mike Christie   [SCSI] iscsi clas...
2580
  	priv->session_cont.ac.grp = &iscsi_session_group;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2581
  	transport_container_register(&priv->session_cont);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2582
2583
2584
2585
2586
2587
  	spin_lock_irqsave(&iscsi_transport_lock, flags);
  	list_add(&priv->list, &iscsi_transports);
  	spin_unlock_irqrestore(&iscsi_transport_lock, flags);
  
  	printk(KERN_NOTICE "iscsi: registered transport (%s)
  ", tt->name);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
2588
  	return &priv->t;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2589

ee959b00c   Tony Jones   SCSI: convert str...
2590
2591
  unregister_dev:
  	device_unregister(&priv->dev);
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
2592
  	return NULL;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2593
2594
  free_priv:
  	kfree(priv);
7b8631b53   Mike Christie   [SCSI] iscsi: sep...
2595
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2596
  }
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2597
2598
2599
2600
2601
2602
2603
2604
  EXPORT_SYMBOL_GPL(iscsi_register_transport);
  
  int iscsi_unregister_transport(struct iscsi_transport *tt)
  {
  	struct iscsi_internal *priv;
  	unsigned long flags;
  
  	BUG_ON(!tt);
0b9506723   Arjan van de Ven   [SCSI] turn most ...
2605
  	mutex_lock(&rx_queue_mutex);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2606
2607
2608
  
  	priv = iscsi_if_transport_lookup(tt);
  	BUG_ON (!priv);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2609
2610
2611
2612
2613
2614
  	spin_lock_irqsave(&iscsi_transport_lock, flags);
  	list_del(&priv->list);
  	spin_unlock_irqrestore(&iscsi_transport_lock, flags);
  
  	transport_container_unregister(&priv->conn_cont);
  	transport_container_unregister(&priv->session_cont);
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
2615
  	transport_container_unregister(&priv->t.host_attrs);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2616

ee959b00c   Tony Jones   SCSI: convert str...
2617
2618
  	sysfs_remove_group(&priv->dev.kobj, &iscsi_transport_group);
  	device_unregister(&priv->dev);
0b9506723   Arjan van de Ven   [SCSI] turn most ...
2619
  	mutex_unlock(&rx_queue_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2620

0896b7523   Alex Aizman   [SCSI] open-iscsi...
2621
2622
2623
  	return 0;
  }
  EXPORT_SYMBOL_GPL(iscsi_unregister_transport);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2624

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2625
2626
  static __init int iscsi_transport_init(void)
  {
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2627
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2628

09492605a   Meelis Roos   [SCSI] iscsi: new...
2629
2630
  	printk(KERN_INFO "Loading iSCSI transport class v%s.
  ",
f4246b33c   Mike Christie   [SCSI] iscsi bugf...
2631
  		ISCSI_TRANSPORT_VERSION);
41be14442   Mike Christie   [SCSI] iscsi tran...
2632
  	atomic_set(&iscsi_session_nr, 0);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2633
  	err = class_register(&iscsi_transport_class);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2634
2635
  	if (err)
  		return err;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2636

d82ff9be7   Mike Christie   [SCSI] iscsi clas...
2637
  	err = class_register(&iscsi_endpoint_class);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2638
2639
  	if (err)
  		goto unregister_transport_class;
8d07913db   Mike Christie   [SCSI] iscsi clas...
2640
  	err = class_register(&iscsi_iface_class);
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
2641
2642
  	if (err)
  		goto unregister_endpoint_class;
8d07913db   Mike Christie   [SCSI] iscsi clas...
2643
2644
2645
  	err = transport_class_register(&iscsi_host_class);
  	if (err)
  		goto unregister_iface_class;
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
2646
2647
2648
  	err = transport_class_register(&iscsi_connection_class);
  	if (err)
  		goto unregister_host_class;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2649
2650
2651
  	err = transport_class_register(&iscsi_session_class);
  	if (err)
  		goto unregister_conn_class;
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
2652
2653
  	nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx,
  				    NULL, THIS_MODULE);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2654
2655
  	if (!nls) {
  		err = -ENOBUFS;
43a145a34   Mike Christie   [SCSI] iscsi clas...
2656
  		goto unregister_session_class;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2657
  	}
d8bf541e6   Mike Christie   [SCSI] iscsi clas...
2658
2659
2660
  	iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh");
  	if (!iscsi_eh_timer_workq)
  		goto release_nls;
43a145a34   Mike Christie   [SCSI] iscsi clas...
2661
  	return 0;
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2662

d8bf541e6   Mike Christie   [SCSI] iscsi clas...
2663
  release_nls:
b7c6ba6eb   Denis V. Lunev   [NETNS]: Consolid...
2664
  	netlink_kernel_release(nls);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2665
2666
2667
2668
  unregister_session_class:
  	transport_class_unregister(&iscsi_session_class);
  unregister_conn_class:
  	transport_class_unregister(&iscsi_connection_class);
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
2669
2670
  unregister_host_class:
  	transport_class_unregister(&iscsi_host_class);
8d07913db   Mike Christie   [SCSI] iscsi clas...
2671
2672
  unregister_iface_class:
  	class_unregister(&iscsi_iface_class);
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
2673
2674
  unregister_endpoint_class:
  	class_unregister(&iscsi_endpoint_class);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2675
2676
2677
  unregister_transport_class:
  	class_unregister(&iscsi_transport_class);
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2678
2679
2680
2681
  }
  
  static void __exit iscsi_transport_exit(void)
  {
d8bf541e6   Mike Christie   [SCSI] iscsi clas...
2682
  	destroy_workqueue(iscsi_eh_timer_workq);
b7c6ba6eb   Denis V. Lunev   [NETNS]: Consolid...
2683
  	netlink_kernel_release(nls);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2684
2685
  	transport_class_unregister(&iscsi_connection_class);
  	transport_class_unregister(&iscsi_session_class);
30a6c6523   Mike Christie   [SCSI] iscsi: fix...
2686
  	transport_class_unregister(&iscsi_host_class);
d82ff9be7   Mike Christie   [SCSI] iscsi clas...
2687
  	class_unregister(&iscsi_endpoint_class);
8d07913db   Mike Christie   [SCSI] iscsi clas...
2688
  	class_unregister(&iscsi_iface_class);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2689
  	class_unregister(&iscsi_transport_class);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2690
2691
2692
2693
  }
  
  module_init(iscsi_transport_init);
  module_exit(iscsi_transport_exit);
0896b7523   Alex Aizman   [SCSI] open-iscsi...
2694
2695
2696
2697
  MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, "
  	      "Dmitry Yusupov <dmitry_yus@yahoo.com>, "
  	      "Alex Aizman <itn780@yahoo.com>");
  MODULE_DESCRIPTION("iSCSI Transport Interface");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2698
  MODULE_LICENSE("GPL");
f4246b33c   Mike Christie   [SCSI] iscsi bugf...
2699
  MODULE_VERSION(ISCSI_TRANSPORT_VERSION);
058548ae2   Stephen Hemminger   [SCSI] iscsi: add...
2700
  MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_ISCSI);