From: Breno Leitao <leitao@debian.org>
To: Shuah Khan <shuah@kernel.org>, Andreas Hindborg <a.hindborg@kernel.org>
Cc: linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
gustavold@gmail.com, linux-fsdevel@vger.kernel.org,
Breno Leitao <leitao@debian.org>,
kernel-team@meta.com, vasilisalmpanis@gmail.com
Subject: [PATCH 3/4] selftests/configfs: cover symlink and unlink
Date: Wed, 26 Aug 2026 03:47:04 -0700 [thread overview]
Message-ID: <20260826-config_selftest-v1-3-e364b07e91ac@debian.org> (raw)
In-Reply-To: <20260826-config_selftest-v1-0-e364b07e91ac@debian.org>
samples/configfs had nothing to link from, so symlink(2) went untested
beyond the EPERM a subsystem without ->allow_link() returns.
Cover creating and removing a link, the relative body configfs stores, the
count ->allow_link() and ->drop_link() keep, the busy errors both ends
return, and what get_target() rejects.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
.../selftests/filesystems/configfs/configfs_test.c | 85 +++++++++++++++++++++-
1 file changed, 83 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/filesystems/configfs/configfs_test.c b/tools/testing/selftests/filesystems/configfs/configfs_test.c
index 072d0dcf3f96b..9b15e1fd69e5b 100644
--- a/tools/testing/selftests/filesystems/configfs/configfs_test.c
+++ b/tools/testing/selftests/filesystems/configfs/configfs_test.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Exercise the configfs userspace interface through the three subsystems
+ * Exercise the configfs userspace interface through the subsystems
* registered by samples/configfs.
*
* Copyright (c) 2026 Meta Platforms, Inc. and affiliates
@@ -10,6 +10,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
@@ -31,16 +32,24 @@
#define CHILDLESS "01-childless"
#define SIMPLE "02-simple-children"
#define GROUPS "03-group-children"
+#define SYMLINKS "04-symlink-children"
#define ITEM_A SIMPLE "/kselftest-a"
#define ITEM_B SIMPLE "/kselftest-b"
#define GROUP GROUPS "/kselftest-group"
#define GROUP_ITEM GROUP "/kselftest-a"
+#define LINK_SRC SYMLINKS "/kselftest-src"
+#define LINK LINK_SRC "/kselftest-link"
+
+static const char * const test_links[] = {
+ LINK,
+};
/* Deepest first, so one pass empties the tree. */
static const char * const test_dirs[] = {
GROUP_ITEM,
GROUP,
+ LINK_SRC,
ITEM_A,
ITEM_B,
};
@@ -49,6 +58,10 @@ static void drop_test_dirs(void)
{
size_t i;
+ /* Links first: they hold both their source and their target. */
+ for (i = 0; i < ARRAY_SIZE(test_links); i++)
+ unlink(test_links[i]);
+
for (i = 0; i < ARRAY_SIZE(test_dirs); i++)
rmdir(test_dirs[i]);
}
@@ -131,7 +144,7 @@ FIXTURE_TEARDOWN(configfs)
TEST_F(configfs, mount_and_subsystems)
{
- const char * const subsys[] = { CHILDLESS, SIMPLE, GROUPS };
+ const char * const subsys[] = { CHILDLESS, SIMPLE, GROUPS, SYMLINKS };
struct statfs sfs;
struct stat st;
size_t i;
@@ -324,6 +337,74 @@ TEST_F(configfs, symlink_without_allow_link)
EXPECT_EQ(errno, EPERM);
}
+TEST_F(configfs, symlink_and_unlink)
+{
+ char buf[PATH_MAX];
+ struct stat st;
+ ssize_t n;
+
+ ASSERT_EQ(mkdir(ITEM_A, 0755), 0);
+ ASSERT_EQ(mkdir(LINK_SRC, 0755), 0);
+
+ ASSERT_EQ(symlink(ITEM_A, LINK), 0);
+
+ /* configfs stores its own body, a path relative to the link. */
+ n = readlink(LINK, buf, sizeof(buf) - 1);
+ ASSERT_GT(n, 0);
+ buf[n] = '\0';
+ EXPECT_STREQ(buf, "../../" ITEM_A);
+ EXPECT_EQ(stat(LINK "/storeme", &st), 0);
+
+ /* ->allow_link() ran on the source, not on the target. */
+ ASSERT_GT(read_attr(LINK_SRC "/nlinks", buf, sizeof(buf)), 0);
+ EXPECT_STREQ(buf, "1\n");
+
+ ASSERT_EQ(unlink(LINK), 0);
+ ASSERT_GT(read_attr(LINK_SRC "/nlinks", buf, sizeof(buf)), 0);
+ EXPECT_STREQ(buf, "0\n");
+}
+
+TEST_F(configfs, symlink_pins_both_ends)
+{
+ ASSERT_EQ(mkdir(ITEM_A, 0755), 0);
+ ASSERT_EQ(mkdir(LINK_SRC, 0755), 0);
+ ASSERT_EQ(symlink(ITEM_A, LINK), 0);
+
+ /* A linked item cannot go away under the link. */
+ ASSERT_EQ(rmdir(ITEM_A), -1);
+ EXPECT_EQ(errno, EBUSY);
+
+ /* The link counts as a child of its source. */
+ ASSERT_EQ(rmdir(LINK_SRC), -1);
+ EXPECT_EQ(errno, ENOTEMPTY);
+
+ ASSERT_EQ(unlink(LINK), 0);
+ EXPECT_EQ(rmdir(ITEM_A), 0);
+}
+
+TEST_F(configfs, symlink_target_outside_configfs)
+{
+ ASSERT_EQ(mkdir(LINK_SRC, 0755), 0);
+ ASSERT_EQ(symlink("/", LINK), -1);
+ EXPECT_EQ(errno, EPERM);
+}
+
+TEST_F(configfs, symlink_target_missing)
+{
+ ASSERT_EQ(mkdir(LINK_SRC, 0755), 0);
+ ASSERT_EQ(symlink(SIMPLE "/kselftest-gone", LINK), -1);
+ EXPECT_EQ(errno, ENOENT);
+}
+
+TEST_F(configfs, symlink_target_is_an_attribute)
+{
+ ASSERT_EQ(mkdir(LINK_SRC, 0755), 0);
+
+ /* The target is resolved with LOOKUP_DIRECTORY. */
+ ASSERT_EQ(symlink(CHILDLESS "/storeme", LINK), -1);
+ EXPECT_EQ(errno, ENOTDIR);
+}
+
TEST_F(configfs, module_pinned_by_item)
{
ASSERT_EQ(mkdir(ITEM_A, 0755), 0);
--
2.53.0-Meta
next prev parent reply other threads:[~2026-08-26 10:47 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-26 10:47 [PATCH 0/4] configfs: add a basic selftest Breno Leitao
2026-08-26 10:47 ` [PATCH 1/4] selftests/configfs: add tests for the userspace interface Breno Leitao
2026-08-26 10:47 ` [PATCH 2/4] samples/configfs: add a subsystem that accepts symlinks Breno Leitao
2026-08-26 10:47 ` Breno Leitao [this message]
2026-08-26 10:47 ` [PATCH 4/4] selftests/configfs: race symlink against rmdir of the target Breno Leitao
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=20260826-config_selftest-v1-3-e364b07e91ac@debian.org \
--to=leitao@debian.org \
--cc=a.hindborg@kernel.org \
--cc=gustavold@gmail.com \
--cc=kernel-team@meta.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=shuah@kernel.org \
--cc=vasilisalmpanis@gmail.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