hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/scsi/scsi_transport_iscsi.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * iSCSI transport class definitions
34 *
....@@ -5,20 +6,6 @@
56 * Copyright (C) Mike Christie, 2004 - 2005
67 * Copyright (C) Dmitry Yusupov, 2004 - 2005
78 * Copyright (C) Alex Aizman, 2004 - 2005
8
- *
9
- * This program is free software; you can redistribute it and/or modify
10
- * it under the terms of the GNU General Public License as published by
11
- * the Free Software Foundation; either version 2 of the License, or
12
- * (at your option) any later version.
13
- *
14
- * This program is distributed in the hope that it will be useful,
15
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
- * GNU General Public License for more details.
18
- *
19
- * You should have received a copy of the GNU General Public License
20
- * along with this program; if not, write to the Free Software
21
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
229 */
2310 #include <linux/module.h>
2411 #include <linux/mutex.h>
....@@ -38,6 +25,18 @@
3825 #define ISCSI_TRANSPORT_VERSION "2.0-870"
3926
4027 #define ISCSI_SEND_MAX_ALLOWED 10
28
+
29
+#define CREATE_TRACE_POINTS
30
+#include <trace/events/iscsi.h>
31
+
32
+/*
33
+ * Export tracepoint symbols to be used by other modules.
34
+ */
35
+EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_conn);
36
+EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_eh);
37
+EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_session);
38
+EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_tcp);
39
+EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_sw_tcp);
4140
4241 static int dbg_session;
4342 module_param_named(debug_session, dbg_session, int,
....@@ -61,6 +60,9 @@
6160 iscsi_cls_session_printk(KERN_INFO, _session, \
6261 "%s: " dbg_fmt, \
6362 __func__, ##arg); \
63
+ iscsi_dbg_trace(trace_iscsi_dbg_trans_session, \
64
+ &(_session)->dev, \
65
+ "%s " dbg_fmt, __func__, ##arg); \
6466 } while (0);
6567
6668 #define ISCSI_DBG_TRANS_CONN(_conn, dbg_fmt, arg...) \
....@@ -68,7 +70,10 @@
6870 if (dbg_conn) \
6971 iscsi_cls_conn_printk(KERN_INFO, _conn, \
7072 "%s: " dbg_fmt, \
71
- __func__, ##arg); \
73
+ __func__, ##arg); \
74
+ iscsi_dbg_trace(trace_iscsi_dbg_trans_conn, \
75
+ &(_conn)->dev, \
76
+ "%s " dbg_fmt, __func__, ##arg); \
7277 } while (0);
7378
7479 struct iscsi_internal {
....@@ -83,6 +88,8 @@
8388
8489 static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
8590 static struct workqueue_struct *iscsi_eh_timer_workq;
91
+
92
+static struct workqueue_struct *iscsi_conn_cleanup_workq;
8693
8794 static DEFINE_IDA(iscsi_sess_ida);
8895 /*
....@@ -255,9 +262,20 @@
255262 }
256263 EXPORT_SYMBOL_GPL(iscsi_destroy_endpoint);
257264
265
+void iscsi_put_endpoint(struct iscsi_endpoint *ep)
266
+{
267
+ put_device(&ep->dev);
268
+}
269
+EXPORT_SYMBOL_GPL(iscsi_put_endpoint);
270
+
271
+/**
272
+ * iscsi_lookup_endpoint - get ep from handle
273
+ * @handle: endpoint handle
274
+ *
275
+ * Caller must do a iscsi_put_endpoint.
276
+ */
258277 struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
259278 {
260
- struct iscsi_endpoint *ep;
261279 struct device *dev;
262280
263281 dev = class_find_device(&iscsi_endpoint_class, NULL, &handle,
....@@ -265,13 +283,7 @@
265283 if (!dev)
266284 return NULL;
267285
268
- ep = iscsi_dev_to_endpoint(dev);
269
- /*
270
- * we can drop this now because the interface will prevent
271
- * removals and lookups from racing.
272
- */
273
- put_device(dev);
274
- return ep;
286
+ return iscsi_dev_to_endpoint(dev);
275287 }
276288 EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
277289
....@@ -1526,7 +1538,7 @@
15261538 return -ENOTSUPP;
15271539
15281540 snprintf(bsg_name, sizeof(bsg_name), "iscsi_host%d", shost->host_no);
1529
- q = bsg_setup_queue(dev, bsg_name, iscsi_bsg_host_dispatch, 0);
1541
+ q = bsg_setup_queue(dev, bsg_name, iscsi_bsg_host_dispatch, NULL, 0);
15301542 if (IS_ERR(q)) {
15311543 shost_printk(KERN_ERR, shost, "bsg interface failed to "
15321544 "initialize - no request queue\n");
....@@ -1560,10 +1572,7 @@
15601572 struct Scsi_Host *shost = dev_to_shost(dev);
15611573 struct iscsi_cls_host *ihost = shost->shost_data;
15621574
1563
- if (ihost->bsg_q) {
1564
- bsg_unregister_queue(ihost->bsg_q);
1565
- blk_cleanup_queue(ihost->bsg_q);
1566
- }
1575
+ bsg_remove_queue(ihost->bsg_q);
15671576 return 0;
15681577 }
15691578
....@@ -1591,6 +1600,7 @@
15911600 static LIST_HEAD(sesslist);
15921601 static DEFINE_SPINLOCK(sesslock);
15931602 static LIST_HEAD(connlist);
1603
+static LIST_HEAD(connlist_err);
15941604 static DEFINE_SPINLOCK(connlock);
15951605
15961606 static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn)
....@@ -1663,6 +1673,13 @@
16631673 }
16641674 return name;
16651675 }
1676
+
1677
+static char *iscsi_session_target_state_name[] = {
1678
+ [ISCSI_SESSION_TARGET_UNBOUND] = "UNBOUND",
1679
+ [ISCSI_SESSION_TARGET_ALLOCATED] = "ALLOCATED",
1680
+ [ISCSI_SESSION_TARGET_SCANNED] = "SCANNED",
1681
+ [ISCSI_SESSION_TARGET_UNBINDING] = "UNBINDING",
1682
+};
16661683
16671684 int iscsi_session_chkready(struct iscsi_cls_session *session)
16681685 {
....@@ -1795,9 +1812,13 @@
17951812 if ((scan_data->channel == SCAN_WILD_CARD ||
17961813 scan_data->channel == 0) &&
17971814 (scan_data->id == SCAN_WILD_CARD ||
1798
- scan_data->id == id))
1815
+ scan_data->id == id)) {
17991816 scsi_scan_target(&session->dev, 0, id,
18001817 scan_data->lun, scan_data->rescan);
1818
+ spin_lock_irqsave(&session->lock, flags);
1819
+ session->target_state = ISCSI_SESSION_TARGET_SCANNED;
1820
+ spin_unlock_irqrestore(&session->lock, flags);
1821
+ }
18011822 }
18021823
18031824 user_scan_exit:
....@@ -1940,12 +1961,15 @@
19401961 */
19411962 void iscsi_unblock_session(struct iscsi_cls_session *session)
19421963 {
1964
+ flush_work(&session->block_work);
1965
+
19431966 queue_work(iscsi_eh_timer_workq, &session->unblock_work);
19441967 /*
1945
- * make sure all the events have completed before tell the driver
1946
- * it is safe
1968
+ * Blocking the session can be done from any context so we only
1969
+ * queue the block work. Make sure the unblock work has completed
1970
+ * because it flushes/cancels the other works and updates the state.
19471971 */
1948
- flush_workqueue(iscsi_eh_timer_workq);
1972
+ flush_work(&session->unblock_work);
19491973 }
19501974 EXPORT_SYMBOL_GPL(iscsi_unblock_session);
19511975
....@@ -1983,31 +2007,49 @@
19832007 struct iscsi_cls_host *ihost = shost->shost_data;
19842008 unsigned long flags;
19852009 unsigned int target_id;
2010
+ bool remove_target = true;
19862011
19872012 ISCSI_DBG_TRANS_SESSION(session, "Unbinding session\n");
19882013
19892014 /* Prevent new scans and make sure scanning is not in progress */
19902015 mutex_lock(&ihost->mutex);
19912016 spin_lock_irqsave(&session->lock, flags);
1992
- if (session->target_id == ISCSI_MAX_TARGET) {
2017
+ if (session->target_state == ISCSI_SESSION_TARGET_ALLOCATED) {
2018
+ remove_target = false;
2019
+ } else if (session->target_state != ISCSI_SESSION_TARGET_SCANNED) {
19932020 spin_unlock_irqrestore(&session->lock, flags);
19942021 mutex_unlock(&ihost->mutex);
1995
- goto unbind_session_exit;
2022
+ ISCSI_DBG_TRANS_SESSION(session,
2023
+ "Skipping target unbinding: Session is unbound/unbinding.\n");
2024
+ return;
19962025 }
19972026
2027
+ session->target_state = ISCSI_SESSION_TARGET_UNBINDING;
19982028 target_id = session->target_id;
19992029 session->target_id = ISCSI_MAX_TARGET;
20002030 spin_unlock_irqrestore(&session->lock, flags);
20012031 mutex_unlock(&ihost->mutex);
20022032
2033
+ if (remove_target)
2034
+ scsi_remove_target(&session->dev);
2035
+
20032036 if (session->ida_used)
20042037 ida_simple_remove(&iscsi_sess_ida, target_id);
20052038
2006
- scsi_remove_target(&session->dev);
2007
-
2008
-unbind_session_exit:
20092039 iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
20102040 ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n");
2041
+
2042
+ spin_lock_irqsave(&session->lock, flags);
2043
+ session->target_state = ISCSI_SESSION_TARGET_UNBOUND;
2044
+ spin_unlock_irqrestore(&session->lock, flags);
2045
+}
2046
+
2047
+static void __iscsi_destroy_session(struct work_struct *work)
2048
+{
2049
+ struct iscsi_cls_session *session =
2050
+ container_of(work, struct iscsi_cls_session, destroy_work);
2051
+
2052
+ session->transport->destroy_session(session);
20112053 }
20122054
20132055 struct iscsi_cls_session *
....@@ -2032,6 +2074,7 @@
20322074 INIT_WORK(&session->block_work, __iscsi_block_session);
20332075 INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
20342076 INIT_WORK(&session->scan_work, iscsi_scan_session);
2077
+ INIT_WORK(&session->destroy_work, __iscsi_destroy_session);
20352078 spin_lock_init(&session->lock);
20362079
20372080 /* this is released in the dev's release function */
....@@ -2067,6 +2110,9 @@
20672110 session->ida_used = true;
20682111 } else
20692112 session->target_id = target_id;
2113
+ spin_lock_irqsave(&session->lock, flags);
2114
+ session->target_state = ISCSI_SESSION_TARGET_ALLOCATED;
2115
+ spin_unlock_irqrestore(&session->lock, flags);
20702116
20712117 dev_set_name(&session->dev, "session%u", session->sid);
20722118 err = device_add(&session->dev);
....@@ -2075,7 +2121,12 @@
20752121 "could not register session's dev\n");
20762122 goto release_ida;
20772123 }
2078
- transport_register_device(&session->dev);
2124
+ err = transport_register_device(&session->dev);
2125
+ if (err) {
2126
+ iscsi_cls_session_printk(KERN_ERR, session,
2127
+ "could not register transport's dev\n");
2128
+ goto release_dev;
2129
+ }
20792130
20802131 spin_lock_irqsave(&sesslock, flags);
20812132 list_add(&session->sess_list, &sesslist);
....@@ -2085,6 +2136,8 @@
20852136 ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n");
20862137 return 0;
20872138
2139
+release_dev:
2140
+ device_del(&session->dev);
20882141 release_ida:
20892142 if (session->ida_used)
20902143 ida_simple_remove(&iscsi_sess_ida, session->target_id);
....@@ -2150,14 +2203,13 @@
21502203 ISCSI_DBG_TRANS_SESSION(session, "Removing session\n");
21512204
21522205 spin_lock_irqsave(&sesslock, flags);
2153
- list_del(&session->sess_list);
2206
+ if (!list_empty(&session->sess_list))
2207
+ list_del(&session->sess_list);
21542208 spin_unlock_irqrestore(&sesslock, flags);
21552209
2156
- /* make sure there are no blocks/unblocks queued */
2157
- flush_workqueue(iscsi_eh_timer_workq);
2158
- /* make sure the timedout callout is not running */
2159
- if (!cancel_delayed_work(&session->recovery_work))
2160
- flush_workqueue(iscsi_eh_timer_workq);
2210
+ flush_work(&session->block_work);
2211
+ flush_work(&session->unblock_work);
2212
+ cancel_delayed_work_sync(&session->recovery_work);
21612213 /*
21622214 * If we are blocked let commands flow again. The lld or iscsi
21632215 * layer should set up the queuecommand to fail commands.
....@@ -2189,6 +2241,155 @@
21892241 device_del(&session->dev);
21902242 }
21912243 EXPORT_SYMBOL_GPL(iscsi_remove_session);
2244
+
2245
+static void iscsi_stop_conn(struct iscsi_cls_conn *conn, int flag)
2246
+{
2247
+ ISCSI_DBG_TRANS_CONN(conn, "Stopping conn.\n");
2248
+
2249
+ switch (flag) {
2250
+ case STOP_CONN_RECOVER:
2251
+ WRITE_ONCE(conn->state, ISCSI_CONN_FAILED);
2252
+ break;
2253
+ case STOP_CONN_TERM:
2254
+ WRITE_ONCE(conn->state, ISCSI_CONN_DOWN);
2255
+ break;
2256
+ default:
2257
+ iscsi_cls_conn_printk(KERN_ERR, conn, "invalid stop flag %d\n",
2258
+ flag);
2259
+ return;
2260
+ }
2261
+
2262
+ conn->transport->stop_conn(conn, flag);
2263
+ ISCSI_DBG_TRANS_CONN(conn, "Stopping conn done.\n");
2264
+}
2265
+
2266
+static void iscsi_ep_disconnect(struct iscsi_cls_conn *conn, bool is_active)
2267
+{
2268
+ struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
2269
+ struct iscsi_endpoint *ep;
2270
+
2271
+ ISCSI_DBG_TRANS_CONN(conn, "disconnect ep.\n");
2272
+ WRITE_ONCE(conn->state, ISCSI_CONN_FAILED);
2273
+
2274
+ if (!conn->ep || !session->transport->ep_disconnect)
2275
+ return;
2276
+
2277
+ ep = conn->ep;
2278
+ conn->ep = NULL;
2279
+
2280
+ session->transport->unbind_conn(conn, is_active);
2281
+ session->transport->ep_disconnect(ep);
2282
+ ISCSI_DBG_TRANS_CONN(conn, "disconnect ep done.\n");
2283
+}
2284
+
2285
+static void iscsi_if_disconnect_bound_ep(struct iscsi_cls_conn *conn,
2286
+ struct iscsi_endpoint *ep,
2287
+ bool is_active)
2288
+{
2289
+ /* Check if this was a conn error and the kernel took ownership */
2290
+ spin_lock_irq(&conn->lock);
2291
+ if (!test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
2292
+ spin_unlock_irq(&conn->lock);
2293
+ iscsi_ep_disconnect(conn, is_active);
2294
+ } else {
2295
+ spin_unlock_irq(&conn->lock);
2296
+ ISCSI_DBG_TRANS_CONN(conn, "flush kernel conn cleanup.\n");
2297
+ mutex_unlock(&conn->ep_mutex);
2298
+
2299
+ flush_work(&conn->cleanup_work);
2300
+ /*
2301
+ * Userspace is now done with the EP so we can release the ref
2302
+ * iscsi_cleanup_conn_work_fn took.
2303
+ */
2304
+ iscsi_put_endpoint(ep);
2305
+ mutex_lock(&conn->ep_mutex);
2306
+ }
2307
+}
2308
+
2309
+static int iscsi_if_stop_conn(struct iscsi_transport *transport,
2310
+ struct iscsi_uevent *ev)
2311
+{
2312
+ int flag = ev->u.stop_conn.flag;
2313
+ struct iscsi_cls_conn *conn;
2314
+
2315
+ conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
2316
+ if (!conn)
2317
+ return -EINVAL;
2318
+
2319
+ ISCSI_DBG_TRANS_CONN(conn, "iscsi if conn stop.\n");
2320
+ /*
2321
+ * If this is a termination we have to call stop_conn with that flag
2322
+ * so the correct states get set. If we haven't run the work yet try to
2323
+ * avoid the extra run.
2324
+ */
2325
+ if (flag == STOP_CONN_TERM) {
2326
+ cancel_work_sync(&conn->cleanup_work);
2327
+ iscsi_stop_conn(conn, flag);
2328
+ } else {
2329
+ /*
2330
+ * For offload, when iscsid is restarted it won't know about
2331
+ * existing endpoints so it can't do a ep_disconnect. We clean
2332
+ * it up here for userspace.
2333
+ */
2334
+ mutex_lock(&conn->ep_mutex);
2335
+ if (conn->ep)
2336
+ iscsi_if_disconnect_bound_ep(conn, conn->ep, true);
2337
+ mutex_unlock(&conn->ep_mutex);
2338
+
2339
+ /*
2340
+ * Figure out if it was the kernel or userspace initiating this.
2341
+ */
2342
+ spin_lock_irq(&conn->lock);
2343
+ if (!test_and_set_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
2344
+ spin_unlock_irq(&conn->lock);
2345
+ iscsi_stop_conn(conn, flag);
2346
+ } else {
2347
+ spin_unlock_irq(&conn->lock);
2348
+ ISCSI_DBG_TRANS_CONN(conn,
2349
+ "flush kernel conn cleanup.\n");
2350
+ flush_work(&conn->cleanup_work);
2351
+ }
2352
+ /*
2353
+ * Only clear for recovery to avoid extra cleanup runs during
2354
+ * termination.
2355
+ */
2356
+ spin_lock_irq(&conn->lock);
2357
+ clear_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags);
2358
+ spin_unlock_irq(&conn->lock);
2359
+ }
2360
+ ISCSI_DBG_TRANS_CONN(conn, "iscsi if conn stop done.\n");
2361
+ return 0;
2362
+}
2363
+
2364
+static void iscsi_cleanup_conn_work_fn(struct work_struct *work)
2365
+{
2366
+ struct iscsi_cls_conn *conn = container_of(work, struct iscsi_cls_conn,
2367
+ cleanup_work);
2368
+ struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
2369
+
2370
+ mutex_lock(&conn->ep_mutex);
2371
+ /*
2372
+ * Get a ref to the ep, so we don't release its ID until after
2373
+ * userspace is done referencing it in iscsi_if_disconnect_bound_ep.
2374
+ */
2375
+ if (conn->ep)
2376
+ get_device(&conn->ep->dev);
2377
+ iscsi_ep_disconnect(conn, false);
2378
+
2379
+ if (system_state != SYSTEM_RUNNING) {
2380
+ /*
2381
+ * If the user has set up for the session to never timeout
2382
+ * then hang like they wanted. For all other cases fail right
2383
+ * away since userspace is not going to relogin.
2384
+ */
2385
+ if (session->recovery_tmo > 0)
2386
+ session->recovery_tmo = 0;
2387
+ }
2388
+
2389
+ iscsi_stop_conn(conn, STOP_CONN_RECOVER);
2390
+ mutex_unlock(&conn->ep_mutex);
2391
+ ISCSI_DBG_TRANS_CONN(conn, "cleanup done.\n");
2392
+}
21922393
21932394 void iscsi_free_session(struct iscsi_cls_session *session)
21942395 {
....@@ -2228,9 +2429,12 @@
22282429 conn->dd_data = &conn[1];
22292430
22302431 mutex_init(&conn->ep_mutex);
2432
+ spin_lock_init(&conn->lock);
22312433 INIT_LIST_HEAD(&conn->conn_list);
2434
+ INIT_WORK(&conn->cleanup_work, iscsi_cleanup_conn_work_fn);
22322435 conn->transport = transport;
22332436 conn->cid = cid;
2437
+ WRITE_ONCE(conn->state, ISCSI_CONN_DOWN);
22342438
22352439 /* this is released in the dev's release function */
22362440 if (!get_device(&session->dev))
....@@ -2245,7 +2449,12 @@
22452449 "register connection's dev\n");
22462450 goto release_parent_ref;
22472451 }
2248
- transport_register_device(&conn->dev);
2452
+ err = transport_register_device(&conn->dev);
2453
+ if (err) {
2454
+ iscsi_cls_session_printk(KERN_ERR, session, "could not "
2455
+ "register transport's dev\n");
2456
+ goto release_conn_ref;
2457
+ }
22492458
22502459 spin_lock_irqsave(&connlock, flags);
22512460 list_add(&conn->conn_list, &connlist);
....@@ -2254,6 +2463,10 @@
22542463 ISCSI_DBG_TRANS_CONN(conn, "Completed conn creation\n");
22552464 return conn;
22562465
2466
+release_conn_ref:
2467
+ device_unregister(&conn->dev);
2468
+ put_device(&session->dev);
2469
+ return NULL;
22572470 release_parent_ref:
22582471 put_device(&session->dev);
22592472 free_conn:
....@@ -2408,6 +2621,32 @@
24082621 struct iscsi_uevent *ev;
24092622 struct iscsi_internal *priv;
24102623 int len = nlmsg_total_size(sizeof(*ev));
2624
+ unsigned long flags;
2625
+ int state;
2626
+
2627
+ spin_lock_irqsave(&conn->lock, flags);
2628
+ /*
2629
+ * Userspace will only do a stop call if we are at least bound. And, we
2630
+ * only need to do the in kernel cleanup if in the UP state so cmds can
2631
+ * be released to upper layers. If in other states just wait for
2632
+ * userspace to avoid races that can leave the cleanup_work queued.
2633
+ */
2634
+ state = READ_ONCE(conn->state);
2635
+ switch (state) {
2636
+ case ISCSI_CONN_BOUND:
2637
+ case ISCSI_CONN_UP:
2638
+ if (!test_and_set_bit(ISCSI_CLS_CONN_BIT_CLEANUP,
2639
+ &conn->flags)) {
2640
+ queue_work(iscsi_conn_cleanup_workq,
2641
+ &conn->cleanup_work);
2642
+ }
2643
+ break;
2644
+ default:
2645
+ ISCSI_DBG_TRANS_CONN(conn, "Got conn error in state %d\n",
2646
+ state);
2647
+ break;
2648
+ }
2649
+ spin_unlock_irqrestore(&conn->lock, flags);
24112650
24122651 priv = iscsi_if_transport_lookup(conn->transport);
24132652 if (!priv)
....@@ -2742,27 +2981,34 @@
27422981 if (!conn)
27432982 return -EINVAL;
27442983
2984
+ ISCSI_DBG_TRANS_CONN(conn, "Flushing cleanup during destruction\n");
2985
+ flush_work(&conn->cleanup_work);
27452986 ISCSI_DBG_TRANS_CONN(conn, "Destroying transport conn\n");
2987
+
27462988 if (transport->destroy_conn)
27472989 transport->destroy_conn(conn);
2748
-
27492990 return 0;
27502991 }
27512992
27522993 static int
2753
-iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
2994
+iscsi_if_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen)
27542995 {
27552996 char *data = (char*)ev + sizeof(*ev);
27562997 struct iscsi_cls_conn *conn;
27572998 struct iscsi_cls_session *session;
2758
- int err = 0, value = 0;
2999
+ int err = 0, value = 0, state;
27593000
2760
- if (ev->u.set_param.len > PAGE_SIZE)
3001
+ if (ev->u.set_param.len > rlen ||
3002
+ ev->u.set_param.len > PAGE_SIZE)
27613003 return -EINVAL;
27623004
27633005 session = iscsi_session_lookup(ev->u.set_param.sid);
27643006 conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
27653007 if (!conn || !session)
3008
+ return -EINVAL;
3009
+
3010
+ /* data will be regarded as NULL-ended string, do length check */
3011
+ if (strlen(data) > ev->u.set_param.len)
27663012 return -EINVAL;
27673013
27683014 switch (ev->u.set_param.param) {
....@@ -2772,8 +3018,13 @@
27723018 session->recovery_tmo = value;
27733019 break;
27743020 default:
2775
- err = transport->set_param(conn, ev->u.set_param.param,
2776
- data, ev->u.set_param.len);
3021
+ state = READ_ONCE(conn->state);
3022
+ if (state == ISCSI_CONN_BOUND || state == ISCSI_CONN_UP) {
3023
+ err = transport->set_param(conn, ev->u.set_param.param,
3024
+ data, ev->u.set_param.len);
3025
+ } else {
3026
+ return -ENOTCONN;
3027
+ }
27773028 }
27783029
27793030 return err;
....@@ -2828,20 +3079,28 @@
28283079 ep = iscsi_lookup_endpoint(ep_handle);
28293080 if (!ep)
28303081 return -EINVAL;
3082
+
28313083 conn = ep->conn;
2832
- if (conn) {
2833
- mutex_lock(&conn->ep_mutex);
2834
- conn->ep = NULL;
2835
- mutex_unlock(&conn->ep_mutex);
3084
+ if (!conn) {
3085
+ /*
3086
+ * conn was not even bound yet, so we can't get iscsi conn
3087
+ * failures yet.
3088
+ */
3089
+ transport->ep_disconnect(ep);
3090
+ goto put_ep;
28363091 }
28373092
2838
- transport->ep_disconnect(ep);
3093
+ mutex_lock(&conn->ep_mutex);
3094
+ iscsi_if_disconnect_bound_ep(conn, ep, false);
3095
+ mutex_unlock(&conn->ep_mutex);
3096
+put_ep:
3097
+ iscsi_put_endpoint(ep);
28393098 return 0;
28403099 }
28413100
28423101 static int
28433102 iscsi_if_transport_ep(struct iscsi_transport *transport,
2844
- struct iscsi_uevent *ev, int msg_type)
3103
+ struct iscsi_uevent *ev, int msg_type, u32 rlen)
28453104 {
28463105 struct iscsi_endpoint *ep;
28473106 int rc = 0;
....@@ -2849,7 +3108,10 @@
28493108 switch (msg_type) {
28503109 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
28513110 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
2852
- rc = iscsi_if_ep_connect(transport, ev, msg_type);
3111
+ if (rlen < sizeof(struct sockaddr))
3112
+ rc = -EINVAL;
3113
+ else
3114
+ rc = iscsi_if_ep_connect(transport, ev, msg_type);
28533115 break;
28543116 case ISCSI_UEVENT_TRANSPORT_EP_POLL:
28553117 if (!transport->ep_poll)
....@@ -2861,6 +3123,7 @@
28613123
28623124 ev->r.retcode = transport->ep_poll(ep,
28633125 ev->u.ep_poll.timeout_ms);
3126
+ iscsi_put_endpoint(ep);
28643127 break;
28653128 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
28663129 rc = iscsi_if_ep_disconnect(transport,
....@@ -2872,11 +3135,14 @@
28723135
28733136 static int
28743137 iscsi_tgt_dscvr(struct iscsi_transport *transport,
2875
- struct iscsi_uevent *ev)
3138
+ struct iscsi_uevent *ev, u32 rlen)
28763139 {
28773140 struct Scsi_Host *shost;
28783141 struct sockaddr *dst_addr;
28793142 int err;
3143
+
3144
+ if (rlen < sizeof(*dst_addr))
3145
+ return -EINVAL;
28803146
28813147 if (!transport->tgt_dscvr)
28823148 return -EINVAL;
....@@ -2898,7 +3164,7 @@
28983164
28993165 static int
29003166 iscsi_set_host_param(struct iscsi_transport *transport,
2901
- struct iscsi_uevent *ev)
3167
+ struct iscsi_uevent *ev, u32 rlen)
29023168 {
29033169 char *data = (char*)ev + sizeof(*ev);
29043170 struct Scsi_Host *shost;
....@@ -2907,7 +3173,8 @@
29073173 if (!transport->set_host_param)
29083174 return -ENOSYS;
29093175
2910
- if (ev->u.set_host_param.len > PAGE_SIZE)
3176
+ if (ev->u.set_host_param.len > rlen ||
3177
+ ev->u.set_host_param.len > PAGE_SIZE)
29113178 return -EINVAL;
29123179
29133180 shost = scsi_host_lookup(ev->u.set_host_param.host_no);
....@@ -2917,6 +3184,10 @@
29173184 return -ENODEV;
29183185 }
29193186
3187
+ /* see similar check in iscsi_if_set_param() */
3188
+ if (strlen(data) > ev->u.set_host_param.len)
3189
+ return -EINVAL;
3190
+
29203191 err = transport->set_host_param(shost, ev->u.set_host_param.param,
29213192 data, ev->u.set_host_param.len);
29223193 scsi_host_put(shost);
....@@ -2924,11 +3195,14 @@
29243195 }
29253196
29263197 static int
2927
-iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
3198
+iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen)
29283199 {
29293200 struct Scsi_Host *shost;
29303201 struct iscsi_path *params;
29313202 int err;
3203
+
3204
+ if (rlen < sizeof(*params))
3205
+ return -EINVAL;
29323206
29333207 if (!transport->set_path)
29343208 return -ENOSYS;
....@@ -2989,11 +3263,14 @@
29893263 }
29903264
29913265 static int
2992
-iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev)
3266
+iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen)
29933267 {
29943268 struct Scsi_Host *shost;
29953269 struct sockaddr *dst_addr;
29963270 int err;
3271
+
3272
+ if (rlen < sizeof(*dst_addr))
3273
+ return -EINVAL;
29973274
29983275 if (!transport->send_ping)
29993276 return -ENOSYS;
....@@ -3491,19 +3768,122 @@
34913768 return err;
34923769 }
34933770
3771
+static int iscsi_if_transport_conn(struct iscsi_transport *transport,
3772
+ struct nlmsghdr *nlh, u32 pdu_len)
3773
+{
3774
+ struct iscsi_uevent *ev = nlmsg_data(nlh);
3775
+ struct iscsi_cls_session *session;
3776
+ struct iscsi_cls_conn *conn = NULL;
3777
+ struct iscsi_endpoint *ep;
3778
+ int err = 0;
3779
+
3780
+ switch (nlh->nlmsg_type) {
3781
+ case ISCSI_UEVENT_CREATE_CONN:
3782
+ return iscsi_if_create_conn(transport, ev);
3783
+ case ISCSI_UEVENT_DESTROY_CONN:
3784
+ return iscsi_if_destroy_conn(transport, ev);
3785
+ case ISCSI_UEVENT_STOP_CONN:
3786
+ return iscsi_if_stop_conn(transport, ev);
3787
+ }
3788
+
3789
+ /*
3790
+ * The following cmds need to be run under the ep_mutex so in kernel
3791
+ * conn cleanup (ep_disconnect + unbind and conn) is not done while
3792
+ * these are running. They also must not run if we have just run a conn
3793
+ * cleanup because they would set the state in a way that might allow
3794
+ * IO or send IO themselves.
3795
+ */
3796
+ switch (nlh->nlmsg_type) {
3797
+ case ISCSI_UEVENT_START_CONN:
3798
+ conn = iscsi_conn_lookup(ev->u.start_conn.sid,
3799
+ ev->u.start_conn.cid);
3800
+ break;
3801
+ case ISCSI_UEVENT_BIND_CONN:
3802
+ conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
3803
+ break;
3804
+ case ISCSI_UEVENT_SEND_PDU:
3805
+ conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
3806
+ break;
3807
+ }
3808
+
3809
+ if (!conn)
3810
+ return -EINVAL;
3811
+
3812
+ mutex_lock(&conn->ep_mutex);
3813
+ spin_lock_irq(&conn->lock);
3814
+ if (test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
3815
+ spin_unlock_irq(&conn->lock);
3816
+ mutex_unlock(&conn->ep_mutex);
3817
+ ev->r.retcode = -ENOTCONN;
3818
+ return 0;
3819
+ }
3820
+ spin_unlock_irq(&conn->lock);
3821
+
3822
+ switch (nlh->nlmsg_type) {
3823
+ case ISCSI_UEVENT_BIND_CONN:
3824
+ session = iscsi_session_lookup(ev->u.b_conn.sid);
3825
+ if (!session) {
3826
+ err = -EINVAL;
3827
+ break;
3828
+ }
3829
+
3830
+ ev->r.retcode = transport->bind_conn(session, conn,
3831
+ ev->u.b_conn.transport_eph,
3832
+ ev->u.b_conn.is_leading);
3833
+ if (!ev->r.retcode)
3834
+ WRITE_ONCE(conn->state, ISCSI_CONN_BOUND);
3835
+
3836
+ if (ev->r.retcode || !transport->ep_connect)
3837
+ break;
3838
+
3839
+ ep = iscsi_lookup_endpoint(ev->u.b_conn.transport_eph);
3840
+ if (ep) {
3841
+ ep->conn = conn;
3842
+ conn->ep = ep;
3843
+ iscsi_put_endpoint(ep);
3844
+ } else {
3845
+ err = -ENOTCONN;
3846
+ iscsi_cls_conn_printk(KERN_ERR, conn,
3847
+ "Could not set ep conn binding\n");
3848
+ }
3849
+ break;
3850
+ case ISCSI_UEVENT_START_CONN:
3851
+ ev->r.retcode = transport->start_conn(conn);
3852
+ if (!ev->r.retcode)
3853
+ WRITE_ONCE(conn->state, ISCSI_CONN_UP);
3854
+
3855
+ break;
3856
+ case ISCSI_UEVENT_SEND_PDU:
3857
+ if ((ev->u.send_pdu.hdr_size > pdu_len) ||
3858
+ (ev->u.send_pdu.data_size > (pdu_len - ev->u.send_pdu.hdr_size))) {
3859
+ err = -EINVAL;
3860
+ break;
3861
+ }
3862
+
3863
+ ev->r.retcode = transport->send_pdu(conn,
3864
+ (struct iscsi_hdr *)((char *)ev + sizeof(*ev)),
3865
+ (char *)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
3866
+ ev->u.send_pdu.data_size);
3867
+ break;
3868
+ default:
3869
+ err = -ENOSYS;
3870
+ }
3871
+
3872
+ mutex_unlock(&conn->ep_mutex);
3873
+ return err;
3874
+}
34943875
34953876 static int
34963877 iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
34973878 {
34983879 int err = 0;
34993880 u32 portid;
3500
- u32 pdu_len;
35013881 struct iscsi_uevent *ev = nlmsg_data(nlh);
35023882 struct iscsi_transport *transport = NULL;
35033883 struct iscsi_internal *priv;
35043884 struct iscsi_cls_session *session;
3505
- struct iscsi_cls_conn *conn;
35063885 struct iscsi_endpoint *ep = NULL;
3886
+ u32 rlen;
35073887
35083888 if (!netlink_capable(skb, CAP_SYS_ADMIN))
35093889 return -EPERM;
....@@ -3522,6 +3902,13 @@
35223902 return -EINVAL;
35233903
35243904 portid = NETLINK_CB(skb).portid;
3905
+
3906
+ /*
3907
+ * Even though the remaining payload may not be regarded as nlattr,
3908
+ * (like address or something else), calculate the remaining length
3909
+ * here to ease following length checks.
3910
+ */
3911
+ rlen = nlmsg_attrlen(nlh, sizeof(*ev));
35253912
35263913 switch (nlh->nlmsg_type) {
35273914 case ISCSI_UEVENT_CREATE_SESSION:
....@@ -3543,6 +3930,7 @@
35433930 ev->u.c_bound_session.initial_cmdsn,
35443931 ev->u.c_bound_session.cmds_max,
35453932 ev->u.c_bound_session.queue_depth);
3933
+ iscsi_put_endpoint(ep);
35463934 break;
35473935 case ISCSI_UEVENT_DESTROY_SESSION:
35483936 session = iscsi_session_lookup(ev->u.d_session.sid);
....@@ -3553,6 +3941,23 @@
35533941 else
35543942 transport->destroy_session(session);
35553943 break;
3944
+ case ISCSI_UEVENT_DESTROY_SESSION_ASYNC:
3945
+ session = iscsi_session_lookup(ev->u.d_session.sid);
3946
+ if (!session)
3947
+ err = -EINVAL;
3948
+ else if (iscsi_session_has_conns(ev->u.d_session.sid))
3949
+ err = -EBUSY;
3950
+ else {
3951
+ unsigned long flags;
3952
+
3953
+ /* Prevent this session from being found again */
3954
+ spin_lock_irqsave(&sesslock, flags);
3955
+ list_del_init(&session->sess_list);
3956
+ spin_unlock_irqrestore(&sesslock, flags);
3957
+
3958
+ queue_work(system_unbound_wq, &session->destroy_work);
3959
+ }
3960
+ break;
35563961 case ISCSI_UEVENT_UNBIND_SESSION:
35573962 session = iscsi_session_lookup(ev->u.d_session.sid);
35583963 if (session)
....@@ -3561,76 +3966,16 @@
35613966 else
35623967 err = -EINVAL;
35633968 break;
3564
- case ISCSI_UEVENT_CREATE_CONN:
3565
- err = iscsi_if_create_conn(transport, ev);
3566
- break;
3567
- case ISCSI_UEVENT_DESTROY_CONN:
3568
- err = iscsi_if_destroy_conn(transport, ev);
3569
- break;
3570
- case ISCSI_UEVENT_BIND_CONN:
3571
- session = iscsi_session_lookup(ev->u.b_conn.sid);
3572
- conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
3573
-
3574
- if (conn && conn->ep)
3575
- iscsi_if_ep_disconnect(transport, conn->ep->id);
3576
-
3577
- if (!session || !conn) {
3578
- err = -EINVAL;
3579
- break;
3580
- }
3581
-
3582
- ev->r.retcode = transport->bind_conn(session, conn,
3583
- ev->u.b_conn.transport_eph,
3584
- ev->u.b_conn.is_leading);
3585
- if (ev->r.retcode || !transport->ep_connect)
3586
- break;
3587
-
3588
- ep = iscsi_lookup_endpoint(ev->u.b_conn.transport_eph);
3589
- if (ep) {
3590
- ep->conn = conn;
3591
-
3592
- mutex_lock(&conn->ep_mutex);
3593
- conn->ep = ep;
3594
- mutex_unlock(&conn->ep_mutex);
3595
- } else
3596
- iscsi_cls_conn_printk(KERN_ERR, conn,
3597
- "Could not set ep conn "
3598
- "binding\n");
3599
- break;
36003969 case ISCSI_UEVENT_SET_PARAM:
3601
- err = iscsi_set_param(transport, ev);
3970
+ err = iscsi_if_set_param(transport, ev, rlen);
36023971 break;
3603
- case ISCSI_UEVENT_START_CONN:
3604
- conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid);
3605
- if (conn)
3606
- ev->r.retcode = transport->start_conn(conn);
3607
- else
3608
- err = -EINVAL;
3609
- break;
3972
+ case ISCSI_UEVENT_CREATE_CONN:
3973
+ case ISCSI_UEVENT_DESTROY_CONN:
36103974 case ISCSI_UEVENT_STOP_CONN:
3611
- conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
3612
- if (conn)
3613
- transport->stop_conn(conn, ev->u.stop_conn.flag);
3614
- else
3615
- err = -EINVAL;
3616
- break;
3975
+ case ISCSI_UEVENT_START_CONN:
3976
+ case ISCSI_UEVENT_BIND_CONN:
36173977 case ISCSI_UEVENT_SEND_PDU:
3618
- pdu_len = nlh->nlmsg_len - sizeof(*nlh) - sizeof(*ev);
3619
-
3620
- if ((ev->u.send_pdu.hdr_size > pdu_len) ||
3621
- (ev->u.send_pdu.data_size > (pdu_len - ev->u.send_pdu.hdr_size))) {
3622
- err = -EINVAL;
3623
- break;
3624
- }
3625
-
3626
- conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
3627
- if (conn)
3628
- ev->r.retcode = transport->send_pdu(conn,
3629
- (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
3630
- (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
3631
- ev->u.send_pdu.data_size);
3632
- else
3633
- err = -EINVAL;
3978
+ err = iscsi_if_transport_conn(transport, nlh, rlen);
36343979 break;
36353980 case ISCSI_UEVENT_GET_STATS:
36363981 err = iscsi_if_get_stats(transport, nlh);
....@@ -3639,23 +3984,22 @@
36393984 case ISCSI_UEVENT_TRANSPORT_EP_POLL:
36403985 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
36413986 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
3642
- err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
3987
+ err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type, rlen);
36433988 break;
36443989 case ISCSI_UEVENT_TGT_DSCVR:
3645
- err = iscsi_tgt_dscvr(transport, ev);
3990
+ err = iscsi_tgt_dscvr(transport, ev, rlen);
36463991 break;
36473992 case ISCSI_UEVENT_SET_HOST_PARAM:
3648
- err = iscsi_set_host_param(transport, ev);
3993
+ err = iscsi_set_host_param(transport, ev, rlen);
36493994 break;
36503995 case ISCSI_UEVENT_PATH_UPDATE:
3651
- err = iscsi_set_path(transport, ev);
3996
+ err = iscsi_set_path(transport, ev, rlen);
36523997 break;
36533998 case ISCSI_UEVENT_SET_IFACE_PARAMS:
3654
- err = iscsi_set_iface_params(transport, ev,
3655
- nlmsg_attrlen(nlh, sizeof(*ev)));
3999
+ err = iscsi_set_iface_params(transport, ev, rlen);
36564000 break;
36574001 case ISCSI_UEVENT_PING:
3658
- err = iscsi_send_ping(transport, ev);
4002
+ err = iscsi_send_ping(transport, ev, rlen);
36594003 break;
36604004 case ISCSI_UEVENT_GET_CHAP:
36614005 err = iscsi_get_chap(transport, nlh);
....@@ -3664,13 +4008,10 @@
36644008 err = iscsi_delete_chap(transport, ev);
36654009 break;
36664010 case ISCSI_UEVENT_SET_FLASHNODE_PARAMS:
3667
- err = iscsi_set_flashnode_param(transport, ev,
3668
- nlmsg_attrlen(nlh,
3669
- sizeof(*ev)));
4011
+ err = iscsi_set_flashnode_param(transport, ev, rlen);
36704012 break;
36714013 case ISCSI_UEVENT_NEW_FLASHNODE:
3672
- err = iscsi_new_flashnode(transport, ev,
3673
- nlmsg_attrlen(nlh, sizeof(*ev)));
4014
+ err = iscsi_new_flashnode(transport, ev, rlen);
36744015 break;
36754016 case ISCSI_UEVENT_DEL_FLASHNODE:
36764017 err = iscsi_del_flashnode(transport, ev);
....@@ -3685,8 +4026,7 @@
36854026 err = iscsi_logout_flashnode_sid(transport, ev);
36864027 break;
36874028 case ISCSI_UEVENT_SET_CHAP:
3688
- err = iscsi_set_chap(transport, ev,
3689
- nlmsg_attrlen(nlh, sizeof(*ev)));
4029
+ err = iscsi_set_chap(transport, ev, rlen);
36904030 break;
36914031 case ISCSI_UEVENT_GET_HOST_STATS:
36924032 err = iscsi_get_host_stats(transport, nlh);
....@@ -3808,6 +4148,28 @@
38084148 iscsi_conn_attr(tcp_recv_wsf, ISCSI_PARAM_TCP_RECV_WSF);
38094149 iscsi_conn_attr(local_ipaddr, ISCSI_PARAM_LOCAL_IPADDR);
38104150
4151
+static const char *const connection_state_names[] = {
4152
+ [ISCSI_CONN_UP] = "up",
4153
+ [ISCSI_CONN_DOWN] = "down",
4154
+ [ISCSI_CONN_FAILED] = "failed",
4155
+ [ISCSI_CONN_BOUND] = "bound"
4156
+};
4157
+
4158
+static ssize_t show_conn_state(struct device *dev,
4159
+ struct device_attribute *attr, char *buf)
4160
+{
4161
+ struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent);
4162
+ const char *state = "unknown";
4163
+ int conn_state = READ_ONCE(conn->state);
4164
+
4165
+ if (conn_state >= 0 &&
4166
+ conn_state < ARRAY_SIZE(connection_state_names))
4167
+ state = connection_state_names[conn_state];
4168
+
4169
+ return sysfs_emit(buf, "%s\n", state);
4170
+}
4171
+static ISCSI_CLASS_ATTR(conn, state, S_IRUGO, show_conn_state,
4172
+ NULL);
38114173
38124174 #define iscsi_conn_ep_attr_show(param) \
38134175 static ssize_t show_conn_ep_param_##param(struct device *dev, \
....@@ -3877,6 +4239,7 @@
38774239 &dev_attr_conn_tcp_xmit_wsf.attr,
38784240 &dev_attr_conn_tcp_recv_wsf.attr,
38794241 &dev_attr_conn_local_ipaddr.attr,
4242
+ &dev_attr_conn_state.attr,
38804243 NULL,
38814244 };
38824245
....@@ -3948,6 +4311,8 @@
39484311 param = ISCSI_PARAM_TCP_RECV_WSF;
39494312 else if (attr == &dev_attr_conn_local_ipaddr.attr)
39504313 param = ISCSI_PARAM_LOCAL_IPADDR;
4314
+ else if (attr == &dev_attr_conn_state.attr)
4315
+ return S_IRUGO;
39514316 else {
39524317 WARN_ONCE(1, "Invalid conn attr");
39534318 return 0;
....@@ -4023,6 +4388,19 @@
40234388 iscsi_session_attr(def_taskmgmt_tmo, ISCSI_PARAM_DEF_TASKMGMT_TMO, 0);
40244389 iscsi_session_attr(discovery_parent_idx, ISCSI_PARAM_DISCOVERY_PARENT_IDX, 0);
40254390 iscsi_session_attr(discovery_parent_type, ISCSI_PARAM_DISCOVERY_PARENT_TYPE, 0);
4391
+
4392
+static ssize_t
4393
+show_priv_session_target_state(struct device *dev, struct device_attribute *attr,
4394
+ char *buf)
4395
+{
4396
+ struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
4397
+
4398
+ return sysfs_emit(buf, "%s\n",
4399
+ iscsi_session_target_state_name[session->target_state]);
4400
+}
4401
+
4402
+static ISCSI_CLASS_ATTR(priv_sess, target_state, S_IRUGO,
4403
+ show_priv_session_target_state, NULL);
40264404
40274405 static ssize_t
40284406 show_priv_session_state(struct device *dev, struct device_attribute *attr,
....@@ -4126,6 +4504,7 @@
41264504 &dev_attr_sess_boot_target.attr,
41274505 &dev_attr_priv_sess_recovery_tmo.attr,
41284506 &dev_attr_priv_sess_state.attr,
4507
+ &dev_attr_priv_sess_target_state.attr,
41294508 &dev_attr_priv_sess_creator.attr,
41304509 &dev_attr_sess_chap_out_idx.attr,
41314510 &dev_attr_sess_chap_in_idx.attr,
....@@ -4238,6 +4617,8 @@
42384617 else if (attr == &dev_attr_priv_sess_recovery_tmo.attr)
42394618 return S_IRUGO | S_IWUSR;
42404619 else if (attr == &dev_attr_priv_sess_state.attr)
4620
+ return S_IRUGO;
4621
+ else if (attr == &dev_attr_priv_sess_target_state.attr)
42414622 return S_IRUGO;
42424623 else if (attr == &dev_attr_priv_sess_creator.attr)
42434624 return S_IRUGO;
....@@ -4454,6 +4835,7 @@
44544835 int err;
44554836
44564837 BUG_ON(!tt);
4838
+ WARN_ON(tt->ep_disconnect && !tt->unbind_conn);
44574839
44584840 priv = iscsi_if_transport_lookup(tt);
44594841 if (priv)
....@@ -4540,6 +4922,20 @@
45404922 }
45414923 EXPORT_SYMBOL_GPL(iscsi_unregister_transport);
45424924
4925
+void iscsi_dbg_trace(void (*trace)(struct device *dev, struct va_format *),
4926
+ struct device *dev, const char *fmt, ...)
4927
+{
4928
+ struct va_format vaf;
4929
+ va_list args;
4930
+
4931
+ va_start(args, fmt);
4932
+ vaf.fmt = fmt;
4933
+ vaf.va = &args;
4934
+ trace(dev, &vaf);
4935
+ va_end(args);
4936
+}
4937
+EXPORT_SYMBOL_GPL(iscsi_dbg_trace);
4938
+
45434939 static __init int iscsi_transport_init(void)
45444940 {
45454941 int err;
....@@ -4586,14 +4982,26 @@
45864982 goto unregister_flashnode_bus;
45874983 }
45884984
4589
- iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh");
4985
+ iscsi_eh_timer_workq = alloc_workqueue("%s",
4986
+ WQ_SYSFS | __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_UNBOUND,
4987
+ 1, "iscsi_eh");
45904988 if (!iscsi_eh_timer_workq) {
45914989 err = -ENOMEM;
45924990 goto release_nls;
45934991 }
45944992
4993
+ iscsi_conn_cleanup_workq = alloc_workqueue("%s",
4994
+ WQ_SYSFS | WQ_MEM_RECLAIM | WQ_UNBOUND, 0,
4995
+ "iscsi_conn_cleanup");
4996
+ if (!iscsi_conn_cleanup_workq) {
4997
+ err = -ENOMEM;
4998
+ goto destroy_wq;
4999
+ }
5000
+
45955001 return 0;
45965002
5003
+destroy_wq:
5004
+ destroy_workqueue(iscsi_eh_timer_workq);
45975005 release_nls:
45985006 netlink_kernel_release(nls);
45995007 unregister_flashnode_bus:
....@@ -4615,6 +5023,7 @@
46155023
46165024 static void __exit iscsi_transport_exit(void)
46175025 {
5026
+ destroy_workqueue(iscsi_conn_cleanup_workq);
46185027 destroy_workqueue(iscsi_eh_timer_workq);
46195028 netlink_kernel_release(nls);
46205029 bus_unregister(&iscsi_flashnode_bus);