mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH 3/6] fs: implement opendir in terms of fdopendir
Date: Thu, 20 Mar 2025 06:20:16 +0100	[thread overview]
Message-ID: <20250320052019.1726331-4-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20250320052019.1726331-1-a.fatoum@pengutronix.de>

While struct filep (FILE) and struct file have been merged, we still
have two different ways the files are created: Regularly in open and
irregularly in an incomplete manner inside opendir.

This breaks file systems that expect the struct file passed to iterate
to have been opened before.

To allow porting such filesystems more easily, let's go all in on
directory FDs and implement opendir using it.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 fs/fs.c          | 114 +++++++++++++++--------------------------------
 include/dirent.h |   2 -
 2 files changed, 35 insertions(+), 81 deletions(-)

diff --git a/fs/fs.c b/fs/fs.c
index fd5818c36c20..0c698981227f 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -2660,20 +2660,6 @@ int openat(int dirfd, const char *pathname, int flags)
 }
 EXPORT_SYMBOL(openat);
 
-static const char *fd_getpath(int fd)
-{
-	struct file *f;
-
-	if (fd < 0)
-		return ERR_PTR(errno_set(fd));
-
-	f = fd_to_file(fd, true);
-	if (IS_ERR(f))
-		return ERR_CAST(f);
-
-	return f->path;
-}
-
 int unlinkat(int dirfd, const char *pathname, int flags)
 {
 	int ret;
@@ -2758,107 +2744,77 @@ static void __release_dir(DIR *d)
 static int __opendir(DIR *d)
 {
 	int ret;
-	struct file file = {};
-	struct path *path = &d->path;
-	struct dentry *dir = path->dentry;
+	struct file *file = fd_to_file(d->fd, true);
 	struct readdir_callback rd = {
 		.ctx = {
 			.actor = fillonedir,
 		},
 	};
 
-	file.f_path.dentry = dir;
-	file.f_inode = d_inode(dir);
-	file.f_op = dir->d_inode->i_fop;
-
 	INIT_LIST_HEAD(&d->entries);
 	rd.dir = d;
 
-	ret = file.f_op->iterate(&file, &rd.ctx);
+	ret = file->f_inode->i_fop->iterate(file, &rd.ctx);
 	if (ret)
 		__release_dir(d);
 
 	return ret;
 }
 
-DIR *opendir(const char *pathname)
-{
-	int ret;
-	struct dentry *dir;
-	struct inode *inode;
-	DIR *d;
-	struct path path = {};
-
-	ret = filename_lookup(AT_FDCWD, getname(pathname),
-			      LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
-	if (ret)
-		goto out;
-
-	dir = path.dentry;
-
-	if (d_is_negative(dir)) {
-		ret = -ENOENT;
-		goto out_put;
-	}
-
-	inode = d_inode(dir);
-
-	if (!S_ISDIR(inode->i_mode)) {
-		ret = -ENOTDIR;
-		goto out_put;
-	}
-
-	d = xzalloc(sizeof(*d));
-	d->path = path;
-	d->fd = -ENOENT;
-
-	ret = __opendir(d);
-	if (ret)
-		goto out_free;
-
-	return d;
-
-out_free:
-	free(d);
-out_put:
-	path_put(&path);
-out:
-	errno_set(ret);
-
-	return NULL;
-}
-EXPORT_SYMBOL(opendir);
-
 DIR *fdopendir(int fd)
 {
-	const char *path;
+	struct stat st;
 	DIR *dir;
+	int ret;
 
-	path = fd_getpath(fd);
-	if (IS_ERR(path))
+	ret = fstat(fd, &st);
+	if (ret)
 		return NULL;
 
-	dir = opendir(path);
-	if (!dir)
-		return NULL;
+	if (!S_ISDIR(st.st_mode)) {
+		ret = -ENOTDIR;
+		goto err;
+	}
+
+	dir = xzalloc(sizeof(*dir));
 
 	/* we intentionally don't increment the reference count,
 	 * as POSIX specifies that fd ownership is transferred
 	 */
 	dir->fd = fd;
+
+	ret = __opendir(dir);
+	if (ret)
+		goto err;
+
 	return dir;
+err:
+	errno_set(ret);
+	return NULL;
 }
 EXPORT_SYMBOL(fdopendir);
 
+DIR *opendir(const char *pathname)
+{
+	int fd;
+
+	fd = open(pathname, O_DIRECTORY);
+	if (fd < 0) {
+		errno_set(fd);
+		return NULL;
+	}
+
+	return fdopendir(fd);
+}
+EXPORT_SYMBOL(opendir);
+
 int closedir(DIR *dir)
 {
 	if (!dir)
 		return errno_set(-EBADF);
 
-	path_put(&dir->path);
 	__release_dir(dir);
-	if (dir->fd >= 0)
-		close(dir->fd);
+	close(dir->fd);
 	free(dir);
 
 	return 0;
diff --git a/include/dirent.h b/include/dirent.h
index 4f7ff2a5f91f..f74541d83d26 100644
--- a/include/dirent.h
+++ b/include/dirent.h
@@ -3,7 +3,6 @@
 #define __DIRENT_H
 
 #include <linux/list.h>
-#include <linux/path.h>
 
 struct dirent {
 	char d_name[256];
@@ -15,7 +14,6 @@ typedef struct dir {
 	struct dirent d;
 	void *priv; /* private data for the fs driver */
 	int fd;
-	struct path path;
 	struct list_head entries;
 } DIR;
 
-- 
2.39.5




  parent reply	other threads:[~2025-03-20  5:20 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-20  5:20 [PATCH 0/6] fs: implement tree and truncate Ahmad Fatoum
2025-03-20  5:20 ` [PATCH 1/6] fs: use filename_create/filename_lookup instead of open-coding Ahmad Fatoum
2025-03-20  5:20 ` [PATCH 2/6] fs: implement O_DIRECTORY Ahmad Fatoum
2025-03-20  5:20 ` Ahmad Fatoum [this message]
2025-03-20  5:20 ` [PATCH 4/6] commands: implement tree command Ahmad Fatoum
2025-03-20  5:20 ` [PATCH 5/6] commands: add new truncate command Ahmad Fatoum
2025-03-20  5:20 ` [PATCH 6/6] Documentation: devel: add short section on file systems Ahmad Fatoum

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=20250320052019.1726331-4-a.fatoum@pengutronix.de \
    --to=a.fatoum@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /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