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