e0f3292948b187041769483c47c87e68183d57da
[mirror/scst/.git] / iscsi-scst / kernel / conn.c
1 /*
2  *  Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
3  *  Copyright (C) 2007 - 2009 Vladislav Bolkhovitin
4  *  Copyright (C) 2007 - 2009 ID7 Ltd.
5  *
6  *  This program is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU General Public License
8  *  as published by the Free Software Foundation, version 2
9  *  of the License.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  *  GNU General Public License for more details.
15  */
16
17 #include <linux/file.h>
18 #include <linux/ip.h>
19 #include <net/tcp.h>
20
21 #include "iscsi.h"
22 #include "digest.h"
23
24 static int print_conn_state(char *p, size_t size, struct iscsi_conn *conn)
25 {
26         int pos = 0;
27
28         if (conn->closing) {
29                 pos += scnprintf(p, size, "%s", "closing");
30                 goto out;
31         }
32
33         switch (conn->rd_state) {
34         case ISCSI_CONN_RD_STATE_PROCESSING:
35                 pos += scnprintf(&p[pos], size - pos, "%s", "read_processing ");
36                 break;
37         case ISCSI_CONN_RD_STATE_IN_LIST:
38                 pos += scnprintf(&p[pos], size - pos, "%s", "in_read_list ");
39                 break;
40         }
41
42         switch (conn->wr_state) {
43         case ISCSI_CONN_WR_STATE_PROCESSING:
44                 pos += scnprintf(&p[pos], size - pos, "%s", "write_processing ");
45                 break;
46         case ISCSI_CONN_WR_STATE_IN_LIST:
47                 pos += scnprintf(&p[pos], size - pos, "%s", "in_write_list ");
48                 break;
49         case ISCSI_CONN_WR_STATE_SPACE_WAIT:
50                 pos += scnprintf(&p[pos], size - pos, "%s", "space_waiting ");
51                 break;
52         }
53
54         if (test_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags))
55                 pos += scnprintf(&p[pos], size - pos, "%s", "reinstating ");
56         else if (pos == 0)
57                 pos += scnprintf(&p[pos], size - pos, "%s", "established idle ");
58
59 out:
60         return pos;
61 }
62
63 static int print_digest_state(char *p, size_t size, unsigned long flags)
64 {
65         int pos;
66
67         if (DIGEST_NONE & flags)
68                 pos = scnprintf(p, size, "%s", "none");
69         else if (DIGEST_CRC32C & flags)
70                 pos = scnprintf(p, size, "%s", "crc32c");
71         else
72                 pos = scnprintf(p, size, "%s", "unknown");
73
74         return pos;
75 }
76
77 #ifdef CONFIG_SCST_PROC
78
79 /* target_mutex supposed to be locked */
80 void conn_info_show(struct seq_file *seq, struct iscsi_session *session)
81 {
82         struct iscsi_conn *conn;
83         struct sock *sk;
84         char buf[64];
85
86         list_for_each_entry(conn, &session->conn_list, conn_list_entry) {
87                 sk = conn->sock->sk;
88                 switch (sk->sk_family) {
89                 case AF_INET:
90                         snprintf(buf, sizeof(buf),
91                                  "%u.%u.%u.%u", NIPQUAD(inet_sk(sk)->daddr));
92                         break;
93                 case AF_INET6:
94 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
95                         snprintf(buf, sizeof(buf),
96                                  "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
97                                  NIP6(inet6_sk(sk)->daddr));
98 #else
99                         snprintf(buf, sizeof(buf), "[%p6]",
100                                 &inet6_sk(sk)->daddr);
101 #endif
102                         break;
103                 default:
104                         break;
105                 }
106                 seq_printf(seq, "\t\tcid:%u ip:%s ", conn->cid, buf);
107                 print_conn_state(buf, sizeof(buf), conn);
108                 seq_printf(seq, "state:%s ", buf);
109                 print_digest_state(buf, sizeof(buf), conn->hdigest_type);
110                 seq_printf(seq, "hd:%s ", buf);
111                 print_digest_state(buf, sizeof(buf), conn->ddigest_type);
112                 seq_printf(seq, "dd:%s\n", buf);
113         }
114 }
115
116 #else /* CONFIG_SCST_PROC */
117
118 static int conn_free(struct iscsi_conn *conn);
119
120 static void iscsi_conn_release(struct kobject *kobj)
121 {
122         struct iscsi_conn *conn;
123
124         TRACE_ENTRY();
125
126         conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj);
127
128         conn_free(conn);
129
130         TRACE_EXIT();
131         return;
132 }
133
134 static struct kobj_type iscsi_conn_ktype = {
135         .sysfs_ops = &scst_sysfs_ops,
136         .release = iscsi_conn_release,
137 };
138
139 static ssize_t iscsi_conn_cid_show(struct kobject *kobj,
140         struct kobj_attribute *attr, char *buf)
141 {
142         int pos;
143         struct iscsi_conn *conn;
144
145         TRACE_ENTRY();
146
147         conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj);
148
149         pos = sprintf(buf, "%u", conn->cid);
150
151         TRACE_EXIT_RES(pos);
152         return pos;
153 }
154
155 static struct kobj_attribute iscsi_conn_cid_attr =
156         __ATTR(cid, S_IRUGO, iscsi_conn_cid_show, NULL);
157
158 static ssize_t iscsi_conn_state_show(struct kobject *kobj,
159         struct kobj_attribute *attr, char *buf)
160 {
161         int pos;
162         struct iscsi_conn *conn;
163
164         TRACE_ENTRY();
165
166         conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj);
167
168         pos = print_conn_state(buf, SCST_SYSFS_BLOCK_SIZE, conn);
169
170         TRACE_EXIT_RES(pos);
171         return pos;
172 }
173
174 static struct kobj_attribute iscsi_conn_state_attr =
175         __ATTR(state, S_IRUGO, iscsi_conn_state_show, NULL);
176
177 static ssize_t iscsi_conn_hdigest_show(struct kobject *kobj,
178         struct kobj_attribute *attr, char *buf)
179 {
180         int pos;
181         struct iscsi_conn *conn;
182
183         TRACE_ENTRY();
184
185         conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj);
186
187         pos = print_digest_state(buf, SCST_SYSFS_BLOCK_SIZE,
188                 conn->hdigest_type);
189
190         TRACE_EXIT_RES(pos);
191         return pos;
192 }
193
194 static struct kobj_attribute iscsi_conn_hdigest_attr =
195         __ATTR(hdigest, S_IRUGO, iscsi_conn_hdigest_show, NULL);
196
197 static ssize_t iscsi_conn_ddigest_show(struct kobject *kobj,
198         struct kobj_attribute *attr, char *buf)
199 {
200         int pos;
201         struct iscsi_conn *conn;
202
203         TRACE_ENTRY();
204
205         conn = container_of(kobj, struct iscsi_conn, iscsi_conn_kobj);
206
207         pos = print_digest_state(buf, SCST_SYSFS_BLOCK_SIZE,
208                 conn->ddigest_type);
209
210         TRACE_EXIT_RES(pos);
211         return pos;
212 }
213
214 static struct kobj_attribute iscsi_conn_ddigest_attr =
215         __ATTR(ddigest, S_IRUGO, iscsi_conn_ddigest_show, NULL);
216
217 #endif /* CONFIG_SCST_PROC */
218
219 /* target_mutex supposed to be locked */
220 struct iscsi_conn *conn_lookup(struct iscsi_session *session, u16 cid)
221 {
222         struct iscsi_conn *conn;
223
224         /*
225          * We need to find the latest conn to correctly handle
226          * multi-reinstatements
227          */
228         list_for_each_entry_reverse(conn, &session->conn_list,
229                                         conn_list_entry) {
230                 if (conn->cid == cid)
231                         return conn;
232         }
233         return NULL;
234 }
235
236 void iscsi_make_conn_rd_active(struct iscsi_conn *conn)
237 {
238         TRACE_ENTRY();
239
240         spin_lock_bh(&iscsi_rd_lock);
241
242         TRACE_DBG("conn %p, rd_state %x, rd_data_ready %d", conn,
243                 conn->rd_state, conn->rd_data_ready);
244
245         conn->rd_data_ready = 1;
246
247         if (conn->rd_state == ISCSI_CONN_RD_STATE_IDLE) {
248                 list_add_tail(&conn->rd_list_entry, &iscsi_rd_list);
249                 conn->rd_state = ISCSI_CONN_RD_STATE_IN_LIST;
250                 wake_up(&iscsi_rd_waitQ);
251         }
252
253         spin_unlock_bh(&iscsi_rd_lock);
254
255         TRACE_EXIT();
256         return;
257 }
258
259 void iscsi_make_conn_wr_active(struct iscsi_conn *conn)
260 {
261         TRACE_ENTRY();
262
263         spin_lock_bh(&iscsi_wr_lock);
264
265         TRACE_DBG("conn %p, wr_state %x, wr_space_ready %d", conn,
266                 conn->wr_state, conn->wr_space_ready);
267
268         if (conn->wr_state == ISCSI_CONN_WR_STATE_IDLE) {
269                 list_add_tail(&conn->wr_list_entry, &iscsi_wr_list);
270                 conn->wr_state = ISCSI_CONN_WR_STATE_IN_LIST;
271                 wake_up(&iscsi_wr_waitQ);
272         }
273
274         spin_unlock_bh(&iscsi_wr_lock);
275
276         TRACE_EXIT();
277         return;
278 }
279
280 void __mark_conn_closed(struct iscsi_conn *conn, int flags)
281 {
282         spin_lock_bh(&iscsi_rd_lock);
283         conn->closing = 1;
284         if (flags & ISCSI_CONN_ACTIVE_CLOSE)
285                 conn->active_close = 1;
286         if (flags & ISCSI_CONN_DELETING)
287                 conn->deleting = 1;
288         spin_unlock_bh(&iscsi_rd_lock);
289
290         iscsi_make_conn_rd_active(conn);
291 }
292
293 void mark_conn_closed(struct iscsi_conn *conn)
294 {
295         __mark_conn_closed(conn, ISCSI_CONN_ACTIVE_CLOSE);
296 }
297
298 static void __iscsi_state_change(struct sock *sk)
299 {
300         struct iscsi_conn *conn = sk->sk_user_data;
301
302         TRACE_ENTRY();
303
304         if (unlikely(sk->sk_state != TCP_ESTABLISHED)) {
305                 if (!conn->closing) {
306                         PRINT_ERROR("Connection with initiator %s "
307                                 "unexpectedly closed!",
308                                 conn->session->initiator_name);
309                         TRACE_MGMT_DBG("conn %p, sk state %d", conn,
310                                 sk->sk_state);
311                         __mark_conn_closed(conn, 0);
312                 }
313         } else
314                 iscsi_make_conn_rd_active(conn);
315
316         TRACE_EXIT();
317         return;
318 }
319
320 static void iscsi_state_change(struct sock *sk)
321 {
322         struct iscsi_conn *conn = sk->sk_user_data;
323
324         __iscsi_state_change(sk);
325         conn->old_state_change(sk);
326
327         return;
328 }
329
330 static void iscsi_data_ready(struct sock *sk, int len)
331 {
332         struct iscsi_conn *conn = sk->sk_user_data;
333
334         TRACE_ENTRY();
335
336         iscsi_make_conn_rd_active(conn);
337
338         conn->old_data_ready(sk, len);
339
340         TRACE_EXIT();
341         return;
342 }
343
344 static void iscsi_write_space_ready(struct sock *sk)
345 {
346         struct iscsi_conn *conn = sk->sk_user_data;
347
348         TRACE_ENTRY();
349
350         TRACE_DBG("Write space ready for conn %p", conn);
351
352         spin_lock_bh(&iscsi_wr_lock);
353         conn->wr_space_ready = 1;
354         if ((conn->wr_state == ISCSI_CONN_WR_STATE_SPACE_WAIT)) {
355                 list_add_tail(&conn->wr_list_entry, &iscsi_wr_list);
356                 conn->wr_state = ISCSI_CONN_WR_STATE_IN_LIST;
357                 wake_up(&iscsi_wr_waitQ);
358         }
359         spin_unlock_bh(&iscsi_wr_lock);
360
361         conn->old_write_space(sk);
362
363         TRACE_EXIT();
364         return;
365 }
366
367 static void conn_rsp_timer_fn(unsigned long arg)
368 {
369         struct iscsi_conn *conn = (struct iscsi_conn *)arg;
370
371         TRACE_ENTRY();
372
373         TRACE_DBG("Timer (conn %p)", conn);
374
375         spin_lock_bh(&conn->write_list_lock);
376
377         if (!list_empty(&conn->written_list)) {
378                 struct iscsi_cmnd *wr_cmd = list_entry(conn->written_list.next,
379                                 struct iscsi_cmnd, written_list_entry);
380
381                 if (unlikely(time_after_eq(jiffies, wr_cmd->write_timeout))) {
382                         if (!conn->closing) {
383                                 PRINT_ERROR("Timeout sending data to initiator"
384                                         " %s (SID %llx), closing connection",
385                                         conn->session->initiator_name,
386                                         (long long unsigned int)
387                                                 conn->session->sid);
388                                 mark_conn_closed(conn);
389                         }
390                 } else {
391                         TRACE_DBG("Restarting timer on %ld (conn %p)",
392                                 wr_cmd->write_timeout, conn);
393                         /*
394                          * Timer might have been restarted while we were
395                          * entering here.
396                          */
397                         mod_timer(&conn->rsp_timer, wr_cmd->write_timeout);
398                 }
399         }
400
401         spin_unlock_bh(&conn->write_list_lock);
402
403         TRACE_EXIT();
404         return;
405 }
406
407 /* target_mutex supposed to be locked */
408 void conn_reinst_finished(struct iscsi_conn *conn)
409 {
410         struct iscsi_cmnd *cmnd, *t;
411
412         TRACE_ENTRY();
413
414         clear_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags);
415
416         list_for_each_entry_safe(cmnd, t, &conn->reinst_pending_cmd_list,
417                                         reinst_pending_cmd_list_entry) {
418                 TRACE_MGMT_DBG("Restarting reinst pending cmnd %p",
419                         cmnd);
420                 list_del(&cmnd->reinst_pending_cmd_list_entry);
421                 iscsi_restart_cmnd(cmnd);
422         }
423
424         TRACE_EXIT();
425         return;
426 }
427
428 static void conn_activate(struct iscsi_conn *conn)
429 {
430         TRACE_MGMT_DBG("Enabling conn %p", conn);
431
432         /* Catch double bind */
433         sBUG_ON(conn->sock->sk->sk_state_change == iscsi_state_change);
434
435         write_lock_bh(&conn->sock->sk->sk_callback_lock);
436
437         conn->old_state_change = conn->sock->sk->sk_state_change;
438         conn->sock->sk->sk_state_change = iscsi_state_change;
439
440         conn->old_data_ready = conn->sock->sk->sk_data_ready;
441         conn->sock->sk->sk_data_ready = iscsi_data_ready;
442
443         conn->old_write_space = conn->sock->sk->sk_write_space;
444         conn->sock->sk->sk_write_space = iscsi_write_space_ready;
445
446         write_unlock_bh(&conn->sock->sk->sk_callback_lock);
447
448         /*
449          * Check, if conn was closed while we were initializing it.
450          * This function will make conn rd_active, if necessary.
451          */
452         __iscsi_state_change(conn->sock->sk);
453
454         return;
455 }
456
457 /*
458  * Note: the code below passes a kernel space pointer (&opt) to setsockopt()
459  * while the declaration of setsockopt specifies that it expects a user space
460  * pointer. This seems to work fine, and this approach is also used in some
461  * other parts of the Linux kernel (see e.g. fs/ocfs2/cluster/tcp.c).
462  */
463 static int conn_setup_sock(struct iscsi_conn *conn)
464 {
465         int res = 0;
466         int opt = 1;
467         mm_segment_t oldfs;
468         struct iscsi_session *session = conn->session;
469
470         TRACE_DBG("%llu", (long long unsigned int)session->sid);
471
472         conn->sock = SOCKET_I(conn->file->f_dentry->d_inode);
473
474         if (conn->sock->ops->sendpage == NULL) {
475                 PRINT_ERROR("Socket for sid %llu doesn't support sendpage()",
476                             (long long unsigned int)session->sid);
477                 res = -EINVAL;
478                 goto out;
479         }
480
481 #if 0
482         conn->sock->sk->sk_allocation = GFP_NOIO;
483 #endif
484         conn->sock->sk->sk_user_data = conn;
485
486         oldfs = get_fs();
487         set_fs(get_ds());
488         conn->sock->ops->setsockopt(conn->sock, SOL_TCP, TCP_NODELAY,
489                 (void __force __user *)&opt, sizeof(opt));
490         set_fs(oldfs);
491
492 out:
493         return res;
494 }
495
496 /* target_mutex supposed to be locked */
497 #ifdef CONFIG_SCST_PROC
498 int conn_free(struct iscsi_conn *conn)
499 #else
500 static int conn_free(struct iscsi_conn *conn)
501 #endif
502 {
503         TRACE_MGMT_DBG("Freeing conn %p (sess=%p, %#Lx %u)", conn,
504                        conn->session,
505                        (long long unsigned int)conn->session->sid,
506                        conn->cid);
507
508         del_timer_sync(&conn->rsp_timer);
509
510         sBUG_ON(atomic_read(&conn->conn_ref_cnt) != 0);
511         sBUG_ON(!list_empty(&conn->cmd_list));
512         sBUG_ON(!list_empty(&conn->write_list));
513         sBUG_ON(!list_empty(&conn->written_list));
514         sBUG_ON(conn->conn_reinst_successor != NULL);
515         sBUG_ON(!test_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags));
516
517         /* Just in case if new conn gets freed before the old one */
518         if (test_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags)) {
519                 struct iscsi_conn *c;
520                 TRACE_MGMT_DBG("Freeing being reinstated conn %p", conn);
521                 list_for_each_entry(c, &conn->session->conn_list,
522                                         conn_list_entry) {
523                         if (c->conn_reinst_successor == conn) {
524                                 c->conn_reinst_successor = NULL;
525                                 break;
526                         }
527                 }
528         }
529
530         list_del(&conn->conn_list_entry);
531
532         fput(conn->file);
533         conn->file = NULL;
534         conn->sock = NULL;
535
536         free_page((unsigned long)conn->read_iov);
537
538         kfree(conn);
539
540         return 0;
541 }
542
543 /* target_mutex supposed to be locked */
544 static int iscsi_conn_alloc(struct iscsi_session *session,
545         struct iscsi_kern_conn_info *info, struct iscsi_conn **new_conn)
546 {
547         struct iscsi_conn *conn;
548         int res = 0;
549 #ifndef CONFIG_SCST_PROC
550         struct sock *sk;
551         char addr[64];
552 #endif
553
554         conn = kzalloc(sizeof(*conn), GFP_KERNEL);
555         if (!conn) {
556                 res = -ENOMEM;
557                 goto out_err;
558         }
559
560         TRACE_MGMT_DBG("Creating connection %p for sid %#Lx, cid %u", conn,
561                        (long long unsigned int)session->sid, info->cid);
562
563         /* Changing it, change ISCSI_CONN_IOV_MAX as well !! */
564         conn->read_iov = (struct iovec *)get_zeroed_page(GFP_KERNEL);
565         if (conn->read_iov == NULL) {
566                 res = -ENOMEM;
567                 goto out_err_free_conn;
568         }
569
570         atomic_set(&conn->conn_ref_cnt, 0);
571         conn->session = session;
572         if (session->sess_reinstating)
573                 __set_bit(ISCSI_CONN_REINSTATING, &conn->conn_aflags);
574         conn->cid = info->cid;
575         conn->stat_sn = info->stat_sn;
576         conn->exp_stat_sn = info->exp_stat_sn;
577         conn->rd_state = ISCSI_CONN_RD_STATE_IDLE;
578         conn->wr_state = ISCSI_CONN_WR_STATE_IDLE;
579
580         conn->hdigest_type = info->header_digest;
581         conn->ddigest_type = info->data_digest;
582         res = digest_init(conn);
583         if (res != 0)
584                 goto out_err_free1;
585
586         conn->target = session->target;
587         spin_lock_init(&conn->cmd_list_lock);
588         INIT_LIST_HEAD(&conn->cmd_list);
589         spin_lock_init(&conn->write_list_lock);
590         INIT_LIST_HEAD(&conn->write_list);
591         INIT_LIST_HEAD(&conn->written_list);
592         setup_timer(&conn->rsp_timer, conn_rsp_timer_fn, (unsigned long)conn);
593         init_waitqueue_head(&conn->read_state_waitQ);
594         init_completion(&conn->ready_to_free);
595         INIT_LIST_HEAD(&conn->reinst_pending_cmd_list);
596
597         conn->file = fget(info->fd);
598
599         res = conn_setup_sock(conn);
600         if (res != 0)
601                 goto out_err_free2;
602
603 #ifndef CONFIG_SCST_PROC
604         sk = conn->sock->sk;
605         switch (sk->sk_family) {
606         case AF_INET:
607                 snprintf(addr, sizeof(addr),
608                          "%u.%u.%u.%u", NIPQUAD(inet_sk(sk)->daddr));
609                 break;
610         case AF_INET6:
611 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
612                 snprintf(addr, sizeof(addr),
613                          "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
614                          NIP6(inet6_sk(sk)->daddr));
615 #else
616                 snprintf(addr, sizeof(addr), "[%p6]",
617                         &inet6_sk(sk)->daddr);
618 #endif
619                 break;
620         default:
621                 break;
622         }
623
624         res = kobject_init_and_add(&conn->iscsi_conn_kobj, &iscsi_conn_ktype,
625                 scst_sysfs_get_sess_kobj(session->scst_sess), addr);
626         if (res != 0) {
627                 PRINT_ERROR("Unable create sysfs entries for conn %s",
628                         addr);
629                 goto out_err_free2;
630         }
631
632         TRACE_DBG("conn %p, iscsi_conn_kobj %p", conn, &conn->iscsi_conn_kobj);
633
634         res = sysfs_create_file(&conn->iscsi_conn_kobj,
635                         &iscsi_conn_state_attr.attr);
636         if (res != 0) {
637                 PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
638                         iscsi_conn_state_attr.attr.name, addr);
639                 goto out_err_free3;
640         }
641
642         res = sysfs_create_file(&conn->iscsi_conn_kobj,
643                         &iscsi_conn_cid_attr.attr);
644         if (res != 0) {
645                 PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
646                         iscsi_conn_state_attr.attr.name, addr);
647                 goto out_err_free3;
648         }
649
650         res = sysfs_create_file(&conn->iscsi_conn_kobj,
651                         &iscsi_conn_hdigest_attr.attr);
652         if (res != 0) {
653                 PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
654                         iscsi_conn_hdigest_attr.attr.name, addr);
655                 goto out_err_free3;
656         }
657
658         res = sysfs_create_file(&conn->iscsi_conn_kobj,
659                         &iscsi_conn_ddigest_attr.attr);
660         if (res != 0) {
661                 PRINT_ERROR("Unable create sysfs attribute %s for conn %s",
662                         iscsi_conn_ddigest_attr.attr.name, addr);
663                 goto out_err_free3;
664         }
665 #endif /* CONFIG_SCST_PROC */
666
667         list_add_tail(&conn->conn_list_entry, &session->conn_list);
668
669         *new_conn = conn;
670
671 out:
672         return res;
673
674 #ifndef CONFIG_SCST_PROC
675 out_err_free3:
676         kobject_put(&conn->iscsi_conn_kobj);
677 #endif
678
679 out_err_free2:
680         fput(conn->file);
681
682 out_err_free1:
683         free_page((unsigned long)conn->read_iov);
684
685 out_err_free_conn:
686         kfree(conn);
687
688 out_err:
689         goto out;
690 }
691
692 /* target_mutex supposed to be locked */
693 int conn_add(struct iscsi_session *session, struct iscsi_kern_conn_info *info)
694 {
695         struct iscsi_conn *conn, *new_conn = NULL;
696         int err;
697         bool reinstatement = false;
698
699         conn = conn_lookup(session, info->cid);
700         if ((conn != NULL) &&
701             !test_bit(ISCSI_CONN_SHUTTINGDOWN, &conn->conn_aflags)) {
702                 /* conn reinstatement */
703                 reinstatement = true;
704         } else if (!list_empty(&session->conn_list)) {
705                 err = -EEXIST;
706                 goto out;
707         }
708
709         err = iscsi_conn_alloc(session, info, &new_conn);
710         if (err != 0)
711                 goto out;
712
713         if (reinstatement) {
714                 TRACE_MGMT_DBG("Reinstating conn (old %p, new %p)", conn,
715                         new_conn);
716                 conn->conn_reinst_successor = new_conn;
717                 __set_bit(ISCSI_CONN_REINSTATING, &new_conn->conn_aflags);
718                 __mark_conn_closed(conn, 0);
719         }
720
721         conn_activate(new_conn);
722
723 out:
724         return err;
725 }
726
727 /* target_mutex supposed to be locked */
728 int conn_del(struct iscsi_session *session, struct iscsi_kern_conn_info *info)
729 {
730         struct iscsi_conn *conn;
731         int err = -EEXIST;
732
733         conn = conn_lookup(session, info->cid);
734         if (!conn) {
735                 PRINT_ERROR("Connection %d not found", info->cid);
736                 return err;
737         }
738
739         PRINT_INFO("Deleting connection with initiator %s (%p)",
740                 conn->session->initiator_name, conn);
741
742         __mark_conn_closed(conn, ISCSI_CONN_ACTIVE_CLOSE|ISCSI_CONN_DELETING);
743
744         return 0;
745 }
746
747 #ifdef CONFIG_SCST_EXTRACHECKS
748
749 void iscsi_extracheck_is_rd_thread(struct iscsi_conn *conn)
750 {
751         if (unlikely(current != conn->rd_task)) {
752                 printk(KERN_EMERG "conn %p rd_task != current %p (pid %d)\n",
753                         conn, current, current->pid);
754                 while (in_softirq())
755                         local_bh_enable();
756                 printk(KERN_EMERG "rd_state %x\n", conn->rd_state);
757                 printk(KERN_EMERG "rd_task %p\n", conn->rd_task);
758                 printk(KERN_EMERG "rd_task->pid %d\n", conn->rd_task->pid);
759                 BUG();
760         }
761 }
762
763 void iscsi_extracheck_is_wr_thread(struct iscsi_conn *conn)
764 {
765         if (unlikely(current != conn->wr_task)) {
766                 printk(KERN_EMERG "conn %p wr_task != current %p (pid %d)\n",
767                         conn, current, current->pid);
768                 while (in_softirq())
769                         local_bh_enable();
770                 printk(KERN_EMERG "wr_state %x\n", conn->wr_state);
771                 printk(KERN_EMERG "wr_task %p\n", conn->wr_task);
772                 printk(KERN_EMERG "wr_task->pid %d\n", conn->wr_task->pid);
773                 BUG();
774         }
775 }
776
777 #endif /* CONFIG_SCST_EXTRACHECKS */