forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 072de836f53be56a70cecf70b43ae43b7ce17376
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)
....@@ -1940,12 +1950,15 @@
19401950 */
19411951 void iscsi_unblock_session(struct iscsi_cls_session *session)
19421952 {
1953
+ flush_work(&session->block_work);
1954
+
19431955 queue_work(iscsi_eh_timer_workq, &session->unblock_work);
19441956 /*
1945
- * make sure all the events have completed before tell the driver
1946
- * it is safe
1957
+ * Blocking the session can be done from any context so we only
1958
+ * queue the block work. Make sure the unblock work has completed
1959
+ * because it flushes/cancels the other works and updates the state.
19471960 */
1948
- flush_workqueue(iscsi_eh_timer_workq);
1961
+ flush_work(&session->unblock_work);
19491962 }
19501963 EXPORT_SYMBOL_GPL(iscsi_unblock_session);
19511964
....@@ -2000,14 +2013,22 @@
20002013 spin_unlock_irqrestore(&session->lock, flags);
20012014 mutex_unlock(&ihost->mutex);
20022015
2016
+ scsi_remove_target(&session->dev);
2017
+
20032018 if (session->ida_used)
20042019 ida_simple_remove(&iscsi_sess_ida, target_id);
2005
-
2006
- scsi_remove_target(&session->dev);
20072020
20082021 unbind_session_exit:
20092022 iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
20102023 ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n");
2024
+}
2025
+
2026
+static void __iscsi_destroy_session(struct work_struct *work)
2027
+{
2028
+ struct iscsi_cls_session *session =
2029
+ container_of(work, struct iscsi_cls_session, destroy_work);
2030
+
2031
+ session->transport->destroy_session(session);
20112032 }
20122033
20132034 struct iscsi_cls_session *
....@@ -2032,6 +2053,7 @@
20322053 INIT_WORK(&session->block_work, __iscsi_block_session);
20332054 INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
20342055 INIT_WORK(&session->scan_work, iscsi_scan_session);
2056
+ INIT_WORK(&session->destroy_work, __iscsi_destroy_session);
20352057 spin_lock_init(&session->lock);
20362058
20372059 /* this is released in the dev's release function */
....@@ -2075,7 +2097,12 @@
20752097 "could not register session's dev\n");
20762098 goto release_ida;
20772099 }
2078
- transport_register_device(&session->dev);
2100
+ err = transport_register_device(&session->dev);
2101
+ if (err) {
2102
+ iscsi_cls_session_printk(KERN_ERR, session,
2103
+ "could not register transport's dev\n");
2104
+ goto release_dev;
2105
+ }
20792106
20802107 spin_lock_irqsave(&sesslock, flags);
20812108 list_add(&session->sess_list, &sesslist);
....@@ -2085,6 +2112,8 @@
20852112 ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n");
20862113 return 0;
20872114
2115
+release_dev:
2116
+ device_del(&session->dev);
20882117 release_ida:
20892118 if (session->ida_used)
20902119 ida_simple_remove(&iscsi_sess_ida, session->target_id);
....@@ -2150,14 +2179,13 @@
21502179 ISCSI_DBG_TRANS_SESSION(session, "Removing session\n");
21512180
21522181 spin_lock_irqsave(&sesslock, flags);
2153
- list_del(&session->sess_list);
2182
+ if (!list_empty(&session->sess_list))
2183
+ list_del(&session->sess_list);
21542184 spin_unlock_irqrestore(&sesslock, flags);
21552185
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);
2186
+ flush_work(&session->block_work);
2187
+ flush_work(&session->unblock_work);
2188
+ cancel_delayed_work_sync(&session->recovery_work);
21612189 /*
21622190 * If we are blocked let commands flow again. The lld or iscsi
21632191 * layer should set up the queuecommand to fail commands.
....@@ -2189,6 +2217,155 @@
21892217 device_del(&session->dev);
21902218 }
21912219 EXPORT_SYMBOL_GPL(iscsi_remove_session);
2220
+
2221
+static void iscsi_stop_conn(struct iscsi_cls_conn *conn, int flag)
2222
+{
2223
+ ISCSI_DBG_TRANS_CONN(conn, "Stopping conn.\n");
2224
+
2225
+ switch (flag) {
2226
+ case STOP_CONN_RECOVER:
2227
+ WRITE_ONCE(conn->state, ISCSI_CONN_FAILED);
2228
+ break;
2229
+ case STOP_CONN_TERM:
2230
+ WRITE_ONCE(conn->state, ISCSI_CONN_DOWN);
2231
+ break;
2232
+ default:
2233
+ iscsi_cls_conn_printk(KERN_ERR, conn, "invalid stop flag %d\n",
2234
+ flag);
2235
+ return;
2236
+ }
2237
+
2238
+ conn->transport->stop_conn(conn, flag);
2239
+ ISCSI_DBG_TRANS_CONN(conn, "Stopping conn done.\n");
2240
+}
2241
+
2242
+static void iscsi_ep_disconnect(struct iscsi_cls_conn *conn, bool is_active)
2243
+{
2244
+ struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
2245
+ struct iscsi_endpoint *ep;
2246
+
2247
+ ISCSI_DBG_TRANS_CONN(conn, "disconnect ep.\n");
2248
+ WRITE_ONCE(conn->state, ISCSI_CONN_FAILED);
2249
+
2250
+ if (!conn->ep || !session->transport->ep_disconnect)
2251
+ return;
2252
+
2253
+ ep = conn->ep;
2254
+ conn->ep = NULL;
2255
+
2256
+ session->transport->unbind_conn(conn, is_active);
2257
+ session->transport->ep_disconnect(ep);
2258
+ ISCSI_DBG_TRANS_CONN(conn, "disconnect ep done.\n");
2259
+}
2260
+
2261
+static void iscsi_if_disconnect_bound_ep(struct iscsi_cls_conn *conn,
2262
+ struct iscsi_endpoint *ep,
2263
+ bool is_active)
2264
+{
2265
+ /* Check if this was a conn error and the kernel took ownership */
2266
+ spin_lock_irq(&conn->lock);
2267
+ if (!test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
2268
+ spin_unlock_irq(&conn->lock);
2269
+ iscsi_ep_disconnect(conn, is_active);
2270
+ } else {
2271
+ spin_unlock_irq(&conn->lock);
2272
+ ISCSI_DBG_TRANS_CONN(conn, "flush kernel conn cleanup.\n");
2273
+ mutex_unlock(&conn->ep_mutex);
2274
+
2275
+ flush_work(&conn->cleanup_work);
2276
+ /*
2277
+ * Userspace is now done with the EP so we can release the ref
2278
+ * iscsi_cleanup_conn_work_fn took.
2279
+ */
2280
+ iscsi_put_endpoint(ep);
2281
+ mutex_lock(&conn->ep_mutex);
2282
+ }
2283
+}
2284
+
2285
+static int iscsi_if_stop_conn(struct iscsi_transport *transport,
2286
+ struct iscsi_uevent *ev)
2287
+{
2288
+ int flag = ev->u.stop_conn.flag;
2289
+ struct iscsi_cls_conn *conn;
2290
+
2291
+ conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
2292
+ if (!conn)
2293
+ return -EINVAL;
2294
+
2295
+ ISCSI_DBG_TRANS_CONN(conn, "iscsi if conn stop.\n");
2296
+ /*
2297
+ * If this is a termination we have to call stop_conn with that flag
2298
+ * so the correct states get set. If we haven't run the work yet try to
2299
+ * avoid the extra run.
2300
+ */
2301
+ if (flag == STOP_CONN_TERM) {
2302
+ cancel_work_sync(&conn->cleanup_work);
2303
+ iscsi_stop_conn(conn, flag);
2304
+ } else {
2305
+ /*
2306
+ * For offload, when iscsid is restarted it won't know about
2307
+ * existing endpoints so it can't do a ep_disconnect. We clean
2308
+ * it up here for userspace.
2309
+ */
2310
+ mutex_lock(&conn->ep_mutex);
2311
+ if (conn->ep)
2312
+ iscsi_if_disconnect_bound_ep(conn, conn->ep, true);
2313
+ mutex_unlock(&conn->ep_mutex);
2314
+
2315
+ /*
2316
+ * Figure out if it was the kernel or userspace initiating this.
2317
+ */
2318
+ spin_lock_irq(&conn->lock);
2319
+ if (!test_and_set_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
2320
+ spin_unlock_irq(&conn->lock);
2321
+ iscsi_stop_conn(conn, flag);
2322
+ } else {
2323
+ spin_unlock_irq(&conn->lock);
2324
+ ISCSI_DBG_TRANS_CONN(conn,
2325
+ "flush kernel conn cleanup.\n");
2326
+ flush_work(&conn->cleanup_work);
2327
+ }
2328
+ /*
2329
+ * Only clear for recovery to avoid extra cleanup runs during
2330
+ * termination.
2331
+ */
2332
+ spin_lock_irq(&conn->lock);
2333
+ clear_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags);
2334
+ spin_unlock_irq(&conn->lock);
2335
+ }
2336
+ ISCSI_DBG_TRANS_CONN(conn, "iscsi if conn stop done.\n");
2337
+ return 0;
2338
+}
2339
+
2340
+static void iscsi_cleanup_conn_work_fn(struct work_struct *work)
2341
+{
2342
+ struct iscsi_cls_conn *conn = container_of(work, struct iscsi_cls_conn,
2343
+ cleanup_work);
2344
+ struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
2345
+
2346
+ mutex_lock(&conn->ep_mutex);
2347
+ /*
2348
+ * Get a ref to the ep, so we don't release its ID until after
2349
+ * userspace is done referencing it in iscsi_if_disconnect_bound_ep.
2350
+ */
2351
+ if (conn->ep)
2352
+ get_device(&conn->ep->dev);
2353
+ iscsi_ep_disconnect(conn, false);
2354
+
2355
+ if (system_state != SYSTEM_RUNNING) {
2356
+ /*
2357
+ * If the user has set up for the session to never timeout
2358
+ * then hang like they wanted. For all other cases fail right
2359
+ * away since userspace is not going to relogin.
2360
+ */
2361
+ if (session->recovery_tmo > 0)
2362
+ session->recovery_tmo = 0;
2363
+ }
2364
+
2365
+ iscsi_stop_conn(conn, STOP_CONN_RECOVER);
2366
+ mutex_unlock(&conn->ep_mutex);
2367
+ ISCSI_DBG_TRANS_CONN(conn, "cleanup done.\n");
2368
+}
21922369
21932370 void iscsi_free_session(struct iscsi_cls_session *session)
21942371 {
....@@ -2228,9 +2405,12 @@
22282405 conn->dd_data = &conn[1];
22292406
22302407 mutex_init(&conn->ep_mutex);
2408
+ spin_lock_init(&conn->lock);
22312409 INIT_LIST_HEAD(&conn->conn_list);
2410
+ INIT_WORK(&conn->cleanup_work, iscsi_cleanup_conn_work_fn);
22322411 conn->transport = transport;
22332412 conn->cid = cid;
2413
+ WRITE_ONCE(conn->state, ISCSI_CONN_DOWN);
22342414
22352415 /* this is released in the dev's release function */
22362416 if (!get_device(&session->dev))
....@@ -2245,7 +2425,12 @@
22452425 "register connection's dev\n");
22462426 goto release_parent_ref;
22472427 }
2248
- transport_register_device(&conn->dev);
2428
+ err = transport_register_device(&conn->dev);
2429
+ if (err) {
2430
+ iscsi_cls_session_printk(KERN_ERR, session, "could not "
2431
+ "register transport's dev\n");
2432
+ goto release_conn_ref;
2433
+ }
22492434
22502435 spin_lock_irqsave(&connlock, flags);
22512436 list_add(&conn->conn_list, &connlist);
....@@ -2254,6 +2439,10 @@
22542439 ISCSI_DBG_TRANS_CONN(conn, "Completed conn creation\n");
22552440 return conn;
22562441
2442
+release_conn_ref:
2443
+ device_unregister(&conn->dev);
2444
+ put_device(&session->dev);
2445
+ return NULL;
22572446 release_parent_ref:
22582447 put_device(&session->dev);
22592448 free_conn:
....@@ -2408,6 +2597,32 @@
24082597 struct iscsi_uevent *ev;
24092598 struct iscsi_internal *priv;
24102599 int len = nlmsg_total_size(sizeof(*ev));
2600
+ unsigned long flags;
2601
+ int state;
2602
+
2603
+ spin_lock_irqsave(&conn->lock, flags);
2604
+ /*
2605
+ * Userspace will only do a stop call if we are at least bound. And, we
2606
+ * only need to do the in kernel cleanup if in the UP state so cmds can
2607
+ * be released to upper layers. If in other states just wait for
2608
+ * userspace to avoid races that can leave the cleanup_work queued.
2609
+ */
2610
+ state = READ_ONCE(conn->state);
2611
+ switch (state) {
2612
+ case ISCSI_CONN_BOUND:
2613
+ case ISCSI_CONN_UP:
2614
+ if (!test_and_set_bit(ISCSI_CLS_CONN_BIT_CLEANUP,
2615
+ &conn->flags)) {
2616
+ queue_work(iscsi_conn_cleanup_workq,
2617
+ &conn->cleanup_work);
2618
+ }
2619
+ break;
2620
+ default:
2621
+ ISCSI_DBG_TRANS_CONN(conn, "Got conn error in state %d\n",
2622
+ state);
2623
+ break;
2624
+ }
2625
+ spin_unlock_irqrestore(&conn->lock, flags);
24112626
24122627 priv = iscsi_if_transport_lookup(conn->transport);
24132628 if (!priv)
....@@ -2742,10 +2957,12 @@
27422957 if (!conn)
27432958 return -EINVAL;
27442959
2960
+ ISCSI_DBG_TRANS_CONN(conn, "Flushing cleanup during destruction\n");
2961
+ flush_work(&conn->cleanup_work);
27452962 ISCSI_DBG_TRANS_CONN(conn, "Destroying transport conn\n");
2963
+
27462964 if (transport->destroy_conn)
27472965 transport->destroy_conn(conn);
2748
-
27492966 return 0;
27502967 }
27512968
....@@ -2755,7 +2972,7 @@
27552972 char *data = (char*)ev + sizeof(*ev);
27562973 struct iscsi_cls_conn *conn;
27572974 struct iscsi_cls_session *session;
2758
- int err = 0, value = 0;
2975
+ int err = 0, value = 0, state;
27592976
27602977 if (ev->u.set_param.len > PAGE_SIZE)
27612978 return -EINVAL;
....@@ -2772,8 +2989,13 @@
27722989 session->recovery_tmo = value;
27732990 break;
27742991 default:
2775
- err = transport->set_param(conn, ev->u.set_param.param,
2776
- data, ev->u.set_param.len);
2992
+ state = READ_ONCE(conn->state);
2993
+ if (state == ISCSI_CONN_BOUND || state == ISCSI_CONN_UP) {
2994
+ err = transport->set_param(conn, ev->u.set_param.param,
2995
+ data, ev->u.set_param.len);
2996
+ } else {
2997
+ return -ENOTCONN;
2998
+ }
27772999 }
27783000
27793001 return err;
....@@ -2828,14 +3050,22 @@
28283050 ep = iscsi_lookup_endpoint(ep_handle);
28293051 if (!ep)
28303052 return -EINVAL;
3053
+
28313054 conn = ep->conn;
2832
- if (conn) {
2833
- mutex_lock(&conn->ep_mutex);
2834
- conn->ep = NULL;
2835
- mutex_unlock(&conn->ep_mutex);
3055
+ if (!conn) {
3056
+ /*
3057
+ * conn was not even bound yet, so we can't get iscsi conn
3058
+ * failures yet.
3059
+ */
3060
+ transport->ep_disconnect(ep);
3061
+ goto put_ep;
28363062 }
28373063
2838
- transport->ep_disconnect(ep);
3064
+ mutex_lock(&conn->ep_mutex);
3065
+ iscsi_if_disconnect_bound_ep(conn, ep, false);
3066
+ mutex_unlock(&conn->ep_mutex);
3067
+put_ep:
3068
+ iscsi_put_endpoint(ep);
28393069 return 0;
28403070 }
28413071
....@@ -2861,6 +3091,7 @@
28613091
28623092 ev->r.retcode = transport->ep_poll(ep,
28633093 ev->u.ep_poll.timeout_ms);
3094
+ iscsi_put_endpoint(ep);
28643095 break;
28653096 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
28663097 rc = iscsi_if_ep_disconnect(transport,
....@@ -3491,18 +3722,123 @@
34913722 return err;
34923723 }
34933724
3725
+static int iscsi_if_transport_conn(struct iscsi_transport *transport,
3726
+ struct nlmsghdr *nlh)
3727
+{
3728
+ struct iscsi_uevent *ev = nlmsg_data(nlh);
3729
+ struct iscsi_cls_session *session;
3730
+ struct iscsi_cls_conn *conn = NULL;
3731
+ struct iscsi_endpoint *ep;
3732
+ uint32_t pdu_len;
3733
+ int err = 0;
3734
+
3735
+ switch (nlh->nlmsg_type) {
3736
+ case ISCSI_UEVENT_CREATE_CONN:
3737
+ return iscsi_if_create_conn(transport, ev);
3738
+ case ISCSI_UEVENT_DESTROY_CONN:
3739
+ return iscsi_if_destroy_conn(transport, ev);
3740
+ case ISCSI_UEVENT_STOP_CONN:
3741
+ return iscsi_if_stop_conn(transport, ev);
3742
+ }
3743
+
3744
+ /*
3745
+ * The following cmds need to be run under the ep_mutex so in kernel
3746
+ * conn cleanup (ep_disconnect + unbind and conn) is not done while
3747
+ * these are running. They also must not run if we have just run a conn
3748
+ * cleanup because they would set the state in a way that might allow
3749
+ * IO or send IO themselves.
3750
+ */
3751
+ switch (nlh->nlmsg_type) {
3752
+ case ISCSI_UEVENT_START_CONN:
3753
+ conn = iscsi_conn_lookup(ev->u.start_conn.sid,
3754
+ ev->u.start_conn.cid);
3755
+ break;
3756
+ case ISCSI_UEVENT_BIND_CONN:
3757
+ conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
3758
+ break;
3759
+ case ISCSI_UEVENT_SEND_PDU:
3760
+ conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
3761
+ break;
3762
+ }
3763
+
3764
+ if (!conn)
3765
+ return -EINVAL;
3766
+
3767
+ mutex_lock(&conn->ep_mutex);
3768
+ spin_lock_irq(&conn->lock);
3769
+ if (test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
3770
+ spin_unlock_irq(&conn->lock);
3771
+ mutex_unlock(&conn->ep_mutex);
3772
+ ev->r.retcode = -ENOTCONN;
3773
+ return 0;
3774
+ }
3775
+ spin_unlock_irq(&conn->lock);
3776
+
3777
+ switch (nlh->nlmsg_type) {
3778
+ case ISCSI_UEVENT_BIND_CONN:
3779
+ session = iscsi_session_lookup(ev->u.b_conn.sid);
3780
+ if (!session) {
3781
+ err = -EINVAL;
3782
+ break;
3783
+ }
3784
+
3785
+ ev->r.retcode = transport->bind_conn(session, conn,
3786
+ ev->u.b_conn.transport_eph,
3787
+ ev->u.b_conn.is_leading);
3788
+ if (!ev->r.retcode)
3789
+ WRITE_ONCE(conn->state, ISCSI_CONN_BOUND);
3790
+
3791
+ if (ev->r.retcode || !transport->ep_connect)
3792
+ break;
3793
+
3794
+ ep = iscsi_lookup_endpoint(ev->u.b_conn.transport_eph);
3795
+ if (ep) {
3796
+ ep->conn = conn;
3797
+ conn->ep = ep;
3798
+ iscsi_put_endpoint(ep);
3799
+ } else {
3800
+ err = -ENOTCONN;
3801
+ iscsi_cls_conn_printk(KERN_ERR, conn,
3802
+ "Could not set ep conn binding\n");
3803
+ }
3804
+ break;
3805
+ case ISCSI_UEVENT_START_CONN:
3806
+ ev->r.retcode = transport->start_conn(conn);
3807
+ if (!ev->r.retcode)
3808
+ WRITE_ONCE(conn->state, ISCSI_CONN_UP);
3809
+
3810
+ break;
3811
+ case ISCSI_UEVENT_SEND_PDU:
3812
+ pdu_len = nlh->nlmsg_len - sizeof(*nlh) - sizeof(*ev);
3813
+
3814
+ if ((ev->u.send_pdu.hdr_size > pdu_len) ||
3815
+ (ev->u.send_pdu.data_size > (pdu_len - ev->u.send_pdu.hdr_size))) {
3816
+ err = -EINVAL;
3817
+ break;
3818
+ }
3819
+
3820
+ ev->r.retcode = transport->send_pdu(conn,
3821
+ (struct iscsi_hdr *)((char *)ev + sizeof(*ev)),
3822
+ (char *)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
3823
+ ev->u.send_pdu.data_size);
3824
+ break;
3825
+ default:
3826
+ err = -ENOSYS;
3827
+ }
3828
+
3829
+ mutex_unlock(&conn->ep_mutex);
3830
+ return err;
3831
+}
34943832
34953833 static int
34963834 iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
34973835 {
34983836 int err = 0;
34993837 u32 portid;
3500
- u32 pdu_len;
35013838 struct iscsi_uevent *ev = nlmsg_data(nlh);
35023839 struct iscsi_transport *transport = NULL;
35033840 struct iscsi_internal *priv;
35043841 struct iscsi_cls_session *session;
3505
- struct iscsi_cls_conn *conn;
35063842 struct iscsi_endpoint *ep = NULL;
35073843
35083844 if (!netlink_capable(skb, CAP_SYS_ADMIN))
....@@ -3543,6 +3879,7 @@
35433879 ev->u.c_bound_session.initial_cmdsn,
35443880 ev->u.c_bound_session.cmds_max,
35453881 ev->u.c_bound_session.queue_depth);
3882
+ iscsi_put_endpoint(ep);
35463883 break;
35473884 case ISCSI_UEVENT_DESTROY_SESSION:
35483885 session = iscsi_session_lookup(ev->u.d_session.sid);
....@@ -3553,6 +3890,23 @@
35533890 else
35543891 transport->destroy_session(session);
35553892 break;
3893
+ case ISCSI_UEVENT_DESTROY_SESSION_ASYNC:
3894
+ session = iscsi_session_lookup(ev->u.d_session.sid);
3895
+ if (!session)
3896
+ err = -EINVAL;
3897
+ else if (iscsi_session_has_conns(ev->u.d_session.sid))
3898
+ err = -EBUSY;
3899
+ else {
3900
+ unsigned long flags;
3901
+
3902
+ /* Prevent this session from being found again */
3903
+ spin_lock_irqsave(&sesslock, flags);
3904
+ list_del_init(&session->sess_list);
3905
+ spin_unlock_irqrestore(&sesslock, flags);
3906
+
3907
+ queue_work(system_unbound_wq, &session->destroy_work);
3908
+ }
3909
+ break;
35563910 case ISCSI_UEVENT_UNBIND_SESSION:
35573911 session = iscsi_session_lookup(ev->u.d_session.sid);
35583912 if (session)
....@@ -3561,76 +3915,16 @@
35613915 else
35623916 err = -EINVAL;
35633917 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;
36003918 case ISCSI_UEVENT_SET_PARAM:
36013919 err = iscsi_set_param(transport, ev);
36023920 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;
3921
+ case ISCSI_UEVENT_CREATE_CONN:
3922
+ case ISCSI_UEVENT_DESTROY_CONN:
36103923 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;
3924
+ case ISCSI_UEVENT_START_CONN:
3925
+ case ISCSI_UEVENT_BIND_CONN:
36173926 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;
3927
+ err = iscsi_if_transport_conn(transport, nlh);
36343928 break;
36353929 case ISCSI_UEVENT_GET_STATS:
36363930 err = iscsi_if_get_stats(transport, nlh);
....@@ -3808,6 +4102,28 @@
38084102 iscsi_conn_attr(tcp_recv_wsf, ISCSI_PARAM_TCP_RECV_WSF);
38094103 iscsi_conn_attr(local_ipaddr, ISCSI_PARAM_LOCAL_IPADDR);
38104104
4105
+static const char *const connection_state_names[] = {
4106
+ [ISCSI_CONN_UP] = "up",
4107
+ [ISCSI_CONN_DOWN] = "down",
4108
+ [ISCSI_CONN_FAILED] = "failed",
4109
+ [ISCSI_CONN_BOUND] = "bound"
4110
+};
4111
+
4112
+static ssize_t show_conn_state(struct device *dev,
4113
+ struct device_attribute *attr, char *buf)
4114
+{
4115
+ struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent);
4116
+ const char *state = "unknown";
4117
+ int conn_state = READ_ONCE(conn->state);
4118
+
4119
+ if (conn_state >= 0 &&
4120
+ conn_state < ARRAY_SIZE(connection_state_names))
4121
+ state = connection_state_names[conn_state];
4122
+
4123
+ return sysfs_emit(buf, "%s\n", state);
4124
+}
4125
+static ISCSI_CLASS_ATTR(conn, state, S_IRUGO, show_conn_state,
4126
+ NULL);
38114127
38124128 #define iscsi_conn_ep_attr_show(param) \
38134129 static ssize_t show_conn_ep_param_##param(struct device *dev, \
....@@ -3877,6 +4193,7 @@
38774193 &dev_attr_conn_tcp_xmit_wsf.attr,
38784194 &dev_attr_conn_tcp_recv_wsf.attr,
38794195 &dev_attr_conn_local_ipaddr.attr,
4196
+ &dev_attr_conn_state.attr,
38804197 NULL,
38814198 };
38824199
....@@ -3948,6 +4265,8 @@
39484265 param = ISCSI_PARAM_TCP_RECV_WSF;
39494266 else if (attr == &dev_attr_conn_local_ipaddr.attr)
39504267 param = ISCSI_PARAM_LOCAL_IPADDR;
4268
+ else if (attr == &dev_attr_conn_state.attr)
4269
+ return S_IRUGO;
39514270 else {
39524271 WARN_ONCE(1, "Invalid conn attr");
39534272 return 0;
....@@ -4454,6 +4773,7 @@
44544773 int err;
44554774
44564775 BUG_ON(!tt);
4776
+ WARN_ON(tt->ep_disconnect && !tt->unbind_conn);
44574777
44584778 priv = iscsi_if_transport_lookup(tt);
44594779 if (priv)
....@@ -4540,6 +4860,20 @@
45404860 }
45414861 EXPORT_SYMBOL_GPL(iscsi_unregister_transport);
45424862
4863
+void iscsi_dbg_trace(void (*trace)(struct device *dev, struct va_format *),
4864
+ struct device *dev, const char *fmt, ...)
4865
+{
4866
+ struct va_format vaf;
4867
+ va_list args;
4868
+
4869
+ va_start(args, fmt);
4870
+ vaf.fmt = fmt;
4871
+ vaf.va = &args;
4872
+ trace(dev, &vaf);
4873
+ va_end(args);
4874
+}
4875
+EXPORT_SYMBOL_GPL(iscsi_dbg_trace);
4876
+
45434877 static __init int iscsi_transport_init(void)
45444878 {
45454879 int err;
....@@ -4586,14 +4920,26 @@
45864920 goto unregister_flashnode_bus;
45874921 }
45884922
4589
- iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh");
4923
+ iscsi_eh_timer_workq = alloc_workqueue("%s",
4924
+ WQ_SYSFS | __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_UNBOUND,
4925
+ 1, "iscsi_eh");
45904926 if (!iscsi_eh_timer_workq) {
45914927 err = -ENOMEM;
45924928 goto release_nls;
45934929 }
45944930
4931
+ iscsi_conn_cleanup_workq = alloc_workqueue("%s",
4932
+ WQ_SYSFS | WQ_MEM_RECLAIM | WQ_UNBOUND, 0,
4933
+ "iscsi_conn_cleanup");
4934
+ if (!iscsi_conn_cleanup_workq) {
4935
+ err = -ENOMEM;
4936
+ goto destroy_wq;
4937
+ }
4938
+
45954939 return 0;
45964940
4941
+destroy_wq:
4942
+ destroy_workqueue(iscsi_eh_timer_workq);
45974943 release_nls:
45984944 netlink_kernel_release(nls);
45994945 unregister_flashnode_bus:
....@@ -4615,6 +4961,7 @@
46154961
46164962 static void __exit iscsi_transport_exit(void)
46174963 {
4964
+ destroy_workqueue(iscsi_conn_cleanup_workq);
46184965 destroy_workqueue(iscsi_eh_timer_workq);
46194966 netlink_kernel_release(nls);
46204967 bus_unregister(&iscsi_flashnode_bus);