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.
This commit is contained in:
Gleb Chesnokov
2026-10-21 09:23:02 +03:00
parent baca511baf
commit aeff3f67ab
4 changed files with 58 additions and 8 deletions
@@ -0,0 +1,43 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/jiffies.h>
#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,
);
+13 -8
View File
@@ -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);
+1
View File
@@ -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 */
+1
View File
@@ -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 := \