[PATCH rtems-libbsd] rtemsbsd/open: Correctly open a mount directory

chrisj at rtems.org chrisj at rtems.org
Thu Sep 23 04:35:07 UTC 2021


From: Chris Johns <chrisj at rtems.org>

- If the open is for a directory and it is the root of the mounted
  file system open from the pseudo's root node.
---
 rtemsbsd/rtems/rtems-bsd-syscall-api.c | 62 ++++++++++++++++++--------
 rtemsbsd/rtems/rtems-kernel-vfs.c      |  3 ++
 testsuite/nfs01/test_main.c            |  5 +++
 3 files changed, 52 insertions(+), 18 deletions(-)

diff --git a/rtemsbsd/rtems/rtems-bsd-syscall-api.c b/rtemsbsd/rtems/rtems-bsd-syscall-api.c
index 434cacbd..3ff73dc1 100644
--- a/rtemsbsd/rtems/rtems-bsd-syscall-api.c
+++ b/rtemsbsd/rtems/rtems-bsd-syscall-api.c
@@ -61,6 +61,8 @@
 
 static int rtems_bsd_sysgen_open_error(
     rtems_libio_t *iop, const char *path, int oflag, mode_t mode);
+static int rtems_bsd_sysgen_opendir(
+    rtems_libio_t *iop, const char *path, int oflag, mode_t mode);
 static int rtems_bsd_sysgen_open(
     rtems_libio_t *iop, const char *path, int oflag, mode_t mode);
 static int rtems_bsd_sysgen_close(rtems_libio_t *iop);
@@ -90,7 +92,7 @@ static int rtems_bsd_sysgen_poll(rtems_libio_t *iop, int events);
 static int rtems_bsd_sysgen_kqfilter(rtems_libio_t *iop, struct knote *kn);
 
 const rtems_filesystem_file_handlers_r rtems_bsd_sysgen_dirops = {
-	.open_h = rtems_bsd_sysgen_open,
+	.open_h = rtems_bsd_sysgen_opendir,
 	.close_h = rtems_bsd_sysgen_close,
 	.read_h = rtems_bsd_sysgen_read,
 	.write_h = rtems_filesystem_default_write,
@@ -928,9 +930,9 @@ rtems_bsd_sysgen_open_error(
 	return rtems_bsd_error_to_status_and_errno(ENXIO);
 }
 
-int
-rtems_bsd_sysgen_open(
-    rtems_libio_t *iop, const char *path, int oflag, mode_t mode)
+static int
+rtems_bsd_sysgen_open_node(
+	rtems_libio_t *iop, const char *path, int oflag, mode_t mode, bool isdir)
 {
 	struct thread *td = rtems_bsd_get_curthread_or_null();
 	struct filedesc *fdp;
@@ -954,13 +956,13 @@ rtems_bsd_sysgen_open(
 
 	/*
 	 * There is no easy or clean means to open a vnode and follow the
-	 * POSIX open semantics. You can open a vnode but the extra
-	 * functionality such as create and truncate are not part of the
-	 * basic vnode open. All the calls that provide that functionality
-	 * take a path as the argument. As a result find the last token in
-	 * the path and use the parent directory vnode to position ourselves
-	 * in the parent directory. The pathloc vnode points to the '.' or
-	 * '..'  directory.
+	 * POSIX open semantics. See `kern_openat`. You can open a vnode but
+	 * the extra functionality such as the file pointer, descriptor,
+	 * create and truncate are not part of the basic vnode open. All the
+	 * calls that provide that functionality take a path as the
+	 * argument. As a result find the last token in the path and use the
+	 * parent directory vnode to position ourselves in the parent
+	 * directory. The pathloc vnode points to the '.' or '..'  directory.
 	 */
 	opath = path + strlen(path);
 	opathlen = 0;
@@ -982,10 +984,20 @@ rtems_bsd_sysgen_open(
 		rtems_filesystem_location_info_t *rootloc =
 		    &iop->pathinfo.mt_entry->mt_fs_root->location;
 		cdir = rtems_bsd_libio_loc_to_vnode_dir(&iop->pathinfo);
-		if (fdp->fd_cdir == NULL ||
-		    rtems_bsd_libio_loc_to_vnode(&iop->pathinfo) ==
-			rtems_bsd_libio_loc_to_vnode(rootloc)) {
+		if (fdp->fd_cdir == NULL) {
 			cdir = rtems_bsd_libio_loc_to_vnode(rootloc);
+		} else if (rtems_bsd_libio_loc_to_vnode(&iop->pathinfo) ==
+				rtems_bsd_libio_loc_to_vnode(rootloc)) {
+			/*
+			 * If this is a directory and this is the root node of
+			 * the mounted file system we need to move up the
+			 * hidden pseudo file system node.
+			 */
+			if (isdir) {
+				cdir = rootvnode;
+			} else {
+				cdir = rtems_bsd_libio_loc_to_vnode(rootloc);
+			}
 		}
 	}
 
@@ -999,10 +1011,10 @@ rtems_bsd_sysgen_open(
 
 	if (RTEMS_BSD_SYSCALL_TRACE) {
 		printf("bsd: sys: open: path=%s opath=%s vn=%p cwd=%p"
-		       " flags=%08x mode=%08x\n",
+		       " flags=%08x mode=%08x isdir=%s\n",
 		    path, opath,
 		    creat ? NULL : rtems_bsd_libio_loc_to_vnode(&iop->pathinfo),
-		    fdp->fd_cdir, oflag, mode);
+		    fdp->fd_cdir, oflag, mode, isdir ? "yes" : "no");
 	}
 
 	VREF(fdp->fd_cdir);
@@ -1047,6 +1059,20 @@ rtems_bsd_sysgen_open(
 	return 0;
 }
 
+int
+rtems_bsd_sysgen_opendir(
+    rtems_libio_t *iop, const char *path, int oflag, mode_t mode)
+{
+	 return rtems_bsd_sysgen_open_node(iop, path, oflag, mode, true);
+}
+
+int
+rtems_bsd_sysgen_open(
+    rtems_libio_t *iop, const char *path, int oflag, mode_t mode)
+{
+	 return rtems_bsd_sysgen_open_node(iop, path, oflag, mode, false);
+}
+
 int
 rtems_bsd_sysgen_close(rtems_libio_t *iop)
 {
@@ -1084,8 +1110,8 @@ rtems_bsd_sysgen_read(rtems_libio_t *iop, void *buffer, size_t count)
 	ssize_t size = 0;
 
 	if (RTEMS_BSD_SYSCALL_TRACE) {
-		printf("bsd: sys: read: %d -> %d: vn=%p len=%d\n",
-		    rtems_libio_iop_to_descriptor(iop), fd, vp, count);
+		printf("bsd: sys: read: %d -> %d: vn=%p vn-type=%d len=%d\n",
+		   rtems_libio_iop_to_descriptor(iop), fd, vp, vp->v_type, count);
 	}
 
 	if (td == NULL) {
diff --git a/rtemsbsd/rtems/rtems-kernel-vfs.c b/rtemsbsd/rtems/rtems-kernel-vfs.c
index c387271b..2f4d009b 100644
--- a/rtemsbsd/rtems/rtems-kernel-vfs.c
+++ b/rtemsbsd/rtems/rtems-kernel-vfs.c
@@ -335,6 +335,9 @@ rtems_bsd_vfs_eval_token(rtems_filesystem_eval_path_context_t *ctx, void *arg,
 
 	if (*vpp != NULL) {
 		rtems_filesystem_eval_path_clear_token(ctx);
+		if ((*vpp)->v_type != VDIR) {
+			currentloc->handlers = &rtems_bsd_sysgen_fileops;
+		}
 	}
 
 	return no_more_path ? RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE :
diff --git a/testsuite/nfs01/test_main.c b/testsuite/nfs01/test_main.c
index a6cb91f3..d0642630 100644
--- a/testsuite/nfs01/test_main.c
+++ b/testsuite/nfs01/test_main.c
@@ -37,6 +37,7 @@
  */
 
 #include <assert.h>
+#include <fcntl.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
@@ -279,7 +280,11 @@ test_walk_tree_unlink(walk_tree_dir state,
 static void
 test_setup(const char *base)
 {
+	struct DIR *ddir;
 	printf("test: nfs: setup\n");
+	printf("test: nfs: opendir: %s\n", base);
+	rtems_test_errno_assert((ddir = opendir(base)) != NULL);
+	rtems_test_errno_assert(closedir(ddir) == 0);
 	printf("test: nfs: chdir: %s\n", base);
 	rtems_test_errno_assert(chdir(base) == 0);
 	printf("test: nfs: mkdir: %s\n", test_top);
-- 
2.24.1



More information about the devel mailing list