netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Chuck Lever <cel@kernel.org>
To: Donald Hunter <donald.hunter@gmail.com>,
	 Jakub Kicinski <kuba@kernel.org>,
	"David S. Miller" <davem@davemloft.net>,
	 Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
	 John Fastabend <john.fastabend@gmail.com>,
	 Sabrina Dubroca <sd@queasysnail.net>,
	Keith Busch <kbusch@kernel.org>,  Jens Axboe <axboe@kernel.dk>,
	Christoph Hellwig <hch@lst.de>,  Sagi Grimberg <sagi@grimberg.me>,
	Chaitanya Kulkarni <kch@nvidia.com>,
	 Chuck Lever <cel@kernel.org>, Jeff Layton <jlayton@kernel.org>,
	 NeilBrown <neil@brown.name>,
	Olga Kornievskaia <okorniev@redhat.com>,
	 Dai Ngo <Dai.Ngo@oracle.com>, Tom Talpey <tom@talpey.com>,
	 Eric Dumazet <edumazet@kernel.org>
Cc: kernel-tls-handshake@lists.linux.dev, netdev@vger.kernel.org,
	 linux-nvme@lists.infradead.org, linux-nfs@vger.kernel.org
Subject: [PATCH net-next v3 06/10] handshake: Add a kunit test for the completion gate
Date: Fri, 13 Nov 2026 14:22:04 -0500	[thread overview]
Message-ID: <20261113-tls-session-tags-v3-6-91271964cdb0@kernel.org> (raw)
In-Reply-To: <20261113-tls-session-tags-v3-0-91271964cdb0@kernel.org>

The genl family runs DONE with parallel_ops, so duplicate or
concurrent DONE downcalls for the same socket can both reach the
same handshake_req. The split try/finish pair guarantees that
exactly one caller drives completion to the consumer's hp_done
callback. Ownership of the collected session tags can then pass to
the request.

Exercise the gate's exclusivity with a kunit case: only the first
handshake_try_complete() wins, and a later handshake_complete() on
the same request leaves hp_done fired exactly once.

Signed-off-by: Chuck Lever <cel@kernel.org>
---
 net/handshake/handshake-test.c | 82 ++++++++++++++++++++++++++++++++++++++++++
 net/handshake/request.c        |  2 ++
 2 files changed, 84 insertions(+)

diff --git a/net/handshake/handshake-test.c b/net/handshake/handshake-test.c
index b4a56c4350bd..b6992d1fa4ce 100644
--- a/net/handshake/handshake-test.c
+++ b/net/handshake/handshake-test.c
@@ -465,6 +465,84 @@ static void handshake_req_cancel_test3(struct kunit *test)
 	fput(filp);
 }
 
+static int handshake_try_complete_done_count;
+
+static void test_done_count_func(struct handshake_req *req, int status,
+				 struct genl_info *info)
+{
+	handshake_try_complete_done_count++;
+}
+
+static struct handshake_proto handshake_req_alloc_proto_count = {
+	.hp_handler_class	= HANDSHAKE_HANDLER_CLASS_TLSHD,
+	.hp_accept		= test_accept_func,
+	.hp_done		= test_done_count_func,
+};
+
+static void handshake_try_complete_test1(struct kunit *test)
+{
+	unsigned long fcount_before;
+	struct handshake_req *req, *next;
+	struct handshake_net *hn;
+	struct socket *sock;
+	struct file *filp;
+	struct net *net;
+	bool first, second;
+	int err;
+
+	/* Arrange */
+	handshake_try_complete_done_count = 0;
+
+	req = handshake_req_alloc(&handshake_req_alloc_proto_count, GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, req);
+
+	err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP,
+			    &sock, 1);
+	KUNIT_ASSERT_EQ(test, err, 0);
+
+	filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp);
+	KUNIT_ASSERT_NOT_NULL(test, sock->sk);
+	sock->file = filp;
+
+	fcount_before = file_count(filp);
+	err = handshake_req_submit(sock, req, GFP_KERNEL);
+	KUNIT_ASSERT_EQ(test, err, 0);
+	KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before + 1);
+
+	net = sock_net(sock->sk);
+	hn = handshake_pernet(net);
+	KUNIT_ASSERT_NOT_NULL(test, hn);
+
+	/* Pretend to accept this request */
+	next = handshake_req_next(hn, HANDSHAKE_HANDLER_CLASS_TLSHD);
+	KUNIT_ASSERT_PTR_EQ(test, req, next);
+	/* Simulate FD_PREPARE() consuming the file reference handed
+	 * off by handshake_req_next(); see handshake_nl_accept_doit().
+	 */
+	fput(filp);
+
+	/* Act */
+	first = handshake_try_complete(req);
+	second = handshake_try_complete(req);
+	handshake_finish_complete(req, 0, NULL, NULL);
+	/* handshake_finish_complete() drops the request's pin on the file. */
+	KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before);
+	/* handshake_complete() re-enters the gate via
+	 * handshake_try_complete(). With the gate already taken,
+	 * hp_done must not fire a second time.
+	 */
+	handshake_complete(req, 0, NULL);
+
+	/* Assert */
+	KUNIT_EXPECT_TRUE(test, first);
+	KUNIT_EXPECT_FALSE(test, second);
+	KUNIT_EXPECT_EQ(test, handshake_try_complete_done_count, 1);
+	KUNIT_EXPECT_EQ(test, file_count(filp), fcount_before);
+
+	fput(filp);
+}
+
 static struct handshake_req *handshake_req_destroy_test;
 
 static void test_destroy_func(struct handshake_req *req)
@@ -751,6 +829,10 @@ static struct kunit_case handshake_api_test_cases[] = {
 		.name			= "req_cancel after done",
 		.run_case		= handshake_req_cancel_test3,
 	},
+	{
+		.name			= "try_complete gate is exclusive",
+		.run_case		= handshake_try_complete_test1,
+	},
 	{
 		.name			= "req_destroy works",
 		.run_case		= handshake_req_destroy_test1,
diff --git a/net/handshake/request.c b/net/handshake/request.c
index 72515e5e8cc2..31a81b7cb7e9 100644
--- a/net/handshake/request.c
+++ b/net/handshake/request.c
@@ -340,6 +340,7 @@ bool handshake_try_complete(struct handshake_req *req)
 {
 	return !test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED, &req->hr_flags);
 }
+EXPORT_SYMBOL_IF_KUNIT(handshake_try_complete);
 
 /**
  * handshake_finish_complete - Deliver completion to the consumer
@@ -372,6 +373,7 @@ void handshake_finish_complete(struct handshake_req *req, int status,
 
 	fput(file);
 }
+EXPORT_SYMBOL_IF_KUNIT(handshake_finish_complete);
 
 void handshake_complete(struct handshake_req *req, int status,
 			struct genl_info *info)

-- 
2.56.0


  parent reply	other threads:[~2026-11-13 19:22 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-13 19:21 [PATCH net-next v3 00/10] Deliver TLS session tags to upper-layer consumers (NFSD) Chuck Lever
2026-11-13 19:21 ` [PATCH net-next v3 01/10] handshake: Add tags to "done" downcall Chuck Lever
2026-11-13 19:22 ` [PATCH net-next v3 02/10] lib: Add a "stringset" data structure Chuck Lever
2026-11-13 19:22 ` [PATCH net-next v3 03/10] lib: Add KUnit tests for the stringset " Chuck Lever
2026-11-13 19:22 ` [PATCH net-next v3 04/10] handshake: Add a session-tags argument to the TLS done callback Chuck Lever
2026-11-13 19:22 ` [PATCH net-next v3 05/10] handshake: Pick up session tags passed during the DONE downcall Chuck Lever
2026-11-13 19:22 ` Chuck Lever [this message]
2026-11-13 19:22 ` [PATCH net-next v3 07/10] handshake: Advertise the session-tag cap to user space Chuck Lever
2026-11-13 19:22 ` [PATCH net-next v3 08/10] SUNRPC: Copy the TLS session tags when they are available Chuck Lever
2026-11-13 19:22 ` [PATCH net-next v3 09/10] NFSD: Implement export tagging Chuck Lever
2026-11-13 19:22 ` [PATCH net-next v3 10/10] NFSD: Add allow_tags to the netlink export interface Chuck Lever

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261113-tls-session-tags-v3-6-91271964cdb0@kernel.org \
    --to=cel@kernel.org \
    --cc=Dai.Ngo@oracle.com \
    --cc=axboe@kernel.dk \
    --cc=davem@davemloft.net \
    --cc=donald.hunter@gmail.com \
    --cc=edumazet@kernel.org \
    --cc=hch@lst.de \
    --cc=horms@kernel.org \
    --cc=jlayton@kernel.org \
    --cc=john.fastabend@gmail.com \
    --cc=kbusch@kernel.org \
    --cc=kch@nvidia.com \
    --cc=kernel-tls-handshake@lists.linux.dev \
    --cc=kuba@kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=linux-nvme@lists.infradead.org \
    --cc=neil@brown.name \
    --cc=netdev@vger.kernel.org \
    --cc=okorniev@redhat.com \
    --cc=pabeni@redhat.com \
    --cc=sagi@grimberg.me \
    --cc=sd@queasysnail.net \
    --cc=tom@talpey.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).