You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/08/09 15:30:10 UTC

[incubator-nuttx] 04/05: fs/directory: move private directory information to filesystem

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit fe17f747a7cf6c9ad868d027e72a396240750bd7
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Fri Aug 5 12:31:25 2022 +0800

    fs/directory: move private directory information to filesystem
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 arch/arm/src/cxd56xx/cxd56_powermgr_procfs.c |  28 +--
 arch/arm/src/lc823450/lc823450_procfs_dvfs.c |   1 -
 drivers/power/pm/pm_procfs.c                 |  28 +--
 fs/binfs/fs_binfs.c                          |  61 ++++-
 fs/cromfs/fs_cromfs.c                        |  57 ++++-
 fs/fat/fs_fat32.c                            |  98 +++++---
 fs/fat/fs_fat32.h                            |  15 +-
 fs/fat/fs_fat32dirent.c                      |  14 +-
 fs/hostfs/hostfs.c                           |  50 +++-
 fs/littlefs/lfs_vfs.c                        |  47 ++--
 fs/mount/fs_procfs_mount.c                   |   1 -
 fs/nfs/nfs_vfsops.c                          | 103 +++++---
 fs/nxffs/nxffs.h                             |   4 +-
 fs/nxffs/nxffs_dirent.c                      |  58 ++++-
 fs/nxffs/nxffs_initialize.c                  |   2 +-
 fs/procfs/fs_procfs.c                        |  43 ++--
 fs/procfs/fs_procfsproc.c                    |  31 +--
 fs/procfs/fs_skeleton.c                      |  33 +--
 fs/romfs/fs_romfs.c                          |  90 +++++--
 fs/romfs/fs_romfs.h                          |  22 +-
 fs/romfs/fs_romfsutil.c                      |   1 -
 fs/rpmsgfs/rpmsgfs.c                         |  48 +++-
 fs/smartfs/smartfs_procfs.c                  |  30 +--
 fs/smartfs/smartfs_smart.c                   | 101 +++++---
 fs/spiffs/src/spiffs_vfs.c                   |  56 +++--
 fs/tmpfs/fs_tmpfs.c                          |  47 +++-
 fs/unionfs/fs_unionfs.c                      | 203 +++++++---------
 fs/userfs/fs_userfs.c                        |  34 ++-
 fs/vfs/fs_dir.c                              | 123 ++++++----
 include/nuttx/fs/dirent.h                    | 348 ---------------------------
 include/nuttx/fs/fs.h                        |  20 +-
 include/nuttx/fs/procfs.h                    |   3 +-
 net/procfs/net_procfs.c                      |  30 +--
 net/procfs/net_procfs_route.c                |  30 +--
 34 files changed, 939 insertions(+), 921 deletions(-)

diff --git a/arch/arm/src/cxd56xx/cxd56_powermgr_procfs.c b/arch/arm/src/cxd56xx/cxd56_powermgr_procfs.c
index f56774901e..fa18097bac 100644
--- a/arch/arm/src/cxd56xx/cxd56_powermgr_procfs.c
+++ b/arch/arm/src/cxd56xx/cxd56_powermgr_procfs.c
@@ -24,7 +24,6 @@
 
 #include <nuttx/config.h>
 #include <nuttx/fs/procfs.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/kmalloc.h>
 
 #include <sys/stat.h>
@@ -97,7 +96,7 @@ static ssize_t cxd56_powermgr_procfs_read(struct file *filep,
 static int cxd56_powermgr_procfs_dup(const struct file *oldp,
                                      struct file *newp);
 static int cxd56_powermgr_procfs_opendir(const char *relpath,
-                                         struct fs_dirent_s *dir);
+                                         struct fs_dirent_s **dir);
 static int cxd56_powermgr_procfs_closedir(struct fs_dirent_s *dir);
 static int cxd56_powermgr_procfs_readdir(struct fs_dirent_s *dir,
                                          struct dirent *entry);
@@ -678,7 +677,7 @@ static int cxd56_powermgr_procfs_stat(const char *relpath,
  ****************************************************************************/
 
 static int cxd56_powermgr_procfs_opendir(const char *relpath,
-                                         struct fs_dirent_s *dir)
+                                         struct fs_dirent_s **dir)
 {
   struct cxd56_powermgr_procfs_dir_s *procfs;
   int ret;
@@ -711,7 +710,7 @@ static int cxd56_powermgr_procfs_opendir(const char *relpath,
     }
 
   procfs->index = 0;
-  dir->u.procfs = (void *)procfs;
+  *dir = (struct fs_dirent_s *)procfs;
 
   return OK;
 }
@@ -726,19 +725,10 @@ static int cxd56_powermgr_procfs_opendir(const char *relpath,
 
 static int cxd56_powermgr_procfs_closedir(struct fs_dirent_s *dir)
 {
-  struct smartfs_level1_s *priv;
-
   pminfo("Closedir\n");
 
-  DEBUGASSERT(dir && dir->u.procfs);
-  priv = dir->u.procfs;
-
-  if (priv)
-    {
-      kmm_free(priv);
-    }
-
-  dir->u.procfs = NULL;
+  DEBUGASSERT(dir);
+  kmm_free(dir);
   return OK;
 }
 
@@ -755,9 +745,9 @@ static int cxd56_powermgr_procfs_readdir(struct fs_dirent_s *dir,
 {
   struct cxd56_powermgr_procfs_dir_s *procfs;
 
-  DEBUGASSERT(dir && dir->u.procfs);
+  DEBUGASSERT(dir);
 
-  procfs = (struct cxd56_powermgr_procfs_dir_s *)dir->u.procfs;
+  procfs = (struct cxd56_powermgr_procfs_dir_s *)dir;
 
   pminfo("Readdir %d\n", procfs->index);
 
@@ -787,9 +777,9 @@ static int cxd56_powermgr_procfs_rewinddir(struct fs_dirent_s *dir)
 {
   struct cxd56_powermgr_procfs_dir_s *procfs;
 
-  DEBUGASSERT(dir && dir->u.procfs);
+  DEBUGASSERT(dir);
 
-  procfs = (struct cxd56_powermgr_procfs_dir_s *)dir->u.procfs;
+  procfs = (struct cxd56_powermgr_procfs_dir_s *)dir;
   pminfo("Rewind %d\n", procfs->index);
   procfs->index = 0;
 
diff --git a/arch/arm/src/lc823450/lc823450_procfs_dvfs.c b/arch/arm/src/lc823450/lc823450_procfs_dvfs.c
index f29fcca04a..ddc499b2e2 100644
--- a/arch/arm/src/lc823450/lc823450_procfs_dvfs.c
+++ b/arch/arm/src/lc823450/lc823450_procfs_dvfs.c
@@ -43,7 +43,6 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/procfs.h>
-#include <nuttx/fs/dirent.h>
 
 #include <arch/irq.h>
 
diff --git a/drivers/power/pm/pm_procfs.c b/drivers/power/pm/pm_procfs.c
index 9b46629d99..924c8a1ab2 100644
--- a/drivers/power/pm/pm_procfs.c
+++ b/drivers/power/pm/pm_procfs.c
@@ -29,10 +29,8 @@
 #include <assert.h>
 #include <debug.h>
 #include <errno.h>
-#include <dirent.h>
 
 #include <nuttx/nuttx.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/procfs.h>
 #include <nuttx/kmalloc.h>
@@ -104,7 +102,7 @@ static int     pm_dup(FAR const struct file *oldp,
                       FAR struct file *newp);
 
 static int     pm_opendir(FAR const char *relpath,
-                          FAR struct fs_dirent_s *dir);
+                          FAR struct fs_dirent_s **dir);
 static int     pm_closedir(FAR struct fs_dirent_s *dir);
 static int     pm_readdir(FAR struct fs_dirent_s *dir,
                           FAR struct dirent *entry);
@@ -437,12 +435,12 @@ static int pm_dup(FAR const struct file *oldp, FAR struct file *newp)
  *
  ****************************************************************************/
 
-static int pm_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
+static int pm_opendir(FAR const char *relpath, FAR struct fs_dirent_s **dir)
 {
   FAR struct procfs_dir_priv_s *level1;
 
   finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
-  DEBUGASSERT(relpath && dir && !dir->u.procfs);
+  DEBUGASSERT(relpath);
 
   /* Assume that path refers to the 1st level subdirectory.  Allocate the
    * level1 the dirent structure before checking.
@@ -460,7 +458,7 @@ static int pm_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
   level1->level    = 1;
   level1->nentries = CONFIG_PM_NDOMAINS * ARRAY_SIZE(g_pm_files);
 
-  dir->u.procfs = (FAR void *)level1;
+  *dir = (FAR struct fs_dirent_s *)level1;
   return OK;
 }
 
@@ -473,14 +471,8 @@ static int pm_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
 
 static int pm_closedir(FAR struct fs_dirent_s *dir)
 {
-  FAR struct procfs_dir_priv_s *level1;
-
-  DEBUGASSERT(dir && dir->u.procfs);
-  level1 = dir->u.procfs;
-
-  kmm_free(level1);
-
-  dir->u.procfs = NULL;
+  DEBUGASSERT(dir);
+  kmm_free(dir);
   return OK;
 }
 
@@ -499,8 +491,8 @@ static int pm_readdir(FAR struct fs_dirent_s *dir,
   int domain;
   int fpos;
 
-  DEBUGASSERT(dir && dir->u.procfs);
-  level1 = dir->u.procfs;
+  DEBUGASSERT(dir);
+  level1 = (FAR struct procfs_dir_priv_s *)dir;
 
   index = level1->index;
   if (index >= level1->nentries)
@@ -535,8 +527,8 @@ static int pm_rewinddir(FAR struct fs_dirent_s *dir)
 {
   FAR struct procfs_dir_priv_s *level1;
 
-  DEBUGASSERT(dir && dir->u.procfs);
-  level1 = dir->u.procfs;
+  DEBUGASSERT(dir);
+  level1 = (FAR struct procfs_dir_priv_s *)dir;
 
   level1->index = 0;
   return OK;
diff --git a/fs/binfs/fs_binfs.c b/fs/binfs/fs_binfs.c
index 8c058aa8a5..c10d9ff3dd 100644
--- a/fs/binfs/fs_binfs.c
+++ b/fs/binfs/fs_binfs.c
@@ -38,7 +38,6 @@
 
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/binfs.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/fs/ioctl.h>
 #include <nuttx/lib/builtin.h>
 
@@ -46,6 +45,16 @@
 
 #if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_BINFS)
 
+/****************************************************************************
+ * Private Type
+ ****************************************************************************/
+
+struct binfs_dir_s
+{
+  struct fs_dirent_s base; /* VFS directory structure */
+  unsigned int index;      /* Index to the next named entry point */
+};
+
 /****************************************************************************
  * Private Function Prototypes
  ****************************************************************************/
@@ -62,8 +71,11 @@ static int     binfs_dup(FAR const struct file *oldp, FAR struct file *newp);
 static int     binfs_fstat(FAR const struct file *filep,
                            FAR struct stat *buf);
 
-static int     binfs_opendir(struct inode *mountpt, const char *relpath,
-                             struct fs_dirent_s *dir);
+static int     binfs_opendir(FAR struct inode *mountpt,
+                             FAR const char *relpath,
+                             FAR struct fs_dirent_s **dir);
+static int     binfs_closedir(FAR struct inode *mountpt,
+                              FAR struct fs_dirent_s *dir);
 static int     binfs_readdir(FAR struct inode *mountpt,
                              FAR struct fs_dirent_s *dir,
                              FAR struct dirent *entry);
@@ -105,7 +117,7 @@ const struct mountpt_operations binfs_operations =
   NULL,              /* truncate */
 
   binfs_opendir,     /* opendir */
-  NULL,              /* closedir */
+  binfs_closedir,    /* closedir */
   binfs_readdir,     /* readdir */
   binfs_rewinddir,   /* rewinddir */
 
@@ -277,9 +289,11 @@ static int binfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
  *
  ****************************************************************************/
 
-static int binfs_opendir(struct inode *mountpt, const char *relpath,
-                         struct fs_dirent_s *dir)
+static int binfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
+                         FAR struct fs_dirent_s **dir)
 {
+  FAR struct binfs_dir_s *bdir;
+
   finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
 
   /* The requested directory must be the volume-relative "root" directory */
@@ -289,12 +303,35 @@ static int binfs_opendir(struct inode *mountpt, const char *relpath,
       return -ENOENT;
     }
 
+  bdir = kmm_zalloc(sizeof(*bdir));
+  if (bdir == NULL)
+    {
+      return -ENOMEM;
+    }
+
   /* Set the index to the first entry */
 
-  dir->u.binfs.fb_index = 0;
+  bdir->index = 0;
+  *dir = (FAR struct fs_dirent_s *)bdir;
   return OK;
 }
 
+/****************************************************************************
+ * Name: binfs_closedir
+ *
+ * Description:
+ *   Close a directory
+ *
+ ****************************************************************************/
+
+static int binfs_closedir(FAR struct inode *mountpt,
+                          FAR struct fs_dirent_s *dir)
+{
+  DEBUGASSERT(dir);
+  kmm_free(dir);
+  return 0;
+}
+
 /****************************************************************************
  * Name: binfs_readdir
  *
@@ -306,13 +343,15 @@ static int binfs_readdir(FAR struct inode *mountpt,
                          FAR struct fs_dirent_s *dir,
                          FAR struct dirent *entry)
 {
+  FAR struct binfs_dir_s *bdir;
   FAR const char *name;
   unsigned int index;
   int ret;
 
   /* Have we reached the end of the directory */
 
-  index = dir->u.binfs.fb_index;
+  bdir = (FAR struct binfs_dir_s *)dir;
+  index = bdir->index;
   name = builtin_getname(index);
   if (name == NULL)
     {
@@ -338,10 +377,10 @@ static int binfs_readdir(FAR struct inode *mountpt,
       index++;
 
       /* Set up the next directory entry offset.  NOTE that we could use the
-       * standard f_pos instead of our own private fb_index.
+       * standard f_pos instead of our own private index.
        */
 
-      dir->u.binfs.fb_index = index;
+      bdir->index = index;
       ret = OK;
     }
 
@@ -359,7 +398,7 @@ static int binfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
 {
   finfo("Entry\n");
 
-  dir->u.binfs.fb_index = 0;
+  ((FAR struct binfs_dir_s *)dir)->index = 0;
   return OK;
 }
 
diff --git a/fs/cromfs/fs_cromfs.c b/fs/cromfs/fs_cromfs.c
index cede01c30f..3f08a6d482 100644
--- a/fs/cromfs/fs_cromfs.c
+++ b/fs/cromfs/fs_cromfs.c
@@ -40,7 +40,6 @@
 
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/fs/ioctl.h>
 
 #include "cromfs.h"
@@ -57,6 +56,13 @@
  * Private Types
  ****************************************************************************/
 
+struct cromfs_dir_s
+{
+  struct fs_dirent_s cr_base; /* VFS directory structure */
+  uint32_t cr_firstoffset;    /* Offset to the first entry in the directory */
+  uint32_t cr_curroffset;     /* Current offset into the directory contents */
+};
+
 /* This structure represents an open, regular file */
 
 struct cromfs_file_s
@@ -142,7 +148,9 @@ static int      cromfs_fstat(FAR const struct file *filep,
                   FAR struct stat *buf);
 
 static int      cromfs_opendir(FAR struct inode *mountpt,
-                  FAR const char *relpath, FAR struct fs_dirent_s *dir);
+                  FAR const char *relpath, FAR struct fs_dirent_s **dir);
+static int      cromfs_closedir(FAR struct inode *mountpt,
+                  FAR struct fs_dirent_s *dir);
 static int      cromfs_readdir(FAR struct inode *mountpt,
                   FAR struct fs_dirent_s *dir,
                   FAR struct dirent *entry);
@@ -184,7 +192,7 @@ const struct mountpt_operations cromfs_operations =
   NULL,              /* truncate */
 
   cromfs_opendir,    /* opendir */
-  NULL,              /* closedir */
+  cromfs_closedir,   /* closedir */
   cromfs_readdir,    /* readdir */
   cromfs_rewinddir,  /* rewinddir */
 
@@ -1181,9 +1189,10 @@ static int cromfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
  ****************************************************************************/
 
 static int cromfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
-                          FAR struct fs_dirent_s *dir)
+                          FAR struct fs_dirent_s **dir)
 {
   FAR const struct cromfs_volume_s *fs;
+  FAR struct cromfs_dir_s *cdir;
   FAR struct cromfs_nodeinfo_s info;
   uint32_t offset;
   int ret;
@@ -1217,13 +1226,35 @@ static int cromfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
       return -ENOTDIR;
     }
 
+  cdir = kmm_zalloc(sizeof(*cdir));
+  if (cdir == NULL)
+    {
+      return -ENOMEM;
+    }
+
   /* Set the start node and next node to the first entry in the directory */
 
-  dir->u.cromfs.cr_firstoffset = info.ci_child;
-  dir->u.cromfs.cr_curroffset  = info.ci_child;
+  cdir->cr_firstoffset = info.ci_child;
+  cdir->cr_curroffset  = info.ci_child;
+  *dir = &cdir->cr_base;
   return OK;
 }
 
+/****************************************************************************
+ * Name: cromfs_closedir
+ *
+ * Description: close directory.
+ *
+ ****************************************************************************/
+
+static int cromfs_closedir(FAR struct inode *mountpt,
+                           FAR struct fs_dirent_s *dir)
+{
+  DEBUGASSERT(mountpt != NULL);
+  kmm_free(dir);
+  return 0;
+}
+
 /****************************************************************************
  * Name: cromfs_readdir
  *
@@ -1237,6 +1268,7 @@ static int cromfs_readdir(FAR struct inode *mountpt,
 {
   FAR const struct cromfs_volume_s *fs;
   FAR const struct cromfs_node_s *node;
+  FAR struct cromfs_dir_s *cdir;
   struct cromfs_node_s newnode;
   FAR char *name;
   uint32_t offset;
@@ -1251,10 +1283,11 @@ static int cromfs_readdir(FAR struct inode *mountpt,
   /* Recover our private data from the inode instance */
 
   fs = mountpt->i_private;
+  cdir = (FAR struct cromfs_dir_s *)dir;
 
   /* Have we reached the end of the directory */
 
-  offset = dir->u.cromfs.cr_curroffset;
+  offset = cdir->cr_curroffset;
   if (offset == 0)
     {
       /* We signal the end of the directory by returning the
@@ -1346,7 +1379,7 @@ static int cromfs_readdir(FAR struct inode *mountpt,
    * standard f_pos instead of our own private fb_index.
    */
 
-  dir->u.cromfs.cr_curroffset = node->cn_peer;
+  cdir->cr_curroffset = node->cn_peer;
   return OK;
 }
 
@@ -1357,11 +1390,15 @@ static int cromfs_readdir(FAR struct inode *mountpt,
  *
  ****************************************************************************/
 
-static int cromfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
+static int cromfs_rewinddir(FAR struct inode *mountpt,
+                            FAR struct fs_dirent_s *dir)
 {
+  FAR struct cromfs_dir_s *cdir;
+
   finfo("mountpt: %p dir: %p\n", mountpt, dir);
 
-  dir->u.cromfs.cr_curroffset  = dir->u.cromfs.cr_firstoffset;
+  cdir = (FAR struct cromfs_dir_s *)dir;
+  cdir->cr_curroffset = cdir->cr_firstoffset;
   return OK;
 }
 
diff --git a/fs/fat/fs_fat32.c b/fs/fat/fs_fat32.c
index d7b359a67d..6d77023943 100644
--- a/fs/fat/fs_fat32.c
+++ b/fs/fat/fs_fat32.c
@@ -40,7 +40,6 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/fat.h>
-#include <nuttx/fs/dirent.h>
 
 #include "inode/inode.h"
 #include "fs_fat32.h"
@@ -67,7 +66,9 @@ static int     fat_fstat(FAR const struct file *filep,
 static int     fat_truncate(FAR struct file *filep, off_t length);
 
 static int     fat_opendir(FAR struct inode *mountpt,
-                 FAR const char *relpath, FAR struct fs_dirent_s *dir);
+                 FAR const char *relpath, FAR struct fs_dirent_s **dir);
+static int     fat_closedir(FAR struct inode *mountpt,
+                 FAR struct fs_dirent_s *dir);
 static int     fat_readdir(FAR struct inode *mountpt,
                  FAR struct fs_dirent_s *dir,
                  FAR struct dirent *entry);
@@ -122,7 +123,7 @@ const struct mountpt_operations fat_operations =
   fat_truncate,      /* truncate */
 
   fat_opendir,       /* opendir */
-  NULL,              /* closedir */
+  fat_closedir,      /* closedir */
   fat_readdir,       /* readdir */
   fat_rewinddir,     /* rewinddir */
 
@@ -1569,8 +1570,9 @@ errout_with_semaphore:
  ****************************************************************************/
 
 static int fat_opendir(FAR struct inode *mountpt, FAR const char *relpath,
-                       FAR struct fs_dirent_s *dir)
+                       FAR struct fs_dirent_s **dir)
 {
+  FAR struct fat_dirent_s *fdir;
   FAR struct fat_mountpt_s *fs;
   FAR struct fat_dirinfo_s  dirinfo;
   uint8_t *direntry;
@@ -1584,12 +1586,18 @@ static int fat_opendir(FAR struct inode *mountpt, FAR const char *relpath,
 
   fs = mountpt->i_private;
 
+  fdir = kmm_zalloc(sizeof(struct fat_dirent_s));
+  if (fdir == NULL)
+    {
+      return -ENOMEM;
+    }
+
   /* Make sure that the mount is still healthy */
 
   ret = fat_semtake(fs);
   if (ret < 0)
     {
-      return ret;
+      goto errout_with_fdir;
     }
 
   ret = fat_checkmount(fs);
@@ -1614,10 +1622,10 @@ static int fat_opendir(FAR struct inode *mountpt, FAR const char *relpath,
        * fat_finddirentry() above.
        */
 
-      dir->u.fat.fd_startcluster = dirinfo.dir.fd_startcluster;
-      dir->u.fat.fd_currcluster  = dirinfo.dir.fd_currcluster;
-      dir->u.fat.fd_currsector   = dirinfo.dir.fd_currsector;
-      dir->u.fat.fd_index        = dirinfo.dir.fd_index;
+      fdir->dir.fd_startcluster = dirinfo.dir.fd_startcluster;
+      fdir->dir.fd_currcluster  = dirinfo.dir.fd_currcluster;
+      fdir->dir.fd_currsector   = dirinfo.dir.fd_currsector;
+      fdir->dir.fd_index        = dirinfo.dir.fd_index;
     }
   else
     {
@@ -1638,23 +1646,43 @@ static int fat_opendir(FAR struct inode *mountpt, FAR const char *relpath,
         {
           /* The entry is a directory (but not the root directory) */
 
-          dir->u.fat.fd_startcluster =
+          fdir->dir.fd_startcluster =
               ((uint32_t)DIR_GETFSTCLUSTHI(direntry) << 16) |
                          DIR_GETFSTCLUSTLO(direntry);
-          dir->u.fat.fd_currcluster  = dir->u.fat.fd_startcluster;
-          dir->u.fat.fd_currsector   = fat_cluster2sector(fs,
-                                         dir->u.fat.fd_currcluster);
-          dir->u.fat.fd_index        = 2;
+          fdir->dir.fd_currcluster  = fdir->dir.fd_startcluster;
+          fdir->dir.fd_currsector   = fat_cluster2sector(fs,
+                                      fdir->dir.fd_currcluster);
+          fdir->dir.fd_index        = 2;
         }
     }
 
-  ret = OK;
+  *dir = (FAR struct fs_dirent_s *)fdir;
+  fat_semgive(fs);
+  return OK;
 
 errout_with_semaphore:
   fat_semgive(fs);
+
+errout_with_fdir:
+  kmm_free(fdir);
   return ret;
 }
 
+/****************************************************************************
+ * Name: fat_closedir
+ *
+ * Description: Close directory
+ *
+ ****************************************************************************/
+
+static int fat_closedir(FAR struct inode *mountpt,
+                        FAR struct fs_dirent_s *dir)
+{
+  DEBUGASSERT(dir);
+  kmm_free(dir);
+  return 0;
+}
+
 /****************************************************************************
  * Name: fat_fstat
  *
@@ -1882,6 +1910,7 @@ static int fat_readdir(FAR struct inode *mountpt,
                        FAR struct fs_dirent_s *dir,
                        FAR struct dirent *entry)
 {
+  FAR struct fat_dirent_s *fdir;
   FAR struct fat_mountpt_s *fs;
   unsigned int dirindex;
   FAR uint8_t *direntry;
@@ -1897,6 +1926,7 @@ static int fat_readdir(FAR struct inode *mountpt,
   /* Recover our private data from the inode instance */
 
   fs = mountpt->i_private;
+  fdir = (FAR struct fat_dirent_s *)dir;
 
   /* Make sure that the mount is still healthy.
    * REVISIT: What if a forced unmount was done since opendir() was called?
@@ -1919,9 +1949,9 @@ static int fat_readdir(FAR struct inode *mountpt,
   entry->d_name[0] = '\0';
   found = false;
 
-  while (dir->u.fat.fd_currsector && !found)
+  while (fdir->dir.fd_currsector && !found)
     {
-      ret = fat_fscacheread(fs, dir->u.fat.fd_currsector);
+      ret = fat_fscacheread(fs, fdir->dir.fd_currsector);
       if (ret < 0)
         {
           goto errout_with_semaphore;
@@ -1929,7 +1959,7 @@ static int fat_readdir(FAR struct inode *mountpt,
 
       /* Get a reference to the current directory entry */
 
-      dirindex = (dir->u.fat.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE;
+      dirindex = (fdir->dir.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE;
       direntry = &fs->fs_buffer[dirindex];
 
       /* Has it reached to end of the directory */
@@ -1981,8 +2011,8 @@ static int fat_readdir(FAR struct inode *mountpt,
                * entry.
                */
 
-              dirindex = (dir->u.fat.fd_index & DIRSEC_NDXMASK(fs)) *
-                          DIR_SIZE;
+              dirindex = (fdir->dir.fd_index & DIRSEC_NDXMASK(fs)) *
+                         DIR_SIZE;
               direntry = &fs->fs_buffer[dirindex];
 
               /* Then re-read the attributes from the short file name entry */
@@ -2010,7 +2040,7 @@ static int fat_readdir(FAR struct inode *mountpt,
 
       /* Set up the next directory index */
 
-      if (fat_nextdirentry(fs, &dir->u.fat) != OK)
+      if (fat_nextdirentry(fs, &fdir->dir) != OK)
         {
           ret = -ENOENT;
           goto errout_with_semaphore;
@@ -2035,6 +2065,7 @@ errout_with_semaphore:
 static int fat_rewinddir(FAR struct inode *mountpt,
                          FAR struct fs_dirent_s *dir)
 {
+  FAR struct fat_dirent_s *fdir;
   FAR struct fat_mountpt_s *fs;
   int ret;
 
@@ -2045,6 +2076,7 @@ static int fat_rewinddir(FAR struct inode *mountpt,
   /* Recover our private data from the inode instance */
 
   fs = mountpt->i_private;
+  fdir = (FAR struct fat_dirent_s *)dir;
 
   /* Make sure that the mount is still healthy
    * REVISIT: What if a forced unmount was done since opendir() was called?
@@ -2067,22 +2099,22 @@ static int fat_rewinddir(FAR struct inode *mountpt,
    */
 
   if (fs->fs_type != FSTYPE_FAT32 &&
-      dir->u.fat.fd_startcluster == 0)
+      fdir->dir.fd_startcluster == 0)
     {
       /* Handle the FAT12/16 root directory */
 
-      dir->u.fat.fd_currcluster  = 0;
-      dir->u.fat.fd_currsector   = fs->fs_rootbase;
-      dir->u.fat.fd_index        = 0;
+      fdir->dir.fd_currcluster  = 0;
+      fdir->dir.fd_currsector   = fs->fs_rootbase;
+      fdir->dir.fd_index        = 0;
     }
   else if (fs->fs_type == FSTYPE_FAT32 &&
-           dir->u.fat.fd_startcluster == fs->fs_rootbase)
+           fdir->dir.fd_startcluster == fs->fs_rootbase)
     {
       /* Handle the FAT32 root directory */
 
-      dir->u.fat.fd_currcluster = dir->u.fat.fd_startcluster;
-      dir->u.fat.fd_currsector  = fat_cluster2sector(fs, fs->fs_rootbase);
-      dir->u.fat.fd_index       = 0;
+      fdir->dir.fd_currcluster = fdir->dir.fd_startcluster;
+      fdir->dir.fd_currsector  = fat_cluster2sector(fs, fs->fs_rootbase);
+      fdir->dir.fd_index       = 0;
     }
 
   /* This is not the root directory.  Here the fd_index is set to 2, skipping
@@ -2091,10 +2123,10 @@ static int fat_rewinddir(FAR struct inode *mountpt,
 
   else
     {
-      dir->u.fat.fd_currcluster  = dir->u.fat.fd_startcluster;
-      dir->u.fat.fd_currsector   = fat_cluster2sector(fs,
-                                     dir->u.fat.fd_currcluster);
-      dir->u.fat.fd_index        = 2;
+      fdir->dir.fd_currcluster  = fdir->dir.fd_startcluster;
+      fdir->dir.fd_currsector   = fat_cluster2sector(fs,
+                                  fdir->dir.fd_currcluster);
+      fdir->dir.fd_index        = 2;
     }
 
   fat_semgive(fs);
diff --git a/fs/fat/fs_fat32.h b/fs/fat/fs_fat32.h
index 3e80308462..d53de32b72 100644
--- a/fs/fat/fs_fat32.h
+++ b/fs/fat/fs_fat32.h
@@ -33,7 +33,6 @@
 #include <time.h>
 
 #include <nuttx/kmalloc.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/semaphore.h>
 
 /****************************************************************************
@@ -953,6 +952,20 @@ typedef uint8_t lfnchar;
 #  endif
 #endif
 
+struct fs_fatdir_s
+{
+  off_t        fd_startcluster;    /* Start cluster number of the directory */
+  off_t        fd_currcluster;     /* Current cluster number being read */
+  off_t        fd_currsector;      /* Current sector being read */
+  unsigned int fd_index;           /* Current index of the directory entry to read */
+};
+
+struct fat_dirent_s
+{
+  struct fs_dirent_s base;
+  struct fs_fatdir_s dir;
+};
+
 /* This structure is used internally for describing directory entries */
 
 struct fat_dirinfo_s
diff --git a/fs/fat/fs_fat32dirent.c b/fs/fat/fs_fat32dirent.c
index 431709b9ba..9149df2238 100644
--- a/fs/fat/fs_fat32dirent.c
+++ b/fs/fat/fs_fat32dirent.c
@@ -1964,6 +1964,7 @@ static inline int fat_getlfname(FAR struct fat_mountpt_s *fs,
                                 FAR struct fs_dirent_s *dir,
                                 FAR struct dirent *entry)
 {
+  FAR struct fat_dirent_s *fdir;
   FAR uint8_t *direntry;
   lfnchar  lfname[LDIR_MAXLFNCHARS];
   uint16_t diroffset;
@@ -1977,7 +1978,8 @@ static inline int fat_getlfname(FAR struct fat_mountpt_s *fs,
 
   /* Get a reference to the current directory entry */
 
-  diroffset = (dir->u.fat.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE;
+  fdir = (FAR struct fat_dirent_s *)dir;
+  diroffset = (fdir->dir.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE;
   direntry  = &fs->fs_buffer[diroffset];
 
   /* Get the starting sequence number */
@@ -2103,14 +2105,14 @@ static inline int fat_getlfname(FAR struct fat_mountpt_s *fs,
 
       /* Read next directory entry */
 
-      if (fat_nextdirentry(fs, &dir->u.fat) != OK)
+      if (fat_nextdirentry(fs, &fdir->dir) != OK)
         {
           return -ENOENT;
         }
 
       /* Make sure that the directory sector into the sector cache */
 
-      ret = fat_fscacheread(fs, dir->u.fat.fd_currsector);
+      ret = fat_fscacheread(fs, fdir->dir.fd_currsector);
       if (ret < 0)
         {
           return ret;
@@ -2118,7 +2120,7 @@ static inline int fat_getlfname(FAR struct fat_mountpt_s *fs,
 
       /* Get a reference to the current directory entry */
 
-      diroffset = (dir->u.fat.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE;
+      diroffset = (fdir->dir.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE;
       direntry  = &fs->fs_buffer[diroffset];
 
       /* Get the next expected sequence number. */
@@ -2943,6 +2945,7 @@ int fat_dirname2path(FAR struct fat_mountpt_s *fs,
                      FAR struct fs_dirent_s *dir,
                      FAR struct dirent *entry)
 {
+  FAR struct fat_dirent_s *fdir;
   uint16_t diroffset;
   FAR uint8_t *direntry;
 #ifdef CONFIG_FAT_LFN
@@ -2951,7 +2954,8 @@ int fat_dirname2path(FAR struct fat_mountpt_s *fs,
 
   /* Get a reference to the current directory entry */
 
-  diroffset = (dir->u.fat.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE;
+  fdir = (FAR struct fat_dirent_s *)dir;
+  diroffset = (fdir->dir.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE;
   direntry = &fs->fs_buffer[diroffset];
 
   /* Does this entry refer to the last entry of a long file name? */
diff --git a/fs/hostfs/hostfs.c b/fs/hostfs/hostfs.c
index a4ebf34940..ba2bee1fb1 100644
--- a/fs/hostfs/hostfs.c
+++ b/fs/hostfs/hostfs.c
@@ -39,7 +39,6 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/fat.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/fs/ioctl.h>
 #include <nuttx/fs/hostfs.h>
 
@@ -51,6 +50,16 @@
 
 #define HOSTFS_RETRY_DELAY_MS       10
 
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct hostfs_dir_s
+{
+  struct fs_dirent_s base;
+  FAR void *dir;
+};
+
 /****************************************************************************
  * Private Function Prototypes
  ****************************************************************************/
@@ -79,7 +88,7 @@ static int     hostfs_ftruncate(FAR struct file *filep,
 
 static int     hostfs_opendir(FAR struct inode *mountpt,
                         FAR const char *relpath,
-                        FAR struct fs_dirent_s *dir);
+                        FAR struct fs_dirent_s **dir);
 static int     hostfs_closedir(FAR struct inode *mountpt,
                         FAR struct fs_dirent_s *dir);
 static int     hostfs_readdir(FAR struct inode *mountpt,
@@ -830,9 +839,10 @@ static int hostfs_ftruncate(FAR struct file *filep, off_t length)
  ****************************************************************************/
 
 static int hostfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
-                          FAR struct fs_dirent_s *dir)
+                          FAR struct fs_dirent_s **dir)
 {
   FAR struct hostfs_mountpt_s *fs;
+  FAR struct hostfs_dir_s *hdir;
   char path[HOSTFS_MAX_PATH];
   int ret;
 
@@ -843,13 +853,18 @@ static int hostfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
   /* Recover our private data from the inode instance */
 
   fs = mountpt->i_private;
+  hdir = kmm_zalloc(sizeof(struct hostfs_dir_s));
+  if (hdir == NULL)
+    {
+      return -ENOMEM;
+    }
 
   /* Take the semaphore */
 
   ret = hostfs_semtake(fs);
   if (ret < 0)
     {
-      return ret;
+      goto errout_with_hdir;
     }
 
   /* Append to the host's root directory */
@@ -858,18 +873,22 @@ static int hostfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
 
   /* Call the host's opendir function */
 
-  dir->u.hostfs.fs_dir = host_opendir(path);
-  if (dir->u.hostfs.fs_dir == NULL)
+  hdir->dir = host_opendir(path);
+  if (hdir->dir == NULL)
     {
       ret = -ENOENT;
       goto errout_with_semaphore;
     }
 
-  ret = OK;
+  *dir = (FAR struct fs_dirent_s *)hdir;
+  hostfs_semgive(fs);
+  return OK;
 
 errout_with_semaphore:
-
   hostfs_semgive(fs);
+
+errout_with_hdir:
+  kmm_free(hdir);
   return ret;
 }
 
@@ -883,7 +902,8 @@ errout_with_semaphore:
 static int hostfs_closedir(FAR struct inode *mountpt,
                            FAR struct fs_dirent_s *dir)
 {
-  struct hostfs_mountpt_s  *fs;
+  FAR struct hostfs_mountpt_s *fs;
+  FAR struct hostfs_dir_s *hdir;
   int ret;
 
   /* Sanity checks */
@@ -893,6 +913,7 @@ static int hostfs_closedir(FAR struct inode *mountpt,
   /* Recover our private data from the inode instance */
 
   fs = mountpt->i_private;
+  hdir = (FAR struct hostfs_dir_s *)dir;
 
   /* Take the semaphore */
 
@@ -904,9 +925,10 @@ static int hostfs_closedir(FAR struct inode *mountpt,
 
   /* Call the host's closedir function */
 
-  host_closedir(dir->u.hostfs.fs_dir);
+  host_closedir(hdir->dir);
 
   hostfs_semgive(fs);
+  kmm_free(hdir);
   return OK;
 }
 
@@ -922,6 +944,7 @@ static int hostfs_readdir(FAR struct inode *mountpt,
                           FAR struct dirent *entry)
 {
   FAR struct hostfs_mountpt_s *fs;
+  FAR struct hostfs_dir_s *hdir;
   int ret;
 
   /* Sanity checks */
@@ -931,6 +954,7 @@ static int hostfs_readdir(FAR struct inode *mountpt,
   /* Recover our private data from the inode instance */
 
   fs = mountpt->i_private;
+  hdir = (FAR struct hostfs_dir_s *)dir;
 
   /* Take the semaphore */
 
@@ -942,7 +966,7 @@ static int hostfs_readdir(FAR struct inode *mountpt,
 
   /* Call the host OS's readdir function */
 
-  ret = host_readdir(dir->u.hostfs.fs_dir, entry);
+  ret = host_readdir(hdir->dir, entry);
 
   hostfs_semgive(fs);
   return ret;
@@ -959,6 +983,7 @@ static int hostfs_rewinddir(FAR struct inode *mountpt,
                             FAR struct fs_dirent_s *dir)
 {
   FAR struct hostfs_mountpt_s *fs;
+  FAR struct hostfs_dir_s *hdir;
   int ret;
 
   /* Sanity checks */
@@ -968,6 +993,7 @@ static int hostfs_rewinddir(FAR struct inode *mountpt,
   /* Recover our private data from the inode instance */
 
   fs = mountpt->i_private;
+  hdir = (FAR struct hostfs_dir_s *)dir;
 
   /* Take the semaphore */
 
@@ -979,7 +1005,7 @@ static int hostfs_rewinddir(FAR struct inode *mountpt,
 
   /* Call the host and let it do all the work */
 
-  host_rewinddir(dir->u.hostfs.fs_dir);
+  host_rewinddir(hdir->dir);
 
   hostfs_semgive(fs);
   return OK;
diff --git a/fs/littlefs/lfs_vfs.c b/fs/littlefs/lfs_vfs.c
index efcacd2a3c..ce4362e558 100644
--- a/fs/littlefs/lfs_vfs.c
+++ b/fs/littlefs/lfs_vfs.c
@@ -28,7 +28,6 @@
 #include <fcntl.h>
 #include <string.h>
 
-#include <nuttx/fs/dirent.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/kmalloc.h>
 #include <nuttx/mtd/mtd.h>
@@ -44,6 +43,12 @@
  * Private Types
  ****************************************************************************/
 
+struct littlefs_dir_s
+{
+  struct fs_dirent_s    base;
+  struct lfs_dir        dir;
+};
+
 struct littlefs_file_s
 {
   struct lfs_file       file;
@@ -93,7 +98,7 @@ static int     littlefs_truncate(FAR struct file *filep,
 
 static int     littlefs_opendir(FAR struct inode *mountpt,
                                 FAR const char *relpath,
-                                FAR struct fs_dirent_s *dir);
+                                FAR struct fs_dirent_s **dir);
 static int     littlefs_closedir(FAR struct inode *mountpt,
                                  FAR struct fs_dirent_s *dir);
 static int     littlefs_readdir(FAR struct inode *mountpt,
@@ -734,10 +739,10 @@ static int littlefs_truncate(FAR struct file *filep, off_t length)
 
 static int littlefs_opendir(FAR struct inode *mountpt,
                             FAR const char *relpath,
-                            FAR struct fs_dirent_s *dir)
+                            FAR struct fs_dirent_s **dir)
 {
   FAR struct littlefs_mountpt_s *fs;
-  FAR struct lfs_dir *priv;
+  FAR struct littlefs_dir_s *ldir;
   int ret;
 
   /* Recover our private data from the inode instance */
@@ -746,8 +751,8 @@ static int littlefs_opendir(FAR struct inode *mountpt,
 
   /* Allocate memory for the open directory */
 
-  priv = kmm_malloc(sizeof(*priv));
-  if (priv == NULL)
+  ldir = kmm_malloc(sizeof(*ldir));
+  if (ldir == NULL)
     {
       return -ENOMEM;
     }
@@ -762,20 +767,20 @@ static int littlefs_opendir(FAR struct inode *mountpt,
 
   /* Call the LFS's opendir function */
 
-  ret = littlefs_convert_result(lfs_dir_open(&fs->lfs, priv, relpath));
+  ret = littlefs_convert_result(lfs_dir_open(&fs->lfs, &ldir->dir, relpath));
   if (ret < 0)
     {
       goto errout;
     }
 
   littlefs_semgive(fs);
-  dir->u.littlefs = priv;
+  *dir = &ldir->base;
   return OK;
 
 errout:
   littlefs_semgive(fs);
 errsem:
-  kmm_free(priv);
+  kmm_free(ldir);
   return ret;
 }
 
@@ -789,13 +794,13 @@ errsem:
 static int littlefs_closedir(FAR struct inode *mountpt,
                              FAR struct fs_dirent_s *dir)
 {
-  struct littlefs_mountpt_s *fs;
-  FAR struct lfs_dir *priv;
+  FAR struct littlefs_mountpt_s *fs;
+  FAR struct littlefs_dir_s *ldir;
   int ret;
 
   /* Recover our private data from the inode instance */
 
-  priv = dir->u.littlefs;
+  ldir = (FAR struct littlefs_dir_s *)dir;
   fs   = mountpt->i_private;
 
   /* Call the LFS's closedir function */
@@ -806,10 +811,10 @@ static int littlefs_closedir(FAR struct inode *mountpt,
       return ret;
     }
 
-  lfs_dir_close(&fs->lfs, priv);
+  lfs_dir_close(&fs->lfs, &ldir->dir);
   littlefs_semgive(fs);
 
-  kmm_free(priv);
+  kmm_free(ldir);
   return OK;
 }
 
@@ -825,13 +830,13 @@ static int littlefs_readdir(FAR struct inode *mountpt,
                             FAR struct dirent *entry)
 {
   FAR struct littlefs_mountpt_s *fs;
-  FAR struct lfs_dir *priv;
+  FAR struct littlefs_dir_s *ldir;
   struct lfs_info info;
   int ret;
 
   /* Recover our private data from the inode instance */
 
-  priv = dir->u.littlefs;
+  ldir = (FAR struct littlefs_dir_s *)dir;
   fs   = mountpt->i_private;
 
   /* Call the LFS's readdir function */
@@ -842,7 +847,7 @@ static int littlefs_readdir(FAR struct inode *mountpt,
       return ret;
     }
 
-  ret = littlefs_convert_result(lfs_dir_read(&fs->lfs, priv, &info));
+  ret = littlefs_convert_result(lfs_dir_read(&fs->lfs, &ldir->dir, &info));
   if (ret > 0)
     {
       if (info.type == LFS_TYPE_REG)
@@ -875,13 +880,13 @@ static int littlefs_readdir(FAR struct inode *mountpt,
 static int littlefs_rewinddir(FAR struct inode *mountpt,
                               FAR struct fs_dirent_s *dir)
 {
-  struct littlefs_mountpt_s *fs;
-  FAR struct lfs_dir *priv;
+  FAR struct littlefs_mountpt_s *fs;
+  FAR struct littlefs_dir_s *ldir;
   int ret;
 
   /* Recover our private data from the inode instance */
 
-  priv = dir->u.littlefs;
+  ldir = (FAR struct littlefs_dir_s *)dir;
   fs   = mountpt->i_private;
 
   /* Call the LFS's rewinddir function */
@@ -892,7 +897,7 @@ static int littlefs_rewinddir(FAR struct inode *mountpt,
       return ret;
     }
 
-  ret = littlefs_convert_result(lfs_dir_rewind(&fs->lfs, priv));
+  ret = littlefs_convert_result(lfs_dir_rewind(&fs->lfs, &ldir->dir));
 
   littlefs_semgive(fs);
   return ret;
diff --git a/fs/mount/fs_procfs_mount.c b/fs/mount/fs_procfs_mount.c
index a3ab3c40b8..72de2ba40f 100644
--- a/fs/mount/fs_procfs_mount.c
+++ b/fs/mount/fs_procfs_mount.c
@@ -44,7 +44,6 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/procfs.h>
-#include <nuttx/fs/dirent.h>
 
 #include "mount/mount.h"
 
diff --git a/fs/nfs/nfs_vfsops.c b/fs/nfs/nfs_vfsops.c
index 99f43b3435..2660724d33 100644
--- a/fs/nfs/nfs_vfsops.c
+++ b/fs/nfs/nfs_vfsops.c
@@ -65,7 +65,6 @@
 #include <debug.h>
 
 #include <nuttx/kmalloc.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/nfs.h>
 #include <nuttx/net/netconfig.h>
@@ -85,6 +84,9 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+#define DIRENT_NFS_MAXHANDLE    64 /* Maximum length of an NFSv3 file handle */
+#define DIRENT_NFS_VERFLEN      8  /* Length of the copy verifier */
+
 /* include/nuttx/fs/dirent.h has its own version of these lengths.  They must
  * match the NFS versions.
  */
@@ -99,6 +101,19 @@
 
 #define CH_STAT_SIZE            (1 << 7)
 
+/****************************************************************************
+ * Private Type
+ ****************************************************************************/
+
+struct nfs_dir_s
+{
+  struct fs_dirent_s nfs_base;                /* VFS diretory structure */
+  uint8_t  nfs_fhsize;                        /* Length of the file handle */
+  uint8_t  nfs_fhandle[DIRENT_NFS_MAXHANDLE]; /* File handle (max size allocated) */
+  uint8_t  nfs_verifier[DIRENT_NFS_VERFLEN];  /* Cookie verifier */
+  uint32_t nfs_cookie[2];                     /* Cookie */
+};
+
 /****************************************************************************
  * Private Data
  ****************************************************************************/
@@ -138,7 +153,9 @@ static int     nfs_fchstat(FAR const struct file *filep,
                    FAR const struct stat *buf, int flags);
 static int     nfs_truncate(FAR struct file *filep, off_t length);
 static int     nfs_opendir(FAR struct inode *mountpt,
-                   FAR const char *relpath, FAR struct fs_dirent_s *dir);
+                   FAR const char *relpath, FAR struct fs_dirent_s **dir);
+static int     nfs_closedir(FAR struct inode *mountpt,
+                   FAR struct fs_dirent_s *dir);
 static int     nfs_readdir(FAR struct inode *mountpt,
                            FAR struct fs_dirent_s *dir,
                            FAR struct dirent *entry);
@@ -192,7 +209,7 @@ const struct mountpt_operations nfs_operations =
   nfs_truncate,                 /* truncate */
 
   nfs_opendir,                  /* opendir */
-  NULL,                         /* closedir */
+  nfs_closedir,                 /* closedir */
   nfs_readdir,                  /* readdir */
   nfs_rewinddir,                /* rewinddir */
 
@@ -1407,10 +1424,11 @@ static int nfs_truncate(FAR struct file *filep, off_t length)
  ****************************************************************************/
 
 static int nfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
-                       FAR struct fs_dirent_s *dir)
+                       FAR struct fs_dirent_s **dir)
 {
   FAR struct nfsmount *nmp;
-  FAR struct file_handle fhandle;
+  FAR struct nfs_dir_s *ndir;
+  struct file_handle fhandle;
   struct nfs_fattr obj_attributes;
   uint32_t objtype;
   int ret;
@@ -1424,15 +1442,16 @@ static int nfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
   /* Recover our private data from the inode instance */
 
   nmp = mountpt->i_private;
-
-  /* Initialize the NFS-specific portions of dirent structure to zero */
-
-  memset(&dir->u.nfs, 0, sizeof(struct nfsdir_s));
+  ndir = kmm_zalloc(sizeof(*ndir));
+  if (ndir == NULL)
+    {
+      return -ENOMEM;
+    }
 
   ret = nfs_semtake(nmp);
   if (ret < 0)
     {
-      return ret;
+      goto errout_with_ndir;
     }
 
   /* Find the NFS node associate with the path */
@@ -1458,16 +1477,40 @@ static int nfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
    * used later when readdir() is called.
    */
 
-  dir->u.nfs.nfs_fhsize = (uint8_t)fhandle.length;
+  ndir->nfs_fhsize = (uint8_t)fhandle.length;
   DEBUGASSERT(fhandle.length <= DIRENT_NFS_MAXHANDLE);
 
-  memcpy(dir->u.nfs.nfs_fhandle, &fhandle.handle, fhandle.length);
+  memcpy(ndir->nfs_fhandle, &fhandle.handle, fhandle.length);
+  *dir = &ndir->nfs_base;
+  nfs_semgive(nmp);
+  return 0;
 
 errout_with_semaphore:
   nfs_semgive(nmp);
+errout_with_ndir:
+  kmm_free(ndir);
   return ret;
 }
 
+/****************************************************************************
+ * Name: nfs_closedir
+ *
+ * Description:
+ *   Close directory
+ *
+ * Returned Value:
+ *   0 on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int nfs_closedir(FAR struct inode *mountpt,
+                        FAR struct fs_dirent_s *dir)
+{
+  DEBUGASSERT(dir);
+  kmm_free(dir);
+  return 0;
+}
+
 /****************************************************************************
  * Name: nfs_readdir
  *
@@ -1483,6 +1526,7 @@ static int nfs_readdir(FAR struct inode *mountpt,
                        FAR struct dirent *entry)
 {
   FAR struct nfsmount *nmp;
+  FAR struct nfs_dir_s *ndir;
   struct file_handle fhandle;
   struct nfs_fattr obj_attributes;
   uint32_t readsize;
@@ -1502,6 +1546,7 @@ static int nfs_readdir(FAR struct inode *mountpt,
   /* Recover our private data from the inode instance */
 
   nmp = mountpt->i_private;
+  ndir = (FAR struct nfs_dir_s *)dir;
 
   ret = nfs_semtake(nmp);
   if (ret < 0)
@@ -1519,21 +1564,21 @@ read_dir:
 
   /* Copy the variable length, directory file handle */
 
-  *ptr++  = txdr_unsigned((uint32_t)dir->u.nfs.nfs_fhsize);
+  *ptr++  = txdr_unsigned((uint32_t)ndir->nfs_fhsize);
   reqlen += sizeof(uint32_t);
 
-  memcpy(ptr, dir->u.nfs.nfs_fhandle, dir->u.nfs.nfs_fhsize);
-  reqlen += uint32_alignup(dir->u.nfs.nfs_fhsize);
-  ptr    += uint32_increment(dir->u.nfs.nfs_fhsize);
+  memcpy(ptr, ndir->nfs_fhandle, ndir->nfs_fhsize);
+  reqlen += uint32_alignup(ndir->nfs_fhsize);
+  ptr    += uint32_increment(ndir->nfs_fhsize);
 
   /* Cookie and cookie verifier */
 
-  ptr[0] = dir->u.nfs.nfs_cookie[0];
-  ptr[1] = dir->u.nfs.nfs_cookie[1];
+  ptr[0] = ndir->nfs_cookie[0];
+  ptr[1] = ndir->nfs_cookie[1];
   ptr    += 2;
   reqlen += 2*sizeof(uint32_t);
 
-  memcpy(ptr, dir->u.nfs.nfs_verifier, DIRENT_NFS_VERFLEN);
+  memcpy(ptr, ndir->nfs_verifier, DIRENT_NFS_VERFLEN);
   ptr    += uint32_increment(DIRENT_NFS_VERFLEN);
   reqlen += DIRENT_NFS_VERFLEN;
 
@@ -1588,7 +1633,7 @@ read_dir:
 
   /* Save the verification cookie */
 
-  memcpy(dir->u.nfs.nfs_verifier, ptr, DIRENT_NFS_VERFLEN);
+  memcpy(ndir->nfs_verifier, ptr, DIRENT_NFS_VERFLEN);
   ptr += uint32_increment(DIRENT_NFS_VERFLEN);
 
 next_entry:
@@ -1650,8 +1695,8 @@ next_entry:
 
   /* Save the cookie and increment the pointer to the next entry */
 
-  dir->u.nfs.nfs_cookie[0] = *ptr++;
-  dir->u.nfs.nfs_cookie[1] = *ptr++;
+  ndir->nfs_cookie[0] = *ptr++;
+  ndir->nfs_cookie[1] = *ptr++;
 
   /* Return the name of the node to the caller */
 
@@ -1674,8 +1719,8 @@ next_entry:
    * the file type.
    */
 
-  fhandle.length = (uint32_t)dir->u.nfs.nfs_fhsize;
-  memcpy(&fhandle.handle, dir->u.nfs.nfs_fhandle, fhandle.length);
+  fhandle.length = (uint32_t)ndir->nfs_fhsize;
+  memcpy(&fhandle.handle, ndir->nfs_fhandle, fhandle.length);
 
   ret = nfs_lookup(nmp, entry->d_name, &fhandle, &obj_attributes, NULL);
   if (ret != OK)
@@ -1744,19 +1789,23 @@ errout_with_semaphore:
 static int nfs_rewinddir(FAR struct inode *mountpt,
                          FAR struct fs_dirent_s *dir)
 {
+  FAR struct nfs_dir_s *ndir;
+
   finfo("Entry\n");
 
   /* Sanity checks */
 
   DEBUGASSERT(mountpt != NULL && dir != NULL);
 
+  ndir = (FAR struct nfs_dir_s *)dir;
+
   /* Reset the NFS-specific portions of dirent structure, retaining only the
    * file handle.
    */
 
-  memset(&dir->u.nfs.nfs_verifier, 0, DIRENT_NFS_VERFLEN);
-  dir->u.nfs.nfs_cookie[0] = 0;
-  dir->u.nfs.nfs_cookie[1] = 0;
+  memset(&ndir->nfs_verifier, 0, DIRENT_NFS_VERFLEN);
+  ndir->nfs_cookie[0] = 0;
+  ndir->nfs_cookie[1] = 0;
   return OK;
 }
 
diff --git a/fs/nxffs/nxffs.h b/fs/nxffs/nxffs.h
index 7fa120b617..8f1116bc29 100644
--- a/fs/nxffs/nxffs.h
+++ b/fs/nxffs/nxffs.h
@@ -1108,7 +1108,9 @@ int nxffs_truncate(FAR struct file *filep, off_t length);
 #endif
 
 int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
-                  FAR struct fs_dirent_s *dir);
+                  FAR struct fs_dirent_s **dir);
+int nxffs_closedir(FAR struct inode *mountpt,
+                   FAR struct fs_dirent_s *dir);
 int nxffs_readdir(FAR struct inode *mountpt,
                   FAR struct fs_dirent_s *dir,
                   FAR struct dirent *entry);
diff --git a/fs/nxffs/nxffs_dirent.c b/fs/nxffs/nxffs_dirent.c
index 8894060bcb..972f587b43 100644
--- a/fs/nxffs/nxffs_dirent.c
+++ b/fs/nxffs/nxffs_dirent.c
@@ -32,10 +32,20 @@
 
 #include <nuttx/fs/fs.h>
 #include <nuttx/mtd/mtd.h>
-#include <nuttx/fs/dirent.h>
+#include <nuttx/kmalloc.h>
 
 #include "nxffs.h"
 
+/****************************************************************************
+ * Private Type
+ ****************************************************************************/
+
+struct nxffs_dir_s
+{
+  struct fs_dirent_s base;
+  off_t offset;
+};
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -49,9 +59,10 @@
  ****************************************************************************/
 
 int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
-                  FAR struct fs_dirent_s *dir)
+                  FAR struct fs_dirent_s **dir)
 {
-  struct nxffs_volume_s *volume;
+  FAR struct nxffs_volume_s *volume;
+  FAR struct nxffs_dir_s *ndir;
   int ret;
 
   finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
@@ -63,10 +74,16 @@ int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
   /* Recover the file system state from the NuttX inode instance */
 
   volume = mountpt->i_private;
+  ndir = kmm_zalloc(sizeof(*ndir));
+  if (ndir == NULL)
+    {
+      return -ENOMEM;
+    }
+
   ret = nxsem_wait(&volume->exclsem);
   if (ret < 0)
     {
-      goto errout;
+      goto errout_with_ndir;
     }
 
   /* The requested directory must be the volume-relative "root" directory */
@@ -79,16 +96,35 @@ int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
 
   /* Set the offset to the offset to the first valid inode */
 
-  dir->u.nxffs.nx_offset = volume->inoffset;
-  ret = OK;
+  ndir->offset = volume->inoffset;
+  nxsem_post(&volume->exclsem);
+  *dir = &ndir->base;
+  return 0;
 
 errout_with_semaphore:
   nxsem_post(&volume->exclsem);
 
-errout:
+errout_with_ndir:
+  kmm_free(ndir);
   return ret;
 }
 
+/****************************************************************************
+ * Name: nxffs_closedir
+ *
+ * Description:
+ *   Close directory
+ *
+ ****************************************************************************/
+
+int nxffs_closedir(FAR struct inode *mountpt,
+                   FAR struct fs_dirent_s *dir)
+{
+  DEBUGASSERT(dir);
+  kmm_free(dir);
+  return 0;
+}
+
 /****************************************************************************
  * Name: nxffs_readdir
  *
@@ -101,6 +137,7 @@ int nxffs_readdir(FAR struct inode *mountpt,
                   FAR struct dirent *dentry)
 {
   FAR struct nxffs_volume_s *volume;
+  FAR struct nxffs_dir_s *ndir;
   struct nxffs_entry_s entry;
   off_t offset;
   int ret;
@@ -112,6 +149,7 @@ int nxffs_readdir(FAR struct inode *mountpt,
   /* Recover the file system state from the NuttX inode instance */
 
   volume = mountpt->i_private;
+  ndir = (FAR struct nxffs_dir_s *)dir;
   ret = nxsem_wait(&volume->exclsem);
   if (ret < 0)
     {
@@ -120,7 +158,7 @@ int nxffs_readdir(FAR struct inode *mountpt,
 
   /* Read the next inode header from the offset */
 
-  offset = dir->u.nxffs.nx_offset;
+  offset = ndir->offset;
   ret = nxffs_nextentry(volume, offset, &entry);
 
   /* If the read was successful, then handle the reported inode.  Note
@@ -138,7 +176,7 @@ int nxffs_readdir(FAR struct inode *mountpt,
 
       /* Discard this entry and set the next offset. */
 
-      dir->u.nxffs.nx_offset = nxffs_inodeend(volume, &entry);
+      ndir->offset = nxffs_inodeend(volume, &entry);
       nxffs_freeentry(&entry);
       ret = OK;
     }
@@ -179,7 +217,7 @@ int nxffs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir)
 
   /* Reset the offset to the FLASH offset to the first valid inode */
 
-  dir->u.nxffs.nx_offset = volume->inoffset;
+  ((FAR struct nxffs_dir_s *)dir)->offset = volume->inoffset;
   ret = OK;
 
   nxsem_post(&volume->exclsem);
diff --git a/fs/nxffs/nxffs_initialize.c b/fs/nxffs/nxffs_initialize.c
index 833b839c41..1aaf9fe848 100644
--- a/fs/nxffs/nxffs_initialize.c
+++ b/fs/nxffs/nxffs_initialize.c
@@ -66,7 +66,7 @@ const struct mountpt_operations nxffs_operations =
 #endif
 
   nxffs_opendir,     /* opendir */
-  NULL,              /* closedir */
+  nxffs_closedir,    /* closedir */
   nxffs_readdir,     /* readdir */
   nxffs_rewinddir,   /* rewinddir */
 
diff --git a/fs/procfs/fs_procfs.c b/fs/procfs/fs_procfs.c
index 2858c33b6e..ccaa3b86d4 100644
--- a/fs/procfs/fs_procfs.c
+++ b/fs/procfs/fs_procfs.c
@@ -45,7 +45,6 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/procfs.h>
-#include <nuttx/fs/dirent.h>
 
 #include "mount/mount.h"
 
@@ -224,7 +223,7 @@ static int     procfs_fstat(FAR const struct file *filep,
                  FAR struct stat *buf);
 
 static int     procfs_opendir(FAR struct inode *mountpt, const char *relpath,
-                 FAR struct fs_dirent_s *dir);
+                 FAR struct fs_dirent_s **dir);
 static int     procfs_closedir(FAR struct inode *mountpt,
                  FAR struct fs_dirent_s *dir);
 static int     procfs_readdir(FAR struct inode *mountpt,
@@ -551,14 +550,12 @@ static int procfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
  ****************************************************************************/
 
 static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
-                          FAR struct fs_dirent_s *dir)
+                          FAR struct fs_dirent_s **dir)
 {
   FAR struct procfs_level0_s *level0;
-  FAR struct procfs_dir_priv_s *dirpriv;
-  FAR void *priv = NULL;
 
   finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
-  DEBUGASSERT(mountpt && relpath && dir && !dir->u.procfs);
+  DEBUGASSERT(mountpt && dir && relpath);
 
   /* The relative must be either:
    *
@@ -601,7 +598,7 @@ static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
       level0->lastlen = 0;
       level0->base.procfsentry = NULL;
 
-      priv = (FAR void *)level0;
+      *dir = (FAR struct fs_dirent_s *)level0;
     }
   else
     {
@@ -619,7 +616,7 @@ static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
             {
               /* Match found!  Call the handler's opendir routine.  If
                * successful, this opendir routine will create an entry
-               * derived from struct procfs_dir_priv_s as dir->u.procfs.
+               * derived from struct procfs_dir_priv_s as dir.
                */
 
               DEBUGASSERT(g_procfs_entries[x].ops != NULL &&
@@ -629,11 +626,13 @@ static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
 
               if (ret == OK)
                 {
-                  DEBUGASSERT(dir->u.procfs);
+                  FAR struct procfs_dir_priv_s *dirpriv;
+
+                  DEBUGASSERT(*dir);
 
                   /* Set the procfs_entry handler */
 
-                  dirpriv = (FAR struct procfs_dir_priv_s *)dir->u.procfs;
+                  dirpriv = (FAR struct procfs_dir_priv_s *)(*dir);
                   dirpriv->procfsentry = &g_procfs_entries[x];
                 }
 
@@ -671,7 +670,7 @@ static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
               level1->lastlen = 0;
               level1->base.procfsentry = NULL;
 
-              priv = (FAR void *)level1;
+              *dir = (FAR struct fs_dirent_s *)level1;
               break;
             }
         }
@@ -682,7 +681,6 @@ static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
         }
     }
 
-  dir->u.procfs = priv;
   return OK;
 }
 
@@ -696,17 +694,8 @@ static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
 static int procfs_closedir(FAR struct inode *mountpt,
                            FAR struct fs_dirent_s *dir)
 {
-  FAR struct procfs_dir_priv_s *priv;
-
-  DEBUGASSERT(mountpt && dir && dir->u.procfs);
-  priv = dir->u.procfs;
-
-  if (priv)
-    {
-      kmm_free(priv);
-    }
-
-  dir->u.procfs = NULL;
+  DEBUGASSERT(mountpt && dir);
+  kmm_free(dir);
   return OK;
 }
 
@@ -730,8 +719,8 @@ static int procfs_readdir(FAR struct inode *mountpt,
   pid_t pid;
   int ret = -ENOENT;
 
-  DEBUGASSERT(mountpt && dir && dir->u.procfs);
-  priv = dir->u.procfs;
+  DEBUGASSERT(mountpt && dir);
+  priv = (FAR struct procfs_dir_priv_s *)dir;
 
   /* Are we reading the 1st directory level with dynamic PID and static
    * entries?
@@ -953,8 +942,8 @@ static int procfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
 {
   FAR struct procfs_dir_priv_s *priv;
 
-  DEBUGASSERT(mountpt && dir && dir->u.procfs);
-  priv = dir->u.procfs;
+  DEBUGASSERT(mountpt && dir);
+  priv = (FAR struct procfs_dir_priv_s *)dir;
 
   if (priv->level > 0 && priv->procfsentry == NULL)
     {
diff --git a/fs/procfs/fs_procfsproc.c b/fs/procfs/fs_procfsproc.c
index 5f53a8c535..56cf64fb10 100644
--- a/fs/procfs/fs_procfsproc.c
+++ b/fs/procfs/fs_procfsproc.c
@@ -51,7 +51,6 @@
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/procfs.h>
 #include <nuttx/fs/ioctl.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/mm/mm.h>
 
 #if defined(CONFIG_SCHED_CPULOAD) || defined(CONFIG_SCHED_CRITMONITOR)
@@ -223,7 +222,7 @@ static int     proc_dup(FAR const struct file *oldp,
                  FAR struct file *newp);
 
 static int     proc_opendir(const char *relpath,
-                 FAR struct fs_dirent_s *dir);
+                 FAR struct fs_dirent_s **dir);
 static int     proc_closedir(FAR struct fs_dirent_s *dir);
 static int     proc_readdir(FAR struct fs_dirent_s *dir,
                             FAR struct dirent *entry);
@@ -1771,7 +1770,8 @@ static int proc_dup(FAR const struct file *oldp, FAR struct file *newp)
  *
  ****************************************************************************/
 
-static int proc_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
+static int proc_opendir(FAR const char *relpath,
+                        FAR struct fs_dirent_s **dir)
 {
   FAR struct proc_dir_s *procdir;
   FAR const struct proc_node_s *node;
@@ -1781,7 +1781,7 @@ static int proc_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
   pid_t pid;
 
   finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
-  DEBUGASSERT(relpath != NULL && dir != NULL && dir->u.procfs == NULL);
+  DEBUGASSERT(relpath != NULL);
 
   /* The relative must be either:
    *
@@ -1887,7 +1887,7 @@ static int proc_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
     }
 
   procdir->pid  = pid;
-  dir->u.procfs = (FAR void *)procdir;
+  *dir = (FAR struct fs_dirent_s *)procdir;
   return OK;
 }
 
@@ -1900,17 +1900,8 @@ static int proc_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
 
 static int proc_closedir(FAR struct fs_dirent_s *dir)
 {
-  FAR struct proc_dir_s *priv;
-
-  DEBUGASSERT(dir != NULL && dir->u.procfs != NULL);
-  priv = dir->u.procfs;
-
-  if (priv)
-    {
-      kmm_free(priv);
-    }
-
-  dir->u.procfs = NULL;
+  DEBUGASSERT(dir != NULL);
+  kmm_free(dir);
   return OK;
 }
 
@@ -1931,8 +1922,8 @@ static int proc_readdir(FAR struct fs_dirent_s *dir,
   pid_t pid;
   int ret;
 
-  DEBUGASSERT(dir != NULL && dir->u.procfs != NULL);
-  procdir = dir->u.procfs;
+  DEBUGASSERT(dir != NULL);
+  procdir = (FAR struct proc_dir_s *)dir;
 
   /* Have we reached the end of the directory */
 
@@ -2011,8 +2002,8 @@ static int proc_rewinddir(struct fs_dirent_s *dir)
 {
   FAR struct proc_dir_s *priv;
 
-  DEBUGASSERT(dir != NULL && dir->u.procfs != NULL);
-  priv = dir->u.procfs;
+  DEBUGASSERT(dir != NULL);
+  priv = (FAR struct proc_dir_s *)dir;
 
   priv->base.index = 0;
   return OK;
diff --git a/fs/procfs/fs_skeleton.c b/fs/procfs/fs_skeleton.c
index 254913a7f7..8136daf036 100644
--- a/fs/procfs/fs_skeleton.c
+++ b/fs/procfs/fs_skeleton.c
@@ -42,7 +42,6 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/procfs.h>
-#include <nuttx/fs/dirent.h>
 
 #include <arch/irq.h>
 
@@ -100,7 +99,7 @@ static int     skel_dup(FAR const struct file *oldp,
                  FAR struct file *newp);
 
 static int     skel_opendir(FAR const char *relpath,
-                 FAR struct fs_dirent_s *dir);
+                 FAR struct fs_dirent_s **dir);
 static int     skel_closedir(FAR struct fs_dirent_s *dir);
 static int     skel_readdir(FAR struct fs_dirent_s *dir,
                             FAR struct dirent *entry);
@@ -338,12 +337,13 @@ static int skel_dup(FAR const struct file *oldp, FAR struct file *newp)
  *
  ****************************************************************************/
 
-static int skel_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
+static int skel_opendir(FAR const char *relpath,
+                        FAR struct fs_dirent_s **dir)
 {
   FAR struct skel_level1_s *level1;
 
   finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
-  DEBUGASSERT(relpath && dir && !dir->u.procfs);
+  DEBUGASSERT(relpath);
 
   /* The path refers to the 1st level sbdirectory.  Allocate the level1
    * dirent structure.
@@ -366,7 +366,7 @@ static int skel_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
   level1->base.nentries = 0;
   level1->base.index    = 0;
 
-  dir->u.procfs = (FAR void *) level1;
+  *dir = (FAR struct fs_dirent_s *)level1;
   return OK;
 }
 
@@ -379,17 +379,8 @@ static int skel_opendir(FAR const char *relpath, FAR struct fs_dirent_s *dir)
 
 static int skel_closedir(FAR struct fs_dirent_s *dir)
 {
-  FAR struct skel_level1_s *priv;
-
-  DEBUGASSERT(dir && dir->u.procfs);
-  priv = dir->u.procfs;
-
-  if (priv)
-    {
-      kmm_free(priv);
-    }
-
-  dir->u.procfs = NULL;
+  DEBUGASSERT(dir);
+  kmm_free(dir);
   return OK;
 }
 
@@ -404,12 +395,12 @@ static int skel_readdir(FAR struct fs_dirent_s *dir,
                         FAR struct dirent *entry)
 {
   FAR struct skel_level1_s *level1;
-  char  filename[16];
+  char filename[16];
   int index;
   int ret;
 
-  DEBUGASSERT(dir && dir->u.procfs);
-  level1 = dir->u.procfs;
+  DEBUGASSERT(dir);
+  level1 = (FAR struct skel_level1_s *)dir;
 
   /* TODO:  Perform device specific readdir function here.  This may
    *        or may not involve validating the nentries variable
@@ -466,8 +457,8 @@ static int skel_rewinddir(FAR struct fs_dirent_s *dir)
 {
   FAR struct skel_level1_s *priv;
 
-  DEBUGASSERT(dir && dir->u.procfs);
-  priv = dir->u.procfs;
+  DEBUGASSERT(dir);
+  priv = (FAR struct skel_level1_s *)dir;
 
   priv->base.index = 0;
   return OK;
diff --git a/fs/romfs/fs_romfs.c b/fs/romfs/fs_romfs.c
index 35ccf4cb78..5db8e1a34c 100644
--- a/fs/romfs/fs_romfs.c
+++ b/fs/romfs/fs_romfs.c
@@ -40,10 +40,27 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/ioctl.h>
-#include <nuttx/fs/dirent.h>
 
 #include "fs_romfs.h"
 
+/****************************************************************************
+ * Private Type
+ ****************************************************************************/
+
+/* This structure represents one entry node in the romfs file system */
+
+struct romfs_dir_s
+{
+  struct fs_dirent_s base;                 /* Vfs directory structure */
+#ifdef CONFIG_FS_ROMFS_CACHE_NODE
+  FAR struct romfs_nodeinfo_s **firstnode; /* The address of first node in the directory */
+  FAR struct romfs_nodeinfo_s **currnode;  /* The address of current node into the directory */
+#else
+  off_t firstoffset;                       /* Offset to the first entry in the directory */
+  off_t curroffset;                        /* Current offset into the directory contents */
+#endif
+};
+
 /****************************************************************************
  * Private Function Prototypes
  ****************************************************************************/
@@ -64,7 +81,9 @@ static int     romfs_fstat(FAR const struct file *filep,
 
 static int     romfs_opendir(FAR struct inode *mountpt,
                              FAR const char *relpath,
-                             FAR struct fs_dirent_s *dir);
+                             FAR struct fs_dirent_s **dir);
+static int     romfs_closedir(FAR struct inode *mountpt,
+                              FAR struct fs_dirent_s *dir);
 static int     romfs_readdir(FAR struct inode *mountpt,
                              FAR struct fs_dirent_s *dir,
                              FAR struct dirent *entry);
@@ -108,7 +127,7 @@ const struct mountpt_operations romfs_operations =
   NULL,            /* truncate */
 
   romfs_opendir,   /* opendir */
-  NULL,            /* closedir */
+  romfs_closedir,  /* closedir */
   romfs_readdir,   /* readdir */
   romfs_rewinddir, /* rewinddir */
 
@@ -738,9 +757,10 @@ static int romfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
  ****************************************************************************/
 
 static int romfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
-                         FAR struct fs_dirent_s *dir)
+                         FAR struct fs_dirent_s **dir)
 {
   FAR struct romfs_mountpt_s *rm;
+  FAR struct romfs_dir_s     *rdir;
   struct romfs_nodeinfo_s     nodeinfo;
   int                         ret;
 
@@ -754,12 +774,18 @@ static int romfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
 
   rm = mountpt->i_private;
 
+  rdir = kmm_zalloc(sizeof(*rdir));
+  if (rdir == NULL)
+    {
+      return -ENOMEM;
+    }
+
   /* Make sure that the mount is still healthy */
 
   ret = romfs_semtake(rm);
   if (ret < 0)
     {
-      return ret;
+      goto errout_with_rdir;
     }
 
   ret = romfs_checkmount(rm);
@@ -792,18 +818,40 @@ static int romfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
   /* The entry is a directory */
 
 #ifdef CONFIG_FS_ROMFS_CACHE_NODE
-  dir->u.romfs.fr_firstnode   = nodeinfo.rn_child;
-  dir->u.romfs.fr_currnode    = nodeinfo.rn_child;
+  rdir->firstnode   = nodeinfo.rn_child;
+  rdir->currnode    = nodeinfo.rn_child;
 #else
-  dir->u.romfs.fr_firstoffset = nodeinfo.rn_offset;
-  dir->u.romfs.fr_curroffset  = nodeinfo.rn_offset;
+  rdir->firstoffset = nodeinfo.rn_offset;
+  rdir->curroffset  = nodeinfo.rn_offset;
 #endif
 
+  *dir = &rdir->base;
+  romfs_semgive(rm);
+  return OK;
+
 errout_with_semaphore:
   romfs_semgive(rm);
+
+errout_with_rdir:
+  kmm_free(rdir);
   return ret;
 }
 
+/****************************************************************************
+ * Name: romfs_closedir
+ *
+ * Description: Close the directory
+ *
+ ****************************************************************************/
+
+static int romfs_closedir(FAR struct inode *mountpt,
+                          FAR struct fs_dirent_s *dir)
+{
+  DEBUGASSERT(dir);
+  kmm_free(dir);
+  return 0;
+}
+
 /****************************************************************************
  * Name: romfs_readdir
  *
@@ -816,6 +864,7 @@ static int romfs_readdir(FAR struct inode *mountpt,
                          FAR struct dirent *entry)
 {
   FAR struct romfs_mountpt_s *rm;
+  FAR struct romfs_dir_s     *rdir;
 #ifndef CONFIG_FS_ROMFS_CACHE_NODE
   uint32_t                    linkoffset;
   uint32_t                    info;
@@ -833,6 +882,7 @@ static int romfs_readdir(FAR struct inode *mountpt,
   /* Recover our private data from the inode instance */
 
   rm = mountpt->i_private;
+  rdir = (FAR struct romfs_dir_s *)dir;
 
   /* Make sure that the mount is still healthy */
 
@@ -856,9 +906,9 @@ static int romfs_readdir(FAR struct inode *mountpt,
       /* Have we reached the end of the directory */
 
 #ifdef CONFIG_FS_ROMFS_CACHE_NODE
-      if (!dir->u.romfs.fr_currnode || !(*dir->u.romfs.fr_currnode))
+      if (!rdir->currnode || !(*rdir->currnode))
 #else
-      if (!dir->u.romfs.fr_curroffset)
+      if (!rdir->curroffset)
 #endif
         {
           /* We signal the end of the directory by returning the
@@ -871,14 +921,14 @@ static int romfs_readdir(FAR struct inode *mountpt,
         }
 
 #ifdef CONFIG_FS_ROMFS_CACHE_NODE
-      next = (*dir->u.romfs.fr_currnode)->rn_next;
-      strlcpy(entry->d_name, (*dir->u.romfs.fr_currnode)->rn_name,
+      next = (*rdir->currnode)->rn_next;
+      strlcpy(entry->d_name, (*rdir->currnode)->rn_name,
               sizeof(entry->d_name));
-      dir->u.romfs.fr_currnode++;
+      rdir->currnode++;
 #else
       /* Parse the directory entry */
 
-      ret = romfs_parsedirentry(rm, dir->u.romfs.fr_curroffset, &linkoffset,
+      ret = romfs_parsedirentry(rm, rdir->curroffset, &linkoffset,
                                 &next, &info, &size);
       if (ret < 0)
         {
@@ -888,7 +938,7 @@ static int romfs_readdir(FAR struct inode *mountpt,
 
       /* Save the filename */
 
-      ret = romfs_parsefilename(rm, dir->u.romfs.fr_curroffset,
+      ret = romfs_parsefilename(rm, rdir->curroffset,
                                 entry->d_name);
       if (ret < 0)
         {
@@ -898,7 +948,7 @@ static int romfs_readdir(FAR struct inode *mountpt,
 
       /* Set up the next directory entry offset */
 
-      dir->u.romfs.fr_curroffset = next & RFNEXT_OFFSETMASK;
+      rdir->curroffset = next & RFNEXT_OFFSETMASK;
 #endif
 
       /* Check the file type */
@@ -936,6 +986,7 @@ static int romfs_rewinddir(FAR struct inode *mountpt,
                            FAR struct fs_dirent_s *dir)
 {
   FAR struct romfs_mountpt_s *rm;
+  FAR struct romfs_dir_s *rdir;
   int ret;
 
   finfo("Entry\n");
@@ -947,6 +998,7 @@ static int romfs_rewinddir(FAR struct inode *mountpt,
   /* Recover our private data from the inode instance */
 
   rm = mountpt->i_private;
+  rdir = (FAR struct romfs_dir_s *)dir;
 
   /* Make sure that the mount is still healthy */
 
@@ -960,9 +1012,9 @@ static int romfs_rewinddir(FAR struct inode *mountpt,
   if (ret == OK)
     {
 #ifdef CONFIG_FS_ROMFS_CACHE_NODE
-      dir->u.romfs.fr_currnode = dir->u.romfs.fr_firstnode;
+      rdir->currnode = rdir->firstnode;
 #else
-      dir->u.romfs.fr_curroffset = dir->u.romfs.fr_firstoffset;
+      rdir->curroffset = rdir->firstoffset;
 #endif
     }
 
diff --git a/fs/romfs/fs_romfs.h b/fs/romfs/fs_romfs.h
index a363bb894d..314f6fafdd 100644
--- a/fs/romfs/fs_romfs.h
+++ b/fs/romfs/fs_romfs.h
@@ -30,8 +30,6 @@
 #include <stdint.h>
 #include <stdbool.h>
 
-#include <nuttx/fs/dirent.h>
-
 #include "inode/inode.h"
 
 /****************************************************************************
@@ -158,18 +156,20 @@ struct romfs_file_s
   char rf_path[1];                /* Path of open file */
 };
 
-/* This structure is used internally for describing the result of
- * walking a path
- */
-
-#ifndef CONFIG_FS_ROMFS_CACHE_NODE
 struct romfs_nodeinfo_s
 {
-  uint32_t rn_offset;             /* Offset of real file header */
-  uint32_t rn_next;               /* Offset of the next file header+flags */
-  uint32_t rn_size;               /* Size (if file) */
-};
+#ifdef CONFIG_FS_ROMFS_CACHE_NODE
+  FAR struct romfs_nodeinfo_s **rn_child;  /* The node array for link to lower level */
+  uint16_t rn_count;                       /* The count of node in rn_child level */
+#endif
+  uint32_t rn_offset;                      /* Offset of real file header */
+  uint32_t rn_next;                        /* Offset of the next file header+flags */
+  uint32_t rn_size;                        /* Size (if file) */
+#ifdef CONFIG_FS_ROMFS_CACHE_NODE
+  uint8_t  rn_namesize;                    /* The length of name of the entry */
+  char     rn_name[1];                     /* The name to the entry */
 #endif
+};
 
 /****************************************************************************
  * Public Data
diff --git a/fs/romfs/fs_romfsutil.c b/fs/romfs/fs_romfsutil.c
index 0cb1038d4a..d70b20a816 100644
--- a/fs/romfs/fs_romfsutil.c
+++ b/fs/romfs/fs_romfsutil.c
@@ -37,7 +37,6 @@
 
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/ioctl.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/mtd/mtd.h>
 
 #include "fs_romfs.h"
diff --git a/fs/rpmsgfs/rpmsgfs.c b/fs/rpmsgfs/rpmsgfs.c
index 7e76c3a00d..520f63df71 100644
--- a/fs/rpmsgfs/rpmsgfs.c
+++ b/fs/rpmsgfs/rpmsgfs.c
@@ -38,7 +38,6 @@
 
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/fs/ioctl.h>
 #include <nuttx/fs/rpmsgfs.h>
 
@@ -54,6 +53,12 @@
  * Private Types
  ****************************************************************************/
 
+struct rpmsgfs_dir_s
+{
+  struct fs_dirent_s base;
+  FAR void *dir;
+};
+
 /* This structure describes the state of one open file.  This structure
  * is protected by the volume semaphore.
  */
@@ -109,7 +114,7 @@ static int     rpmsgfs_ftruncate(FAR struct file *filep,
 
 static int     rpmsgfs_opendir(FAR struct inode *mountpt,
                                FAR const char *relpath,
-                               FAR struct fs_dirent_s *dir);
+                               FAR struct fs_dirent_s **dir);
 static int     rpmsgfs_closedir(FAR struct inode *mountpt,
                                 FAR struct fs_dirent_s *dir);
 static int     rpmsgfs_readdir(FAR struct inode *mountpt,
@@ -869,9 +874,10 @@ static int rpmsgfs_ftruncate(FAR struct file *filep, off_t length)
 
 static int rpmsgfs_opendir(FAR struct inode *mountpt,
                            FAR const char *relpath,
-                           FAR struct fs_dirent_s *dir)
+                           FAR struct fs_dirent_s **dir)
 {
   FAR struct rpmsgfs_mountpt_s *fs;
+  FAR struct rpmsgfs_dir_s *rdir;
   char path[PATH_MAX];
   int ret;
 
@@ -882,13 +888,18 @@ static int rpmsgfs_opendir(FAR struct inode *mountpt,
   /* Recover our private data from the inode instance */
 
   fs = mountpt->i_private;
+  rdir = kmm_zalloc(sizeof(struct rpmsgfs_dir_s));
+  if (rdir == NULL)
+    {
+      return -ENOMEM;
+    }
 
   /* Take the semaphore */
 
   ret = rpmsgfs_semtake(fs);
   if (ret < 0)
     {
-      return ret;
+      goto errout_with_rdir;
     }
 
   /* Append to the host's root directory */
@@ -897,18 +908,23 @@ static int rpmsgfs_opendir(FAR struct inode *mountpt,
 
   /* Call the host's opendir function */
 
-  dir->u.rpmsgfs.fs_dir = rpmsgfs_client_opendir(fs->handle, path);
-  if (dir->u.rpmsgfs.fs_dir == NULL)
+  rdir->dir = rpmsgfs_client_opendir(fs->handle, path);
+  if (rdir->dir == NULL)
     {
       ret = -ENOENT;
+      kmm_free(rdir);
       goto errout_with_semaphore;
     }
 
-  ret = OK;
+  *dir = (FAR struct fs_dirent_s *)rdir;
+  rpmsgfs_semgive(fs);
+  return OK;
 
 errout_with_semaphore:
-
   rpmsgfs_semgive(fs);
+
+errout_with_rdir:
+  kmm_free(rdir);
   return ret;
 }
 
@@ -922,7 +938,8 @@ errout_with_semaphore:
 static int rpmsgfs_closedir(FAR struct inode *mountpt,
                             FAR struct fs_dirent_s *dir)
 {
-  struct rpmsgfs_mountpt_s  *fs;
+  FAR struct rpmsgfs_mountpt_s *fs;
+  FAR struct rpmsgfs_dir_s *rdir;
   int ret;
 
   /* Sanity checks */
@@ -932,6 +949,7 @@ static int rpmsgfs_closedir(FAR struct inode *mountpt,
   /* Recover our private data from the inode instance */
 
   fs = mountpt->i_private;
+  rdir = (FAR struct rpmsgfs_dir_s *)dir;
 
   /* Take the semaphore */
 
@@ -943,9 +961,10 @@ static int rpmsgfs_closedir(FAR struct inode *mountpt,
 
   /* Call the host's closedir function */
 
-  rpmsgfs_client_closedir(fs->handle, dir->u.rpmsgfs.fs_dir);
+  rpmsgfs_client_closedir(fs->handle, rdir->dir);
 
   rpmsgfs_semgive(fs);
+  kmm_free(rdir);
   return OK;
 }
 
@@ -961,6 +980,7 @@ static int rpmsgfs_readdir(FAR struct inode *mountpt,
                            FAR struct dirent *entry)
 {
   FAR struct rpmsgfs_mountpt_s *fs;
+  FAR struct rpmsgfs_dir_s *rdir;
   int ret;
 
   /* Sanity checks */
@@ -970,6 +990,7 @@ static int rpmsgfs_readdir(FAR struct inode *mountpt,
   /* Recover our private data from the inode instance */
 
   fs = mountpt->i_private;
+  rdir = (FAR struct rpmsgfs_dir_s *)dir;
 
   /* Take the semaphore */
 
@@ -981,8 +1002,7 @@ static int rpmsgfs_readdir(FAR struct inode *mountpt,
 
   /* Call the host OS's readdir function */
 
-  ret = rpmsgfs_client_readdir(fs->handle,
-                               dir->u.rpmsgfs.fs_dir, entry);
+  ret = rpmsgfs_client_readdir(fs->handle, rdir->dir, entry);
 
   rpmsgfs_semgive(fs);
   return ret;
@@ -999,6 +1019,7 @@ static int rpmsgfs_rewinddir(FAR struct inode *mountpt,
                              FAR struct fs_dirent_s *dir)
 {
   FAR struct rpmsgfs_mountpt_s *fs;
+  FAR struct rpmsgfs_dir_s *rdir;
   int ret;
 
   /* Sanity checks */
@@ -1008,6 +1029,7 @@ static int rpmsgfs_rewinddir(FAR struct inode *mountpt,
   /* Recover our private data from the inode instance */
 
   fs = mountpt->i_private;
+  rdir = (FAR struct rpmsgfs_dir_s *)dir;
 
   /* Take the semaphore */
 
@@ -1019,7 +1041,7 @@ static int rpmsgfs_rewinddir(FAR struct inode *mountpt,
 
   /* Call the host and let it do all the work */
 
-  rpmsgfs_client_rewinddir(fs->handle, dir->u.rpmsgfs.fs_dir);
+  rpmsgfs_client_rewinddir(fs->handle, rdir->dir);
 
   rpmsgfs_semgive(fs);
   return OK;
diff --git a/fs/smartfs/smartfs_procfs.c b/fs/smartfs/smartfs_procfs.c
index b59f295e2c..d489066a5e 100644
--- a/fs/smartfs/smartfs_procfs.c
+++ b/fs/smartfs/smartfs_procfs.c
@@ -42,7 +42,6 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/procfs.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/fs/ioctl.h>
 #include <nuttx/mtd/smart.h>
 
@@ -116,7 +115,7 @@ static int      smartfs_dup(FAR const struct file *oldp,
                  FAR struct file *newp);
 
 static int      smartfs_opendir(const char *relpath,
-                  FAR struct fs_dirent_s *dir);
+                  FAR struct fs_dirent_s **dir);
 static int      smartfs_closedir(FAR struct fs_dirent_s *dir);
 static int      smartfs_readdir(FAR struct fs_dirent_s *dir,
                                 FAR struct dirent *entry);
@@ -535,13 +534,13 @@ static int smartfs_dup(FAR const struct file *oldp, FAR struct file *newp)
  ****************************************************************************/
 
 static int smartfs_opendir(FAR const char *relpath,
-                           FAR struct fs_dirent_s *dir)
+                           FAR struct fs_dirent_s **dir)
 {
   FAR struct smartfs_level1_s *level1;
   int        ret;
 
   finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
-  DEBUGASSERT(relpath && dir && !dir->u.procfs);
+  DEBUGASSERT(relpath);
 
   /* The path refers to the 1st level subdirectory.  Allocate the level1
    * dirent structure.
@@ -562,7 +561,7 @@ static int smartfs_opendir(FAR const char *relpath,
 
   if (ret == OK)
     {
-      dir->u.procfs = (FAR void *) level1;
+      *dir = (FAR struct fs_dirent_s *)level1;
     }
   else
     {
@@ -581,17 +580,8 @@ static int smartfs_opendir(FAR const char *relpath,
 
 static int smartfs_closedir(FAR struct fs_dirent_s *dir)
 {
-  FAR struct smartfs_level1_s *priv;
-
-  DEBUGASSERT(dir && dir->u.procfs);
-  priv = dir->u.procfs;
-
-  if (priv)
-    {
-      kmm_free(priv);
-    }
-
-  dir->u.procfs = NULL;
+  DEBUGASSERT(dir);
+  kmm_free(dir);
   return OK;
 }
 
@@ -609,8 +599,8 @@ static int smartfs_readdir(FAR struct fs_dirent_s *dir,
   int ret;
   int index;
 
-  DEBUGASSERT(dir && dir->u.procfs);
-  level1 = dir->u.procfs;
+  DEBUGASSERT(dir);
+  level1 = (FAR struct smartfs_level1_s *)dir;
 
   /* Have we reached the end of the directory */
 
@@ -690,8 +680,8 @@ static int smartfs_rewinddir(struct fs_dirent_s *dir)
 {
   FAR struct smartfs_level1_s *priv;
 
-  DEBUGASSERT(dir && dir->u.procfs);
-  priv = dir->u.procfs;
+  DEBUGASSERT(dir);
+  priv = (FAR struct smartfs_level1_s *)dir;
 
   priv->base.index = 0;
   return OK;
diff --git a/fs/smartfs/smartfs_smart.c b/fs/smartfs/smartfs_smart.c
index 413eaf80d8..11b146bef5 100644
--- a/fs/smartfs/smartfs_smart.c
+++ b/fs/smartfs/smartfs_smart.c
@@ -39,13 +39,24 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/fat.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/fs/ioctl.h>
 #include <nuttx/mtd/mtd.h>
 #include <nuttx/fs/smart.h>
 
 #include "smartfs.h"
 
+/****************************************************************************
+ * Private Type
+ ****************************************************************************/
+
+struct smartfs_dir_s
+{
+  struct fs_dirent_s fs_base; /* VFS directory structure */
+  uint16_t fs_firstsector;    /* First sector of directory list */
+  uint16_t fs_currsector;     /* Current sector of directory list */
+  uint16_t fs_curroffset;     /* Current offset within current sector */
+};
+
 /****************************************************************************
  * Private Function Prototypes
  ****************************************************************************/
@@ -71,6 +82,8 @@ static int     smartfs_truncate(FAR struct file *filep, off_t length);
 
 static int     smartfs_opendir(FAR struct inode *mountpt,
                         FAR const char *relpath,
+                        FAR struct fs_dirent_s **dir);
+static int     smartfs_closedir(FAR struct inode *mountpt,
                         FAR struct fs_dirent_s *dir);
 static int     smartfs_readdir(FAR struct inode *mountpt,
                         FAR struct fs_dirent_s *dir,
@@ -135,7 +148,7 @@ const struct mountpt_operations smartfs_operations =
   smartfs_truncate,      /* truncate */
 
   smartfs_opendir,       /* opendir */
-  NULL,                  /* closedir */
+  smartfs_closedir,      /* closedir */
   smartfs_readdir,       /* readdir */
   smartfs_rewinddir,     /* rewinddir */
 
@@ -1190,13 +1203,14 @@ errout_with_semaphore:
 
 static int smartfs_opendir(FAR struct inode *mountpt,
                            FAR const char *relpath,
-                           FAR struct fs_dirent_s *dir)
+                           FAR struct fs_dirent_s **dir)
 {
-  struct smartfs_mountpt_s *fs;
-  int                       ret;
-  struct smartfs_entry_s    entry;
-  uint16_t                  parentdirsector;
-  const char               *filename;
+  FAR struct smartfs_mountpt_s *fs;
+  FAR struct smartfs_dir_s     *sdir;
+  int                           ret;
+  struct smartfs_entry_s        entry;
+  uint16_t                      parentdirsector;
+  FAR const char               *filename;
 
   /* Sanity checks */
 
@@ -1205,13 +1219,18 @@ static int smartfs_opendir(FAR struct inode *mountpt,
   /* Recover our private data from the inode instance */
 
   fs = mountpt->i_private;
+  sdir = kmm_zalloc(sizeof(*sdir));
+  if (sdir == NULL)
+    {
+      return -ENOMEM;
+    }
 
   /* Take the semaphore */
 
   ret = smartfs_semtake(fs);
   if (ret < 0)
     {
-      return ret;
+      goto errout_with_sdir;
     }
 
   /* Search for the path on the volume */
@@ -1226,11 +1245,13 @@ static int smartfs_opendir(FAR struct inode *mountpt,
 
   /* Populate our private data in the fs_dirent_s struct */
 
-  dir->u.smartfs.fs_firstsector = entry.firstsector;
-  dir->u.smartfs.fs_currsector = entry.firstsector;
-  dir->u.smartfs.fs_curroffset = sizeof(struct smartfs_chain_header_s);
+  sdir->fs_firstsector = entry.firstsector;
+  sdir->fs_currsector = entry.firstsector;
+  sdir->fs_curroffset = sizeof(struct smartfs_chain_header_s);
 
-  ret = OK;
+  *dir = &sdir->fs_base;
+  smartfs_semgive(fs);
+  return OK;
 
 errout_with_semaphore:
 
@@ -1243,9 +1264,27 @@ errout_with_semaphore:
     }
 
   smartfs_semgive(fs);
+
+errout_with_sdir:
+  kmm_free(sdir);
   return ret;
 }
 
+/****************************************************************************
+ * Name: smartfs_closedir
+ *
+ * Description: Close directory
+ *
+ ****************************************************************************/
+
+static int smartfs_closedir(FAR struct inode *mountpt,
+                            FAR struct fs_dirent_s *dir)
+{
+  DEBUGASSERT(dir);
+  kmm_free(dir);
+  return 0;
+}
+
 /****************************************************************************
  * Name: smartfs_readdir
  *
@@ -1257,7 +1296,8 @@ static int smartfs_readdir(FAR struct inode *mountpt,
                            FAR struct fs_dirent_s *dir,
                            FAR struct dirent *dentry)
 {
-  struct smartfs_mountpt_s *fs;
+  FAR struct smartfs_mountpt_s *fs;
+  FAR struct smartfs_dir_s *sdir;
   int                   ret;
   uint16_t              entrysize;
   struct                smartfs_chain_header_s *header;
@@ -1271,6 +1311,7 @@ static int smartfs_readdir(FAR struct inode *mountpt,
   /* Recover our private data from the inode instance */
 
   fs = mountpt->i_private;
+  sdir = (FAR struct smartfs_dir_s *)dir;
 
   /* Take the semaphore */
 
@@ -1284,11 +1325,11 @@ static int smartfs_readdir(FAR struct inode *mountpt,
 
   entrysize = sizeof(struct smartfs_entry_header_s) +
     fs->fs_llformat.namesize;
-  while (dir->u.smartfs.fs_currsector != SMARTFS_ERASEDSTATE_16BIT)
+  while (sdir->fs_currsector != SMARTFS_ERASEDSTATE_16BIT)
     {
       /* Read the logical sector */
 
-      readwrite.logsector = dir->u.smartfs.fs_currsector;
+      readwrite.logsector = sdir->fs_currsector;
       readwrite.count = fs->fs_llformat.availbytes;
       readwrite.buffer = (uint8_t *)fs->fs_rwbuffer;
       readwrite.offset = 0;
@@ -1300,12 +1341,12 @@ static int smartfs_readdir(FAR struct inode *mountpt,
 
       /* Now search for entries, starting at curroffset */
 
-      while (dir->u.smartfs.fs_curroffset < ret)
+      while (sdir->fs_curroffset < ret)
         {
           /* Point to next entry */
 
           entry = (struct smartfs_entry_header_s *) &fs->fs_rwbuffer[
-            dir->u.smartfs.fs_curroffset];
+            sdir->fs_curroffset];
 
           /* Test if this entry is valid and active */
 
@@ -1316,9 +1357,9 @@ static int smartfs_readdir(FAR struct inode *mountpt,
             {
               /* This entry isn't valid, skip it */
 
-              dir->u.smartfs.fs_curroffset += entrysize;
+              sdir->fs_curroffset += entrysize;
               entry = (struct smartfs_entry_header_s *)
-                &fs->fs_rwbuffer[dir->u.smartfs.fs_curroffset];
+                &fs->fs_rwbuffer[sdir->fs_curroffset];
 
               continue;
             }
@@ -1341,16 +1382,16 @@ static int smartfs_readdir(FAR struct inode *mountpt,
 
           /* Now advance to the next entry */
 
-          dir->u.smartfs.fs_curroffset += entrysize;
-          if (dir->u.smartfs.fs_curroffset + entrysize >=
+          sdir->fs_curroffset += entrysize;
+          if (sdir->fs_curroffset + entrysize >=
                 fs->fs_llformat.availbytes)
             {
               /* We advanced past the end of the sector.  Go to next sector */
 
-              dir->u.smartfs.fs_curroffset =
+              sdir->fs_curroffset =
                 sizeof(struct smartfs_chain_header_s);
               header = (struct smartfs_chain_header_s *) fs->fs_rwbuffer;
-              dir->u.smartfs.fs_currsector = SMARTFS_NEXTSECTOR(header);
+              sdir->fs_currsector = SMARTFS_NEXTSECTOR(header);
             }
 
           /* Now exit */
@@ -1365,8 +1406,8 @@ static int smartfs_readdir(FAR struct inode *mountpt,
        */
 
       header = (struct smartfs_chain_header_s *) fs->fs_rwbuffer;
-      dir->u.smartfs.fs_curroffset = sizeof(struct smartfs_chain_header_s);
-      dir->u.smartfs.fs_currsector = SMARTFS_NEXTSECTOR(header);
+      sdir->fs_curroffset = sizeof(struct smartfs_chain_header_s);
+      sdir->fs_currsector = SMARTFS_NEXTSECTOR(header);
     }
 
   /* If we arrive here, then there are no more entries */
@@ -1387,7 +1428,7 @@ errout_with_semaphore:
 
 static int smartfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
 {
-  int ret = OK;
+  FAR struct smartfs_dir_s *sdir = (FAR struct smartfs_dir_s *)dir;
 
   /* Sanity checks */
 
@@ -1395,10 +1436,10 @@ static int smartfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
 
   /* Reset the directory to the first entry */
 
-  dir->u.smartfs.fs_currsector = dir->u.smartfs.fs_firstsector;
-  dir->u.smartfs.fs_curroffset = sizeof(struct smartfs_chain_header_s);
+  sdir->fs_currsector = sdir->fs_firstsector;
+  sdir->fs_curroffset = sizeof(struct smartfs_chain_header_s);
 
-  return ret;
+  return 0;
 }
 
 /****************************************************************************
diff --git a/fs/spiffs/src/spiffs_vfs.c b/fs/spiffs/src/spiffs_vfs.c
index de4cc8797e..fb857a0a5b 100644
--- a/fs/spiffs/src/spiffs_vfs.c
+++ b/fs/spiffs/src/spiffs_vfs.c
@@ -50,7 +50,6 @@
 #include <stdint.h>
 #include <string.h>
 #include <fcntl.h>
-#include <dirent.h>
 #include <errno.h>
 #include <assert.h>
 #include <queue.h>
@@ -59,7 +58,6 @@
 
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/fs/ioctl.h>
 
 #include "spiffs.h"
@@ -75,6 +73,17 @@
 #define spiffs_lock_volume(fs)       (nxrmutex_lock(&fs->lock))
 #define spiffs_unlock_volume(fs)     (nxrmutex_unlock(&fs->lock))
 
+/****************************************************************************
+ * Private Type
+ ****************************************************************************/
+
+struct spiffs_dir_s
+{
+  struct fs_dirent_s base;
+  int16_t block;
+  int entry;
+};
+
 /****************************************************************************
  * Private Function Prototypes
  ****************************************************************************/
@@ -97,10 +106,9 @@ static int  spiffs_fstat(FAR const struct file *filep, FAR struct stat *buf);
 static int  spiffs_truncate(FAR struct file *filep, off_t length);
 
 static int  spiffs_opendir(FAR struct inode *mountpt,
-              FAR const char *relpath, FAR struct fs_dirent_s *dir);
+              FAR const char *relpath, FAR struct fs_dirent_s **dir);
 static int  spiffs_closedir(FAR struct inode *mountpt,
-              FAR struct fs_dirent_s *dir,
-              FAR struct dirent *entry);
+              FAR struct fs_dirent_s *dir);
 static int  spiffs_readdir(FAR struct inode *mountpt,
               FAR struct fs_dirent_s *dir,
               FAR struct dirent *dentry);
@@ -1244,17 +1252,26 @@ static int spiffs_truncate(FAR struct file *filep, off_t length)
  ****************************************************************************/
 
 static int spiffs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
-                         FAR struct fs_dirent_s *dir)
+                          FAR struct fs_dirent_s **dir)
 {
+  FAR struct spiffs_dir_s *sdir;
+
   finfo("mountpt=%p relpath=%s dir=%p\n",
         mountpt, relpath, dir);
 
   DEBUGASSERT(mountpt != NULL && relpath != NULL && dir != NULL);
 
+  sdir = kmm_zalloc(sizeof(*sdir));
+  if (sdir == NULL)
+    {
+      return -ENOMEM;
+    }
+
   /* Initialize for traversal of the 'directory' */
 
-  dir->u.spiffs.block   = 0;
-  dir->u.spiffs.entry   = 0;
+  sdir->block = 0;
+  sdir->entry = 0;
+  *dir        = &sdir->base;
   return OK;
 }
 
@@ -1263,13 +1280,11 @@ static int spiffs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
  ****************************************************************************/
 
 static int spiffs_closedir(FAR struct inode *mountpt,
-                          FAR struct fs_dirent_s *dir)
+                           FAR struct fs_dirent_s *dir)
 {
   finfo("mountpt=%p dir=%p\n",  mountpt, dir);
   DEBUGASSERT(mountpt != NULL && dir != NULL);
-
-  /* There is nothing to be done */
-
+  kmm_free(dir);
   return OK;
 }
 
@@ -1281,6 +1296,7 @@ static int spiffs_readdir(FAR struct inode *mountpt,
                           FAR struct fs_dirent_s *dir,
                           FAR struct dirent *dentry)
 {
+  FAR struct spiffs_dir_s *sdir;
   FAR struct spiffs_s *fs;
   int16_t blkndx;
   int entry;
@@ -1289,6 +1305,8 @@ static int spiffs_readdir(FAR struct inode *mountpt,
   finfo("mountpt=%p dir=%p\n",  mountpt, dir);
   DEBUGASSERT(mountpt != NULL && dir != NULL);
 
+  sdir = (FAR struct spiffs_dir_s *)dir;
+
   /* Get the mountpoint private data from the inode structure */
 
   fs = mountpt->i_private;
@@ -1300,13 +1318,13 @@ static int spiffs_readdir(FAR struct inode *mountpt,
 
   /* And visit the next file object */
 
-  ret = spiffs_foreach_objlu(fs, dir->u.spiffs.block, dir->u.spiffs.entry,
+  ret = spiffs_foreach_objlu(fs, sdir->block, sdir->entry,
                              SPIFFS_VIS_NO_WRAP, 0, spiffs_readdir_callback,
                              NULL, dentry, &blkndx, &entry);
   if (ret >= 0)
     {
-      dir->u.spiffs.block = blkndx;
-      dir->u.spiffs.entry = entry + 1;
+      sdir->block = blkndx;
+      sdir->entry = entry + 1;
     }
 
   /* Release the lock on the file system */
@@ -1322,13 +1340,17 @@ static int spiffs_readdir(FAR struct inode *mountpt,
 static int spiffs_rewinddir(FAR struct inode *mountpt,
                            FAR struct fs_dirent_s *dir)
 {
+  FAR struct spiffs_dir_s *sdir;
+
   finfo("mountpt=%p dir=%p\n",  mountpt, dir);
   DEBUGASSERT(mountpt != NULL && dir != NULL);
 
+  sdir = (FAR struct spiffs_dir_s *)dir;
+
   /* Reset as when opendir() was called. */
 
-  dir->u.spiffs.block   = 0;
-  dir->u.spiffs.entry   = 0;
+  sdir->block = 0;
+  sdir->entry = 0;
 
   return OK;
 }
diff --git a/fs/tmpfs/fs_tmpfs.c b/fs/tmpfs/fs_tmpfs.c
index 8ea2e1d7f5..e6fb66394a 100644
--- a/fs/tmpfs/fs_tmpfs.c
+++ b/fs/tmpfs/fs_tmpfs.c
@@ -29,14 +29,12 @@
 #include <stdint.h>
 #include <string.h>
 #include <fcntl.h>
-#include <dirent.h>
 #include <errno.h>
 #include <assert.h>
 #include <debug.h>
 
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/fs/ioctl.h>
 
 #include "fs_tmpfs.h"
@@ -72,6 +70,17 @@
 #define tmpfs_unlock_directory(tdo) \
            nxrmutex_unlock(&tdo->tdo_lock)
 
+/****************************************************************************
+ * Private Type
+ ****************************************************************************/
+
+struct tmpfs_dir_s
+{
+  struct fs_dirent_s tf_base;           /* Vfs directory structure */
+  FAR struct tmpfs_directory_s *tf_tdo; /* Directory being enumerated */
+  unsigned int tf_index;                /* Directory index */
+};
+
 /****************************************************************************
  * Private Function Prototypes
  ****************************************************************************/
@@ -132,7 +141,7 @@ static int  tmpfs_fstat(FAR const struct file *filep, FAR struct stat *buf);
 static int  tmpfs_truncate(FAR struct file *filep, off_t length);
 
 static int  tmpfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
-              FAR struct fs_dirent_s *dir);
+              FAR struct fs_dirent_s **dir);
 static int  tmpfs_closedir(FAR struct inode *mountpt,
               FAR struct fs_dirent_s *dir);
 static int  tmpfs_readdir(FAR struct inode *mountpt,
@@ -1802,9 +1811,10 @@ errout_with_lock:
  ****************************************************************************/
 
 static int tmpfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
-                         FAR struct fs_dirent_s *dir)
+                         FAR struct fs_dirent_s **dir)
 {
   FAR struct tmpfs_s *fs;
+  FAR struct tmpfs_dir_s *tdir;
   FAR struct tmpfs_directory_s *tdo;
   int ret;
 
@@ -1817,11 +1827,18 @@ static int tmpfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
   fs = mountpt->i_private;
   DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL);
 
+  tdir = kmm_zalloc(sizeof(*tdir));
+  if (tdir == NULL)
+    {
+      return -ENOMEM;
+    }
+
   /* Get exclusive access to the file system */
 
   ret = tmpfs_lock(fs);
   if (ret < 0)
     {
+      kmm_free(tdir);
       return ret;
     }
 
@@ -1839,8 +1856,8 @@ static int tmpfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
   ret = tmpfs_find_directory(fs, relpath, strlen(relpath), &tdo, NULL);
   if (ret >= 0)
     {
-      dir->u.tmpfs.tf_tdo   = tdo;
-      dir->u.tmpfs.tf_index = tdo->tdo_nentries;
+      tdir->tf_tdo   = tdo;
+      tdir->tf_index = tdo->tdo_nentries;
 
       tmpfs_unlock_directory(tdo);
     }
@@ -1848,6 +1865,7 @@ static int tmpfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
   /* Release the lock on the file system and return the result */
 
   tmpfs_unlock(fs);
+  *dir = &tdir->tf_base;
   return ret;
 }
 
@@ -1865,7 +1883,7 @@ static int tmpfs_closedir(FAR struct inode *mountpt,
 
   /* Get the directory structure from the dir argument */
 
-  tdo = dir->u.tmpfs.tf_tdo;
+  tdo = ((FAR struct tmpfs_dir_s *)dir)->tf_tdo;
   DEBUGASSERT(tdo != NULL);
 
   /* Decrement the reference count on the directory object */
@@ -1873,6 +1891,7 @@ static int tmpfs_closedir(FAR struct inode *mountpt,
   tmpfs_lock_directory(tdo);
   tdo->tdo_refs--;
   tmpfs_unlock_directory(tdo);
+  kmm_free(dir);
   return OK;
 }
 
@@ -1885,6 +1904,7 @@ static int tmpfs_readdir(FAR struct inode *mountpt,
                          FAR struct dirent *entry)
 {
   FAR struct tmpfs_directory_s *tdo;
+  FAR struct tmpfs_dir_s *tdir;
   unsigned int index;
   int ret;
 
@@ -1893,14 +1913,15 @@ static int tmpfs_readdir(FAR struct inode *mountpt,
 
   /* Get the directory structure from the dir argument and lock it */
 
-  tdo = dir->u.tmpfs.tf_tdo;
+  tdir = (FAR struct tmpfs_dir_s *)dir;
+  tdo = tdir->tf_tdo;
   DEBUGASSERT(tdo != NULL);
 
   tmpfs_lock_directory(tdo);
 
   /* Have we reached the end of the directory? */
 
-  index = dir->u.tmpfs.tf_index;
+  index = tdir->tf_index;
   if (index-- == 0)
     {
       /* We signal the end of the directory by returning the special error:
@@ -1940,7 +1961,7 @@ static int tmpfs_readdir(FAR struct inode *mountpt,
 
       /* Save the index for next time */
 
-      dir->u.tmpfs.tf_index = index;
+      tdir->tf_index = index;
       ret = OK;
     }
 
@@ -1956,18 +1977,20 @@ static int tmpfs_rewinddir(FAR struct inode *mountpt,
                            FAR struct fs_dirent_s *dir)
 {
   FAR struct tmpfs_directory_s *tdo;
+  FAR struct tmpfs_dir_s *tdir;
 
   finfo("mountpt: %p dir: %p\n",  mountpt, dir);
   DEBUGASSERT(mountpt != NULL && dir != NULL);
 
   /* Get the directory structure from the dir argument and lock it */
 
-  tdo = dir->u.tmpfs.tf_tdo;
+  tdir = (FAR struct tmpfs_dir_s *)dir;
+  tdo = tdir->tf_tdo;
   DEBUGASSERT(tdo != NULL);
 
   /* Set the readdir index pass the end */
 
-  dir->u.tmpfs.tf_index = tdo->tdo_nentries;
+  tdir->tf_index = tdo->tdo_nentries;
   return OK;
 }
 
diff --git a/fs/unionfs/fs_unionfs.c b/fs/unionfs/fs_unionfs.c
index 37e77e4c13..7d3e22019b 100644
--- a/fs/unionfs/fs_unionfs.c
+++ b/fs/unionfs/fs_unionfs.c
@@ -42,7 +42,6 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/unionfs.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/fs/ioctl.h>
 #include <nuttx/semaphore.h>
 
@@ -63,6 +62,16 @@
  * Private Types
  ****************************************************************************/
 
+struct unionfs_dir_s
+{
+  struct fs_dirent_s fu_base;          /* Vfs directory structure */
+  uint8_t fu_ndx;                      /* Index of file system being enumerated */
+  bool fu_eod;                         /* True: At end of directory */
+  bool fu_prefix[2];                   /* True: Fake directory in prefix */
+  FAR char *fu_relpath;                /* Path being enumerated */
+  FAR struct fs_dirent_s *fu_lower[2]; /* dirent struct used by contained file system */
+};
+
 /* This structure describes one contained file system mountpoint */
 
 struct unionfs_mountpt_s
@@ -107,7 +116,7 @@ static int     unionfs_tryopen(FAR struct file *filep,
                  mode_t mode);
 static int     unionfs_tryopendir(FAR struct inode *inode,
                  FAR const char *relpath, FAR const char *prefix,
-                 FAR struct fs_dirent_s *dir);
+                 FAR struct fs_dirent_s **dir);
 static int     unionfs_trymkdir(FAR struct inode *inode,
                  FAR const char *relpath, FAR const char *prefix,
                  mode_t mode);
@@ -159,7 +168,7 @@ static int     unionfs_truncate(FAR struct file *filep, off_t length);
 /* Operations on directories */
 
 static int     unionfs_opendir(struct inode *mountpt, const char *relpath,
-                 FAR struct fs_dirent_s *dir);
+                 FAR struct fs_dirent_s **dir);
 static int     unionfs_closedir(FAR struct inode *mountpt,
                  FAR struct fs_dirent_s *dir);
 static int     unionfs_readdir(FAR struct inode *mountpt,
@@ -427,7 +436,7 @@ static int unionfs_tryopen(FAR struct file *filep, FAR const char *relpath,
 static int unionfs_tryopendir(FAR struct inode *inode,
                               FAR const char *relpath,
                               FAR const char *prefix,
-                              FAR struct fs_dirent_s *dir)
+                              FAR struct fs_dirent_s **dir)
 {
   FAR const struct mountpt_operations *ops;
   FAR const char *trypath;
@@ -1411,13 +1420,11 @@ static int unionfs_truncate(FAR struct file *filep, off_t length)
 
 static int unionfs_opendir(FAR struct inode *mountpt,
                            FAR const char *relpath,
-                           FAR struct fs_dirent_s *dir)
+                           FAR struct fs_dirent_s **dir)
 {
   FAR struct unionfs_inode_s *ui;
   FAR struct unionfs_mountpt_s *um;
-  FAR struct fs_unionfsdir_s *fu;
-  FAR const struct mountpt_operations *ops;
-  FAR struct fs_dirent_s *lowerdir;
+  FAR struct unionfs_dir_s *udir;
   int ret;
 
   finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
@@ -1432,16 +1439,21 @@ static int unionfs_opendir(FAR struct inode *mountpt,
   DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
   ui = (FAR struct unionfs_inode_s *)mountpt->i_private;
 
+  udir = kmm_zalloc(sizeof(*udir));
+  if (udir == NULL)
+    {
+      return -ENOMEM;
+    }
+
   /* Get exclusive access to the file system data structures */
 
   ret = unionfs_semtake(ui, false);
   if (ret < 0)
     {
-      return ret;
+      goto errout_with_udir;
     }
 
   DEBUGASSERT(dir);
-  fu = &dir->u.unionfs;
 
   /* Clone the path.  We will need this when we traverse file system 2 to
    * omit duplicates on file system 1.
@@ -1449,44 +1461,24 @@ static int unionfs_opendir(FAR struct inode *mountpt,
 
   if (strlen(relpath) > 0)
     {
-      fu->fu_relpath = strdup(relpath);
-      if (!fu->fu_relpath)
+      udir->fu_relpath = strdup(relpath);
+      if (!udir->fu_relpath)
         {
           goto errout_with_semaphore;
         }
     }
 
-  /* Allocate another dirent structure for the lower file system */
-
-  lowerdir = (FAR struct fs_dirent_s *)
-    kmm_zalloc(sizeof(struct fs_dirent_s));
-  if (lowerdir == NULL)
-    {
-      ret = -ENOMEM;
-      goto errout_with_relpath;
-    }
-
   /* Check file system 2 first. */
 
   um = &ui->ui_fs[1];
-  lowerdir->fd_root = um->um_node;
-  ret = unionfs_tryopendir(um->um_node, relpath, um->um_prefix, lowerdir);
+  ret = unionfs_tryopendir(um->um_node, relpath, um->um_prefix,
+                           &udir->fu_lower[1]);
   if (ret >= 0)
     {
       /* Save the file system 2 access info */
 
-      fu->fu_ndx = 1;
-      fu->fu_lower[1] = lowerdir;
-
-      /* Allocate yet another dirent structure for the lower file system 1 */
-
-      lowerdir = (FAR struct fs_dirent_s *)
-        kmm_zalloc(sizeof(struct fs_dirent_s));
-      if (lowerdir == NULL)
-        {
-          ret = -ENOMEM;
-          goto errout_with_fs2open;
-        }
+      udir->fu_ndx = 1;
+      udir->fu_lower[1]->fd_root = um->um_node;
     }
 
   /* Check if the user is stat'ing some "fake" node between the unionfs root
@@ -1497,30 +1489,24 @@ static int unionfs_opendir(FAR struct inode *mountpt,
     {
       /* File system 2 prefix includes this relpath */
 
-      fu->fu_ndx = 1;
-      fu->fu_prefix[1] = true;
+      udir->fu_ndx = 1;
+      udir->fu_prefix[1] = true;
     }
 
   /* Check file system 1 last, possibly overwriting fu_ndx */
 
   um = &ui->ui_fs[0];
-  lowerdir->fd_root = um->um_node;
-  ret = unionfs_tryopendir(um->um_node, relpath, um->um_prefix, lowerdir);
+  ret = unionfs_tryopendir(um->um_node, relpath, um->um_prefix,
+                           &udir->fu_lower[0]);
   if (ret >= 0)
     {
       /* Save the file system 1 access info */
 
-      fu->fu_ndx = 0;
-      fu->fu_lower[0] = lowerdir;
+      udir->fu_ndx = 0;
+      udir->fu_lower[0]->fd_root = um->um_node;
     }
   else
     {
-      /* File system 1 was not opened... then we won't be needing that last
-       * localdir allocation after all.
-       */
-
-      kmm_free(lowerdir);
-
       /* Check if the user is stat'ing some "fake" node between the unionfs
        * root and the file system 1 root directory.
        */
@@ -1531,16 +1517,16 @@ static int unionfs_opendir(FAR struct inode *mountpt,
            * one
            */
 
-          fu->fu_ndx = 0;
-          fu->fu_prefix[0] = true;
-          fu->fu_prefix[1] = false;
+          udir->fu_ndx = 0;
+          udir->fu_prefix[0] = true;
+          udir->fu_prefix[1] = false;
         }
 
       /* If the directory was not found on either file system, then we have
        * failed to open this path on either file system.
        */
 
-      else if (fu->fu_lower[1] == NULL && !fu->fu_prefix[1])
+      else if (udir->fu_lower[1] == NULL && !udir->fu_prefix[1])
         {
           /* Neither of the two path file systems include this relpath */
 
@@ -1555,26 +1541,20 @@ static int unionfs_opendir(FAR struct inode *mountpt,
   DEBUGASSERT(ui->ui_nopen > 0);
 
   unionfs_semgive(ui);
+  *dir = &udir->fu_base;
   return OK;
 
-errout_with_fs2open:
-  ops = ui->ui_fs[1].um_node->u.i_mops;
-  DEBUGASSERT(ops != NULL);
-  if (ops->closedir != NULL)
-    {
-      ret = ops->closedir(um->um_node, fu->fu_lower[1]);
-    }
-
-  kmm_free(fu->fu_lower[1]);
-
 errout_with_relpath:
-  if (fu->fu_relpath != NULL)
+  if (udir->fu_relpath != NULL)
     {
-      kmm_free(fu->fu_relpath);
+      kmm_free(udir->fu_relpath);
     }
 
 errout_with_semaphore:
   unionfs_semgive(ui);
+
+errout_with_udir:
+  kmm_free(udir);
   return ret;
 }
 
@@ -1588,7 +1568,7 @@ static int unionfs_closedir(FAR struct inode *mountpt,
   FAR struct unionfs_inode_s *ui;
   FAR struct unionfs_mountpt_s *um;
   FAR const struct mountpt_operations *ops;
-  FAR struct fs_unionfsdir_s *fu;
+  FAR struct unionfs_dir_s *udir;
   int ret = OK;
   int i;
 
@@ -1608,7 +1588,7 @@ static int unionfs_closedir(FAR struct inode *mountpt,
     }
 
   DEBUGASSERT(dir);
-  fu = &dir->u.unionfs;
+  udir = (FAR struct unionfs_dir_s *)dir;
 
   /* Close both contained file systems */
 
@@ -1616,7 +1596,7 @@ static int unionfs_closedir(FAR struct inode *mountpt,
     {
       /* Was this file system opened? */
 
-      if (fu->fu_lower[i] != NULL)
+      if (udir->fu_lower[i] != NULL)
         {
           um = &ui->ui_fs[i];
 
@@ -1628,26 +1608,22 @@ static int unionfs_closedir(FAR struct inode *mountpt,
 
           if (ops->closedir != NULL)
             {
-              ret = ops->closedir(um->um_node, fu->fu_lower[i]);
+              ret = ops->closedir(um->um_node, udir->fu_lower[i]);
             }
-
-          /* Free the lower dirent structure */
-
-          kmm_free(fu->fu_lower[i]);
         }
     }
 
   /* Free any allocated path */
 
-  if (fu->fu_relpath != NULL)
+  if (udir->fu_relpath != NULL)
     {
-      kmm_free(fu->fu_relpath);
+      kmm_free(udir->fu_relpath);
     }
 
-  fu->fu_ndx      = 0;
-  fu->fu_relpath  = NULL;
-  fu->fu_lower[0] = NULL;
-  fu->fu_lower[1] = NULL;
+  udir->fu_ndx      = 0;
+  udir->fu_relpath  = NULL;
+  udir->fu_lower[0] = NULL;
+  udir->fu_lower[1] = NULL;
 
   /* Decrement the count of open reference.  If that count would go to zero
    * and if the file system has been unmounted, then destroy the file system
@@ -1678,7 +1654,7 @@ static int unionfs_readdir(FAR struct inode *mountpt,
   FAR struct unionfs_mountpt_s *um;
   FAR struct unionfs_mountpt_s *um0;
   FAR const struct mountpt_operations *ops;
-  FAR struct fs_unionfsdir_s *fu;
+  FAR struct unionfs_dir_s *udir;
   FAR char *relpath;
   struct stat buf;
   bool duplicate;
@@ -1690,11 +1666,11 @@ static int unionfs_readdir(FAR struct inode *mountpt,
   ui = (FAR struct unionfs_inode_s *)mountpt->i_private;
 
   DEBUGASSERT(dir);
-  fu = &dir->u.unionfs;
+  udir = (FAR struct unionfs_dir_s *)dir;
 
   /* Check if we are at the end of the directory listing. */
 
-  if (fu->fu_eod)
+  if (udir->fu_eod)
     {
       /* End of file and error conditions are not distinguishable
        * with readdir.  Here we return -ENOENT to signal the end
@@ -1704,16 +1680,17 @@ static int unionfs_readdir(FAR struct inode *mountpt,
       return -ENOENT;
     }
 
-  DEBUGASSERT(fu->fu_ndx == 0 || fu->fu_ndx == 1);
-  um = &ui->ui_fs[fu->fu_ndx];
+  DEBUGASSERT(udir->fu_ndx == 0 || udir->fu_ndx == 1);
+  um = &ui->ui_fs[udir->fu_ndx];
 
   /* Special case: If the open directory is a 'fake' node in the prefix on
    * one of the mounted file system, then we must also fake the return value.
    */
 
-  if (fu->fu_prefix[fu->fu_ndx])
+  if (udir->fu_prefix[udir->fu_ndx])
     {
-      DEBUGASSERT(fu->fu_lower[fu->fu_ndx] == NULL && um->um_prefix != NULL);
+      DEBUGASSERT(udir->fu_lower[udir->fu_ndx] == NULL &&
+                  um->um_prefix != NULL);
 
       /* Copy the file system offset into the dirent structure.
        * REVISIT:  This will not handle the case where the prefix contains
@@ -1729,17 +1706,18 @@ static int unionfs_readdir(FAR struct inode *mountpt,
 
       /* Increment the index to file system 2 (maybe) */
 
-      if (fu->fu_ndx == 0 && (fu->fu_prefix[1] || fu->fu_lower[1] != NULL))
+      if (udir->fu_ndx == 0 && (udir->fu_prefix[1] ||
+                                udir->fu_lower[1] != NULL))
         {
           /* Yes.. set up to do file system 2 next time */
 
-          fu->fu_ndx++;
+          udir->fu_ndx++;
         }
       else
         {
           /* No.. we are finished */
 
-          fu->fu_eod = true;
+          udir->fu_eod = true;
         }
 
       return OK;
@@ -1747,11 +1725,11 @@ static int unionfs_readdir(FAR struct inode *mountpt,
 
   /* This is a normal, mediated file system readdir() */
 
-  DEBUGASSERT(fu->fu_lower[fu->fu_ndx] != NULL);
+  DEBUGASSERT(udir->fu_lower[udir->fu_ndx] != NULL);
   DEBUGASSERT(um->um_node != NULL && um->um_node->u.i_mops != NULL);
   ops = um->um_node->u.i_mops;
 
-  finfo("fu_ndx: %d\n", fu->fu_ndx);
+  finfo("fu_ndx: %d\n", udir->fu_ndx);
 
   /* Perform the lower level readdir operation */
 
@@ -1763,7 +1741,8 @@ static int unionfs_readdir(FAR struct inode *mountpt,
         {
           /* Read the directory entry */
 
-          ret = ops->readdir(um->um_node, fu->fu_lower[fu->fu_ndx], entry);
+          ret = ops->readdir(um->um_node, udir->fu_lower[udir->fu_ndx],
+                             entry);
 
           /* Did the read operation fail because we reached the end of the
            * directory?  In that case, the error would be -ENOENT.  If we
@@ -1771,20 +1750,20 @@ static int unionfs_readdir(FAR struct inode *mountpt,
            * move to the second file system (if there is one).
            */
 
-          if (ret == -ENOENT && fu->fu_ndx == 0)
+          if (ret == -ENOENT && udir->fu_ndx == 0)
             {
               /* Special case: If the open directory is a 'fake' node in the
                * prefix on file system2, then we must also fake the return
                * value.
                */
 
-              if (fu->fu_prefix[1])
+              if (udir->fu_prefix[1])
                 {
-                  DEBUGASSERT(fu->fu_lower[1] == NULL);
+                  DEBUGASSERT(udir->fu_lower[1] == NULL);
 
                   /* Switch to the second file system */
 
-                  fu->fu_ndx = 1;
+                  udir->fu_ndx = 1;
                   um = &ui->ui_fs[1];
 
                   DEBUGASSERT(um != NULL && um->um_prefix != NULL);
@@ -1804,13 +1783,13 @@ static int unionfs_readdir(FAR struct inode *mountpt,
 
                   /* Mark the end of the directory listing */
 
-                  fu->fu_eod = true;
+                  udir->fu_eod = true;
 
                   /* Check if have already reported something of this name
                    * in file system 1.
                    */
 
-                  relpath = unionfs_relpath(fu->fu_relpath, um->um_prefix);
+                  relpath = unionfs_relpath(udir->fu_relpath, um->um_prefix);
                   if (relpath)
                     {
                       int tmp;
@@ -1845,11 +1824,11 @@ static int unionfs_readdir(FAR struct inode *mountpt,
 
               /* No.. check for a normal directory access */
 
-              else if (fu->fu_lower[1] != NULL)
+              else if (udir->fu_lower[1] != NULL)
                 {
                   /* Switch to the second file system */
 
-                  fu->fu_ndx = 1;
+                  udir->fu_ndx = 1;
                   um = &ui->ui_fs[1];
 
                   DEBUGASSERT(um != NULL && um->um_node != NULL &&
@@ -1863,7 +1842,7 @@ static int unionfs_readdir(FAR struct inode *mountpt,
 
                   if (ops->rewinddir != NULL)
                     {
-                      ret = ops->rewinddir(um->um_node, fu->fu_lower[1]);
+                      ret = ops->rewinddir(um->um_node, udir->fu_lower[1]);
                       if (ret < 0)
                         {
                           return ret;
@@ -1872,7 +1851,7 @@ static int unionfs_readdir(FAR struct inode *mountpt,
 
                   /* Then try the read operation again */
 
-                  ret = ops->readdir(um->um_node, fu->fu_lower[1], entry);
+                  ret = ops->readdir(um->um_node, udir->fu_lower[1], entry);
                 }
             }
 
@@ -1883,14 +1862,14 @@ static int unionfs_readdir(FAR struct inode *mountpt,
            */
 
           duplicate = false;
-          if (ret >= 0 && fu->fu_ndx == 1 && fu->fu_lower[0] != NULL)
+          if (ret >= 0 && udir->fu_ndx == 1 && udir->fu_lower[0] != NULL)
             {
               /* Get the relative path to the same file on file system 1.
                * NOTE: the on any failures we just assume that the filep
                * is not a duplicate.
                */
 
-              relpath = unionfs_relpath(fu->fu_relpath, entry->d_name);
+              relpath = unionfs_relpath(udir->fu_relpath, entry->d_name);
               if (relpath)
                 {
                   int tmp;
@@ -1931,7 +1910,7 @@ static int unionfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
   FAR struct unionfs_inode_s *ui;
   FAR struct unionfs_mountpt_s *um;
   FAR const struct mountpt_operations *ops;
-  FAR struct fs_unionfsdir_s *fu;
+  FAR struct unionfs_dir_s *udir;
   int ret = -EINVAL;
 
   finfo("mountpt=%p dir=%p\n", mountpt, dir);
@@ -1942,24 +1921,24 @@ static int unionfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
   ui = (FAR struct unionfs_inode_s *)mountpt->i_private;
 
   DEBUGASSERT(dir);
-  fu = &dir->u.unionfs;
+  udir = (FAR struct unionfs_dir_s *)dir;
 
   /* Were we currently enumerating on file system 1?  If not, is an
    * enumeration possible on file system 1?
    */
 
-  DEBUGASSERT(fu->fu_ndx == 0 || fu->fu_ndx == 1);
-  if (/* fu->fu_ndx != 0 && */ fu->fu_prefix[0] || fu->fu_lower[0] != NULL)
+  DEBUGASSERT(udir->fu_ndx == 0 || udir->fu_ndx == 1);
+  if (/* udir->fu_ndx != 0 && */ udir->fu_prefix[0] || udir->fu_lower[0] != NULL)
     {
       /* Yes.. switch to file system 1 */
 
-      fu->fu_ndx = 0;
+      udir->fu_ndx = 0;
     }
 
-  if (!fu->fu_prefix[fu->fu_ndx])
+  if (!udir->fu_prefix[udir->fu_ndx])
     {
-      DEBUGASSERT(fu->fu_lower[fu->fu_ndx] != NULL);
-      um = &ui->ui_fs[fu->fu_ndx];
+      DEBUGASSERT(udir->fu_lower[udir->fu_ndx] != NULL);
+      um = &ui->ui_fs[udir->fu_ndx];
 
       DEBUGASSERT(um != NULL && um->um_node != NULL &&
                   um->um_node->u.i_mops != NULL);
@@ -1969,7 +1948,7 @@ static int unionfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
 
       if (ops->rewinddir != NULL)
         {
-          ret = ops->rewinddir(um->um_node, fu->fu_lower[fu->fu_ndx]);
+          ret = ops->rewinddir(um->um_node, udir->fu_lower[udir->fu_ndx]);
         }
     }
 
diff --git a/fs/userfs/fs_userfs.c b/fs/userfs/fs_userfs.c
index 83577a70df..81bf34b154 100644
--- a/fs/userfs/fs_userfs.c
+++ b/fs/userfs/fs_userfs.c
@@ -43,7 +43,6 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/userfs.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/fs/ioctl.h>
 #include <nuttx/net/net.h>
 #include <nuttx/semaphore.h>
@@ -58,6 +57,12 @@
  * Private Types
  ****************************************************************************/
 
+struct userfs_dir_s
+{
+  struct fs_dirent_s base;
+  FAR void *dir;
+};
+
 /* This structure holds the internal state of the UserFS proxy */
 
 struct userfs_state_s
@@ -106,7 +111,7 @@ static int     userfs_fstat(FAR const struct file *filep,
 static int     userfs_truncate(FAR struct file *filep, off_t length);
 
 static int     userfs_opendir(FAR struct inode *mountpt,
-                 FAR const char *relpath, FAR struct fs_dirent_s *dir);
+                 FAR const char *relpath, FAR struct fs_dirent_s **dir);
 static int     userfs_closedir(FAR struct inode *mountpt,
                  FAR struct fs_dirent_s *dir);
 static int     userfs_readdir(FAR struct inode *mountpt,
@@ -1071,8 +1076,9 @@ static int userfs_truncate(FAR struct file *filep, off_t length)
  ****************************************************************************/
 
 static int userfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
-                          FAR struct fs_dirent_s *dir)
+                          FAR struct fs_dirent_s **dir)
 {
+  FAR struct userfs_dir_s *udir;
   FAR struct userfs_state_s *priv;
   FAR struct userfs_opendir_request_s *req;
   FAR struct userfs_opendir_response_s *resp;
@@ -1150,7 +1156,14 @@ static int userfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
   /* Save the opaque dir reference in struct fs_dirent_s */
 
   DEBUGASSERT(dir != NULL);
-  dir->u.userfs.fs_dir = resp->dir;
+  udir = kmm_zalloc(sizeof(struct userfs_dir_s));
+  if (udir == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  udir->dir = resp->dir;
+  *dir = (FAR struct fs_dirent_s *)udir;
   return resp->ret;
 }
 
@@ -1165,6 +1178,7 @@ static int userfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
 static int userfs_closedir(FAR struct inode *mountpt,
                            FAR struct fs_dirent_s *dir)
 {
+  FAR struct userfs_dir_s *udir;
   FAR struct userfs_state_s *priv;
   FAR struct userfs_closedir_request_s *req;
   FAR struct userfs_closedir_response_s *resp;
@@ -1175,6 +1189,7 @@ static int userfs_closedir(FAR struct inode *mountpt,
   DEBUGASSERT(mountpt != NULL &&
               mountpt->i_private != NULL);
   priv = mountpt->i_private;
+  udir = (FAR struct userfs_dir_s *)dir;
 
   /* Get exclusive access */
 
@@ -1188,7 +1203,7 @@ static int userfs_closedir(FAR struct inode *mountpt,
 
   req      = (FAR struct userfs_closedir_request_s *)priv->iobuffer;
   req->req = USERFS_REQ_CLOSEDIR;
-  req->dir = dir->u.userfs.fs_dir;
+  req->dir = udir->dir;
 
   nsent = psock_sendto(&priv->psock, priv->iobuffer,
                        sizeof(struct userfs_closedir_request_s), 0,
@@ -1226,6 +1241,7 @@ static int userfs_closedir(FAR struct inode *mountpt,
       return -EIO;
     }
 
+  kmm_free(udir);
   return resp->ret;
 }
 
@@ -1240,6 +1256,7 @@ static int userfs_readdir(FAR struct inode *mountpt,
                           FAR struct fs_dirent_s *dir,
                           FAR struct dirent *entry)
 {
+  FAR struct userfs_dir_s *udir;
   FAR struct userfs_state_s *priv;
   FAR struct userfs_readdir_request_s *req;
   FAR struct userfs_readdir_response_s *resp;
@@ -1250,6 +1267,7 @@ static int userfs_readdir(FAR struct inode *mountpt,
   DEBUGASSERT(mountpt != NULL &&
               mountpt->i_private != NULL);
   priv = mountpt->i_private;
+  udir = (FAR struct userfs_dir_s *)dir;
 
   /* Get exclusive access */
 
@@ -1263,7 +1281,7 @@ static int userfs_readdir(FAR struct inode *mountpt,
 
   req      = (FAR struct userfs_readdir_request_s *)priv->iobuffer;
   req->req = USERFS_REQ_READDIR;
-  req->dir = dir->u.userfs.fs_dir;
+  req->dir = udir->dir;
 
   nsent = psock_sendto(&priv->psock, priv->iobuffer,
                        sizeof(struct userfs_readdir_request_s), 0,
@@ -1318,6 +1336,7 @@ static int userfs_readdir(FAR struct inode *mountpt,
 static int userfs_rewinddir(FAR struct inode *mountpt,
                             FAR struct fs_dirent_s *dir)
 {
+  FAR struct userfs_dir_s *udir;
   FAR struct userfs_state_s *priv;
   FAR struct userfs_rewinddir_request_s *req;
   FAR struct userfs_rewinddir_response_s *resp;
@@ -1328,6 +1347,7 @@ static int userfs_rewinddir(FAR struct inode *mountpt,
   DEBUGASSERT(mountpt != NULL &&
               mountpt->i_private != NULL);
   priv = mountpt->i_private;
+  udir = (FAR struct userfs_dir_s *)dir;
 
   /* Get exclusive access */
 
@@ -1341,7 +1361,7 @@ static int userfs_rewinddir(FAR struct inode *mountpt,
 
   req      = (FAR struct userfs_rewinddir_request_s *)priv->iobuffer;
   req->req = USERFS_REQ_REWINDDIR;
-  req->dir = dir->u.userfs.fs_dir;
+  req->dir = udir->dir;
 
   nsent = psock_sendto(&priv->psock, priv->iobuffer,
                        sizeof(struct userfs_rewinddir_request_s), 0,
diff --git a/fs/vfs/fs_dir.c b/fs/vfs/fs_dir.c
index 2161703088..21371f32bd 100644
--- a/fs/vfs/fs_dir.c
+++ b/fs/vfs/fs_dir.c
@@ -29,10 +29,24 @@
 
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
-#include <nuttx/fs/dirent.h>
 
 #include "inode/inode.h"
 
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* For the root pseudo-file system, we need retain only the 'next' inode
+ * need for the next readdir() operation. We hold a reference on this
+ * inode so we know that it will persist until closedir is called.
+ */
+
+struct fs_pseudodir_s
+{
+  struct fs_dirent_s dir;
+  FAR struct inode *next;
+};
+
 /****************************************************************************
  * Private Functions Prototypes
  ****************************************************************************/
@@ -92,8 +106,10 @@ static struct inode g_dir_inode =
 
 #ifndef CONFIG_DISABLE_MOUNTPOINT
 static int open_mountpoint(FAR struct inode *inode, FAR const char *relpath,
-                           FAR struct fs_dirent_s *dir)
+                           FAR struct fs_dirent_s **dir)
 {
+  int ret;
+
   /* The inode itself as the 'root' of mounted volume. The actually
    * directory is at relpath into the mounted filesystem.
    *
@@ -106,9 +122,13 @@ static int open_mountpoint(FAR struct inode *inode, FAR const char *relpath,
       return -ENOSYS;
     }
 
-  dir->fd_root = inode;
+  ret = inode->u.i_mops->opendir(inode, relpath, dir);
+  if (ret >= 0)
+    {
+      (*dir)->fd_root = inode;
+    }
 
-  return inode->u.i_mops->opendir(inode, relpath, dir);
+  return ret;
 }
 #endif
 
@@ -124,16 +144,26 @@ static int open_mountpoint(FAR struct inode *inode, FAR const char *relpath,
  *   dir -- the dirent structure to be initialized
  *
  * Returned Value:
- *   None
+ *   On success, 0 is returned; Otherwise, a negative errno is returned.
  *
  ****************************************************************************/
 
-static void open_pseudodir(FAR struct inode *inode,
-                           FAR struct fs_dirent_s *dir)
+static int open_pseudodir(FAR struct inode *inode,
+                          FAR struct fs_dirent_s **dir)
 {
-  dir->fd_root          = inode;          /* Save the inode where we start */
-  dir->u.pseudo.fd_next = inode->i_child; /* The next node for readdir */
+  FAR struct fs_pseudodir_s *pdir;
+
+  pdir = kmm_zalloc(sizeof(*pdir));
+  if (pdir == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  *dir              = &pdir->dir;
+  pdir->dir.fd_root = inode;          /* Save the inode where we start */
+  pdir->next        = inode->i_child; /* This next node for readdir */
   inode_addref(inode->i_child);
+  return 0;
 }
 
 /****************************************************************************
@@ -142,7 +172,7 @@ static void open_pseudodir(FAR struct inode *inode,
 
 static off_t seek_pseudodir(FAR struct file *filep, off_t offset)
 {
-  FAR struct fs_dirent_s *dir = filep->f_priv;
+  FAR struct fs_pseudodir_s *pdir = filep->f_priv;
   FAR struct inode *curr;
   FAR struct inode *prev;
   off_t pos;
@@ -156,12 +186,12 @@ static off_t seek_pseudodir(FAR struct file *filep, off_t offset)
   if (offset < filep->f_pos)
     {
       pos  = 0;
-      curr = dir->fd_root->i_child;
+      curr = pdir->dir.fd_root->i_child;
     }
   else
     {
       pos  = filep->f_pos;
-      curr = dir->u.pseudo.fd_next;
+      curr = pdir->next;
     }
 
   /* Traverse the peer list starting at the 'root' of the
@@ -176,11 +206,11 @@ static off_t seek_pseudodir(FAR struct file *filep, off_t offset)
 
   /* Now get the inode to vist next time that readdir() is called */
 
-  prev = dir->u.pseudo.fd_next;
+  prev = pdir->next;
 
   /* The next node to visit (might be null) */
 
-  dir->u.pseudo.fd_next = curr;
+  pdir->next = curr;
   if (curr != NULL)
     {
       /* Increment the reference count on this next node */
@@ -263,11 +293,12 @@ static off_t seek_mountptdir(FAR struct file *filep, off_t offset)
 static int read_pseudodir(FAR struct fs_dirent_s *dir,
                           FAR struct dirent *entry)
 {
+  FAR struct fs_pseudodir_s *pdir = (FAR struct fs_pseudodir_s *)dir;
   FAR struct inode *prev;
 
   /* Check if we are at the end of the list */
 
-  if (dir->u.pseudo.fd_next == NULL)
+  if (pdir->next == NULL)
     {
       /* End of file and error conditions are not distinguishable with
        * readdir. Here we return -ENOENT to signal the end of the directory.
@@ -278,49 +309,48 @@ static int read_pseudodir(FAR struct fs_dirent_s *dir,
 
   /* Copy the inode name into the dirent structure */
 
-  strlcpy(entry->d_name, dir->u.pseudo.fd_next->i_name,
-          sizeof(entry->d_name));
+  strlcpy(entry->d_name, pdir->next->i_name, sizeof(entry->d_name));
 
   /* If the node has file operations, we will say that it is a file. */
 
   entry->d_type = DTYPE_UNKNOWN;
-  if (dir->u.pseudo.fd_next->u.i_ops != NULL)
+  if (pdir->next->u.i_ops != NULL)
     {
 #ifndef CONFIG_DISABLE_MOUNTPOINT
-      if (INODE_IS_BLOCK(dir->u.pseudo.fd_next))
+      if (INODE_IS_BLOCK(pdir->next))
         {
           entry->d_type = DTYPE_BLK;
         }
-      else if (INODE_IS_MTD(dir->u.pseudo.fd_next))
+      else if (INODE_IS_MTD(pdir->next))
         {
           entry->d_type = DTYPE_MTD;
         }
-      else if (INODE_IS_MOUNTPT(dir->u.pseudo.fd_next))
+      else if (INODE_IS_MOUNTPT(pdir->next))
         {
           entry->d_type = DTYPE_DIRECTORY;
         }
       else
 #endif
 #ifdef CONFIG_PSEUDOFS_SOFTLINKS
-      if (INODE_IS_SOFTLINK(dir->u.pseudo.fd_next))
+      if (INODE_IS_SOFTLINK(pdir->next))
         {
           entry->d_type = DTYPE_LINK;
         }
       else
 #endif
-      if (INODE_IS_DRIVER(dir->u.pseudo.fd_next))
+      if (INODE_IS_DRIVER(pdir->next))
         {
           entry->d_type = DTYPE_CHR;
         }
-      else if (INODE_IS_NAMEDSEM(dir->u.pseudo.fd_next))
+      else if (INODE_IS_NAMEDSEM(pdir->next))
         {
           entry->d_type = DTYPE_SEM;
         }
-      else if (INODE_IS_MQUEUE(dir->u.pseudo.fd_next))
+      else if (INODE_IS_MQUEUE(pdir->next))
         {
           entry->d_type = DTYPE_MQ;
         }
-      else if (INODE_IS_SHM(dir->u.pseudo.fd_next))
+      else if (INODE_IS_SHM(pdir->next))
         {
           entry->d_type = DTYPE_SHM;
         }
@@ -331,8 +361,8 @@ static int read_pseudodir(FAR struct fs_dirent_s *dir,
    * be both!
    */
 
-  if (dir->u.pseudo.fd_next->i_child != NULL ||
-      dir->u.pseudo.fd_next->u.i_ops == NULL)
+  if (pdir->next->i_child != NULL ||
+      pdir->next->u.i_ops == NULL)
     {
       entry->d_type = DTYPE_DIRECTORY;
     }
@@ -341,14 +371,14 @@ static int read_pseudodir(FAR struct fs_dirent_s *dir,
 
   inode_semtake();
 
-  prev                  = dir->u.pseudo.fd_next;
-  dir->u.pseudo.fd_next = prev->i_peer; /* The next node to visit */
+  prev       = pdir->next;
+  pdir->next = prev->i_peer; /* The next node to visit */
 
-  if (dir->u.pseudo.fd_next != NULL)
+  if (pdir->next != NULL)
     {
       /* Increment the reference count on this next node */
 
-      dir->u.pseudo.fd_next->i_crefs++;
+      pdir->next->i_crefs++;
     }
 
   inode_semgive();
@@ -391,13 +421,15 @@ static int dir_close(FAR struct file *filep)
   else
 #endif
     {
+      FAR struct fs_pseudodir_s *pdir = filep->f_priv;
+
       /* The node is part of the root pseudo file system, release
        * our contained reference to the 'next' inode.
        */
 
-      if (dir->u.pseudo.fd_next != NULL)
+      if (pdir->next != NULL)
         {
-          inode_release(dir->u.pseudo.fd_next);
+          inode_release(pdir->next);
         }
 
       /* Then release the container */
@@ -517,13 +549,7 @@ int dir_allocate(FAR struct file *filep, FAR const char *relpath)
 {
   FAR struct fs_dirent_s *dir;
   FAR struct inode *inode = filep->f_inode;
-  int ret = 0;
-
-  dir = kmm_zalloc(sizeof(struct fs_dirent_s));
-  if (dir == NULL)
-    {
-      return -ENOMEM;
-    }
+  int ret;
 
   /* Is this a node in the pseudo filesystem? Or a mountpoint? */
 
@@ -532,25 +558,24 @@ int dir_allocate(FAR struct file *filep, FAR const char *relpath)
     {
       /* Open the directory at the relative path */
 
-      ret = open_mountpoint(inode, relpath, dir);
+      ret = open_mountpoint(inode, relpath, &dir);
       if (ret < 0)
         {
-          goto errout_with_direntry;
+          return ret;
         }
     }
   else
 #endif
     {
-      open_pseudodir(inode, dir);
+      ret = open_pseudodir(inode, &dir);
+      if (ret < 0)
+        {
+          return ret;
+        }
     }
 
   filep->f_inode  = &g_dir_inode;
   filep->f_priv   = dir;
   inode_addref(&g_dir_inode);
-
-  return ret;
-
-errout_with_direntry:
-  kmm_free(dir);
   return ret;
 }
diff --git a/include/nuttx/fs/dirent.h b/include/nuttx/fs/dirent.h
deleted file mode 100644
index 5c4b19bcd6..0000000000
--- a/include/nuttx/fs/dirent.h
+++ /dev/null
@@ -1,348 +0,0 @@
-/****************************************************************************
- * include/nuttx/fs/dirent.h
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.  The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- ****************************************************************************/
-
-#ifndef __INCLUDE_NUTTX_FS_DIRENT_H
-#define __INCLUDE_NUTTX_FS_DIRENT_H
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <nuttx/config.h>
-
-#include <sys/types.h>
-#include <stdint.h>
-#include <dirent.h>
-
-#include <nuttx/fs/fs.h>
-
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-#ifdef CONFIG_NFS
-#  define DIRENT_NFS_MAXHANDLE 64        /* Maximum length of an NFSv3 file handle */
-#  define DIRENT_NFS_VERFLEN    8        /* Length of the copy verifier */
-#endif
-
-/****************************************************************************
- * Public Types
- ****************************************************************************/
-
-/* The internal representation of type DIR is just a container for an inode
- * reference, a position, a dirent structure, and file-system-specific
- * information.
- *
- * For the root pseudo-file system, we need retain only the 'next' inode
- * need for the next readdir() operation.  We hold a reference on this
- * inode so we know that it will persist until closedir is called.
- */
-
-struct fs_pseudodir_s
-{
-  struct inode *fd_next;             /* The inode for the next call to readdir() */
-};
-
-#ifndef CONFIG_DISABLE_MOUNTPOINT
-#ifdef CONFIG_FS_FAT
-/* For fat, we need to return the start cluster, current cluster, current
- * sector and current directory index.
- */
-
-struct fs_fatdir_s
-{
-  off_t        fd_startcluster;        /* Start cluster number of the directory */
-  off_t        fd_currcluster;         /* Current cluster number being read */
-  off_t        fd_currsector;          /* Current sector being read */
-  unsigned int fd_index;               /* Current index of the directory entry to read */
-};
-#endif /* CONFIG_FS_FAT */
-
-#ifdef CONFIG_FS_ROMFS
-#ifdef CONFIG_FS_ROMFS_CACHE_NODE
-
-/* This structure represents one entry node in the romfs file system */
-
-struct romfs_nodeinfo_s
-{
-  FAR struct romfs_nodeinfo_s **rn_child;  /* The node array for link to lower level */
-  uint16_t rn_count;                       /* The count of node in rn_child level */
-  uint32_t rn_offset;                      /* The offset to real file header of the current entry */
-  uint32_t rn_next;                        /* The offset of the next file header+flags */
-  uint32_t rn_size;                        /* The size to the entry (if file) */
-  uint8_t  rn_namesize;                    /* The length of name of the entry */
-  char rn_name[1];                         /* The name to the entry */
-};
-
-/* For ROMFS, we need to return the node to the current and start node
- * of the directory entry being read
- */
-
-struct fs_romfsdir_s
-{
-  FAR struct romfs_nodeinfo_s **fr_firstnode; /* The address of first node in the directory */
-  FAR struct romfs_nodeinfo_s **fr_currnode;  /* The address of current node into the directory */
-};
-#else
-
-/* For ROMFS, we need to return the offset to the current and start positions
- * of the directory entry being read
- */
-
-struct fs_romfsdir_s
-{
-  off_t        fr_firstoffset;         /* Offset to the first entry in the directory */
-  off_t        fr_curroffset;          /* Current offset into the directory contents */
-};
-#endif
-#endif /* CONFIG_FS_ROMFS */
-
-#ifdef CONFIG_FS_CROMFS
-/* For CROMFS, we need to return the next compressed node to be examined. */
-
-struct fs_cromfsdir_s
-{
-  uint32_t     cr_firstoffset;         /* Offset to the first entry in the directory */
-  uint32_t     cr_curroffset;          /* Current offset into the directory contents */
-};
-#endif /* CONFIG_FS_CROMFS */
-
-#ifdef CONFIG_FS_TMPFS
-/* For TMPFS, we need the directory object and an index into the directory
- * entries.
- */
-
-struct tmpfs_directory_s;               /* Forward reference */
-struct fs_tmpfsdir_s
-{
-  FAR struct tmpfs_directory_s *tf_tdo; /* Directory being enumerated */
-  unsigned int tf_index;                /* Directory index */
-};
-#endif /* CONFIG_FS_TMPFS */
-
-#ifdef CONFIG_FS_BINFS
-/* The apps/ pseudo bin/ directory.  The state value is simply an index */
-
-struct fs_binfsdir_s
-{
-  unsigned int fb_index;               /* Index to the next named entry point */
-};
-#endif
-
-#ifdef CONFIG_FS_NXFFS
-/* NXFFS is the tiny NuttX wear-leveling FLASH file system.
- * The state value is the offset in FLASH memory to the next inode entry.
- */
-
-struct fs_nxffsdir_s
-{
-  off_t nx_offset;                     /* Offset to the next inode */
-};
-#endif
-
-#ifdef CONFIG_NFS
-/* The NFS client file system */
-
-struct nfsdir_s
-{
-  uint8_t  nfs_fhsize;                        /* Length of the file handle */
-  uint8_t  nfs_fhandle[DIRENT_NFS_MAXHANDLE]; /* File handle (max size allocated) */
-  uint8_t  nfs_verifier[DIRENT_NFS_VERFLEN];  /* Cookie verifier */
-  uint32_t nfs_cookie[2];                     /* Cookie */
-};
-#endif
-
-#ifdef CONFIG_FS_SMARTFS
-/* SMARTFS is the Sector Mapped Allocation for Really Tiny FLASH filesystem.
- * it is designed to use small sectors on small serial FLASH devices, using
- * minimal RAM footprint.
- */
-
-struct fs_smartfsdir_s
-{
-  uint16_t fs_firstsector;                    /* First sector of directory list */
-  uint16_t fs_currsector;                     /* Current sector of directory list */
-  uint16_t fs_curroffset;                     /* Current offset within current sector */
-};
-#endif
-
-#ifdef CONFIG_FS_SPIFFS
-
-/* SPIFFS is an SPI-oriented FLASH file system
- * originally by Peter Andersson
- */
-
-struct fs_spiffsdir_s
-{
-  int16_t block;                               /* Current block */
-  int entry;                                   /* Current entry */
-};
-#endif
-
-#ifdef CONFIG_FS_UNIONFS
-/* The Union File System can be used to merge to different mountpoints so
- * that they appear as a single merged directory.
- */
-
-struct fs_dirent_s;                           /* Forward reference */
-struct fs_unionfsdir_s
-{
-  uint8_t fu_ndx;                             /* Index of file system being enumerated */
-  bool fu_eod;                                /* True: At end of directory */
-  bool fu_prefix[2];                          /* True: Fake directory in prefix */
-  FAR char *fu_relpath;                       /* Path being enumerated */
-  FAR struct fs_dirent_s *fu_lower[2];        /* dirent struct used by contained file system */
-};
-#endif
-
-#ifdef CONFIG_FS_USERFS
-/* The UserFS uses an opaque representation since the actual userspace
- * representation of the directory state structure is unknowable.
- */
-
-struct fs_userfsdir_s
-{
-  FAR void *fs_dir;                           /* Opaque pointer to UserFS DIR */
-};
-#endif
-
-#ifdef CONFIG_FS_HOSTFS
-/* HOSTFS provides mapping to directories on the host machine in the
- * sim environment.
- */
-
-struct fs_hostfsdir_s
-{
-  FAR void *fs_dir;                           /* Opaque pointer to host DIR */
-};
-#endif
-
-#ifdef CONFIG_FS_RPMSGFS
-/* RPMSGFS provides mapping to directories on the host machine in the
- * sim environment.
- */
-
-struct fs_rpmsgfsdir_s
-{
-  FAR void *fs_dir;                           /* Opaque pointer to remote DIR */
-};
-#endif
-
-#endif /* CONFIG_DISABLE_MOUNTPOINT */
-
-struct fs_dirent_s
-{
-  /* This is the node that was opened by opendir.  The type of the inode
-   * determines the way that the readdir() operations are performed. For the
-   * pseudo root pseudo-file system, it is also used to support rewind.
-   *
-   * We hold a reference on this inode so we know that it will persist until
-   * closedir() is called (although inodes linked to this inode may change).
-   */
-
-  struct inode *fd_root;
-
-  /* Retained control information depends on the type of file system that
-   * provides the mountpoint.  Ideally this information should
-   * be hidden behind an opaque, file-system-dependent void *, but we put
-   * the private definitions in line here for now to reduce allocations.
-   */
-
-  union
-    {
-      /* Private data used by the built-in pseudo-file system */
-
-      struct fs_pseudodir_s pseudo;
-
-      /* Private data used by other file systems */
-
-#ifndef CONFIG_DISABLE_MOUNTPOINT
-#ifdef CONFIG_FS_FAT
-      struct fs_fatdir_s     fat;
-#endif
-#ifdef CONFIG_FS_ROMFS
-      struct fs_romfsdir_s   romfs;
-#endif
-#ifdef CONFIG_FS_CROMFS
-      struct fs_cromfsdir_s  cromfs;
-#endif
-#ifdef CONFIG_FS_TMPFS
-      struct fs_tmpfsdir_s   tmpfs;
-#endif
-#ifdef CONFIG_FS_BINFS
-      struct fs_binfsdir_s   binfs;
-#endif
-#ifdef CONFIG_FS_PROCFS
-      FAR void              *procfs;
-#endif
-#ifdef CONFIG_FS_NXFFS
-      struct fs_nxffsdir_s   nxffs;
-#endif
-#ifdef CONFIG_NFS
-      struct nfsdir_s        nfs;
-#endif
-#ifdef CONFIG_FS_SMARTFS
-      struct fs_smartfsdir_s smartfs;
-#endif
-#ifdef CONFIG_FS_SPIFFS
-      struct fs_spiffsdir_s  spiffs;
-#endif
-#ifdef CONFIG_FS_LITTLEFS
-      FAR void              *littlefs;
-#endif
-#ifdef CONFIG_FS_UNIONFS
-      struct fs_unionfsdir_s unionfs;
-#endif
-#ifdef CONFIG_FS_USERFS
-      struct fs_userfsdir_s  userfs;
-#endif
-#ifdef CONFIG_FS_HOSTFS
-      struct fs_hostfsdir_s  hostfs;
-#endif
-#ifdef CONFIG_FS_RPMSGFS
-      struct fs_rpmsgfsdir_s rpmsgfs;
-#endif
-#endif /* !CONFIG_DISABLE_MOUNTPOINT */
-  } u;
-};
-
-/****************************************************************************
- * Public Data
- ****************************************************************************/
-
-/****************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-#undef EXTERN
-#if defined(__cplusplus)
-#define EXTERN extern "C"
-extern "C"
-{
-#else
-#define EXTERN extern
-#endif
-
-#undef EXTERN
-#if defined(__cplusplus)
-}
-#endif
-
-#endif /* __INCLUDE_NUTTX_FS_DIRENT_H */
diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h
index 43d9d5c9ec..032706e1be 100644
--- a/include/nuttx/fs/fs.h
+++ b/include/nuttx/fs/fs.h
@@ -174,9 +174,25 @@ struct inode;
 struct stat;
 struct statfs;
 struct pollfd;
-struct fs_dirent_s;
 struct mtd_dev_s;
 
+/* The internal representation of type DIR is just a container for an inode
+ * reference, and the path of directory.
+ */
+
+struct fs_dirent_s
+{
+  /* This is the node that was opened by opendir.  The type of the inode
+   * determines the way that the readdir() operations are performed. For the
+   * pseudo root pseudo-file system, it is also used to support rewind.
+   *
+   * We hold a reference on this inode so we know that it will persist until
+   * closedir() is called (although inodes linked to this inode may change).
+   */
+
+  FAR struct inode *fd_root;
+};
+
 /* This structure is provided by devices when they are registered with the
  * system.  It is used to call back to perform device specific operations.
  */
@@ -302,7 +318,7 @@ struct mountpt_operations
   /* Directory operations */
 
   int     (*opendir)(FAR struct inode *mountpt, FAR const char *relpath,
-            FAR struct fs_dirent_s *dir);
+            FAR struct fs_dirent_s **dir);
   int     (*closedir)(FAR struct inode *mountpt,
             FAR struct fs_dirent_s *dir);
   int     (*readdir)(FAR struct inode *mountpt,
diff --git a/include/nuttx/fs/procfs.h b/include/nuttx/fs/procfs.h
index 62e5373546..17a5da2c54 100644
--- a/include/nuttx/fs/procfs.h
+++ b/include/nuttx/fs/procfs.h
@@ -73,7 +73,7 @@ struct procfs_operations
   /* Directory operations */
 
   int     (*opendir)(FAR const char *relpath,
-                     FAR struct fs_dirent_s *dir);
+                     FAR struct fs_dirent_s **dir);
   int     (*closedir)(FAR struct fs_dirent_s *dir);
   int     (*readdir)(FAR struct fs_dirent_s *dir, FAR struct dirent *entry);
   int     (*rewinddir)(FAR struct fs_dirent_s *dir);
@@ -119,6 +119,7 @@ struct procfs_file_s
 
 struct procfs_dir_priv_s
 {
+  struct fs_dirent_s dir;                       /* VFS directory structure */
   uint8_t level;                                /* Directory level.  Currently 0 or 1 */
   uint16_t index;                               /* Index to the next directory entry */
   uint16_t nentries;                            /* Number of directory entries */
diff --git a/net/procfs/net_procfs.c b/net/procfs/net_procfs.c
index eeb5e443a8..e0e239a07b 100644
--- a/net/procfs/net_procfs.c
+++ b/net/procfs/net_procfs.c
@@ -40,7 +40,6 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/procfs.h>
-#include <nuttx/fs/dirent.h>
 #include <nuttx/net/netdev.h>
 
 #include "netdev/netdev.h"
@@ -91,7 +90,7 @@ static int     netprocfs_dup(FAR const struct file *oldp,
                  FAR struct file *newp);
 
 static int     netprocfs_opendir(FAR const char *relpath,
-                 FAR struct fs_dirent_s *dir);
+                 FAR struct fs_dirent_s **dir);
 static int     netprocfs_closedir(FAR struct fs_dirent_s *dir);
 static int     netprocfs_readdir(FAR struct fs_dirent_s *dir,
                                  FAR struct dirent *entry);
@@ -380,14 +379,14 @@ static int netprocfs_dup(FAR const struct file *oldp, FAR struct file *newp)
  ****************************************************************************/
 
 static int netprocfs_opendir(FAR const char *relpath,
-                             FAR struct fs_dirent_s *dir)
+                             FAR struct fs_dirent_s **dir)
 {
   FAR struct netprocfs_level1_s *level1;
   int ndevs;
   int ret;
 
   finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
-  DEBUGASSERT(relpath && dir && !dir->u.procfs);
+  DEBUGASSERT(relpath && dir);
 
   /* "net" and "net/route" are the only values of relpath that are
    * directories.
@@ -449,7 +448,7 @@ static int netprocfs_opendir(FAR const char *relpath,
       goto errout_with_alloc;
     }
 
-  dir->u.procfs = (FAR void *)level1;
+  *dir = (FAR struct fs_dirent_s *)level1;
   return OK;
 
 errout_with_alloc:
@@ -466,17 +465,8 @@ errout_with_alloc:
 
 static int netprocfs_closedir(FAR struct fs_dirent_s *dir)
 {
-  FAR struct netprocfs_level1_s *priv;
-
-  DEBUGASSERT(dir && dir->u.procfs);
-  priv = dir->u.procfs;
-
-  if (priv)
-    {
-      kmm_free(priv);
-    }
-
-  dir->u.procfs = NULL;
+  DEBUGASSERT(dir);
+  kmm_free(dir);
   return OK;
 }
 
@@ -495,8 +485,8 @@ static int netprocfs_readdir(FAR struct fs_dirent_s *dir,
   int index;
   int ret;
 
-  DEBUGASSERT(dir && dir->u.procfs);
-  level1 = dir->u.procfs;
+  DEBUGASSERT(dir);
+  level1 = (FAR struct netprocfs_level1_s *)dir;
   DEBUGASSERT(level1->base.level > 0);
 
   /* Are we searching this directory?  Or is it just an intermediate on the
@@ -630,8 +620,8 @@ static int netprocfs_rewinddir(FAR struct fs_dirent_s *dir)
 {
   FAR struct netprocfs_level1_s *priv;
 
-  DEBUGASSERT(dir && dir->u.procfs);
-  priv = dir->u.procfs;
+  DEBUGASSERT(dir);
+  priv = (FAR struct netprocfs_level1_s *)dir;
 
   priv->base.index = 0;
   return OK;
diff --git a/net/procfs/net_procfs_route.c b/net/procfs/net_procfs_route.c
index b18aee3a35..cd78441c4d 100644
--- a/net/procfs/net_procfs_route.c
+++ b/net/procfs/net_procfs_route.c
@@ -41,7 +41,6 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/procfs.h>
-#include <nuttx/fs/dirent.h>
 
 #include "route/route.h"
 
@@ -159,7 +158,7 @@ static int     route_dup(FAR const struct file *oldp,
                  FAR struct file *newp);
 
 static int     route_opendir(const char *relpath,
-                 FAR struct fs_dirent_s *dir);
+                 FAR struct fs_dirent_s **dir);
 static int     route_closedir(FAR struct fs_dirent_s *dir);
 static int     route_readdir(FAR struct fs_dirent_s *dir,
                              FAR struct dirent *entry);
@@ -610,12 +609,12 @@ static int route_dup(FAR const struct file *oldp, FAR struct file *newp)
  ****************************************************************************/
 
 static int route_opendir(FAR const char *relpath,
-                         FAR struct fs_dirent_s *dir)
+                         FAR struct fs_dirent_s **dir)
 {
   FAR struct route_dir_s *level2;
 
   finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
-  DEBUGASSERT(relpath && dir && !dir->u.procfs);
+  DEBUGASSERT(relpath);
 
   /* Check the relative path */
 
@@ -652,7 +651,7 @@ static int route_opendir(FAR const char *relpath,
   level2->base.nentries    = 2;
   level2->name             = "";
   level2->node             = PROC_ROUTE;
-  dir->u.procfs            = (FAR void *)level2;
+  *dir                     = (FAR struct fs_dirent_s *)level2;
   return OK;
 }
 
@@ -665,17 +664,8 @@ static int route_opendir(FAR const char *relpath,
 
 static int route_closedir(FAR struct fs_dirent_s *dir)
 {
-  FAR struct route_dir_s *priv;
-
-  DEBUGASSERT(dir && dir->u.procfs);
-  priv = dir->u.procfs;
-
-  if (priv != NULL)
-    {
-      kmm_free(priv);
-    }
-
-  dir->u.procfs = NULL;
+  DEBUGASSERT(dir);
+  kmm_free(dir);
   return OK;
 }
 
@@ -693,8 +683,8 @@ static int route_readdir(FAR struct fs_dirent_s *dir,
   FAR const char *dname;
   unsigned int index;
 
-  DEBUGASSERT(dir != NULL && dir->u.procfs != NULL);
-  level2 = dir->u.procfs;
+  DEBUGASSERT(dir != NULL);
+  level2 = (FAR struct route_dir_s *)dir;
 
   /* The index determines which entry to return */
 
@@ -746,8 +736,8 @@ static int route_rewinddir(struct fs_dirent_s *dir)
 {
   FAR struct route_dir_s *priv;
 
-  DEBUGASSERT(dir && dir->u.procfs);
-  priv = dir->u.procfs;
+  DEBUGASSERT(dir);
+  priv = (FAR struct route_dir_s *)dir;
 
   priv->base.index = 0;
   return OK;