From 714bfca75340d8d0a96b37b75e408c95b8bbf398 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Tue, 13 Oct 2026 11:56:00 +0300 Subject: [PATCH] kunit: Test iSCSI transmit progress and completion Integrate iSCSI test objects in out-of-tree module builds. Move transmit state names to a private header and link a separate suite with task-scoped socket and completion boundaries. Exercise data, padding and digest progress, retries, short sends and TX_END completion. Preserve socket arguments and completion order without creating a socket or initiator session. --- doc/KUNIT.md | 1 + iscsi-scst/AGENTS.md | 6 +- iscsi-scst/Makefile | 12 +- iscsi-scst/kernel/Kbuild | 3 + .../kernel/kunit/suites/iscsi_tx_test.c | 241 ++++++++++++++++++ iscsi-scst/kernel/nthread.c | 41 +-- iscsi-scst/kernel/nthread.h | 15 ++ iscsi-scst/kernel/nthread_test.h | 19 ++ scripts/kunit/test_make.py | 1 + scst/src/kunit/modules.mk | 5 +- scst/src/kunit/objects.mk | 3 + 11 files changed, 326 insertions(+), 21 deletions(-) create mode 100644 iscsi-scst/kernel/kunit/suites/iscsi_tx_test.c create mode 100644 iscsi-scst/kernel/nthread.h create mode 100644 iscsi-scst/kernel/nthread_test.h diff --git a/doc/KUNIT.md b/doc/KUNIT.md index a2aaee159..3601be732 100644 --- a/doc/KUNIT.md +++ b/doc/KUNIT.md @@ -63,6 +63,7 @@ validates the selection against the supplied `.ko` files. | `scst.ko` | `ALUA CDB CM EVENT LIB LIFECYCLE ORDER UNMAP` | | `scst_vdisk.ko` | `VDISK` | | `scst_user.ko` | `USER` | +| `iscsi-scst.ko` | `ISCSI` | The runner reads suite metadata and dependencies from the modules and loads selected owners in dependency order. Supply all required SCST modules from the same build; diff --git a/iscsi-scst/AGENTS.md b/iscsi-scst/AGENTS.md index f29cd3d8a..b01669055 100644 --- a/iscsi-scst/AGENTS.md +++ b/iscsi-scst/AGENTS.md @@ -54,8 +54,10 @@ artifacts. Change their sources or recipes instead. The focused compile entry point is top-level `make iscsi` or `make -C iscsi-scst`; it builds both user and kernel parts and may run compatibility -conftests. There is no component unit-test target; use repository CI, -checkpatch, and regression entry points as appropriate. +conftests. Use repository CI, checkpatch, and regression entry points as +appropriate. Before changing tests under `kernel/kunit/`, read +[the KUnit guide](../doc/KUNIT.md) for build and execution entry points, +private interfaces and fixture cleanup. Do not install or run the daemon, open portals, apply iSCSI configuration, create targets/sessions/connections, perform discovery/login/logout, manipulate diff --git a/iscsi-scst/Makefile b/iscsi-scst/Makefile index 15e9d844b..ffe0163f1 100644 --- a/iscsi-scst/Makefile +++ b/iscsi-scst/Makefile @@ -138,7 +138,7 @@ CONFTEST_CFLAGS = \ ISER_CFLAGS = $(OFED_CFLAGS) -DOFED_FLAVOR=$(OFED_FLAVOR) $(CONFTEST_CFLAGS) mods: include/iscsi_scst_itf_ver.h $(CONFTEST_OUTPUTS) - $(MAKE) -C $(KDIR) M=$(KMOD) CONFTEST_CFLAGS="$(CONFTEST_CFLAGS)"\ + $(MAKE) -C $(KDIR) M=$(KMOD) $(SCST_KUNIT_FLAGS) CONFTEST_CFLAGS="$(CONFTEST_CFLAGS)"\ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ modules echo "$@: INFINIBAND_ENABLED = $(INFINIBAND_ENABLED)" @@ -149,6 +149,12 @@ mods: include/iscsi_scst_itf_ver.h $(CONFTEST_OUTPUTS) $(OFED_CONFIG) modules; \ fi +.PHONY: kunit-build +kunit-build: include/iscsi_scst_itf_ver.h conftest/sock_recvmsg/result-$(KVER).txt + $(MAKE) -C $(KDIR) M=$(KMOD) $(SCST_KUNIT_FLAGS) \ + CONFTEST_CFLAGS="$(CONFTEST_CFLAGS)" \ + $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") iscsi-scst.ko + progs: include/iscsi_scst_itf_ver.h $(MAKE) -C usr @@ -166,7 +172,7 @@ install: all @install -vD -m 755 usr/iscsi-scst-adm $(DESTDIR)$(SBINDIR)/iscsi-scst-adm @install -vD -m 644 doc/manpages/iscsi-scst-adm.8 $(DESTDIR)$(MANDIR)/man8/iscsi-scst-adm.8 (cd $(KMOD) && KDIR=$(KDIR) ../../scripts/sign-modules) - $(MAKE) -C $(KDIR) M=$(KMOD) \ + $(MAKE) -C $(KDIR) M=$(KMOD) $(SCST_KUNIT_FLAGS) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ @@ -333,3 +339,5 @@ release-archive: ../scripts/generate-release-archive iscsi-scst "$$(sed -n 's/^#define[[:blank:]]ISCSI_VERSION_STRING[[:blank:]]*\"\([^\"]*\)\".*/\1/p' include/iscsi_scst_ver.h)" .PHONY: all mods progs install clean extraclean + +include ../scst/src/kunit/select.mk diff --git a/iscsi-scst/kernel/Kbuild b/iscsi-scst/kernel/Kbuild index 499d82553..9055cf79c 100644 --- a/iscsi-scst/kernel/Kbuild +++ b/iscsi-scst/kernel/Kbuild @@ -39,3 +39,6 @@ obj-m += iscsi-scst.o iscsi-scst-objs := iscsi.o nthread.o config.o digest.o \ conn.o session.o target.o event.o param.o \ iscsit_transport.o + +scst-kunit-module := iscsi-scst +include $(src)/../../scst/src/kunit/Makefile diff --git a/iscsi-scst/kernel/kunit/suites/iscsi_tx_test.c b/iscsi-scst/kernel/kunit/suites/iscsi_tx_test.c new file mode 100644 index 000000000..9b0ed3d9f --- /dev/null +++ b/iscsi-scst/kernel/kunit/suites/iscsi_tx_test.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0-only +#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.h" +#include "../../nthread_test.h" + +struct iscsi_tx_fixture { + struct iscsi_conn conn; + struct iscsi_session session; + struct iscsi_cmnd rsp; + struct iscsit_transport transport; + struct socket socket; + int send_result; + unsigned int sends; + unsigned int closes; + unsigned int completions; +}; + +static int iscsi_tx_write_stub(struct iscsi_conn *conn) +{ + struct kunit *test = kunit_get_current_test(); + struct iscsi_tx_fixture *f = test->priv; + + KUNIT_EXPECT_PTR_EQ(test, conn, &f->conn); + f->sends++; + if (f->send_result > 0) + conn->write_size -= f->send_result; + return f->send_result; +} + +static int iscsi_tx_send_stub(struct socket *sock, struct msghdr *msg, + struct kvec *iov, size_t size) +{ + struct kunit *test = kunit_get_current_test(); + struct iscsi_tx_fixture *f = test->priv; + unsigned int i; + + KUNIT_EXPECT_PTR_EQ(test, sock, &f->socket); + KUNIT_EXPECT_EQ(test, msg->msg_flags, MSG_NOSIGNAL | MSG_DONTWAIT); + KUNIT_EXPECT_EQ(test, size, (size_t)f->conn.write_size); + KUNIT_EXPECT_EQ(test, iov->iov_len, size); + if (f->conn.write_state == TX_PADDING) { + for (i = 0; i < size; i++) + KUNIT_EXPECT_EQ(test, ((u8 *)iov->iov_base)[i], (u8)0); + } else { + KUNIT_EXPECT_EQ(test, f->conn.write_state, TX_DDIGEST); + KUNIT_EXPECT_PTR_EQ(test, iov->iov_base, + (u8 *)&f->rsp.ddigest + sizeof(u32) - size); + } + f->sends++; + return f->send_result; +} + +static void iscsi_tx_close_stub(struct iscsi_conn *conn, int flags) +{ + struct kunit *test = kunit_get_current_test(); + struct iscsi_tx_fixture *f = test->priv; + + KUNIT_EXPECT_PTR_EQ(test, conn, &f->conn); + KUNIT_EXPECT_EQ(test, flags, ISCSI_CONN_ACTIVE_CLOSE); + KUNIT_EXPECT_EQ(test, conn->write_state, TX_END); + KUNIT_EXPECT_EQ(test, conn->write_size, 0); + KUNIT_EXPECT_EQ(test, f->completions, 0U); + conn->closing = 1; + f->closes++; +} + +static void iscsi_tx_complete_stub(struct iscsi_cmnd *cmnd) +{ + struct kunit *test = kunit_get_current_test(); + struct iscsi_tx_fixture *f = test->priv; + + KUNIT_EXPECT_PTR_EQ(test, cmnd, &f->rsp); + KUNIT_EXPECT_EQ(test, f->conn.write_state, TX_END); + KUNIT_EXPECT_EQ(test, f->conn.write_size, 0); + KUNIT_EXPECT_PTR_EQ(test, f->conn.write_cmnd, cmnd); + f->completions++; +} + +static int iscsi_tx_test_init(struct kunit *test) +{ + struct iscsi_tx_fixture *f; + + f = kunit_kzalloc(test, sizeof(*f), GFP_KERNEL); + if (!f) + return -ENOMEM; + test->priv = f; + f->conn.session = &f->session; + f->session.initiator_name = "kunit-private-initiator"; + f->conn.transport = &f->transport; + f->transport.iscsit_mark_conn_closed = iscsi_tx_close_stub; + f->conn.sock = &f->socket; + f->conn.write_cmnd = &f->rsp; + f->conn.ddigest_type = DIGEST_NONE; + f->conn.wr_state = ISCSI_CONN_WR_STATE_PROCESSING; +#ifdef CONFIG_SCST_EXTRACHECKS + f->conn.wr_task = current; +#endif + f->rsp.conn = &f->conn; + f->rsp.ddigest = 0x12345678; + kunit_activate_static_stub(test, write_data, iscsi_tx_write_stub); + kunit_activate_static_stub(test, iscsi_tx_sendmsg, iscsi_tx_send_stub); + kunit_activate_static_stub(test, iscsi_tx_complete, iscsi_tx_complete_stub); + return 0; +} + +struct iscsi_tx_result_case { + const char *name; + int state; + int result; +}; + +#define TX_RESULTS(phase, state) \ + { phase "-closed", state, 0 }, \ + { phase "-io-error", state, -EIO }, \ + { phase "-broken-pipe", state, -EPIPE }, \ + { phase "-retry", state, -EAGAIN }, \ + { phase "-interrupted", state, -ERESTARTSYS }, \ + { phase "-short-write", state, 1 }, \ + { phase "-complete", state, 3 } + +static const struct iscsi_tx_result_case iscsi_tx_results[] = { + TX_RESULTS("data", TX_BHS_DATA), + TX_RESULTS("padding", TX_PADDING), + TX_RESULTS("digest", TX_DDIGEST), +}; + +#undef TX_RESULTS + +static void iscsi_tx_result_desc(const struct iscsi_tx_result_case *p, char *desc) +{ + strscpy(desc, p->name, KUNIT_PARAM_DESC_SIZE); +} + +KUNIT_ARRAY_PARAM(iscsi_tx_result, iscsi_tx_results, iscsi_tx_result_desc); + +static void iscsi_tx_result_test(struct kunit *test) +{ + const struct iscsi_tx_result_case *p = test->param_value; + struct iscsi_tx_fixture *f = test->priv; + bool fatal = p->result <= 0 && p->result != -EAGAIN && p->result != -ERESTARTSYS; + bool done = fatal || p->result == 3; + + f->conn.write_state = p->state; + f->conn.write_size = 3; + f->send_result = p->result; + KUNIT_EXPECT_EQ(test, iscsi_send(&f->conn), p->result); + KUNIT_EXPECT_EQ(test, f->sends, 1U); + KUNIT_EXPECT_EQ(test, f->closes, (unsigned int)fatal); + KUNIT_EXPECT_EQ(test, f->completions, (unsigned int)done); + KUNIT_EXPECT_EQ(test, f->conn.write_state, done ? TX_INIT : p->state); + KUNIT_EXPECT_EQ(test, f->conn.write_size, done ? 0 : (p->result > 0 ? 2 : 3)); + if (done) + KUNIT_EXPECT_PTR_EQ(test, f->conn.write_cmnd, NULL); + else + KUNIT_EXPECT_PTR_EQ(test, f->conn.write_cmnd, &f->rsp); + + if (!done) { + /* Retry continues the same response, including the digest offset. */ + f->send_result = f->conn.write_size; + KUNIT_EXPECT_GT(test, iscsi_send(&f->conn), 0); + KUNIT_EXPECT_EQ(test, f->completions, 1U); + KUNIT_EXPECT_EQ(test, f->closes, 0U); + KUNIT_EXPECT_EQ(test, f->conn.write_state, TX_INIT); + KUNIT_EXPECT_PTR_EQ(test, f->conn.write_cmnd, NULL); + } +} + +struct iscsi_tx_padding_case { + const char *name; + unsigned int data_size; + bool digest; +}; + +static const struct iscsi_tx_padding_case iscsi_tx_paddings[] = { + { "aligned", 4, false }, + { "one-byte", 3, false }, + { "two-bytes", 2, false }, + { "three-bytes", 1, false }, + { "aligned-digest", 4, true }, + { "one-byte-digest", 3, true }, + { "two-bytes-digest", 2, true }, + { "three-bytes-digest", 1, true }, +}; + +static void iscsi_tx_padding_desc(const struct iscsi_tx_padding_case *p, char *desc) +{ + strscpy(desc, p->name, KUNIT_PARAM_DESC_SIZE); +} + +KUNIT_ARRAY_PARAM(iscsi_tx_padding_case, iscsi_tx_paddings, iscsi_tx_padding_desc); + +static void iscsi_tx_padding_test(struct kunit *test) +{ + const struct iscsi_tx_padding_case *p = test->param_value; + struct iscsi_tx_fixture *f = test->priv; + unsigned int padding = (4 - p->data_size) & 3; + + f->conn.write_state = TX_BHS_DATA; + f->conn.write_size = 1; + f->rsp.pdu.datasize = p->data_size; + f->conn.ddigest_type = p->digest ? DIGEST_CRC32C : DIGEST_NONE; + f->send_result = 1; + KUNIT_EXPECT_EQ(test, iscsi_send(&f->conn), 1); + KUNIT_EXPECT_EQ(test, f->conn.write_state, + padding ? TX_PADDING : (p->digest ? TX_INIT_DDIGEST : TX_INIT)); + KUNIT_EXPECT_EQ(test, f->completions, (unsigned int)(!padding && !p->digest)); + if (padding) { + f->send_result = -EAGAIN; + KUNIT_EXPECT_EQ(test, iscsi_send(&f->conn), -EAGAIN); + KUNIT_EXPECT_EQ(test, f->conn.write_size, (int)padding); + /* With a digest, the same call also makes a short digest write. */ + f->send_result = padding; + KUNIT_EXPECT_EQ(test, iscsi_send(&f->conn), (int)padding); + } + if (p->digest) { + f->send_result = padding ? sizeof(u32) - padding : sizeof(u32); + KUNIT_EXPECT_GT(test, iscsi_send(&f->conn), 0); + } + KUNIT_EXPECT_EQ(test, f->completions, 1U); + KUNIT_EXPECT_EQ(test, f->closes, 0U); + KUNIT_EXPECT_EQ(test, f->conn.write_size, 0); + KUNIT_EXPECT_EQ(test, f->conn.write_state, TX_INIT); + KUNIT_EXPECT_PTR_EQ(test, f->conn.write_cmnd, NULL); +} + +static struct kunit_case iscsi_tx_cases[] = { + KUNIT_CASE_PARAM(iscsi_tx_result_test, iscsi_tx_result_gen_params), + KUNIT_CASE_PARAM(iscsi_tx_padding_test, iscsi_tx_padding_case_gen_params), + {} +}; + +scst_kunit_suite(iscsi_tx_suite, "ISCSI", "-tx", + .init = iscsi_tx_test_init, + .test_cases = iscsi_tx_cases, +); diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index a2e8669f0..537a1a5f5 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -28,6 +28,8 @@ #include "iscsi_trace_flag.h" #include "iscsi.h" #include "digest.h" +#include "nthread.h" +#include "nthread_test.h" #undef DEFAULT_SYMBOL_NAMESPACE #define DEFAULT_SYMBOL_NAMESPACE SCST_NAMESPACE @@ -49,16 +51,6 @@ enum rx_state { RX_PADDING, }; -enum tx_state { - TX_INIT = 0, /* Must be zero for better "switch" optimization. */ - TX_BHS_DATA, - TX_INIT_PADDING, - TX_PADDING, - TX_INIT_DDIGEST, - TX_DDIGEST, - TX_END, -}; - static void free_pending_commands(struct iscsi_conn *conn) { struct iscsi_session *session = conn->session; @@ -1068,7 +1060,8 @@ out: TRACE_EXIT(); } -static int write_data(struct iscsi_conn *conn) +SCST_KUNIT_VISIBLE +int write_data(struct iscsi_conn *conn) { struct socket *sock; #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) @@ -1087,6 +1080,8 @@ static int write_data(struct iscsi_conn *conn) int offset, idx, flags, res = 0; bool ref_cmd_to_parent; + SCST_KUNIT_REDIRECT(write_data, conn); + TRACE_ENTRY(); write_cmnd = conn->write_cmnd; @@ -1324,6 +1319,22 @@ static void exit_tx(struct iscsi_conn *conn, int res) } } +SCST_KUNIT_VISIBLE +int iscsi_tx_sendmsg(struct socket *sock, struct msghdr *msg, + struct kvec *iov, size_t size) +{ + SCST_KUNIT_REDIRECT(iscsi_tx_sendmsg, sock, msg, iov, size); + return kernel_sendmsg(sock, msg, iov, 1, size); +} + +SCST_KUNIT_VISIBLE +void iscsi_tx_complete(struct iscsi_cmnd *cmnd) +{ + SCST_KUNIT_REDIRECT(iscsi_tx_complete, cmnd); + cmnd_tx_end(cmnd); + rsp_cmnd_release(cmnd); +} + static int tx_ddigest(struct iscsi_cmnd *cmnd, int state) { int res, rest = cmnd->conn->write_size; @@ -1337,7 +1348,7 @@ static int tx_ddigest(struct iscsi_cmnd *cmnd, int state) iov.iov_base = (char *)(&cmnd->ddigest) + (sizeof(u32) - rest); iov.iov_len = rest; - res = kernel_sendmsg(cmnd->conn->sock, &msg, &iov, 1, rest); + res = iscsi_tx_sendmsg(cmnd->conn->sock, &msg, &iov, rest); if (res > 0) { cmnd->conn->write_size -= res; if (!cmnd->conn->write_size) @@ -1383,7 +1394,7 @@ static int tx_padding(struct iscsi_cmnd *cmnd, int state) iov.iov_base = (char *)&padding; iov.iov_len = rest; - res = kernel_sendmsg(cmnd->conn->sock, &msg, &iov, 1, rest); + res = iscsi_tx_sendmsg(cmnd->conn->sock, &msg, &iov, rest); if (res > 0) { cmnd->conn->write_size -= res; if (!cmnd->conn->write_size) @@ -1485,9 +1496,7 @@ int iscsi_send(struct iscsi_conn *conn) res, cmnd_opcode(cmnd), conn->write_size); sBUG(); } - cmnd_tx_end(cmnd); - - rsp_cmnd_release(cmnd); + iscsi_tx_complete(cmnd); conn->write_cmnd = NULL; conn->write_state = TX_INIT; diff --git a/iscsi-scst/kernel/nthread.h b/iscsi-scst/kernel/nthread.h new file mode 100644 index 000000000..79f8fa4fc --- /dev/null +++ b/iscsi-scst/kernel/nthread.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef SCST_ISCSI_NTHREAD_H +#define SCST_ISCSI_NTHREAD_H + +enum tx_state { + TX_INIT = 0, /* Must be zero for better "switch" optimization. */ + TX_BHS_DATA, + TX_INIT_PADDING, + TX_PADDING, + TX_INIT_DDIGEST, + TX_DDIGEST, + TX_END, +}; + +#endif /* SCST_ISCSI_NTHREAD_H */ diff --git a/iscsi-scst/kernel/nthread_test.h b/iscsi-scst/kernel/nthread_test.h new file mode 100644 index 000000000..1de09489a --- /dev/null +++ b/iscsi-scst/kernel/nthread_test.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef SCST_ISCSI_NTHREAD_TEST_H +#define SCST_ISCSI_NTHREAD_TEST_H + +#ifdef INSIDE_KERNEL_TREE +#include "../scst_test.h" +#else +#include "../../scst/src/scst_test.h" +#endif + +#ifdef SCST_KUNIT_ENABLED + +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); + +#endif /* SCST_KUNIT_ENABLED */ +#endif /* SCST_ISCSI_NTHREAD_TEST_H */ diff --git a/scripts/kunit/test_make.py b/scripts/kunit/test_make.py index 79566601a..6731400a2 100644 --- a/scripts/kunit/test_make.py +++ b/scripts/kunit/test_make.py @@ -25,6 +25,7 @@ OWNERS = { 'scst': ('scst/src', 'scst/kernel/in-tree/Makefile.scst'), 'scst_vdisk': ('scst/src/dev_handlers', 'scst/kernel/in-tree/Makefile.dev_handlers'), 'scst_user': ('scst/src/dev_handlers', 'scst/kernel/in-tree/Makefile.dev_handlers'), + 'iscsi-scst': ('iscsi-scst/kernel', 'iscsi-scst/kernel/Makefile.in-kernel'), } diff --git a/scst/src/kunit/modules.mk b/scst/src/kunit/modules.mk index ac2c12634..338a45200 100644 --- a/scst/src/kunit/modules.mk +++ b/scst/src/kunit/modules.mk @@ -1,10 +1,13 @@ # SPDX-License-Identifier: GPL-2.0-only # Build components in dependency order and record their test modules. -SCST_KUNIT_COMPONENTS := scst +SCST_KUNIT_COMPONENTS := scst iscsi-scst SCST_KUNIT_MODULES_scst := \ scst/src/scst.ko \ scst/src/dev_handlers/scst_vdisk.ko \ scst/src/dev_handlers/scst_user.ko +SCST_KUNIT_MODULES_iscsi-scst := \ + iscsi-scst/kernel/iscsi-scst.ko + SCST_KUNIT_MODULES = $(foreach component,$(SCST_KUNIT_COMPONENTS),$(SCST_KUNIT_MODULES_$(component))) diff --git a/scst/src/kunit/objects.mk b/scst/src/kunit/objects.mk index 4f9e002ed..4e4a2194b 100644 --- a/scst/src/kunit/objects.mk +++ b/scst/src/kunit/objects.mk @@ -14,6 +14,9 @@ scst-kunit-scst := \ kunit/order/suites/scst_kunit_order.o \ kunit/unmap/suites/scst_kunit_unmap.o +scst-kunit-iscsi-scst := \ + kunit/suites/iscsi_tx_test.o + scst-kunit-scst_user := \ kunit/user/suites/scst_user_cleanup_test.o