linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] ceph: introduce Kunit based unit-tests for string operations
@ 2025-09-19 18:11 Viacheslav Dubeyko
  2025-09-25 13:04 ` kernel test robot
  0 siblings, 1 reply; 2+ messages in thread
From: Viacheslav Dubeyko @ 2025-09-19 18:11 UTC (permalink / raw)
  To: ceph-devel
  Cc: idryomov, linux-fsdevel, pdonnell, amarkuze, Slava.Dubeyko, slava,
	vdubeyko

From: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>

This patch implements the Kunit based set of
unit tests for string operations. It checks
functionality of ceph_mds_state_name(),
ceph_session_op_name(), ceph_mds_op_name(),
ceph_cap_op_name(), ceph_lease_op_name(), and
ceph_snap_op_name().

./tools/testing/kunit/kunit.py run --kunitconfig ./fs/ceph/.kunitconfig
[11:05:53] Configuring KUnit Kernel ...
[11:05:53] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=22
[11:06:01] Starting KUnit Kernel (1/1)...
[11:06:01] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[11:06:01] ================ ceph_strings (6 subtests) =================
[11:06:01] [PASSED] ceph_mds_state_name_test
[11:06:01] [PASSED] ceph_session_op_name_test
[11:06:01] [PASSED] ceph_mds_op_name_test
[11:06:01] [PASSED] ceph_cap_op_name_test
[11:06:01] [PASSED] ceph_lease_op_name_test
[11:06:01] [PASSED] ceph_snap_op_name_test
[11:06:01] ================== [PASSED] ceph_strings ===================
[11:06:01] ============================================================
[11:06:01] Testing complete. Ran 6 tests: passed: 6
[11:06:01] Elapsed time: 8.286s total, 0.002s configuring, 8.117s building, 0.128s running

Signed-off-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
cc: Alex Markuze <amarkuze@redhat.com>
cc: Ilya Dryomov <idryomov@gmail.com>
cc: Ceph Development <ceph-devel@vger.kernel.org>
---
 fs/ceph/.kunitconfig         |  16 +
 fs/ceph/Kconfig              |  12 +
 fs/ceph/Makefile             |   2 +
 fs/ceph/kunit_tests.h        |  30 ++
 fs/ceph/strings.c            | 381 +++++++++++++++++------
 fs/ceph/strings_test.c       | 588 +++++++++++++++++++++++++++++++++++
 include/linux/ceph/ceph_fs.h | 191 ++++++++----
 7 files changed, 1062 insertions(+), 158 deletions(-)
 create mode 100644 fs/ceph/.kunitconfig
 create mode 100644 fs/ceph/kunit_tests.h
 create mode 100644 fs/ceph/strings_test.c

diff --git a/fs/ceph/.kunitconfig b/fs/ceph/.kunitconfig
new file mode 100644
index 000000000000..f342622020a6
--- /dev/null
+++ b/fs/ceph/.kunitconfig
@@ -0,0 +1,16 @@
+CONFIG_KUNIT=y
+CONFIG_NET=y
+CONFIG_INET=y
+CONFIG_IPV6=y
+CONFIG_CRYPTO=y
+CONFIG_CRC32=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_GCM=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_KEYS=y
+CONFIG_NETFS_SUPPORT=y
+CONFIG_CEPH_LIB=y
+CONFIG_CEPH_FS=y
+CONFIG_CEPH_FS_KUNIT_TEST=y
diff --git a/fs/ceph/Kconfig b/fs/ceph/Kconfig
index 3e7def3d31c1..2091fa12ed26 100644
--- a/fs/ceph/Kconfig
+++ b/fs/ceph/Kconfig
@@ -50,3 +50,15 @@ config CEPH_FS_SECURITY_LABEL
 
 	  If you are not using a security module that requires using
 	  extended attributes for file security labels, say N.
+
+config CEPH_FS_KUNIT_TEST
+	tristate "KUnit tests for Ceph FS" if !KUNIT_ALL_TESTS
+	depends on CEPH_FS && KUNIT
+	default KUNIT_ALL_TESTS
+	help
+	  This builds KUnit tests for Ceph file system functions.
+
+	  For more information on KUnit and unit tests in general, please refer
+	  to the KUnit documentation in Documentation/dev-tools/kunit.
+
+	  If unsure, say N.
diff --git a/fs/ceph/Makefile b/fs/ceph/Makefile
index 1f77ca04c426..a27309c6500a 100644
--- a/fs/ceph/Makefile
+++ b/fs/ceph/Makefile
@@ -13,3 +13,5 @@ ceph-y := super.o inode.o dir.o file.o locks.o addr.o ioctl.o \
 ceph-$(CONFIG_CEPH_FSCACHE) += cache.o
 ceph-$(CONFIG_CEPH_FS_POSIX_ACL) += acl.o
 ceph-$(CONFIG_FS_ENCRYPTION) += crypto.o
+
+obj-$(CONFIG_CEPH_FS_KUNIT_TEST) += strings_test.o
diff --git a/fs/ceph/kunit_tests.h b/fs/ceph/kunit_tests.h
new file mode 100644
index 000000000000..73a83e570e0a
--- /dev/null
+++ b/fs/ceph/kunit_tests.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * KUnit tests declarations
+ *
+ * Copyright (C) 2025, IBM Corporation
+ *
+ * Author: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
+ */
+
+#ifndef _CEPH_KUNIT_TESTS_H
+#define _CEPH_KUNIT_TESTS_H
+
+#include <kunit/visibility.h>
+
+#if IS_ENABLED(CONFIG_KUNIT)
+int ceph_mds_state_2_str_idx(int mds_state);
+extern const char *ceph_mds_state_name_strings[];
+int ceph_session_op_2_str_idx(int op);
+extern const char *ceph_session_op_name_strings[];
+int ceph_mds_op_2_str_idx(int op);
+extern const char *ceph_mds_op_name_strings[];
+int ceph_cap_op_2_str_idx(int op);
+extern const char *ceph_cap_op_name_strings[];
+int ceph_lease_op_2_str_idx(int op);
+extern const char *ceph_lease_op_name_strings[];
+int ceph_snap_op_2_str_idx(int op);
+extern const char *ceph_snap_op_name_strings[];
+#endif
+
+#endif /* _CEPH_KUNIT_TESTS_H */
diff --git a/fs/ceph/strings.c b/fs/ceph/strings.c
index e36e8948e728..6585a8b12028 100644
--- a/fs/ceph/strings.c
+++ b/fs/ceph/strings.c
@@ -5,126 +5,319 @@
 #include <linux/module.h>
 #include <linux/ceph/types.h>
 
+#include "kunit_tests.h"
 
-const char *ceph_mds_state_name(int s)
+const char *ceph_mds_state_name_strings[] = {
+/* 0 */		"down:dne",
+/* 1 */		"down:stopped",
+/* 2 */		"up:boot",
+/* 3 */		"up:standby",
+/* 4 */		"up:standby-replay",
+/* 5 */		"up:oneshot-replay",
+/* 6 */		"up:creating",
+/* 7 */		"up:starting",
+/* 8 */		"up:replay",
+/* 9 */		"up:resolve",
+/* 10 */	"up:reconnect",
+/* 11 */	"up:rejoin",
+/* 12 */	"up:clientreplay",
+/* 13 */	"up:active",
+/* 14 */	"up:stopping",
+/* 15 */	"???"
+};
+EXPORT_SYMBOL_IF_KUNIT(ceph_mds_state_name_strings);
+
+VISIBLE_IF_KUNIT
+int ceph_mds_state_2_str_idx(int mds_state)
 {
-	switch (s) {
+	switch (mds_state) {
 		/* down and out */
-	case CEPH_MDS_STATE_DNE:        return "down:dne";
-	case CEPH_MDS_STATE_STOPPED:    return "down:stopped";
+	case CEPH_MDS_STATE_DNE:
+		return CEPH_MDS_STATE_DNE_STR_IDX;		/* 0 */
+	case CEPH_MDS_STATE_STOPPED:
+		return CEPH_MDS_STATE_STOPPED_STR_IDX;		/* 1 */
 		/* up and out */
-	case CEPH_MDS_STATE_BOOT:       return "up:boot";
-	case CEPH_MDS_STATE_STANDBY:    return "up:standby";
-	case CEPH_MDS_STATE_STANDBY_REPLAY:    return "up:standby-replay";
-	case CEPH_MDS_STATE_REPLAYONCE: return "up:oneshot-replay";
-	case CEPH_MDS_STATE_CREATING:   return "up:creating";
-	case CEPH_MDS_STATE_STARTING:   return "up:starting";
+	case CEPH_MDS_STATE_BOOT:
+		return CEPH_MDS_STATE_BOOT_STR_IDX;		/* 2 */
+	case CEPH_MDS_STATE_STANDBY:
+		return CEPH_MDS_STATE_STANDBY_STR_IDX;		/* 3 */
+	case CEPH_MDS_STATE_STANDBY_REPLAY:
+		return CEPH_MDS_STATE_CREATING_STR_IDX;		/* 4 */
+	case CEPH_MDS_STATE_REPLAYONCE:
+		return CEPH_MDS_STATE_STARTING_STR_IDX;		/* 5 */
+	case CEPH_MDS_STATE_CREATING:
+		return CEPH_MDS_STATE_STANDBY_REPLAY_STR_IDX;	/* 6 */
+	case CEPH_MDS_STATE_STARTING:
+		return CEPH_MDS_STATE_REPLAYONCE_STR_IDX;	/* 7 */
 		/* up and in */
-	case CEPH_MDS_STATE_REPLAY:     return "up:replay";
-	case CEPH_MDS_STATE_RESOLVE:    return "up:resolve";
-	case CEPH_MDS_STATE_RECONNECT:  return "up:reconnect";
-	case CEPH_MDS_STATE_REJOIN:     return "up:rejoin";
-	case CEPH_MDS_STATE_CLIENTREPLAY: return "up:clientreplay";
-	case CEPH_MDS_STATE_ACTIVE:     return "up:active";
-	case CEPH_MDS_STATE_STOPPING:   return "up:stopping";
+	case CEPH_MDS_STATE_REPLAY:
+		return CEPH_MDS_STATE_REPLAY_STR_IDX;		/* 8 */
+	case CEPH_MDS_STATE_RESOLVE:
+		return CEPH_MDS_STATE_RESOLVE_STR_IDX;		/* 9 */
+	case CEPH_MDS_STATE_RECONNECT:
+		return CEPH_MDS_STATE_RECONNECT_STR_IDX;	/* 10 */
+	case CEPH_MDS_STATE_REJOIN:
+		return CEPH_MDS_STATE_REJOIN_STR_IDX;		/* 11 */
+	case CEPH_MDS_STATE_CLIENTREPLAY:
+		return CEPH_MDS_STATE_CLIENTREPLAY_STR_IDX;	/* 12 */
+	case CEPH_MDS_STATE_ACTIVE:
+		return CEPH_MDS_STATE_ACTIVE_STR_IDX;		/* 13 */
+	case CEPH_MDS_STATE_STOPPING:
+		return CEPH_MDS_STATE_STOPPING_STR_IDX;		/* 14 */
+	default:
+		/* do nothing */
+		break;
 	}
-	return "???";
+
+	return CEPH_MDS_STATE_UNKNOWN_NAME_STR_IDX;
+}
+EXPORT_SYMBOL_IF_KUNIT(ceph_mds_state_2_str_idx);
+
+const char *ceph_mds_state_name(int s)
+{
+	return ceph_mds_state_name_strings[ceph_mds_state_2_str_idx(s)];
+}
+EXPORT_SYMBOL_IF_KUNIT(ceph_mds_state_name);
+
+const char *ceph_session_op_name_strings[] = {
+/* 0 */		"request_open",
+/* 1 */		"open",
+/* 2 */		"request_close",
+/* 3 */		"close",
+/* 4 */		"request_renewcaps",
+/* 5 */		"renewcaps",
+/* 6 */		"stale",
+/* 7 */		"recall_state",
+/* 8 */		"flushmsg",
+/* 9 */		"flushmsg_ack",
+/* 10 */	"force_ro",
+/* 11 */	"reject",
+/* 12 */	"flush_mdlog",
+/* 13 */	"???"
+};
+EXPORT_SYMBOL_IF_KUNIT(ceph_session_op_name_strings);
+
+VISIBLE_IF_KUNIT
+int ceph_session_op_2_str_idx(int op)
+{
+	if (op < CEPH_SESSION_REQUEST_OPEN ||
+	    op >= CEPH_SESSION_UNKNOWN_NAME)
+		return CEPH_SESSION_UNKNOWN_NAME;
+
+	return op;
 }
+EXPORT_SYMBOL_IF_KUNIT(ceph_session_op_2_str_idx);
 
 const char *ceph_session_op_name(int op)
+{
+	return ceph_session_op_name_strings[ceph_session_op_2_str_idx(op)];
+}
+EXPORT_SYMBOL_IF_KUNIT(ceph_session_op_name);
+
+const char *ceph_mds_op_name_strings[] = {
+/* 0 */		"lookup",
+/* 1 */		"getattr",
+/* 2 */		"lookuphash",
+/* 3 */		"lookupparent",
+/* 4 */		"lookupino",
+/* 5 */		"lookupname",
+/* 6 */		"getvxattr",
+/* 7 */		"setxattr",
+/* 8 */		"rmxattr",
+/* 9 */		"setlayou",
+/* 10 */	"setattr",
+/* 11 */	"setfilelock",
+/* 12 */	"getfilelock",
+/* 13 */	"setdirlayout",
+/* 14 */	"mknod",
+/* 15 */	"link",
+/* 16 */	"unlink",
+/* 17 */	"rename",
+/* 18 */	"mkdir",
+/* 19 */	"rmdir",
+/* 20 */	"symlink",
+/* 21 */	"create",
+/* 22 */	"open",
+/* 23 */	"readdir",
+/* 24 */	"lookupsnap",
+/* 25 */	"mksnap",
+/* 26 */	"rmsnap",
+/* 27 */	"lssnap",
+/* 28 */	"renamesnap",
+/* 29 */	"???"
+};
+EXPORT_SYMBOL_IF_KUNIT(ceph_mds_op_name_strings);
+
+VISIBLE_IF_KUNIT
+int ceph_mds_op_2_str_idx(int op)
 {
 	switch (op) {
-	case CEPH_SESSION_REQUEST_OPEN: return "request_open";
-	case CEPH_SESSION_OPEN: return "open";
-	case CEPH_SESSION_REQUEST_CLOSE: return "request_close";
-	case CEPH_SESSION_CLOSE: return "close";
-	case CEPH_SESSION_REQUEST_RENEWCAPS: return "request_renewcaps";
-	case CEPH_SESSION_RENEWCAPS: return "renewcaps";
-	case CEPH_SESSION_STALE: return "stale";
-	case CEPH_SESSION_RECALL_STATE: return "recall_state";
-	case CEPH_SESSION_FLUSHMSG: return "flushmsg";
-	case CEPH_SESSION_FLUSHMSG_ACK: return "flushmsg_ack";
-	case CEPH_SESSION_FORCE_RO: return "force_ro";
-	case CEPH_SESSION_REJECT: return "reject";
-	case CEPH_SESSION_REQUEST_FLUSH_MDLOG: return "flush_mdlog";
+	case CEPH_MDS_OP_LOOKUP:
+		return CEPH_MDS_OP_LOOKUP_STR_IDX;		/* 0 */
+	case CEPH_MDS_OP_LOOKUPHASH:
+		return CEPH_MDS_OP_LOOKUPHASH_STR_IDX;		/* 2 */
+	case CEPH_MDS_OP_LOOKUPPARENT:
+		return CEPH_MDS_OP_LOOKUPPARENT_STR_IDX;	/* 3 */
+	case CEPH_MDS_OP_LOOKUPINO:
+		return CEPH_MDS_OP_LOOKUPINO_STR_IDX;		/* 4 */
+	case CEPH_MDS_OP_LOOKUPNAME:
+		return CEPH_MDS_OP_LOOKUPNAME_STR_IDX;		/* 5 */
+	case CEPH_MDS_OP_GETATTR:
+		return CEPH_MDS_OP_GETATTR_STR_IDX;		/* 1 */
+	case CEPH_MDS_OP_GETVXATTR:
+		return CEPH_MDS_OP_GETVXATTR_STR_IDX;		/* 6 */
+	case CEPH_MDS_OP_SETXATTR:
+		return CEPH_MDS_OP_SETXATTR_STR_IDX;		/* 7 */
+	case CEPH_MDS_OP_SETATTR:
+		return CEPH_MDS_OP_SETATTR_STR_IDX;		/* 10 */
+	case CEPH_MDS_OP_RMXATTR:
+		return CEPH_MDS_OP_RMXATTR_STR_IDX;		/* 8 */
+	case CEPH_MDS_OP_SETLAYOUT:
+		return CEPH_MDS_OP_SETLAYOUT_STR_IDX;		/* 9 */
+	case CEPH_MDS_OP_SETDIRLAYOUT:
+		return CEPH_MDS_OP_SETDIRLAYOUT_STR_IDX;	/* 13 */
+	case CEPH_MDS_OP_READDIR:
+		return CEPH_MDS_OP_READDIR_STR_IDX;		/* 23 */
+	case CEPH_MDS_OP_MKNOD:
+		return CEPH_MDS_OP_MKNOD_STR_IDX;		/* 14 */
+	case CEPH_MDS_OP_LINK:
+		return CEPH_MDS_OP_LINK_STR_IDX;		/* 15 */
+	case CEPH_MDS_OP_UNLINK:
+		return CEPH_MDS_OP_UNLINK_STR_IDX;		/* 16 */
+	case CEPH_MDS_OP_RENAME:
+		return CEPH_MDS_OP_RENAME_STR_IDX;		/* 17 */
+	case CEPH_MDS_OP_MKDIR:
+		return CEPH_MDS_OP_MKDIR_STR_IDX;		/* 18 */
+	case CEPH_MDS_OP_RMDIR:
+		return CEPH_MDS_OP_RMDIR_STR_IDX;		/* 19 */
+	case CEPH_MDS_OP_SYMLINK:
+		return CEPH_MDS_OP_SYMLINK_STR_IDX;		/* 20 */
+	case CEPH_MDS_OP_CREATE:
+		return CEPH_MDS_OP_CREATE_STR_IDX;		/* 21 */
+	case CEPH_MDS_OP_OPEN:
+		return CEPH_MDS_OP_OPEN_STR_IDX;		/* 22 */
+	case CEPH_MDS_OP_LOOKUPSNAP:
+		return CEPH_MDS_OP_LOOKUPSNAP_STR_IDX;		/* 24 */
+	case CEPH_MDS_OP_LSSNAP:
+		return CEPH_MDS_OP_LSSNAP_STR_IDX;		/* 27 */
+	case CEPH_MDS_OP_MKSNAP:
+		return CEPH_MDS_OP_MKSNAP_STR_IDX;		/* 25 */
+	case CEPH_MDS_OP_RMSNAP:
+		return CEPH_MDS_OP_RMSNAP_STR_IDX;		/* 26 */
+	case CEPH_MDS_OP_RENAMESNAP:
+		return CEPH_MDS_OP_RENAMESNAP_STR_IDX;		/* 28 */
+	case CEPH_MDS_OP_SETFILELOCK:
+		return CEPH_MDS_OP_SETFILELOCK_STR_IDX;		/* 11 */
+	case CEPH_MDS_OP_GETFILELOCK:
+		return CEPH_MDS_OP_GETFILELOCK_STR_IDX;		/* 12 */
+	default:
+		/* do nothing */
+		break;
 	}
-	return "???";
+
+	return CEPH_MDS_OP_UNKNOWN_NAME_STR_IDX;
 }
+EXPORT_SYMBOL_IF_KUNIT(ceph_mds_op_2_str_idx);
 
 const char *ceph_mds_op_name(int op)
 {
-	switch (op) {
-	case CEPH_MDS_OP_LOOKUP:  return "lookup";
-	case CEPH_MDS_OP_LOOKUPHASH:  return "lookuphash";
-	case CEPH_MDS_OP_LOOKUPPARENT:  return "lookupparent";
-	case CEPH_MDS_OP_LOOKUPINO:  return "lookupino";
-	case CEPH_MDS_OP_LOOKUPNAME:  return "lookupname";
-	case CEPH_MDS_OP_GETATTR:  return "getattr";
-	case CEPH_MDS_OP_GETVXATTR:  return "getvxattr";
-	case CEPH_MDS_OP_SETXATTR: return "setxattr";
-	case CEPH_MDS_OP_SETATTR: return "setattr";
-	case CEPH_MDS_OP_RMXATTR: return "rmxattr";
-	case CEPH_MDS_OP_SETLAYOUT: return "setlayou";
-	case CEPH_MDS_OP_SETDIRLAYOUT: return "setdirlayout";
-	case CEPH_MDS_OP_READDIR: return "readdir";
-	case CEPH_MDS_OP_MKNOD: return "mknod";
-	case CEPH_MDS_OP_LINK: return "link";
-	case CEPH_MDS_OP_UNLINK: return "unlink";
-	case CEPH_MDS_OP_RENAME: return "rename";
-	case CEPH_MDS_OP_MKDIR: return "mkdir";
-	case CEPH_MDS_OP_RMDIR: return "rmdir";
-	case CEPH_MDS_OP_SYMLINK: return "symlink";
-	case CEPH_MDS_OP_CREATE: return "create";
-	case CEPH_MDS_OP_OPEN: return "open";
-	case CEPH_MDS_OP_LOOKUPSNAP: return "lookupsnap";
-	case CEPH_MDS_OP_LSSNAP: return "lssnap";
-	case CEPH_MDS_OP_MKSNAP: return "mksnap";
-	case CEPH_MDS_OP_RMSNAP: return "rmsnap";
-	case CEPH_MDS_OP_RENAMESNAP: return "renamesnap";
-	case CEPH_MDS_OP_SETFILELOCK: return "setfilelock";
-	case CEPH_MDS_OP_GETFILELOCK: return "getfilelock";
-	}
-	return "???";
+	return ceph_mds_op_name_strings[ceph_mds_op_2_str_idx(op)];
 }
+EXPORT_SYMBOL_IF_KUNIT(ceph_mds_op_name);
+
+const char *ceph_cap_op_name_strings[] = {
+/* 0 */		"grant",
+/* 1 */		"revoke",
+/* 2 */		"trunc",
+/* 3 */		"export",
+/* 4 */		"import",
+/* 5 */		"update",
+/* 6 */		"drop",
+/* 7 */		"flush",
+/* 8 */		"flush_ack",
+/* 9 */		"flushsnap",
+/* 10 */	"flushsnap_ack",
+/* 11 */	"release",
+/* 12 */	"renew",
+/* 13 */	"???"
+};
+EXPORT_SYMBOL_IF_KUNIT(ceph_cap_op_name_strings);
+
+VISIBLE_IF_KUNIT
+int ceph_cap_op_2_str_idx(int op)
+{
+	if (op < CEPH_CAP_OP_GRANT ||
+	    op >= CEPH_CAP_OP_UNKNOWN_NAME)
+		return CEPH_SESSION_UNKNOWN_NAME;
+
+	return op;
+}
+EXPORT_SYMBOL_IF_KUNIT(ceph_cap_op_2_str_idx);
 
 const char *ceph_cap_op_name(int op)
+{
+	return ceph_cap_op_name_strings[ceph_cap_op_2_str_idx(op)];
+}
+EXPORT_SYMBOL_IF_KUNIT(ceph_cap_op_name);
+
+const char *ceph_lease_op_name_strings[] = {
+/* 0 */		"revoke",
+/* 1 */		"release",
+/* 2 */		"renew",
+/* 3 */		"revoke_ack",
+/* 4 */		"???"
+};
+EXPORT_SYMBOL_IF_KUNIT(ceph_lease_op_name_strings);
+
+VISIBLE_IF_KUNIT
+int ceph_lease_op_2_str_idx(int op)
 {
 	switch (op) {
-	case CEPH_CAP_OP_GRANT: return "grant";
-	case CEPH_CAP_OP_REVOKE: return "revoke";
-	case CEPH_CAP_OP_TRUNC: return "trunc";
-	case CEPH_CAP_OP_EXPORT: return "export";
-	case CEPH_CAP_OP_IMPORT: return "import";
-	case CEPH_CAP_OP_UPDATE: return "update";
-	case CEPH_CAP_OP_DROP: return "drop";
-	case CEPH_CAP_OP_FLUSH: return "flush";
-	case CEPH_CAP_OP_FLUSH_ACK: return "flush_ack";
-	case CEPH_CAP_OP_FLUSHSNAP: return "flushsnap";
-	case CEPH_CAP_OP_FLUSHSNAP_ACK: return "flushsnap_ack";
-	case CEPH_CAP_OP_RELEASE: return "release";
-	case CEPH_CAP_OP_RENEW: return "renew";
+	case CEPH_MDS_LEASE_REVOKE:
+		return CEPH_MDS_LEASE_REVOKE_STR_IDX;
+	case CEPH_MDS_LEASE_RELEASE:
+		return CEPH_MDS_LEASE_RELEASE_STR_IDX;
+	case CEPH_MDS_LEASE_RENEW:
+		return CEPH_MDS_LEASE_RENEW_STR_IDX;
+	case CEPH_MDS_LEASE_REVOKE_ACK:
+		return CEPH_MDS_LEASE_REVOKE_ACK_STR_IDX;
+	default:
+		/* do nothing */
+		break;
 	}
-	return "???";
+
+	return CEPH_MDS_LEASE_UNKNOWN_NAME_STR_IDX;
 }
+EXPORT_SYMBOL_IF_KUNIT(ceph_lease_op_2_str_idx);
 
-const char *ceph_lease_op_name(int o)
+const char *ceph_lease_op_name(int op)
 {
-	switch (o) {
-	case CEPH_MDS_LEASE_REVOKE: return "revoke";
-	case CEPH_MDS_LEASE_RELEASE: return "release";
-	case CEPH_MDS_LEASE_RENEW: return "renew";
-	case CEPH_MDS_LEASE_REVOKE_ACK: return "revoke_ack";
-	}
-	return "???";
+	return ceph_lease_op_name_strings[ceph_lease_op_2_str_idx(op)];
 }
+EXPORT_SYMBOL_IF_KUNIT(ceph_lease_op_name);
 
-const char *ceph_snap_op_name(int o)
+const char *ceph_snap_op_name_strings[] = {
+/* 0 */		"update",
+/* 1 */		"create",
+/* 2 */		"destroy",
+/* 3 */		"split",
+/* 4 */		"???"
+};
+EXPORT_SYMBOL_IF_KUNIT(ceph_snap_op_name_strings);
+
+VISIBLE_IF_KUNIT
+int ceph_snap_op_2_str_idx(int op)
 {
-	switch (o) {
-	case CEPH_SNAP_OP_UPDATE: return "update";
-	case CEPH_SNAP_OP_CREATE: return "create";
-	case CEPH_SNAP_OP_DESTROY: return "destroy";
-	case CEPH_SNAP_OP_SPLIT: return "split";
-	}
-	return "???";
+	if (op < CEPH_SNAP_OP_UPDATE ||
+	    op >= CEPH_SNAP_OP_UNKNOWN_NAME)
+		return CEPH_SNAP_OP_UNKNOWN_NAME;
+
+	return op;
+}
+EXPORT_SYMBOL_IF_KUNIT(ceph_snap_op_2_str_idx);
+
+const char *ceph_snap_op_name(int op)
+{
+	return ceph_snap_op_name_strings[ceph_snap_op_2_str_idx(op)];
 }
+EXPORT_SYMBOL_IF_KUNIT(ceph_snap_op_name);
diff --git a/fs/ceph/strings_test.c b/fs/ceph/strings_test.c
new file mode 100644
index 000000000000..9e5204508192
--- /dev/null
+++ b/fs/ceph/strings_test.c
@@ -0,0 +1,588 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * KUnit tests for fs/ceph/strings.c
+ *
+ * Copyright (C) 2025, IBM Corporation
+ *
+ * Author: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
+ */
+
+#include <kunit/test.h>
+#include <linux/ceph/types.h>
+
+#include "kunit_tests.h"
+
+#define CEPH_KUNIT_STRINGS_TEST_RANGE		(20)
+#define CEPH_KUNIT_OP_INVALID_MIN		(-999)
+#define CEPH_KUNIT_OP_INVALID_MAX		(999)
+
+typedef int (*next_op_func)(int);
+
+struct ceph_op_iterator {
+	int start;
+	int cur;
+	int next;
+	int end;
+	next_op_func get_next_op;
+};
+
+static inline
+void ceph_op_iterator_init(struct ceph_op_iterator *iter,
+			   int start, int end,
+			   next_op_func get_next_op)
+{
+	if (!iter || !get_next_op)
+		return;
+
+	iter->start = iter->cur = start;
+	iter->end = end;
+	iter->get_next_op = get_next_op;
+	iter->next = iter->get_next_op(start);
+}
+
+static inline
+int ceph_op_iterator_next(struct ceph_op_iterator *iter)
+{
+	int threshold1, threshold2;
+
+	if (!iter)
+		return CEPH_KUNIT_OP_INVALID_MAX;
+
+	if (iter->cur >= iter->end)
+		return CEPH_KUNIT_OP_INVALID_MAX;
+
+	threshold1 = iter->start + CEPH_KUNIT_STRINGS_TEST_RANGE;
+	if (threshold1 > iter->next)
+		threshold1 = iter->next;
+
+	threshold2 = iter->next - CEPH_KUNIT_STRINGS_TEST_RANGE;
+	if (threshold2 < threshold1)
+		threshold2 = iter->next;
+
+	iter->cur++;
+
+	if (iter->cur <= threshold1)
+		goto finish_method;
+
+	if (iter->cur >= threshold2 && iter->cur <= iter->next)
+		goto finish_method;
+
+	iter->start = iter->next;
+	iter->next = iter->get_next_op(iter->start);
+
+	if (iter->start >= iter->next)
+		iter->next = iter->end;
+
+finish_method:
+	return iter->cur;
+}
+
+static inline
+bool ceph_op_iterator_valid(struct ceph_op_iterator *iter)
+{
+	if (!iter)
+		return false;
+
+	return iter->cur < iter->end;
+}
+
+static inline
+int __ceph_next_op(int prev, int lower_bound, int upper_bound)
+{
+	if (prev < lower_bound)
+		return lower_bound;
+
+	if (prev >= lower_bound && prev < upper_bound)
+		return prev + 1;
+
+	return upper_bound;
+}
+
+#define CEPH_MDS_STATE_STR_COUNT	(CEPH_MDS_STATE_UNKNOWN_NAME_STR_IDX)
+const int ceph_str_idx_2_mds_state[CEPH_MDS_STATE_STR_COUNT] = {
+/* 0 */		CEPH_MDS_STATE_DNE,
+/* 1 */		CEPH_MDS_STATE_STOPPED,
+/* 2 */		CEPH_MDS_STATE_BOOT,
+/* 3 */		CEPH_MDS_STATE_STANDBY,
+/* 4 */		CEPH_MDS_STATE_STANDBY_REPLAY,
+/* 5 */		CEPH_MDS_STATE_REPLAYONCE,
+/* 6 */		CEPH_MDS_STATE_CREATING,
+/* 7 */		CEPH_MDS_STATE_STARTING,
+/* 8 */		CEPH_MDS_STATE_REPLAY,
+/* 9 */		CEPH_MDS_STATE_RESOLVE,
+/* 10 */	CEPH_MDS_STATE_RECONNECT,
+/* 11 */	CEPH_MDS_STATE_REJOIN,
+/* 12 */	CEPH_MDS_STATE_CLIENTREPLAY,
+/* 13 */	CEPH_MDS_STATE_ACTIVE,
+/* 14 */	CEPH_MDS_STATE_STOPPING
+};
+
+static int ceph_mds_state_next_op(int prev)
+{
+	if (prev < CEPH_MDS_STATE_REPLAYONCE)
+		return CEPH_MDS_STATE_REPLAYONCE;
+
+	/* [-9..-4] */
+	if (prev >= CEPH_MDS_STATE_REPLAYONCE &&
+	    prev < CEPH_MDS_STATE_BOOT)
+		return prev + 1;
+
+	/* [-4..-1] */
+	if (prev == CEPH_MDS_STATE_BOOT)
+		return CEPH_MDS_STATE_STOPPED;
+
+	/* [-1..0] */
+	if (prev >= CEPH_MDS_STATE_STOPPED &&
+	    prev < CEPH_MDS_STATE_DNE)
+		return prev + 1;
+
+	/* [0..8] */
+	if (prev == CEPH_MDS_STATE_DNE)
+		return CEPH_MDS_STATE_REPLAY;
+
+	/* [8..14] */
+	if (prev >= CEPH_MDS_STATE_REPLAY &&
+	    prev < CEPH_MDS_STATE_STOPPING)
+		return prev + 1;
+
+	return CEPH_MDS_STATE_STOPPING;
+}
+
+static void ceph_mds_state_name_test(struct kunit *test)
+{
+	const char *unknown_name =
+		ceph_mds_state_name_strings[CEPH_MDS_STATE_UNKNOWN_NAME_STR_IDX];
+	struct ceph_op_iterator iter;
+	int start, end;
+	int i;
+
+	/* Test valid MDS states */
+	for (i = 0; i < CEPH_MDS_STATE_STR_COUNT; i++) {
+		KUNIT_EXPECT_STREQ(test,
+			   ceph_mds_state_name(ceph_str_idx_2_mds_state[i]),
+			   ceph_mds_state_name_strings[i]);
+	}
+
+	/* Test invalid/unknown states */
+	start = CEPH_MDS_STATE_REPLAYONCE - CEPH_KUNIT_STRINGS_TEST_RANGE;
+	end = CEPH_MDS_STATE_STOPPING + CEPH_KUNIT_STRINGS_TEST_RANGE;
+	ceph_op_iterator_init(&iter, start, end, ceph_mds_state_next_op);
+
+	while (ceph_op_iterator_valid(&iter)) {
+		switch (ceph_mds_state_2_str_idx(iter.cur)) {
+		case CEPH_MDS_STATE_UNKNOWN_NAME_STR_IDX:
+			KUNIT_EXPECT_STREQ(test,
+					   ceph_mds_state_name(iter.cur),
+					   unknown_name);
+			break;
+
+		default:
+			/* do nothing */
+			break;
+		}
+
+		ceph_op_iterator_next(&iter);
+	}
+
+	KUNIT_EXPECT_STREQ(test,
+			   ceph_mds_state_name(CEPH_KUNIT_OP_INVALID_MIN),
+			   unknown_name);
+	KUNIT_EXPECT_STREQ(test,
+			   ceph_mds_state_name(CEPH_KUNIT_OP_INVALID_MAX),
+			   unknown_name);
+}
+
+static int ceph_session_next_op(int prev)
+{
+	return __ceph_next_op(prev,
+			      CEPH_SESSION_REQUEST_OPEN,
+			      CEPH_SESSION_REQUEST_FLUSH_MDLOG);
+}
+
+static void ceph_session_op_name_test(struct kunit *test)
+{
+	const char *unknown_name =
+			ceph_session_op_name_strings[CEPH_SESSION_UNKNOWN_NAME];
+	struct ceph_op_iterator iter;
+	int start, end;
+	int i;
+
+	/* Test valid session operations */
+	for (i = CEPH_SESSION_REQUEST_OPEN; i < CEPH_SESSION_UNKNOWN_NAME; i++) {
+		KUNIT_EXPECT_STREQ(test,
+				   ceph_session_op_name(i),
+				   ceph_session_op_name_strings[i]);
+	}
+
+	/* Test invalid/unknown operations */
+	start = CEPH_SESSION_REQUEST_OPEN - CEPH_KUNIT_STRINGS_TEST_RANGE;
+	end = CEPH_SESSION_REQUEST_FLUSH_MDLOG + CEPH_KUNIT_STRINGS_TEST_RANGE;
+	ceph_op_iterator_init(&iter, start, end, ceph_session_next_op);
+
+	while (ceph_op_iterator_valid(&iter)) {
+		switch (ceph_session_op_2_str_idx(iter.cur)) {
+		case CEPH_SESSION_UNKNOWN_NAME:
+			KUNIT_EXPECT_STREQ(test,
+					   ceph_session_op_name(iter.cur),
+					   unknown_name);
+			break;
+
+		default:
+			/* do nothing */
+			break;
+		}
+
+		ceph_op_iterator_next(&iter);
+	}
+
+	KUNIT_EXPECT_STREQ(test,
+			   ceph_session_op_name(CEPH_KUNIT_OP_INVALID_MIN),
+			   unknown_name);
+	KUNIT_EXPECT_STREQ(test,
+			   ceph_session_op_name(CEPH_KUNIT_OP_INVALID_MAX),
+			   unknown_name);
+}
+
+#define CEPH_MDS_OP_STR_COUNT	(CEPH_MDS_OP_UNKNOWN_NAME_STR_IDX)
+const int ceph_str_idx_2_mds_op[CEPH_MDS_OP_STR_COUNT] = {
+/* 0 */		CEPH_MDS_OP_LOOKUP,
+/* 1 */		CEPH_MDS_OP_GETATTR,
+/* 2 */		CEPH_MDS_OP_LOOKUPHASH,
+/* 3 */		CEPH_MDS_OP_LOOKUPPARENT,
+/* 4 */		CEPH_MDS_OP_LOOKUPINO,
+/* 5 */		CEPH_MDS_OP_LOOKUPNAME,
+/* 6 */		CEPH_MDS_OP_GETVXATTR,
+/* 7 */		CEPH_MDS_OP_SETXATTR,
+/* 8 */		CEPH_MDS_OP_RMXATTR,
+/* 9 */		CEPH_MDS_OP_SETLAYOUT,
+/* 10 */	CEPH_MDS_OP_SETATTR,
+/* 11 */	CEPH_MDS_OP_SETFILELOCK,
+/* 12 */	CEPH_MDS_OP_GETFILELOCK,
+/* 13 */	CEPH_MDS_OP_SETDIRLAYOUT,
+/* 14 */	CEPH_MDS_OP_MKNOD,
+/* 15 */	CEPH_MDS_OP_LINK,
+/* 16 */	CEPH_MDS_OP_UNLINK,
+/* 17 */	CEPH_MDS_OP_RENAME,
+/* 18 */	CEPH_MDS_OP_MKDIR,
+/* 19 */	CEPH_MDS_OP_RMDIR,
+/* 20 */	CEPH_MDS_OP_SYMLINK,
+/* 21 */	CEPH_MDS_OP_CREATE,
+/* 22 */	CEPH_MDS_OP_OPEN,
+/* 23 */	CEPH_MDS_OP_READDIR,
+/* 24 */	CEPH_MDS_OP_LOOKUPSNAP,
+/* 25 */	CEPH_MDS_OP_MKSNAP,
+/* 26 */	CEPH_MDS_OP_RMSNAP,
+/* 27 */	CEPH_MDS_OP_LSSNAP,
+/* 28 */	CEPH_MDS_OP_RENAMESNAP
+};
+
+static int ceph_mds_next_op(int prev)
+{
+	if (prev < CEPH_MDS_OP_LOOKUP)
+		return CEPH_MDS_OP_LOOKUP;
+
+	/* [0x00100..0x00106] */
+	if (prev >= CEPH_MDS_OP_LOOKUP &&
+	    prev < CEPH_MDS_OP_GETVXATTR)
+		return prev + 1;
+
+	/* [0x00106..0x00110] */
+	if (prev >= CEPH_MDS_OP_GETVXATTR &&
+	    prev < CEPH_MDS_OP_GETFILELOCK)
+		return CEPH_MDS_OP_GETFILELOCK;
+
+	/* [0x00110..0x00302] */
+	if (prev >= CEPH_MDS_OP_GETFILELOCK &&
+	    prev < CEPH_MDS_OP_OPEN)
+		return CEPH_MDS_OP_OPEN;
+
+	/* [0x00302..0x00305] */
+	if (prev >= CEPH_MDS_OP_OPEN &&
+	    prev < CEPH_MDS_OP_READDIR)
+		return CEPH_MDS_OP_READDIR;
+
+	/* [0x00305..0x00400] */
+	if (prev >= CEPH_MDS_OP_READDIR &&
+	    prev < CEPH_MDS_OP_LOOKUPSNAP)
+		return CEPH_MDS_OP_LOOKUPSNAP;
+
+	/* [0x00400..0x00402] */
+	if (prev >= CEPH_MDS_OP_LOOKUPSNAP &&
+	    prev < CEPH_MDS_OP_LSSNAP)
+		return CEPH_MDS_OP_LSSNAP;
+
+	/* [0x00402..0x01105] */
+	if (prev >= CEPH_MDS_OP_LSSNAP &&
+	    prev < CEPH_MDS_OP_SETXATTR)
+		return CEPH_MDS_OP_SETXATTR;
+
+	/* [0x01105..0x0110a] */
+	if (prev >= CEPH_MDS_OP_SETXATTR &&
+	    prev < CEPH_MDS_OP_SETDIRLAYOUT)
+		return prev + 1;
+
+	/* [0x0110a..0x01201] */
+	if (prev >= CEPH_MDS_OP_SETDIRLAYOUT &&
+	    prev < CEPH_MDS_OP_MKNOD)
+		return CEPH_MDS_OP_MKNOD;
+
+	/* [0x01201..0x01204] */
+	if (prev >= CEPH_MDS_OP_MKNOD &&
+	    prev < CEPH_MDS_OP_RENAME)
+		return prev + 1;
+
+	/* [0x01204..0x01220] */
+	if (prev >= CEPH_MDS_OP_RENAME &&
+	    prev < CEPH_MDS_OP_MKDIR)
+		return CEPH_MDS_OP_MKDIR;
+
+	/* [0x01220..0x01222] */
+	if (prev >= CEPH_MDS_OP_MKDIR &&
+	    prev < CEPH_MDS_OP_SYMLINK)
+		return prev + 1;
+
+	/* [0x01222..0x01301] */
+	if (prev >= CEPH_MDS_OP_SYMLINK &&
+	    prev < CEPH_MDS_OP_CREATE)
+		return CEPH_MDS_OP_CREATE;
+
+	/* [0x01301..0x01400] */
+	if (prev >= CEPH_MDS_OP_CREATE &&
+	    prev < CEPH_MDS_OP_MKSNAP)
+		return CEPH_MDS_OP_MKSNAP;
+
+	/* [0x01400..0x01401] */
+	if (prev >= CEPH_MDS_OP_MKSNAP &&
+	    prev < CEPH_MDS_OP_RMSNAP)
+		return prev + 1;
+
+	/* [0x01401..0x01403] */
+	if (prev >= CEPH_MDS_OP_RMSNAP &&
+	    prev < CEPH_MDS_OP_RENAMESNAP)
+		return CEPH_MDS_OP_RENAMESNAP;
+
+	return CEPH_MDS_OP_RENAMESNAP;
+}
+
+static void ceph_mds_op_name_test(struct kunit *test)
+{
+	const char *unknown_name =
+		ceph_mds_op_name_strings[CEPH_MDS_OP_UNKNOWN_NAME_STR_IDX];
+	struct ceph_op_iterator iter;
+	int start, end;
+	int i;
+
+	/* Test valid MDS operations */
+	for (i = 0; i < CEPH_MDS_OP_STR_COUNT; i++) {
+		KUNIT_EXPECT_STREQ(test,
+				   ceph_mds_op_name(ceph_str_idx_2_mds_op[i]),
+				   ceph_mds_op_name_strings[i]);
+	}
+
+	/* Test invalid/unknown operations */
+	start = CEPH_MDS_OP_LOOKUP - CEPH_KUNIT_STRINGS_TEST_RANGE;
+	end = CEPH_MDS_OP_RENAMESNAP + CEPH_KUNIT_STRINGS_TEST_RANGE;
+	ceph_op_iterator_init(&iter, start, end, ceph_mds_next_op);
+
+	while (ceph_op_iterator_valid(&iter)) {
+		switch (ceph_mds_op_2_str_idx(iter.cur)) {
+		case CEPH_MDS_OP_UNKNOWN_NAME_STR_IDX:
+			KUNIT_EXPECT_STREQ(test,
+					   ceph_mds_op_name(iter.cur),
+					   unknown_name);
+			break;
+
+		default:
+			/* do nothing */
+			break;
+		}
+
+		ceph_op_iterator_next(&iter);
+	}
+
+	KUNIT_EXPECT_STREQ(test, ceph_mds_op_name(-0x99999), unknown_name);
+	KUNIT_EXPECT_STREQ(test, ceph_mds_op_name(0x99999), unknown_name);
+}
+
+static int ceph_cap_next_op(int prev)
+{
+	return __ceph_next_op(prev,
+			      CEPH_CAP_OP_GRANT,
+			      CEPH_CAP_OP_RENEW);
+}
+
+static void ceph_cap_op_name_test(struct kunit *test)
+{
+	const char *unknown_name =
+			ceph_cap_op_name_strings[CEPH_CAP_OP_UNKNOWN_NAME];
+	struct ceph_op_iterator iter;
+	int start, end;
+	int i;
+
+	/* Test valid capability operations */
+	for (i = 0; i < CEPH_CAP_OP_UNKNOWN_NAME; i++) {
+		KUNIT_EXPECT_STREQ(test,
+				   ceph_cap_op_name(i),
+				   ceph_cap_op_name_strings[i]);
+	}
+
+	/* Test invalid/unknown operations */
+	start = CEPH_CAP_OP_GRANT - CEPH_KUNIT_STRINGS_TEST_RANGE;
+	end = CEPH_CAP_OP_RENEW + CEPH_KUNIT_STRINGS_TEST_RANGE;
+	ceph_op_iterator_init(&iter, start, end, ceph_cap_next_op);
+
+	while (ceph_op_iterator_valid(&iter)) {
+		switch (ceph_cap_op_2_str_idx(iter.cur)) {
+		case CEPH_CAP_OP_UNKNOWN_NAME:
+			KUNIT_EXPECT_STREQ(test,
+					   ceph_cap_op_name(iter.cur),
+					   unknown_name);
+			break;
+
+		default:
+			/* do nothing */
+			break;
+		}
+
+		ceph_op_iterator_next(&iter);
+	}
+
+	KUNIT_EXPECT_STREQ(test,
+			   ceph_cap_op_name(CEPH_KUNIT_OP_INVALID_MIN),
+			   unknown_name);
+	KUNIT_EXPECT_STREQ(test,
+			   ceph_cap_op_name(CEPH_KUNIT_OP_INVALID_MAX),
+			   unknown_name);
+}
+
+#define CEPH_MDS_LEASE_OP_STR_COUNT	(CEPH_MDS_LEASE_UNKNOWN_NAME_STR_IDX)
+const int ceph_str_idx_2_lease_op[CEPH_MDS_LEASE_OP_STR_COUNT] = {
+/* 0 */		CEPH_MDS_LEASE_REVOKE,
+/* 1 */		CEPH_MDS_LEASE_RELEASE,
+/* 2 */		CEPH_MDS_LEASE_RENEW,
+/* 3 */		CEPH_MDS_LEASE_REVOKE_ACK
+};
+
+static int ceph_lease_next_op(int prev)
+{
+	return __ceph_next_op(prev,
+			      CEPH_MDS_LEASE_REVOKE,
+			      CEPH_MDS_LEASE_REVOKE_ACK);
+}
+
+static void ceph_lease_op_name_test(struct kunit *test)
+{
+	const char *unknown_name =
+		ceph_lease_op_name_strings[CEPH_MDS_LEASE_UNKNOWN_NAME_STR_IDX];
+	struct ceph_op_iterator iter;
+	int start, end;
+	int i;
+
+	/* Test valid lease operations */
+	for (i = 0; i < CEPH_MDS_LEASE_OP_STR_COUNT; i++) {
+		KUNIT_EXPECT_STREQ(test,
+				   ceph_lease_op_name(ceph_str_idx_2_lease_op[i]),
+				   ceph_lease_op_name_strings[i]);
+	}
+
+	/* Test invalid/unknown operations */
+	start = CEPH_MDS_LEASE_REVOKE - CEPH_KUNIT_STRINGS_TEST_RANGE;
+	end = CEPH_MDS_LEASE_REVOKE_ACK + CEPH_KUNIT_STRINGS_TEST_RANGE;
+	ceph_op_iterator_init(&iter, start, end, ceph_lease_next_op);
+
+	while (ceph_op_iterator_valid(&iter)) {
+		switch (ceph_lease_op_2_str_idx(iter.cur)) {
+		case CEPH_MDS_LEASE_UNKNOWN_NAME_STR_IDX:
+			KUNIT_EXPECT_STREQ(test,
+					   ceph_lease_op_name(iter.cur),
+					   unknown_name);
+			break;
+
+		default:
+			/* do nothing */
+			break;
+		}
+
+		ceph_op_iterator_next(&iter);
+	}
+
+	KUNIT_EXPECT_STREQ(test,
+			   ceph_lease_op_name(CEPH_KUNIT_OP_INVALID_MIN),
+			   unknown_name);
+	KUNIT_EXPECT_STREQ(test,
+			   ceph_lease_op_name(CEPH_KUNIT_OP_INVALID_MAX),
+			   unknown_name);
+}
+
+static int ceph_snap_next_op(int prev)
+{
+	return __ceph_next_op(prev,
+			      CEPH_SNAP_OP_UPDATE,
+			      CEPH_SNAP_OP_SPLIT);
+}
+
+static void ceph_snap_op_name_test(struct kunit *test)
+{
+	const char *unknown_name =
+		ceph_snap_op_name_strings[CEPH_SNAP_OP_UNKNOWN_NAME];
+	struct ceph_op_iterator iter;
+	int start, end;
+	int i;
+
+	/* Test valid snapshot operations */
+	for (i = 0; i < CEPH_SNAP_OP_UNKNOWN_NAME; i++) {
+		KUNIT_EXPECT_STREQ(test,
+				   ceph_snap_op_name(i),
+				   ceph_snap_op_name_strings[i]);
+	}
+
+	/* Test invalid/unknown operations */
+	start = CEPH_SNAP_OP_UPDATE - CEPH_KUNIT_STRINGS_TEST_RANGE;
+	end = CEPH_SNAP_OP_SPLIT + CEPH_KUNIT_STRINGS_TEST_RANGE;
+	ceph_op_iterator_init(&iter, start, end, ceph_snap_next_op);
+
+	while (ceph_op_iterator_valid(&iter)) {
+		switch (ceph_snap_op_2_str_idx(iter.cur)) {
+		case CEPH_MDS_LEASE_UNKNOWN_NAME_STR_IDX:
+			KUNIT_EXPECT_STREQ(test,
+					   ceph_snap_op_name(iter.cur),
+					   unknown_name);
+			break;
+
+		default:
+			/* do nothing */
+			break;
+		}
+
+		ceph_op_iterator_next(&iter);
+	}
+
+	KUNIT_EXPECT_STREQ(test,
+			   ceph_snap_op_name(CEPH_KUNIT_OP_INVALID_MIN),
+			   unknown_name);
+	KUNIT_EXPECT_STREQ(test,
+			   ceph_snap_op_name(CEPH_KUNIT_OP_INVALID_MAX),
+			   unknown_name);
+}
+
+static struct kunit_case ceph_strings_test_cases[] = {
+	KUNIT_CASE(ceph_mds_state_name_test),
+	KUNIT_CASE(ceph_session_op_name_test),
+	KUNIT_CASE(ceph_mds_op_name_test),
+	KUNIT_CASE(ceph_cap_op_name_test),
+	KUNIT_CASE(ceph_lease_op_name_test),
+	KUNIT_CASE(ceph_snap_op_name_test),
+	{}
+};
+
+static struct kunit_suite ceph_strings_test_suite = {
+	.name = "ceph_strings",
+	.test_cases = ceph_strings_test_cases,
+};
+
+kunit_test_suites(&ceph_strings_test_suite);
+
+MODULE_AUTHOR("Viacheslav Dubeyko <slava@dubeyko.com>");
+MODULE_DESCRIPTION("KUnit tests for ceph strings functions");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
diff --git a/include/linux/ceph/ceph_fs.h b/include/linux/ceph/ceph_fs.h
index c7f2c63b3bc3..c41d3996a2b1 100644
--- a/include/linux/ceph/ceph_fs.h
+++ b/include/linux/ceph/ceph_fs.h
@@ -262,6 +262,25 @@ struct ceph_mon_subscribe_ack {
 #define CEPH_MDS_STATE_ACTIVE       13 /* up, active */
 #define CEPH_MDS_STATE_STOPPING     14 /* up, but exporting metadata */
 
+enum {
+/* 0 */		CEPH_MDS_STATE_DNE_STR_IDX,
+/* 1 */		CEPH_MDS_STATE_STOPPED_STR_IDX,
+/* 2 */		CEPH_MDS_STATE_BOOT_STR_IDX,
+/* 3 */		CEPH_MDS_STATE_STANDBY_STR_IDX,
+/* 4 */		CEPH_MDS_STATE_CREATING_STR_IDX,
+/* 5 */		CEPH_MDS_STATE_STARTING_STR_IDX,
+/* 6 */		CEPH_MDS_STATE_STANDBY_REPLAY_STR_IDX,
+/* 7 */		CEPH_MDS_STATE_REPLAYONCE_STR_IDX,
+/* 8 */		CEPH_MDS_STATE_REPLAY_STR_IDX,
+/* 9 */		CEPH_MDS_STATE_RESOLVE_STR_IDX,
+/* 10 */	CEPH_MDS_STATE_RECONNECT_STR_IDX,
+/* 11 */	CEPH_MDS_STATE_REJOIN_STR_IDX,
+/* 12 */	CEPH_MDS_STATE_CLIENTREPLAY_STR_IDX,
+/* 13 */	CEPH_MDS_STATE_ACTIVE_STR_IDX,
+/* 14 */	CEPH_MDS_STATE_STOPPING_STR_IDX,
+/* 15 */	CEPH_MDS_STATE_UNKNOWN_NAME_STR_IDX
+};
+
 extern const char *ceph_mds_state_name(int s);
 
 
@@ -287,19 +306,20 @@ extern const char *ceph_mds_state_name(int s);
 
 /* client_session ops */
 enum {
-	CEPH_SESSION_REQUEST_OPEN,
-	CEPH_SESSION_OPEN,
-	CEPH_SESSION_REQUEST_CLOSE,
-	CEPH_SESSION_CLOSE,
-	CEPH_SESSION_REQUEST_RENEWCAPS,
-	CEPH_SESSION_RENEWCAPS,
-	CEPH_SESSION_STALE,
-	CEPH_SESSION_RECALL_STATE,
-	CEPH_SESSION_FLUSHMSG,
-	CEPH_SESSION_FLUSHMSG_ACK,
-	CEPH_SESSION_FORCE_RO,
-	CEPH_SESSION_REJECT,
-	CEPH_SESSION_REQUEST_FLUSH_MDLOG,
+/* 0 */		CEPH_SESSION_REQUEST_OPEN,
+/* 1 */		CEPH_SESSION_OPEN,
+/* 2 */		CEPH_SESSION_REQUEST_CLOSE,
+/* 3 */		CEPH_SESSION_CLOSE,
+/* 4 */		CEPH_SESSION_REQUEST_RENEWCAPS,
+/* 5 */		CEPH_SESSION_RENEWCAPS,
+/* 6 */		CEPH_SESSION_STALE,
+/* 7 */		CEPH_SESSION_RECALL_STATE,
+/* 8 */		CEPH_SESSION_FLUSHMSG,
+/* 9 */		CEPH_SESSION_FLUSHMSG_ACK,
+/* 10 */	CEPH_SESSION_FORCE_RO,
+/* 11 */	CEPH_SESSION_REJECT,
+/* 12 */	CEPH_SESSION_REQUEST_FLUSH_MDLOG,
+/* 13 */	CEPH_SESSION_UNKNOWN_NAME
 };
 
 #define CEPH_SESSION_BLOCKLISTED	(1 << 0)  /* session blocklisted */
@@ -322,39 +342,39 @@ struct ceph_mds_session_head {
  */
 #define CEPH_MDS_OP_WRITE        0x001000
 enum {
-	CEPH_MDS_OP_LOOKUP     = 0x00100,
-	CEPH_MDS_OP_GETATTR    = 0x00101,
-	CEPH_MDS_OP_LOOKUPHASH = 0x00102,
-	CEPH_MDS_OP_LOOKUPPARENT = 0x00103,
-	CEPH_MDS_OP_LOOKUPINO  = 0x00104,
-	CEPH_MDS_OP_LOOKUPNAME = 0x00105,
-	CEPH_MDS_OP_GETVXATTR  = 0x00106,
-
-	CEPH_MDS_OP_SETXATTR   = 0x01105,
-	CEPH_MDS_OP_RMXATTR    = 0x01106,
-	CEPH_MDS_OP_SETLAYOUT  = 0x01107,
-	CEPH_MDS_OP_SETATTR    = 0x01108,
-	CEPH_MDS_OP_SETFILELOCK= 0x01109,
-	CEPH_MDS_OP_GETFILELOCK= 0x00110,
-	CEPH_MDS_OP_SETDIRLAYOUT=0x0110a,
-
-	CEPH_MDS_OP_MKNOD      = 0x01201,
-	CEPH_MDS_OP_LINK       = 0x01202,
-	CEPH_MDS_OP_UNLINK     = 0x01203,
-	CEPH_MDS_OP_RENAME     = 0x01204,
-	CEPH_MDS_OP_MKDIR      = 0x01220,
-	CEPH_MDS_OP_RMDIR      = 0x01221,
-	CEPH_MDS_OP_SYMLINK    = 0x01222,
-
-	CEPH_MDS_OP_CREATE     = 0x01301,
-	CEPH_MDS_OP_OPEN       = 0x00302,
-	CEPH_MDS_OP_READDIR    = 0x00305,
-
-	CEPH_MDS_OP_LOOKUPSNAP = 0x00400,
-	CEPH_MDS_OP_MKSNAP     = 0x01400,
-	CEPH_MDS_OP_RMSNAP     = 0x01401,
-	CEPH_MDS_OP_LSSNAP     = 0x00402,
-	CEPH_MDS_OP_RENAMESNAP = 0x01403,
+/* 0 */		CEPH_MDS_OP_LOOKUP		= 0x00100,
+/* 1 */		CEPH_MDS_OP_GETATTR		= 0x00101,
+/* 2 */		CEPH_MDS_OP_LOOKUPHASH		= 0x00102,
+/* 3 */		CEPH_MDS_OP_LOOKUPPARENT	= 0x00103,
+/* 4 */		CEPH_MDS_OP_LOOKUPINO		= 0x00104,
+/* 5 */		CEPH_MDS_OP_LOOKUPNAME		= 0x00105,
+/* 6 */		CEPH_MDS_OP_GETVXATTR		= 0x00106,
+
+/* 7 */		CEPH_MDS_OP_SETXATTR		= 0x01105,
+/* 8 */		CEPH_MDS_OP_RMXATTR		= 0x01106,
+/* 9 */		CEPH_MDS_OP_SETLAYOUT		= 0x01107,
+/* 10 */	CEPH_MDS_OP_SETATTR		= 0x01108,
+/* 11 */	CEPH_MDS_OP_SETFILELOCK		= 0x01109,
+/* 12 */	CEPH_MDS_OP_GETFILELOCK		= 0x00110,
+/* 13 */	CEPH_MDS_OP_SETDIRLAYOUT	= 0x0110a,
+
+/* 14 */	CEPH_MDS_OP_MKNOD		= 0x01201,
+/* 15 */	CEPH_MDS_OP_LINK		= 0x01202,
+/* 16 */	CEPH_MDS_OP_UNLINK		= 0x01203,
+/* 17 */	CEPH_MDS_OP_RENAME		= 0x01204,
+/* 18 */	CEPH_MDS_OP_MKDIR		= 0x01220,
+/* 19 */	CEPH_MDS_OP_RMDIR		= 0x01221,
+/* 20 */	CEPH_MDS_OP_SYMLINK		= 0x01222,
+
+/* 21 */	CEPH_MDS_OP_CREATE		= 0x01301,
+/* 22 */	CEPH_MDS_OP_OPEN		= 0x00302,
+/* 23 */	CEPH_MDS_OP_READDIR		= 0x00305,
+
+/* 24 */	CEPH_MDS_OP_LOOKUPSNAP		= 0x00400,
+/* 25 */	CEPH_MDS_OP_MKSNAP		= 0x01400,
+/* 26 */	CEPH_MDS_OP_RMSNAP		= 0x01401,
+/* 27 */	CEPH_MDS_OP_LSSNAP		= 0x00402,
+/* 28 */	CEPH_MDS_OP_RENAMESNAP		= 0x01403,
 };
 
 #define IS_CEPH_MDS_OP_NEWINODE(op) (op == CEPH_MDS_OP_CREATE     || \
@@ -362,6 +382,39 @@ enum {
 				     op == CEPH_MDS_OP_MKDIR      || \
 				     op == CEPH_MDS_OP_SYMLINK)
 
+enum {
+/* 0 */		CEPH_MDS_OP_LOOKUP_STR_IDX,
+/* 1 */		CEPH_MDS_OP_GETATTR_STR_IDX,
+/* 2 */		CEPH_MDS_OP_LOOKUPHASH_STR_IDX,
+/* 3 */		CEPH_MDS_OP_LOOKUPPARENT_STR_IDX,
+/* 4 */		CEPH_MDS_OP_LOOKUPINO_STR_IDX,
+/* 5 */		CEPH_MDS_OP_LOOKUPNAME_STR_IDX,
+/* 6 */		CEPH_MDS_OP_GETVXATTR_STR_IDX,
+/* 7 */		CEPH_MDS_OP_SETXATTR_STR_IDX,
+/* 8 */		CEPH_MDS_OP_RMXATTR_STR_IDX,
+/* 9 */		CEPH_MDS_OP_SETLAYOUT_STR_IDX,
+/* 10 */	CEPH_MDS_OP_SETATTR_STR_IDX,
+/* 11 */	CEPH_MDS_OP_SETFILELOCK_STR_IDX,
+/* 12 */	CEPH_MDS_OP_GETFILELOCK_STR_IDX,
+/* 13 */	CEPH_MDS_OP_SETDIRLAYOUT_STR_IDX,
+/* 14 */	CEPH_MDS_OP_MKNOD_STR_IDX,
+/* 15 */	CEPH_MDS_OP_LINK_STR_IDX,
+/* 16 */	CEPH_MDS_OP_UNLINK_STR_IDX,
+/* 17 */	CEPH_MDS_OP_RENAME_STR_IDX,
+/* 18 */	CEPH_MDS_OP_MKDIR_STR_IDX,
+/* 19 */	CEPH_MDS_OP_RMDIR_STR_IDX,
+/* 20 */	CEPH_MDS_OP_SYMLINK_STR_IDX,
+/* 21 */	CEPH_MDS_OP_CREATE_STR_IDX,
+/* 22 */	CEPH_MDS_OP_OPEN_STR_IDX,
+/* 23 */	CEPH_MDS_OP_READDIR_STR_IDX,
+/* 24 */	CEPH_MDS_OP_LOOKUPSNAP_STR_IDX,
+/* 25 */	CEPH_MDS_OP_MKSNAP_STR_IDX,
+/* 26 */	CEPH_MDS_OP_RMSNAP_STR_IDX,
+/* 27 */	CEPH_MDS_OP_LSSNAP_STR_IDX,
+/* 28 */	CEPH_MDS_OP_RENAMESNAP_STR_IDX,
+/* 29 */	CEPH_MDS_OP_UNKNOWN_NAME_STR_IDX
+};
+
 extern const char *ceph_mds_op_name(int op);
 
 #define CEPH_SETATTR_MODE              (1 << 0)
@@ -739,19 +792,20 @@ int ceph_flags_to_mode(int flags);
 int ceph_caps_for_mode(int mode);
 
 enum {
-	CEPH_CAP_OP_GRANT,         /* mds->client grant */
-	CEPH_CAP_OP_REVOKE,        /* mds->client revoke */
-	CEPH_CAP_OP_TRUNC,         /* mds->client trunc notify */
-	CEPH_CAP_OP_EXPORT,        /* mds has exported the cap */
-	CEPH_CAP_OP_IMPORT,        /* mds has imported the cap */
-	CEPH_CAP_OP_UPDATE,        /* client->mds update */
-	CEPH_CAP_OP_DROP,          /* client->mds drop cap bits */
-	CEPH_CAP_OP_FLUSH,         /* client->mds cap writeback */
-	CEPH_CAP_OP_FLUSH_ACK,     /* mds->client flushed */
-	CEPH_CAP_OP_FLUSHSNAP,     /* client->mds flush snapped metadata */
-	CEPH_CAP_OP_FLUSHSNAP_ACK, /* mds->client flushed snapped metadata */
-	CEPH_CAP_OP_RELEASE,       /* client->mds release (clean) cap */
-	CEPH_CAP_OP_RENEW,         /* client->mds renewal request */
+/* 0 */		CEPH_CAP_OP_GRANT,         /* mds->client grant */
+/* 1 */		CEPH_CAP_OP_REVOKE,        /* mds->client revoke */
+/* 2 */		CEPH_CAP_OP_TRUNC,         /* mds->client trunc notify */
+/* 3 */		CEPH_CAP_OP_EXPORT,        /* mds has exported the cap */
+/* 4 */		CEPH_CAP_OP_IMPORT,        /* mds has imported the cap */
+/* 5 */		CEPH_CAP_OP_UPDATE,        /* client->mds update */
+/* 6 */		CEPH_CAP_OP_DROP,          /* client->mds drop cap bits */
+/* 7 */		CEPH_CAP_OP_FLUSH,         /* client->mds cap writeback */
+/* 8 */		CEPH_CAP_OP_FLUSH_ACK,     /* mds->client flushed */
+/* 9 */		CEPH_CAP_OP_FLUSHSNAP,     /* client->mds flush snapped metadata */
+/* 10 */	CEPH_CAP_OP_FLUSHSNAP_ACK, /* mds->client flushed snapped metadata */
+/* 11 */	CEPH_CAP_OP_RELEASE,       /* client->mds release (clean) cap */
+/* 12 */	CEPH_CAP_OP_RENEW,         /* client->mds renewal request */
+/* 13 */	CEPH_CAP_OP_UNKNOWN_NAME
 };
 
 extern const char *ceph_cap_op_name(int op);
@@ -816,7 +870,15 @@ struct ceph_mds_cap_item {
 #define CEPH_MDS_LEASE_RENEW            3  /* client <-> mds    */
 #define CEPH_MDS_LEASE_REVOKE_ACK       4  /* client  -> mds    */
 
-extern const char *ceph_lease_op_name(int o);
+enum {
+/* 0 */		CEPH_MDS_LEASE_REVOKE_STR_IDX,
+/* 1 */		CEPH_MDS_LEASE_RELEASE_STR_IDX,
+/* 2 */		CEPH_MDS_LEASE_RENEW_STR_IDX,
+/* 3 */		CEPH_MDS_LEASE_REVOKE_ACK_STR_IDX,
+/* 4 */		CEPH_MDS_LEASE_UNKNOWN_NAME_STR_IDX
+};
+
+extern const char *ceph_lease_op_name(int op);
 
 /* lease msg header */
 struct ceph_mds_lease {
@@ -860,10 +922,11 @@ struct ceph_mds_snaprealm_reconnect {
  * snaps
  */
 enum {
-	CEPH_SNAP_OP_UPDATE,  /* CREATE or DESTROY */
-	CEPH_SNAP_OP_CREATE,
-	CEPH_SNAP_OP_DESTROY,
-	CEPH_SNAP_OP_SPLIT,
+/* 0 */		CEPH_SNAP_OP_UPDATE,  /* CREATE or DESTROY */
+/* 1 */		CEPH_SNAP_OP_CREATE,
+/* 2 */		CEPH_SNAP_OP_DESTROY,
+/* 3 */		CEPH_SNAP_OP_SPLIT,
+/* 4 */		CEPH_SNAP_OP_UNKNOWN_NAME
 };
 
 extern const char *ceph_snap_op_name(int o);
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] ceph: introduce Kunit based unit-tests for string operations
  2025-09-19 18:11 [PATCH] ceph: introduce Kunit based unit-tests for string operations Viacheslav Dubeyko
@ 2025-09-25 13:04 ` kernel test robot
  0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2025-09-25 13:04 UTC (permalink / raw)
  To: Viacheslav Dubeyko, ceph-devel
  Cc: oe-kbuild-all, idryomov, linux-fsdevel, pdonnell, amarkuze,
	Slava.Dubeyko, slava, vdubeyko

Hi Viacheslav,

kernel test robot noticed the following build warnings:

[auto build test WARNING on ceph-client/testing]
[also build test WARNING on ceph-client/for-linus linus/master v6.17-rc7 next-20250924]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Viacheslav-Dubeyko/ceph-introduce-Kunit-based-unit-tests-for-string-operations/20250920-021357
base:   https://github.com/ceph/ceph-client.git testing
patch link:    https://lore.kernel.org/r/20250919181149.500408-2-slava%40dubeyko.com
patch subject: [PATCH] ceph: introduce Kunit based unit-tests for string operations
config: loongarch-randconfig-r133-20250925 (https://download.01.org/0day-ci/archive/20250925/202509252015.tfuSHe3S-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250925/202509252015.tfuSHe3S-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202509252015.tfuSHe3S-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> fs/ceph/strings_test.c:102:11: sparse: sparse: symbol 'ceph_str_idx_2_mds_state' was not declared. Should it be static?
>> fs/ceph/strings_test.c:247:11: sparse: sparse: symbol 'ceph_str_idx_2_mds_op' was not declared. Should it be static?
>> fs/ceph/strings_test.c:459:11: sparse: sparse: symbol 'ceph_str_idx_2_lease_op' was not declared. Should it be static?

vim +/ceph_str_idx_2_mds_state +102 fs/ceph/strings_test.c

   100	
   101	#define CEPH_MDS_STATE_STR_COUNT	(CEPH_MDS_STATE_UNKNOWN_NAME_STR_IDX)
 > 102	const int ceph_str_idx_2_mds_state[CEPH_MDS_STATE_STR_COUNT] = {
   103	/* 0 */		CEPH_MDS_STATE_DNE,
   104	/* 1 */		CEPH_MDS_STATE_STOPPED,
   105	/* 2 */		CEPH_MDS_STATE_BOOT,
   106	/* 3 */		CEPH_MDS_STATE_STANDBY,
   107	/* 4 */		CEPH_MDS_STATE_STANDBY_REPLAY,
   108	/* 5 */		CEPH_MDS_STATE_REPLAYONCE,
   109	/* 6 */		CEPH_MDS_STATE_CREATING,
   110	/* 7 */		CEPH_MDS_STATE_STARTING,
   111	/* 8 */		CEPH_MDS_STATE_REPLAY,
   112	/* 9 */		CEPH_MDS_STATE_RESOLVE,
   113	/* 10 */	CEPH_MDS_STATE_RECONNECT,
   114	/* 11 */	CEPH_MDS_STATE_REJOIN,
   115	/* 12 */	CEPH_MDS_STATE_CLIENTREPLAY,
   116	/* 13 */	CEPH_MDS_STATE_ACTIVE,
   117	/* 14 */	CEPH_MDS_STATE_STOPPING
   118	};
   119	
   120	static int ceph_mds_state_next_op(int prev)
   121	{
   122		if (prev < CEPH_MDS_STATE_REPLAYONCE)
   123			return CEPH_MDS_STATE_REPLAYONCE;
   124	
   125		/* [-9..-4] */
   126		if (prev >= CEPH_MDS_STATE_REPLAYONCE &&
   127		    prev < CEPH_MDS_STATE_BOOT)
   128			return prev + 1;
   129	
   130		/* [-4..-1] */
   131		if (prev == CEPH_MDS_STATE_BOOT)
   132			return CEPH_MDS_STATE_STOPPED;
   133	
   134		/* [-1..0] */
   135		if (prev >= CEPH_MDS_STATE_STOPPED &&
   136		    prev < CEPH_MDS_STATE_DNE)
   137			return prev + 1;
   138	
   139		/* [0..8] */
   140		if (prev == CEPH_MDS_STATE_DNE)
   141			return CEPH_MDS_STATE_REPLAY;
   142	
   143		/* [8..14] */
   144		if (prev >= CEPH_MDS_STATE_REPLAY &&
   145		    prev < CEPH_MDS_STATE_STOPPING)
   146			return prev + 1;
   147	
   148		return CEPH_MDS_STATE_STOPPING;
   149	}
   150	
   151	static void ceph_mds_state_name_test(struct kunit *test)
   152	{
   153		const char *unknown_name =
   154			ceph_mds_state_name_strings[CEPH_MDS_STATE_UNKNOWN_NAME_STR_IDX];
   155		struct ceph_op_iterator iter;
   156		int start, end;
   157		int i;
   158	
   159		/* Test valid MDS states */
   160		for (i = 0; i < CEPH_MDS_STATE_STR_COUNT; i++) {
   161			KUNIT_EXPECT_STREQ(test,
   162				   ceph_mds_state_name(ceph_str_idx_2_mds_state[i]),
   163				   ceph_mds_state_name_strings[i]);
   164		}
   165	
   166		/* Test invalid/unknown states */
   167		start = CEPH_MDS_STATE_REPLAYONCE - CEPH_KUNIT_STRINGS_TEST_RANGE;
   168		end = CEPH_MDS_STATE_STOPPING + CEPH_KUNIT_STRINGS_TEST_RANGE;
   169		ceph_op_iterator_init(&iter, start, end, ceph_mds_state_next_op);
   170	
   171		while (ceph_op_iterator_valid(&iter)) {
   172			switch (ceph_mds_state_2_str_idx(iter.cur)) {
   173			case CEPH_MDS_STATE_UNKNOWN_NAME_STR_IDX:
   174				KUNIT_EXPECT_STREQ(test,
   175						   ceph_mds_state_name(iter.cur),
   176						   unknown_name);
   177				break;
   178	
   179			default:
   180				/* do nothing */
   181				break;
   182			}
   183	
   184			ceph_op_iterator_next(&iter);
   185		}
   186	
   187		KUNIT_EXPECT_STREQ(test,
   188				   ceph_mds_state_name(CEPH_KUNIT_OP_INVALID_MIN),
   189				   unknown_name);
   190		KUNIT_EXPECT_STREQ(test,
   191				   ceph_mds_state_name(CEPH_KUNIT_OP_INVALID_MAX),
   192				   unknown_name);
   193	}
   194	
   195	static int ceph_session_next_op(int prev)
   196	{
   197		return __ceph_next_op(prev,
   198				      CEPH_SESSION_REQUEST_OPEN,
   199				      CEPH_SESSION_REQUEST_FLUSH_MDLOG);
   200	}
   201	
   202	static void ceph_session_op_name_test(struct kunit *test)
   203	{
   204		const char *unknown_name =
   205				ceph_session_op_name_strings[CEPH_SESSION_UNKNOWN_NAME];
   206		struct ceph_op_iterator iter;
   207		int start, end;
   208		int i;
   209	
   210		/* Test valid session operations */
   211		for (i = CEPH_SESSION_REQUEST_OPEN; i < CEPH_SESSION_UNKNOWN_NAME; i++) {
   212			KUNIT_EXPECT_STREQ(test,
   213					   ceph_session_op_name(i),
   214					   ceph_session_op_name_strings[i]);
   215		}
   216	
   217		/* Test invalid/unknown operations */
   218		start = CEPH_SESSION_REQUEST_OPEN - CEPH_KUNIT_STRINGS_TEST_RANGE;
   219		end = CEPH_SESSION_REQUEST_FLUSH_MDLOG + CEPH_KUNIT_STRINGS_TEST_RANGE;
   220		ceph_op_iterator_init(&iter, start, end, ceph_session_next_op);
   221	
   222		while (ceph_op_iterator_valid(&iter)) {
   223			switch (ceph_session_op_2_str_idx(iter.cur)) {
   224			case CEPH_SESSION_UNKNOWN_NAME:
   225				KUNIT_EXPECT_STREQ(test,
   226						   ceph_session_op_name(iter.cur),
   227						   unknown_name);
   228				break;
   229	
   230			default:
   231				/* do nothing */
   232				break;
   233			}
   234	
   235			ceph_op_iterator_next(&iter);
   236		}
   237	
   238		KUNIT_EXPECT_STREQ(test,
   239				   ceph_session_op_name(CEPH_KUNIT_OP_INVALID_MIN),
   240				   unknown_name);
   241		KUNIT_EXPECT_STREQ(test,
   242				   ceph_session_op_name(CEPH_KUNIT_OP_INVALID_MAX),
   243				   unknown_name);
   244	}
   245	
   246	#define CEPH_MDS_OP_STR_COUNT	(CEPH_MDS_OP_UNKNOWN_NAME_STR_IDX)
 > 247	const int ceph_str_idx_2_mds_op[CEPH_MDS_OP_STR_COUNT] = {
   248	/* 0 */		CEPH_MDS_OP_LOOKUP,
   249	/* 1 */		CEPH_MDS_OP_GETATTR,
   250	/* 2 */		CEPH_MDS_OP_LOOKUPHASH,
   251	/* 3 */		CEPH_MDS_OP_LOOKUPPARENT,
   252	/* 4 */		CEPH_MDS_OP_LOOKUPINO,
   253	/* 5 */		CEPH_MDS_OP_LOOKUPNAME,
   254	/* 6 */		CEPH_MDS_OP_GETVXATTR,
   255	/* 7 */		CEPH_MDS_OP_SETXATTR,
   256	/* 8 */		CEPH_MDS_OP_RMXATTR,
   257	/* 9 */		CEPH_MDS_OP_SETLAYOUT,
   258	/* 10 */	CEPH_MDS_OP_SETATTR,
   259	/* 11 */	CEPH_MDS_OP_SETFILELOCK,
   260	/* 12 */	CEPH_MDS_OP_GETFILELOCK,
   261	/* 13 */	CEPH_MDS_OP_SETDIRLAYOUT,
   262	/* 14 */	CEPH_MDS_OP_MKNOD,
   263	/* 15 */	CEPH_MDS_OP_LINK,
   264	/* 16 */	CEPH_MDS_OP_UNLINK,
   265	/* 17 */	CEPH_MDS_OP_RENAME,
   266	/* 18 */	CEPH_MDS_OP_MKDIR,
   267	/* 19 */	CEPH_MDS_OP_RMDIR,
   268	/* 20 */	CEPH_MDS_OP_SYMLINK,
   269	/* 21 */	CEPH_MDS_OP_CREATE,
   270	/* 22 */	CEPH_MDS_OP_OPEN,
   271	/* 23 */	CEPH_MDS_OP_READDIR,
   272	/* 24 */	CEPH_MDS_OP_LOOKUPSNAP,
   273	/* 25 */	CEPH_MDS_OP_MKSNAP,
   274	/* 26 */	CEPH_MDS_OP_RMSNAP,
   275	/* 27 */	CEPH_MDS_OP_LSSNAP,
   276	/* 28 */	CEPH_MDS_OP_RENAMESNAP
   277	};
   278	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2025-09-25 13:05 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-19 18:11 [PATCH] ceph: introduce Kunit based unit-tests for string operations Viacheslav Dubeyko
2025-09-25 13:04 ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).