[PATCH 1/6] fs: use filename_create/filename_lookup instead of open-coding
Ahmad Fatoum
a.fatoum at pengutronix.de
Wed Mar 19 22:20:14 PDT 2025
By reusing the existing file lookup code, open can open all directories,
e.g. / and /tmp/., which so far wasn't possible.
We need to be able to open these paths for directory FDs to work as one
would expect.
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
fs/fs.c | 55 ++++++++---------------------------------------
test/self/dirfd.c | 7 +-----
2 files changed, 10 insertions(+), 52 deletions(-)
diff --git a/fs/fs.c b/fs/fs.c
index 96ca60341ea4..1766719c567a 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -2543,9 +2543,7 @@ int openat(int dirfd, const char *pathname, int flags)
int error = 0;
struct inode *inode = NULL;
struct dentry *dentry = NULL;
- struct nameidata nd;
- const char *s;
- struct filename *filename;
+ struct path path;
if (flags & O_TMPFILE) {
fsdev = get_fsdevice_by_path(dirfd, pathname);
@@ -2575,57 +2573,22 @@ int openat(int dirfd, const char *pathname, int flags)
return file_to_fd(f);
}
- filename = getname(pathname);
- if (IS_ERR(filename))
- return PTR_ERR(filename);
-
- set_nameidata(&nd, filename);
-
- s = path_init(dirfd, &nd, LOOKUP_FOLLOW);
- if (IS_ERR(s))
- return PTR_ERR(s);
-
- while (1) {
- error = link_path_walk(s, &nd);
- if (error)
- break;
-
- if (!d_is_dir(nd.path.dentry)) {
- error = -ENOTDIR;
- break;
- }
-
- dentry = __lookup_hash(&nd.last, nd.path.dentry, 0);
- if (IS_ERR(dentry)) {
- error = PTR_ERR(dentry);
- break;
- }
-
- if (!d_is_symlink(dentry))
- break;
-
- dput(dentry);
-
- error = lookup_last(&nd);
- if (error <= 0)
- break;
-
- s = trailing_symlink(&nd);
- if (IS_ERR(s)) {
- error = PTR_ERR(s);
- break;
- }
+ if (flags & O_CREAT) {
+ dentry = filename_create(dirfd, getname(pathname), &path, 0);
+ error = PTR_ERR_OR_ZERO(dentry);
}
- terminate_walk(&nd);
- putname(nd.name);
+ if (!(flags & O_CREAT) || error == -EEXIST) {
+ error = filename_lookup(dirfd, getname(pathname), LOOKUP_FOLLOW, &path);
+ dentry = path.dentry;
+ }
if (error)
goto out1;
if (d_is_negative(dentry)) {
if (flags & O_CREAT) {
- error = create(nd.path.dentry, dentry);
+ error = create(path.dentry, dentry);
if (error)
goto out1;
} else {
diff --git a/test/self/dirfd.c b/test/self/dirfd.c
index 644ff214fb37..20b54258715a 100644
--- a/test/self/dirfd.c
+++ b/test/self/dirfd.c
@@ -100,13 +100,8 @@ static void test_dirfd(void)
int fd;
fd = open("/", O_PATH);
- if (expect(fd < 0, false, "open(/, O_PATH) = %d", fd)) {
+ if (expect(fd < 0, false, "open(/, O_PATH) = %d", fd))
close(fd);
- } else {
- pr_info("\tIgnoring expected failure\n");
- failed_tests--;
- skipped_tests++;
- }
#define B(dot, dotdot, zero, dev) 0b##dev##zero##dotdot##dot
/* We do fiften tests for every configuration
--
2.39.5
More information about the barebox
mailing list