From aeff3f67abac22057fd217d23250492dcb45f2c8 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Tue, 20 Oct 2026 18:12:34 +0300 Subject: [PATCH] iscsi-scst: Measure shutdown grace from the start of the wait The saved pre-fix Cppcheck log reports: iscsi-scst/kernel/nthread.c:326: style: Clarify calculation precedence for '+' and '?'. [clarifyCalculation] close_conn calculates its shutdown deadline with this expression: shut_start_waiting + conn->deleting ? CONN_DEL_SHUT_TIMEOUT : CONN_REG_SHUT_TIMEOUT Addition binds more tightly than the conditional operator. The expression therefore tests shut_start_waiting + conn->deleting and selects an absolute 10- or 125-second jiffies value, rather than adding an interval to the start timestamp. On a host with sufficient uptime, the transport can be closed immediately after shutdown starts. Select the interval first, add it to shut_start_waiting, and retain the wrap-safe time_after comparison. Move the check into a private helper so its timing behavior can be covered without a live connection. Add KUnit coverage for both deletion and normal shutdown, high uptime, the ticks before/at/after expiry and jiffies wraparound. The tests retain the original strict-after deadline convention. --- .../kernel/kunit/suites/iscsi_close_test.c | 43 +++++++++++++++++++ iscsi-scst/kernel/nthread.c | 21 +++++---- iscsi-scst/kernel/nthread_test.h | 1 + scst/src/kunit/objects.mk | 1 + 4 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 iscsi-scst/kernel/kunit/suites/iscsi_close_test.c diff --git a/iscsi-scst/kernel/kunit/suites/iscsi_close_test.c b/iscsi-scst/kernel/kunit/suites/iscsi_close_test.c new file mode 100644 index 000000000..b9815e5ac --- /dev/null +++ b/iscsi-scst/kernel/kunit/suites/iscsi_close_test.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#ifdef INSIDE_KERNEL_TREE +#include "../../../kunit/scst_kunit.h" +#else +#include "../../../../scst/src/kunit/scst_kunit.h" +#endif +#include "../../iscsi_trace_flag.h" +#include "../../iscsi.h" +#include "../../nthread_test.h" + +static void iscsi_shutdown_grace_period(struct kunit *test) +{ + static const unsigned long starts[] = { 10000UL * HZ, ULONG_MAX - 5UL * HZ }; + unsigned int i, deleting; + + for (i = 0; i < ARRAY_SIZE(starts); i++) { + for (deleting = 0; deleting <= 1; deleting++) { + unsigned long grace = deleting ? 10UL * HZ : 125UL * HZ; + unsigned long started = starts[i]; + bool expired; + + /* A close starts a relative deadline, independent of uptime. */ + expired = iscsi_shutdown_timed_out(deleting, started, started); + KUNIT_EXPECT_FALSE(test, expired); + expired = iscsi_shutdown_timed_out(deleting, started, started + grace - 1); + KUNIT_EXPECT_FALSE(test, expired); + expired = iscsi_shutdown_timed_out(deleting, started, started + grace); + KUNIT_EXPECT_FALSE(test, expired); + expired = iscsi_shutdown_timed_out(deleting, started, started + grace + 1); + KUNIT_EXPECT_TRUE(test, expired); + } + } +} + +static struct kunit_case iscsi_close_cases[] = { + KUNIT_CASE(iscsi_shutdown_grace_period), + {} +}; + +scst_kunit_suite(iscsi_close_suite, "ISCSI", "-close", + .test_cases = iscsi_close_cases, +); diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index c978bdbc1..418696875 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -210,6 +210,18 @@ void iscsi_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *scst_mcmd) } } +#define CONN_PENDING_TIMEOUT ((typeof(jiffies))10 * HZ) +#define CONN_WAIT_TIMEOUT ((typeof(jiffies))10 * HZ) +#define CONN_REG_SHUT_TIMEOUT ((typeof(jiffies))125 * HZ) +#define CONN_DEL_SHUT_TIMEOUT ((typeof(jiffies))10 * HZ) + +SCST_KUNIT_VISIBLE +bool iscsi_shutdown_timed_out(bool deleting, unsigned long started, unsigned long now) +{ + return time_after(now, started + + (deleting ? CONN_DEL_SHUT_TIMEOUT : CONN_REG_SHUT_TIMEOUT)); +} + /* No locks */ static void close_conn(struct iscsi_conn *conn) { @@ -223,11 +235,6 @@ static void close_conn(struct iscsi_conn *conn) int rc; int lun = 0; -#define CONN_PENDING_TIMEOUT ((typeof(jiffies))10 * HZ) -#define CONN_WAIT_TIMEOUT ((typeof(jiffies))10 * HZ) -#define CONN_REG_SHUT_TIMEOUT ((typeof(jiffies))125 * HZ) -#define CONN_DEL_SHUT_TIMEOUT ((typeof(jiffies))10 * HZ) - TRACE_ENTRY(); TRACE_MGMT_DBG("Closing connection %p (conn_ref_cnt=%d)", @@ -322,9 +329,7 @@ static void close_conn(struct iscsi_conn *conn) } if (wait_expired && !shut_expired && - time_after(jiffies, shut_start_waiting + - conn->deleting ? CONN_DEL_SHUT_TIMEOUT : - CONN_REG_SHUT_TIMEOUT)) { + iscsi_shutdown_timed_out(conn->deleting, shut_start_waiting, jiffies)) { TRACE_CONN_CLOSE("Wait time after shutdown expired (conn %p)", conn); conn->transport->iscsit_conn_close(conn, 0); diff --git a/iscsi-scst/kernel/nthread_test.h b/iscsi-scst/kernel/nthread_test.h index 1de09489a..395d79ae3 100644 --- a/iscsi-scst/kernel/nthread_test.h +++ b/iscsi-scst/kernel/nthread_test.h @@ -14,6 +14,7 @@ int write_data(struct iscsi_conn *conn); int iscsi_tx_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *iov, size_t size); void iscsi_tx_complete(struct iscsi_cmnd *cmnd); +bool iscsi_shutdown_timed_out(bool deleting, unsigned long started, unsigned long now); #endif /* SCST_KUNIT_ENABLED */ #endif /* SCST_ISCSI_NTHREAD_TEST_H */ diff --git a/scst/src/kunit/objects.mk b/scst/src/kunit/objects.mk index 8473d67e9..2fcafc721 100644 --- a/scst/src/kunit/objects.mk +++ b/scst/src/kunit/objects.mk @@ -20,6 +20,7 @@ scst-kunit-scst := \ kunit/unmap/suites/scst_kunit_unmap.o scst-kunit-iscsi-scst := \ + kunit/suites/iscsi_close_test.o \ kunit/suites/iscsi_tx_test.o scst-kunit-qla2x00tgt := \