scsi_transport_iscsi.c 58.3 KB
Newer Older
1
/*
Linus Torvalds's avatar
Linus Torvalds committed
2
3
4
 * iSCSI transport class definitions
 *
 * Copyright (C) IBM Corporation, 2004
5
6
7
 * Copyright (C) Mike Christie, 2004 - 2005
 * Copyright (C) Dmitry Yusupov, 2004 - 2005
 * Copyright (C) Alex Aizman, 2004 - 2005
Linus Torvalds's avatar
Linus Torvalds committed
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>
24
#include <linux/mutex.h>
25
#include <linux/slab.h>
26
#include <net/tcp.h>
Linus Torvalds's avatar
Linus Torvalds committed
27
28
29
30
31
#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>
32
#include <scsi/iscsi_if.h>
Linus Torvalds's avatar
Linus Torvalds committed
33

34
#define ISCSI_SESSION_ATTRS 23
35
#define ISCSI_CONN_ATTRS 13
36
#define ISCSI_HOST_ATTRS 4
37

38
#define ISCSI_TRANSPORT_VERSION "2.0-870"
Linus Torvalds's avatar
Linus Torvalds committed
39

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
71
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);

Linus Torvalds's avatar
Linus Torvalds committed
72
73
struct iscsi_internal {
	struct scsi_transport_template t;
74
75
	struct iscsi_transport *iscsi_transport;
	struct list_head list;
76
	struct device dev;
Mike Christie's avatar
Mike Christie committed
77

78
	struct device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
79
	struct transport_container conn_cont;
80
	struct device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1];
81
	struct transport_container session_cont;
82
	struct device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
Linus Torvalds's avatar
Linus Torvalds committed
83
84
};

85
static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
86
static struct workqueue_struct *iscsi_eh_timer_workq;
87

88
89
90
/*
 * list of registered transports and lock that must
 * be held while accessing list. The iscsi_transport_lock must
91
 * be acquired after the rx_queue_mutex.
92
93
94
95
96
97
98
 */
static LIST_HEAD(iscsi_transports);
static DEFINE_SPINLOCK(iscsi_transport_lock);

#define to_iscsi_internal(tmpl) \
	container_of(tmpl, struct iscsi_internal, t)

99
100
#define dev_to_iscsi_internal(_dev) \
	container_of(_dev, struct iscsi_internal, dev)
101

102
static void iscsi_transport_release(struct device *dev)
103
{
104
	struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
105
106
	kfree(priv);
}
Linus Torvalds's avatar
Linus Torvalds committed
107

108
109
110
111
112
113
/*
 * iscsi_transport_class represents the iscsi_transports that are
 * registered.
 */
static struct class iscsi_transport_class = {
	.name = "iscsi_transport",
114
	.dev_release = iscsi_transport_release,
115
116
117
};

static ssize_t
118
119
show_transport_handle(struct device *dev, struct device_attribute *attr,
		      char *buf)
120
{
121
	struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
122
	return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport));
123
}
124
static DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
125
126
127

#define show_transport_attr(name, format)				\
static ssize_t								\
128
129
show_transport_##name(struct device *dev, 				\
		      struct device_attribute *attr,char *buf)		\
130
{									\
131
	struct iscsi_internal *priv = dev_to_iscsi_internal(dev);	\
132
133
	return sprintf(buf, format"\n", priv->iscsi_transport->name);	\
}									\
134
static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
135
136
137
138

show_transport_attr(caps, "0x%x");

static struct attribute *iscsi_transport_attrs[] = {
139
140
	&dev_attr_handle.attr,
	&dev_attr_caps.attr,
141
142
143
144
145
146
147
	NULL,
};

static struct attribute_group iscsi_transport_group = {
	.attrs = iscsi_transport_attrs,
};

148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
 * 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);
173
	return sprintf(buf, "%llu\n", (unsigned long long) ep->id);
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
}
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);
191
	uint64_t *epid = (uint64_t *) data;
192
193
194
195
196
197
198
199
200

	return *epid == ep->id;
}

struct iscsi_endpoint *
iscsi_create_endpoint(int dd_size)
{
	struct device *dev;
	struct iscsi_endpoint *ep;
201
	uint64_t id;
202
203
204
	int err;

	for (id = 1; id < ISCSI_MAX_EPID; id++) {
205
		dev = class_find_device(&iscsi_endpoint_class, NULL, &id,
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
					iscsi_match_epid);
		if (!dev)
			break;
	}
	if (id == ISCSI_MAX_EPID) {
		printk(KERN_ERR "Too many connections. Max supported %u\n",
		       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;
222
	dev_set_name(&ep->dev, "ep-%llu", (unsigned long long) id);
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
252
253
	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)
{
254
	struct iscsi_endpoint *ep;
255
256
	struct device *dev;

257
	dev = class_find_device(&iscsi_endpoint_class, NULL, &handle,
258
259
260
261
				iscsi_match_epid);
	if (!dev)
		return NULL;

262
263
264
265
266
267
268
	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;
269
270
271
}
EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);

Mike Christie's avatar
Mike Christie committed
272
static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
273
			    struct device *cdev)
Mike Christie's avatar
Mike Christie committed
274
275
{
	struct Scsi_Host *shost = dev_to_shost(dev);
276
	struct iscsi_cls_host *ihost = shost->shost_data;
Mike Christie's avatar
Mike Christie committed
277
278

	memset(ihost, 0, sizeof(*ihost));
279
	atomic_set(&ihost->nr_scans, 0);
280
	mutex_init(&ihost->mutex);
Mike Christie's avatar
Mike Christie committed
281
282
283
284
285
286
	return 0;
}

static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
			       "iscsi_host",
			       iscsi_setup_host,
287
			       NULL,
Mike Christie's avatar
Mike Christie committed
288
289
			       NULL);

290
291
static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
			       "iscsi_session",
Linus Torvalds's avatar
Linus Torvalds committed
292
293
294
295
			       NULL,
			       NULL,
			       NULL);

296
297
static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
			       "iscsi_connection",
Linus Torvalds's avatar
Linus Torvalds committed
298
299
300
			       NULL,
			       NULL,
			       NULL);
301
302

static struct sock *nls;
303
static DEFINE_MUTEX(rx_queue_mutex);
304

305
306
static LIST_HEAD(sesslist);
static DEFINE_SPINLOCK(sesslock);
307
308
static LIST_HEAD(connlist);
static DEFINE_SPINLOCK(connlock);
309

310
311
312
313
314
315
316
317
318
319
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)
320
321
322
323
324
325
{
	unsigned long flags;
	struct iscsi_cls_session *sess;

	spin_lock_irqsave(&sesslock, flags);
	list_for_each_entry(sess, &sesslist, sess_list) {
326
		if (sess->sid == sid) {
327
328
329
330
331
332
333
334
			spin_unlock_irqrestore(&sesslock, flags);
			return sess;
		}
	}
	spin_unlock_irqrestore(&sesslock, flags);
	return NULL;
}

335
336
337
338
/*
 * Returns the matching connection to a given sid / cid tuple
 */
static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid)
339
340
341
342
343
344
{
	unsigned long flags;
	struct iscsi_cls_conn *conn;

	spin_lock_irqsave(&connlock, flags);
	list_for_each_entry(conn, &connlist, conn_list) {
345
		if ((conn->cid == cid) && (iscsi_conn_get_sid(conn) == sid)) {
346
347
348
349
350
351
352
353
			spin_unlock_irqrestore(&connlock, flags);
			return conn;
		}
	}
	spin_unlock_irqrestore(&connlock, flags);
	return NULL;
}

354
355
356
357
/*
 * The following functions can be used by LLDs that allocate
 * their own scsi_hosts or by software iscsi LLDs
 */
358
359
360
361
362
363
364
365
366
static struct {
	int value;
	char *name;
} iscsi_session_state_names[] = {
	{ ISCSI_SESSION_LOGGED_IN,	"LOGGED_IN" },
	{ ISCSI_SESSION_FAILED,		"FAILED" },
	{ ISCSI_SESSION_FREE,		"FREE" },
};

367
static const char *iscsi_session_state_name(int state)
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
{
	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:
392
		err = DID_IMM_RETRY << 16;
393
394
		break;
	case ISCSI_SESSION_FREE:
395
		err = DID_TRANSPORT_FAILFAST << 16;
396
397
398
399
400
401
402
403
404
405
		break;
	default:
		err = DID_NO_CONNECT << 16;
		break;
	}
	spin_unlock_irqrestore(&session->lock, flags);
	return err;
}
EXPORT_SYMBOL_GPL(iscsi_session_chkready);

406
407
408
409
static void iscsi_session_release(struct device *dev)
{
	struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
	struct Scsi_Host *shost;
410

411
412
	shost = iscsi_session_to_shost(session);
	scsi_host_put(shost);
413
	ISCSI_DBG_TRANS_SESSION(session, "Completing session release\n");
414
415
	kfree(session);
}
416

417
418
419
420
static int iscsi_is_session_dev(const struct device *dev)
{
	return dev->release == iscsi_session_release;
}
421

422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
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);

440
441
442
443
444
445
446
447
448
449
/**
 * 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)
{
450
	struct iscsi_cls_host *ihost = shost->shost_data;
451
452
453
454
455
456
457
458
	/*
	 * 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);

459
460
461
462
463
464
465
struct iscsi_scan_data {
	unsigned int channel;
	unsigned int id;
	unsigned int lun;
};

static int iscsi_user_scan_session(struct device *dev, void *data)
Mike Christie's avatar
Mike Christie committed
466
{
467
	struct iscsi_scan_data *scan_data = data;
Mike Christie's avatar
Mike Christie committed
468
	struct iscsi_cls_session *session;
469
470
471
472
473
474
475
476
477
	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);
478
479
480

	ISCSI_DBG_TRANS_SESSION(session, "Scanning session\n");

481
482
	shost = iscsi_session_to_shost(session);
	ihost = shost->shost_data;
Mike Christie's avatar
Mike Christie committed
483
484

	mutex_lock(&ihost->mutex);
485
486
487
	spin_lock_irqsave(&session->lock, flags);
	if (session->state != ISCSI_SESSION_LOGGED_IN) {
		spin_unlock_irqrestore(&session->lock, flags);
488
		goto user_scan_exit;
Mike Christie's avatar
Mike Christie committed
489
	}
490
491
	id = session->target_id;
	spin_unlock_irqrestore(&session->lock, flags);
Mike Christie's avatar
Mike Christie committed
492

493
494
495
496
497
498
499
500
	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);
	}
501
502

user_scan_exit:
503
	mutex_unlock(&ihost->mutex);
504
	ISCSI_DBG_TRANS_SESSION(session, "Completed session scan\n");
Mike Christie's avatar
Mike Christie committed
505
506
507
	return 0;
}

508
509
510
511
512
513
514
515
516
517
518
519
520
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);
}

521
522
523
524
static void iscsi_scan_session(struct work_struct *work)
{
	struct iscsi_cls_session *session =
			container_of(work, struct iscsi_cls_session, scan_work);
525
	struct Scsi_Host *shost = iscsi_session_to_shost(session);
526
	struct iscsi_cls_host *ihost = shost->shost_data;
527
	struct iscsi_scan_data scan_data;
528

529
530
531
	scan_data.channel = 0;
	scan_data.id = SCAN_WILD_CARD;
	scan_data.lun = SCAN_WILD_CARD;
532

533
	iscsi_user_scan_session(&session->dev, &scan_data);
534
	atomic_dec(&ihost->nr_scans);
535
536
}

David Howells's avatar
David Howells committed
537
static void session_recovery_timedout(struct work_struct *work)
Mike Christie's avatar
Mike Christie committed
538
{
David Howells's avatar
David Howells committed
539
540
541
	struct iscsi_cls_session *session =
		container_of(work, struct iscsi_cls_session,
			     recovery_work.work);
542
	unsigned long flags;
Mike Christie's avatar
Mike Christie committed
543

544
545
546
	iscsi_cls_session_printk(KERN_INFO, session,
				 "session recovery timed out after %d secs\n",
				 session->recovery_tmo);
Mike Christie's avatar
Mike Christie committed
547

548
549
550
551
552
553
554
555
556
557
558
559
560
	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);

Mike Christie's avatar
Mike Christie committed
561
562
563
	if (session->transport->session_recovery_timedout)
		session->transport->session_recovery_timedout(session);

564
	ISCSI_DBG_TRANS_SESSION(session, "Unblocking SCSI target\n");
Mike Christie's avatar
Mike Christie committed
565
	scsi_target_unblock(&session->dev);
566
	ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking SCSI target\n");
Mike Christie's avatar
Mike Christie committed
567
568
}

569
static void __iscsi_unblock_session(struct work_struct *work)
570
{
571
572
573
	struct iscsi_cls_session *session =
			container_of(work, struct iscsi_cls_session,
				     unblock_work);
574
	struct Scsi_Host *shost = iscsi_session_to_shost(session);
575
	struct iscsi_cls_host *ihost = shost->shost_data;
576
577
	unsigned long flags;

578
	ISCSI_DBG_TRANS_SESSION(session, "Unblocking session\n");
579
580
581
582
583
	/*
	 * 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);
584
585
586
	spin_lock_irqsave(&session->lock, flags);
	session->state = ISCSI_SESSION_LOGGED_IN;
	spin_unlock_irqrestore(&session->lock, flags);
587
588
	/* start IO */
	scsi_target_unblock(&session->dev);
589
590
591
592
593
594
	/*
	 * 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) {
595
		if (scsi_queue_work(shost, &session->scan_work))
596
597
			atomic_inc(&ihost->nr_scans);
	}
598
	ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking session\n");
599
}
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615

/**
 * 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);
}
Mike Christie's avatar
Mike Christie committed
616
617
EXPORT_SYMBOL_GPL(iscsi_unblock_session);

618
static void __iscsi_block_session(struct work_struct *work)
Mike Christie's avatar
Mike Christie committed
619
{
620
621
622
	struct iscsi_cls_session *session =
			container_of(work, struct iscsi_cls_session,
				     block_work);
623
624
	unsigned long flags;

625
	ISCSI_DBG_TRANS_SESSION(session, "Blocking session\n");
626
627
628
	spin_lock_irqsave(&session->lock, flags);
	session->state = ISCSI_SESSION_FAILED;
	spin_unlock_irqrestore(&session->lock, flags);
Mike Christie's avatar
Mike Christie committed
629
	scsi_target_block(&session->dev);
630
	ISCSI_DBG_TRANS_SESSION(session, "Completed SCSI target blocking\n");
631
632
633
634
	if (session->recovery_tmo >= 0)
		queue_delayed_work(iscsi_eh_timer_workq,
				   &session->recovery_work,
				   session->recovery_tmo * HZ);
Mike Christie's avatar
Mike Christie committed
635
}
636
637
638
639
640

void iscsi_block_session(struct iscsi_cls_session *session)
{
	queue_work(iscsi_eh_timer_workq, &session->block_work);
}
Mike Christie's avatar
Mike Christie committed
641
642
EXPORT_SYMBOL_GPL(iscsi_block_session);

Mike Christie's avatar
Mike Christie committed
643
644
645
646
647
648
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);
649
	struct iscsi_cls_host *ihost = shost->shost_data;
650
	unsigned long flags;
Mike Christie's avatar
Mike Christie committed
651

652
653
	ISCSI_DBG_TRANS_SESSION(session, "Unbinding session\n");

Mike Christie's avatar
Mike Christie committed
654
655
	/* Prevent new scans and make sure scanning is not in progress */
	mutex_lock(&ihost->mutex);
656
657
658
	spin_lock_irqsave(&session->lock, flags);
	if (session->target_id == ISCSI_MAX_TARGET) {
		spin_unlock_irqrestore(&session->lock, flags);
Mike Christie's avatar
Mike Christie committed
659
660
661
		mutex_unlock(&ihost->mutex);
		return;
	}
662
663
	session->target_id = ISCSI_MAX_TARGET;
	spin_unlock_irqrestore(&session->lock, flags);
Mike Christie's avatar
Mike Christie committed
664
665
666
667
	mutex_unlock(&ihost->mutex);

	scsi_remove_target(&session->dev);
	iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
668
	ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n");
Mike Christie's avatar
Mike Christie committed
669
670
}

671
struct iscsi_cls_session *
672
673
iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
		    int dd_size)
674
675
676
{
	struct iscsi_cls_session *session;

677
	session = kzalloc(sizeof(*session) + dd_size,
678
			  GFP_KERNEL);
679
	if (!session)
680
681
		return NULL;

682
	session->transport = transport;
Mike Christie's avatar
Mike Christie committed
683
	session->recovery_tmo = 120;
684
	session->state = ISCSI_SESSION_FREE;
David Howells's avatar
David Howells committed
685
	INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
Mike Christie's avatar
Mike Christie committed
686
	INIT_LIST_HEAD(&session->sess_list);
687
688
	INIT_WORK(&session->unblock_work, __iscsi_unblock_session);
	INIT_WORK(&session->block_work, __iscsi_block_session);
Mike Christie's avatar
Mike Christie committed
689
	INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
690
	INIT_WORK(&session->scan_work, iscsi_scan_session);
691
	spin_lock_init(&session->lock);
692

693
694
	/* this is released in the dev's release function */
	scsi_host_get(shost);
695
696
697
	session->dev.parent = &shost->shost_gendev;
	session->dev.release = iscsi_session_release;
	device_initialize(&session->dev);
698
	if (dd_size)
699
		session->dd_data = &session[1];
700
701

	ISCSI_DBG_TRANS_SESSION(session, "Completed session allocation\n");
702
703
704
705
	return session;
}
EXPORT_SYMBOL_GPL(iscsi_alloc_session);

706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
static int iscsi_get_next_target_id(struct device *dev, void *data)
{
	struct iscsi_cls_session *session;
	unsigned long flags;
	int err = 0;

	if (!iscsi_is_session_dev(dev))
		return 0;

	session = iscsi_dev_to_session(dev);
	spin_lock_irqsave(&session->lock, flags);
	if (*((unsigned int *) data) == session->target_id)
		err = -EEXIST;
	spin_unlock_irqrestore(&session->lock, flags);
	return err;
}

723
int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
724
725
{
	struct Scsi_Host *shost = iscsi_session_to_shost(session);
726
	struct iscsi_cls_host *ihost;
Mike Christie's avatar
Mike Christie committed
727
	unsigned long flags;
728
	unsigned int id = target_id;
729
	int err;
730

Mike Christie's avatar
Mike Christie committed
731
	ihost = shost->shost_data;
732
	session->sid = atomic_add_return(1, &iscsi_session_nr);
733
734
735
736
737
738
739
740
741
742
743
744
745
746

	if (id == ISCSI_MAX_TARGET) {
		for (id = 0; id < ISCSI_MAX_TARGET; id++) {
			err = device_for_each_child(&shost->shost_gendev, &id,
						    iscsi_get_next_target_id);
			if (!err)
				break;
		}

		if (id == ISCSI_MAX_TARGET) {
			iscsi_cls_session_printk(KERN_ERR, session,
						 "Too many iscsi targets. Max "
						 "number of targets is %d.\n",
						 ISCSI_MAX_TARGET - 1);
747
			err = -EOVERFLOW;
748
749
750
751
			goto release_host;
		}
	}
	session->target_id = id;
Mike Christie's avatar
Mike Christie committed
752

753
	dev_set_name(&session->dev, "session%u", session->sid);
754
	err = device_add(&session->dev);
755
	if (err) {
756
757
		iscsi_cls_session_printk(KERN_ERR, session,
					 "could not register session's dev\n");
758
		goto release_host;
759
760
761
	}
	transport_register_device(&session->dev);

Mike Christie's avatar
Mike Christie committed
762
763
764
765
766
	spin_lock_irqsave(&sesslock, flags);
	list_add(&session->sess_list, &sesslist);
	spin_unlock_irqrestore(&sesslock, flags);

	iscsi_session_event(session, ISCSI_KEVENT_CREATE_SESSION);
767
	ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n");
768
	return 0;
Mike Christie's avatar
Mike Christie committed
769

770
771
772
release_host:
	scsi_host_put(shost);
	return err;
773
}
774
EXPORT_SYMBOL_GPL(iscsi_add_session);
775
776

/**
777
778
779
 * iscsi_create_session - create iscsi class session
 * @shost: scsi host
 * @transport: iscsi transport
780
 * @dd_size: private driver data size
781
 * @target_id: which target
782
 *
783
 * This can be called from a LLD or iscsi_transport.
784
 */
785
struct iscsi_cls_session *
786
787
iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
		     int dd_size, unsigned int target_id)
788
789
790
{
	struct iscsi_cls_session *session;

791
	session = iscsi_alloc_session(shost, transport, dd_size);
792
793
794
	if (!session)
		return NULL;

795
	if (iscsi_add_session(session, target_id)) {
796
797
798
799
800
801
802
		iscsi_free_session(session);
		return NULL;
	}
	return session;
}
EXPORT_SYMBOL_GPL(iscsi_create_session);

Mike Christie's avatar
Mike Christie committed
803
804
805
806
807
static void iscsi_conn_release(struct device *dev)
{
	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
	struct device *parent = conn->dev.parent;

808
	ISCSI_DBG_TRANS_CONN(conn, "Releasing conn\n");
Mike Christie's avatar
Mike Christie committed
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
	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));
}

825
void iscsi_remove_session(struct iscsi_cls_session *session)
826
{
Mike Christie's avatar
Mike Christie committed
827
	struct Scsi_Host *shost = iscsi_session_to_shost(session);
Mike Christie's avatar
Mike Christie committed
828
829
830
	unsigned long flags;
	int err;

831
832
	ISCSI_DBG_TRANS_SESSION(session, "Removing session\n");

Mike Christie's avatar
Mike Christie committed
833
834
835
	spin_lock_irqsave(&sesslock, flags);
	list_del(&session->sess_list);
	spin_unlock_irqrestore(&sesslock, flags);
Mike Christie's avatar
Mike Christie committed
836

837
838
839
840
841
	/* 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);
Mike Christie's avatar
Mike Christie committed
842
843
844
	/*
	 * If we are blocked let commands flow again. The lld or iscsi
	 * layer should set up the queuecommand to fail commands.
845
846
	 * We assume that LLD will not be calling block/unblock while
	 * removing the session.
Mike Christie's avatar
Mike Christie committed
847
	 */
848
849
850
	spin_lock_irqsave(&session->lock, flags);
	session->state = ISCSI_SESSION_FREE;
	spin_unlock_irqrestore(&session->lock, flags);
851

852
853
	scsi_target_unblock(&session->dev);
	/* flush running scans then delete devices */
854
	scsi_flush_work(shost);
855
	__iscsi_unbind_session(&session->unbind_work);
Mike Christie's avatar
Mike Christie committed
856

Mike Christie's avatar
Mike Christie committed
857
858
859
860
	/* 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)
861
862
863
		iscsi_cls_session_printk(KERN_ERR, session,
					 "Could not delete all connections "
					 "for session. Error %d.\n", err);
864

865
	transport_unregister_device(&session->dev);
866
867

	ISCSI_DBG_TRANS_SESSION(session, "Completing session removal\n");
868
869
870
871
872
873
	device_del(&session->dev);
}
EXPORT_SYMBOL_GPL(iscsi_remove_session);

void iscsi_free_session(struct iscsi_cls_session *session)
{
874
	ISCSI_DBG_TRANS_SESSION(session, "Freeing session\n");
Mike Christie's avatar
Mike Christie committed
875
	iscsi_session_event(session, ISCSI_KEVENT_DESTROY_SESSION);
876
	put_device(&session->dev);
877
}
878
879
880
881
882
883
884
885
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.
886
 */
887
888
889
int iscsi_destroy_session(struct iscsi_cls_session *session)
{
	iscsi_remove_session(session);
890
	ISCSI_DBG_TRANS_SESSION(session, "Completing session destruction\n");
891
892
893
	iscsi_free_session(session);
	return 0;
}
894
895
896
897
898
EXPORT_SYMBOL_GPL(iscsi_destroy_session);

/**
 * iscsi_create_conn - create iscsi class connection
 * @session: iscsi cls session
899
 * @dd_size: private driver data size
900
901
902
903
904
 * @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.
905
906
907
908
909
 *
 * 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.
910
 */
911
struct iscsi_cls_conn *
912
iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
913
914
915
{
	struct iscsi_transport *transport = session->transport;
	struct iscsi_cls_conn *conn;
Mike Christie's avatar
Mike Christie committed
916
	unsigned long flags;
917
918
	int err;

919
	conn = kzalloc(sizeof(*conn) + dd_size, GFP_KERNEL);
920
921
	if (!conn)
		return NULL;
922
	if (dd_size)
923
924
925
926
		conn->dd_data = &conn[1];

	INIT_LIST_HEAD(&conn->conn_list);
	conn->transport = transport;
927
	conn->cid = cid;
928
929
930

	/* this is released in the dev's release function */
	if (!get_device(&session->dev))
931
		goto free_conn;
932

933
	dev_set_name(&conn->dev, "connection%d:%u", session->sid, cid);
934
935
936
937
	conn->dev.parent = &session->dev;
	conn->dev.release = iscsi_conn_release;
	err = device_register(&conn->dev);
	if (err) {
938
939
		iscsi_cls_session_printk(KERN_ERR, session, "could not "
					 "register connection's dev\n");
940
941
942
		goto release_parent_ref;
	}
	transport_register_device(&conn->dev);
Mike Christie's avatar
Mike Christie committed
943
944
945
946
947

	spin_lock_irqsave(&connlock, flags);
	list_add(&conn->conn_list, &connlist);
	conn->active = 1;
	spin_unlock_irqrestore(&connlock, flags);
948
949

	ISCSI_DBG_TRANS_CONN(conn, "Completed conn creation\n");
950
951
952
953
954
955
956
957
958
959
960
961
962
	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
963
 * @conn: iscsi cls session
964
 *
Mike Christie's avatar
Mike Christie committed
965
 * This can be called from a LLD or iscsi_transport.
966
 */
967
968
int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
{
Mike Christie's avatar
Mike Christie committed
969
970
971
972
973
974
975
	unsigned long flags;

	spin_lock_irqsave(&connlock, flags);
	conn->active = 0;
	list_del(&conn->conn_list);
	spin_unlock_irqrestore(&connlock, flags);

976
	transport_unregister_device(&conn->dev);
977
	ISCSI_DBG_TRANS_CONN(conn, "Completing conn destruction\n");
978
979
980
981
982
983
984
985
	device_unregister(&conn->dev);
	return 0;
}
EXPORT_SYMBOL_GPL(iscsi_destroy_conn);

/*
 * iscsi interface functions
 */
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
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;
}
Linus Torvalds's avatar
Linus Torvalds committed
1002

1003
static int
1004
iscsi_multicast_skb(struct sk_buff *skb, uint32_t group, gfp_t gfp)
1005
{
1006
	return nlmsg_multicast(nls, skb, 0, group, gfp);
Linus Torvalds's avatar
Linus Torvalds committed
1007
1008
}

1009
int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
1010
		   char *data, uint32_t data_size)
Linus Torvalds's avatar
Linus Torvalds committed
1011
{
1012
1013
1014
1015
	struct nlmsghdr	*nlh;
	struct sk_buff *skb;
	struct iscsi_uevent *ev;
	char *pdu;
1016
	struct iscsi_internal *priv;
1017
1018
1019
	int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
			      data_size);

1020
1021
1022
1023
	priv = iscsi_if_transport_lookup(conn->transport);
	if (!priv)
		return -EINVAL;

1024
	skb = alloc_skb(len, GFP_ATOMIC);
1025
	if (!skb) {
1026
		iscsi_conn_error_event(conn, ISCSI_ERR_CONN_FAILED);
1027
1028
		iscsi_cls_conn_printk(KERN_ERR, conn, "can not deliver "
				      "control PDU: OOM\n");
1029
1030
		return -ENOMEM;
	}
Linus Torvalds's avatar
Linus Torvalds committed
1031

1032
	nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
1033
1034
1035
1036
	ev = NLMSG_DATA(nlh);
	memset(ev, 0, sizeof(*ev));
	ev->transport_handle = iscsi_handle(conn->transport);
	ev->type = ISCSI_KEVENT_RECV_PDU;
1037
1038
	ev->r.recv_req.cid = conn->cid;
	ev->r.recv_req.sid = iscsi_conn_get_sid(conn);
1039
1040
1041
	pdu = (char*)ev + sizeof(*ev);
	memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
	memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
Linus Torvalds's avatar
Linus Torvalds committed
1042

1043
	return iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
Linus Torvalds's avatar
Linus Torvalds committed
1044
}
1045
EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
Linus Torvalds's avatar
Linus Torvalds committed
1046

1047
1048
1049
1050
1051
1052
1053
1054
1055
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);

1056
	skb = alloc_skb(len, GFP_ATOMIC);
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
	if (!skb) {
		printk(KERN_ERR "can not deliver iscsi offload message:OOM\n");
		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);

1078
	return iscsi_multicast_skb(skb, ISCSI_NL_GRP_UIP, GFP_ATOMIC);
1079
1080
1081
}
EXPORT_SYMBOL_GPL(iscsi_offload_mesg);

1082
void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
Linus Torvalds's avatar
Linus Torvalds committed
1083
{
1084
1085
1086
	struct nlmsghdr	*nlh;
	struct sk_buff	*skb;
	struct iscsi_uevent *ev;
1087
	struct iscsi_internal *priv;
1088
1089
	int len = NLMSG_SPACE(sizeof(*ev));

1090
1091
1092
1093
	priv = iscsi_if_transport_lookup(conn->transport);
	if (!priv)
		return;

1094
	skb = alloc_skb(len, GFP_ATOMIC);
1095
	if (!skb) {
1096
1097
		iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
				      "conn error (%d)\n", error);
1098
1099
1100
		return;
	}

1101
	nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
1102
1103
1104
1105
	ev = NLMSG_DATA(nlh);
	ev->transport_handle = iscsi_handle(conn->transport);
	ev->type = ISCSI_KEVENT_CONN_ERROR;
	ev->r.connerror.error = error;
1106
1107
	ev->r.connerror.cid = conn->cid;
	ev->r.connerror.sid = iscsi_conn_get_sid(conn);
Linus Torvalds's avatar
Linus Torvalds committed
1108

1109
	iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
Linus Torvalds's avatar
Linus Torvalds committed
1110

1111
1112
	iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn error (%d)\n",
			      error);
1113
}
1114
EXPORT_SYMBOL_GPL(iscsi_conn_error_event);
1115
1116

static int
1117
1118
iscsi_if_send_reply(uint32_t group, int seq, int type, int done, int multi,
		    void *payload, int size)
1119
1120
1121
1122
1123
1124
1125
{
	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;

1126
	skb = alloc_skb(len, GFP_ATOMIC);
1127
1128
1129
1130
	if (!skb) {
		printk(KERN_ERR "Could not allocate skb to send reply.\n");
		return -ENOMEM;
	}
1131

1132
	nlh = __nlmsg_put(skb, 0, 0, t, (len - sizeof(*nlh)), 0);
1133
1134
	nlh->nlmsg_flags = flags;
	memcpy(NLMSG_DATA(nlh), payload, size);
1135
	return iscsi_multicast_skb(skb, group, GFP_ATOMIC);
Linus Torvalds's avatar
Linus Torvalds committed
1136
1137
}

1138
static int
1139
iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
1140
1141
1142
1143
1144
1145
1146
{
	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;
1147
	struct iscsi_internal *priv;
1148
1149
1150
1151
1152
	int len = NLMSG_SPACE(sizeof(*ev) +
			      sizeof(struct iscsi_stats) +
			      sizeof(struct iscsi_stats_custom) *
			      ISCSI_STATS_CUSTOM_MAX);
	int err = 0;
1153

1154
1155
1156
1157
	priv = iscsi_if_transport_lookup(transport);
	if (!priv)
		return -EINVAL;