summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/ChangeLog.txt7
-rw-r--r--apps/nshlib/nsh.h6
-rw-r--r--apps/nshlib/nsh_command.c2
-rw-r--r--apps/nshlib/nsh_fscmds.c2
-rw-r--r--nuttx/ChangeLog7
-rw-r--r--nuttx/fs/Makefile4
-rw-r--r--nuttx/fs/fs_inode.c7
-rw-r--r--nuttx/fs/fs_inodeaddref.c2
-rw-r--r--nuttx/fs/fs_inodebasename.c96
-rw-r--r--nuttx/fs/fs_inoderemove.c108
-rw-r--r--nuttx/fs/fs_inodereserve.c2
-rw-r--r--nuttx/fs/fs_internal.h25
-rw-r--r--nuttx/fs/fs_rename.c147
-rw-r--r--nuttx/include/nuttx/fs/fs.h4
14 files changed, 315 insertions, 104 deletions
diff --git a/apps/ChangeLog.txt b/apps/ChangeLog.txt
index c5c513d02..cd58a46c7 100644
--- a/apps/ChangeLog.txt
+++ b/apps/ChangeLog.txt
@@ -825,9 +825,12 @@
(2014-2-10).
* apps/examples/nximage/Kconfig and apps/examples/uip/Kconfig: Incomplete
Kconfig files fleshed out by Alan Carvalho de Assis (2014-2-18).
- * apps/nshilib: rmdir can now be used in the pseudo-filesystem. Hence,
+ * apps/nshlib: 'rmdir' can now be used in the pseudo-filesystem. Hence,
the command needs to be available even if there are no write-able
filesystem enabled (2014-2-19).
- * apps/nshilib: mkdir can now be used in the pseudo-filesystem. Hence,
+ * apps/nshlib: 'mkdir' can now be used in the pseudo-filesystem. Hence,
the command needs to be available even if there are no write-able
filesystem enabled (2014-2-19).
+ * apps/nshlib: 'rename' can now be used in the pseudo-filesystem. Hence,
+ the 'mv' command needs to be available even if there are no write-able
+ filesystem enabled (2014-2-19).
diff --git a/apps/nshlib/nsh.h b/apps/nshlib/nsh.h
index 97afc430f..223799b41 100644
--- a/apps/nshlib/nsh.h
+++ b/apps/nshlib/nsh.h
@@ -720,6 +720,9 @@ void nsh_usbtrace(void);
# ifndef CONFIG_NSH_DISABLE_MKDIR
int cmd_mkdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
# endif
+# ifndef CONFIG_NSH_DISABLE_MV
+ int cmd_mv(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
# ifndef CONFIG_NSH_DISABLE_RMDIR
int cmd_rmdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
# endif
@@ -752,9 +755,6 @@ void nsh_usbtrace(void);
# ifndef CONFIG_NSH_DISABLE_MKRD
int cmd_mkrd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
# endif
-# ifndef CONFIG_NSH_DISABLE_MV
- int cmd_mv(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
-# endif
# ifndef CONFIG_NSH_DISABLE_RM
int cmd_rm(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
# endif
diff --git a/apps/nshlib/nsh_command.c b/apps/nshlib/nsh_command.c
index 447036bc1..a52a91d4a 100644
--- a/apps/nshlib/nsh_command.c
+++ b/apps/nshlib/nsh_command.c
@@ -300,7 +300,7 @@ static const struct cmdmap_s g_cmdmap[] =
# endif
#endif
-#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE)
+#if CONFIG_NFILE_DESCRIPTORS > 0
# ifndef CONFIG_NSH_DISABLE_MV
{ "mv", cmd_mv, 3, 3, "<old-path> <new-path>" },
# endif
diff --git a/apps/nshlib/nsh_fscmds.c b/apps/nshlib/nsh_fscmds.c
index ccd831949..c56be9497 100644
--- a/apps/nshlib/nsh_fscmds.c
+++ b/apps/nshlib/nsh_fscmds.c
@@ -1298,7 +1298,7 @@ int cmd_mksmartfs(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
* Name: cmd_mv
****************************************************************************/
-#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE)
+#if CONFIG_NFILE_DESCRIPTORS > 0
#ifndef CONFIG_NSH_DISABLE_MV
int cmd_mv(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 892aae458..de41ca5b1 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -6610,10 +6610,11 @@
* fs/fs_opendir.c, fs_readdir.c, et al: Modified so that errors
will not be reported if you attempt to list a empty pseudo-directory
(2014-2-19).
- * fs/fs_rmdir.c: rmdir can now be used to remove empty directories in
+ * fs/fs_rmdir.c: 'rmdir' can now be used to remove empty directories in
the pseudo-filesystem such as might be left after umounting a
file system (2014-2-19).
- * fs/fs_mkdir.c: mkdir can now be used to create empty directories in
+ * fs/fs_mkdir.c: 'mkdir' can now be used to create empty directories in
the pseudo-filesystem (2014-2-19).
* drivers/lcd/mio283qt9a.c: Bug fix from Toby Duckwork (2014-2-19).
-
+ * fs/fs_rename.c: 'rename' can now be used to rename nodes in the
+ pseudo-filesystem (2014-2-19).
diff --git a/nuttx/fs/Makefile b/nuttx/fs/Makefile
index 828535cfe..615d655fb 100644
--- a/nuttx/fs/Makefile
+++ b/nuttx/fs/Makefile
@@ -68,8 +68,8 @@ CSRCS += fs_rewinddir.c fs_rmdir.c fs_seekdir.c fs_stat.c fs_statfs.c
CSRCS += fs_select.c fs_write.c
CSRCS += fs_files.c fs_foreachinode.c fs_inode.c fs_inodeaddref.c
-CSRCS += fs_inodefind.c fs_inoderelease.c fs_inoderemove.c
-CSRCS += fs_inodereserve.c
+CSRCS += fs_inodebasename.c fs_inodefind.c fs_inoderelease.c
+CSRCS += fs_inoderemove.c fs_inodereserve.c
CSRCS += fs_registerdriver.c fs_unregisterdriver.c
CSRCS += fs_registerblockdriver.c fs_unregisterblockdriver.c
diff --git a/nuttx/fs/fs_inode.c b/nuttx/fs/fs_inode.c
index afb88532c..913e58a5d 100644
--- a/nuttx/fs/fs_inode.c
+++ b/nuttx/fs/fs_inode.c
@@ -408,15 +408,15 @@ void inode_free(FAR struct inode *node)
* Name: inode_nextname
*
* Description:
- * Given a path with node names separated by '/', return the next node
- * name.
+ * Given a path with node names separated by '/', return the next path
+ * segment name.
*
****************************************************************************/
FAR const char *inode_nextname(FAR const char *name)
{
/* Search for the '/' delimiter or the NUL terminator at the end of the
- * string.
+ * path segment.
*/
while (*name && *name != '/')
@@ -435,4 +435,3 @@ FAR const char *inode_nextname(FAR const char *name)
return name;
}
-
diff --git a/nuttx/fs/fs_inodeaddref.c b/nuttx/fs/fs_inodeaddref.c
index 32d4426d2..ebe6b4888 100644
--- a/nuttx/fs/fs_inodeaddref.c
+++ b/nuttx/fs/fs_inodeaddref.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * fs_inodeaddref.c
+ * fs/fs_inodeaddref.c
*
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
diff --git a/nuttx/fs/fs_inodebasename.c b/nuttx/fs/fs_inodebasename.c
new file mode 100644
index 000000000..76d8a8e20
--- /dev/null
+++ b/nuttx/fs/fs_inodebasename.c
@@ -0,0 +1,96 @@
+/****************************************************************************
+ * fs/fs_basename.c
+ *
+ * Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "fs_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: inode_nextname
+ *
+ * Description:
+ * Given a path with node names separated by '/', return the next node
+ * name.
+ *
+ ****************************************************************************/
+
+FAR const char *inode_basename(FAR const char *name)
+{
+ FAR const char *basename = NULL;
+
+ for (;;)
+ {
+ /* Get the name for the next path segment */
+
+ name = inode_nextname(name);
+
+ /* When the final segment is terminated by the NUL character, then
+ * previous name that we saved is the basename.
+ */
+
+ if (*name == '\0')
+ {
+ return basename;
+ }
+ }
+
+ /* We won't get here */
+
+ return NULL;
+}
diff --git a/nuttx/fs/fs_inoderemove.c b/nuttx/fs/fs_inoderemove.c
index c349b1759..8258b1151 100644
--- a/nuttx/fs/fs_inoderemove.c
+++ b/nuttx/fs/fs_inoderemove.c
@@ -63,83 +63,103 @@
****************************************************************************/
/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
* Name: inode_unlink
+ *
+ * Description:
+ * Given a path, remove a the node from the in-memory, inode tree that the
+ * path refers to. This is normally done in preparation to removing or
+ * moving an inode.
+ *
+ * Assumptions/Limitations:
+ * The caller must hold the inode semaphore
+ *
****************************************************************************/
-static void inode_unlink(struct inode *node,
- struct inode *peer,
- struct inode *parent)
+FAR struct inode *inode_unlink(FAR const char *path)
{
- /* If peer is non-null, then remove the node from the right of
- * of that peer node.
- */
+ const char *name = path;
+ FAR struct inode *node;
+ FAR struct inode *peer;
+ FAR struct inode *parent;
+
+ /* Verify parameters. Ignore null paths and relative paths */
- if (peer)
+ if (!path || *path == '\0' || path[0] != '/')
{
- peer->i_peer = node->i_peer;
+ return NULL;
}
- /* If parent is non-null, then remove the node from head of
- * of the list of children.
- */
+ /* Find the node to unlink */
- else if (parent)
+ node = inode_search(&name, &peer, &parent, (const char **)NULL);
+ if (node)
{
- parent->i_child = node->i_peer;
- }
+ /* If peer is non-null, then remove the node from the right of
+ * of that peer node.
+ */
- /* Otherwise, we must be removing the root inode. */
+ if (peer)
+ {
+ peer->i_peer = node->i_peer;
+ }
- else
- {
- root_inode = node->i_peer;
+ /* If parent is non-null, then remove the node from head of
+ * of the list of children.
+ */
+
+ else if (parent)
+ {
+ parent->i_child = node->i_peer;
+ }
+
+ /* Otherwise, we must be removing the root inode. */
+
+ else
+ {
+ root_inode = node->i_peer;
+ }
+
+ node->i_peer = NULL;
}
- node->i_peer = NULL;
+ return node;
}
/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
* Name: inode_remove
*
* Description:
- * Remove a node from the in-memory, inode tree
+ * Given a path, remove a the node from the in-memory, inode tree that the
+ * path refers to and free all resources related to the inode. If the
+ * inode is in-use, then it will be unlinked, but will not be freed until
+ * the last reference to the inode is released.
*
- * NOTE: Caller must hold the inode semaphore
+ * Assumptions/Limitations:
+ * The caller must hold the inode semaphore
*
****************************************************************************/
int inode_remove(FAR const char *path)
{
- const char *name = path;
FAR struct inode *node;
- FAR struct inode *left;
- FAR struct inode *parent;
- if (!*path || path[0] != '/')
- {
- return -EINVAL;
- }
-
- /* Find the node to delete */
+ /* Find the inode and unlink it from the in-memory inode tree */
- node = inode_search(&name, &left, &parent, (const char **)NULL);
+ node = inode_unlink(path);
if (node)
{
- /* Found it, now remove it from the tree */
-
- inode_unlink(node, left, parent);
-
- /* We cannot delete it if there reference to the inode */
+ /* Found it! But we cannot delete the inode if there are references
+ * to it
+ */
if (node->i_crefs)
{
- /* In that case, we will mark it deleted, when the FS
- * releases the inode, we will then, finally delete
- * the subtree.
+ /* In that case, we will mark it deleted, when the filesystem
+ * releases the inode, we will then, finally delete the subtree
*/
node->i_flags |= FSNODEFLAG_DELETED;
@@ -155,7 +175,7 @@ int inode_remove(FAR const char *path)
}
}
- /* The node does not exist or it has references */
+ /* The node does not exist */
return -ENOENT;
}
diff --git a/nuttx/fs/fs_inodereserve.c b/nuttx/fs/fs_inodereserve.c
index 73e0fff28..ad3a8107e 100644
--- a/nuttx/fs/fs_inodereserve.c
+++ b/nuttx/fs/fs_inodereserve.c
@@ -165,7 +165,7 @@ static void inode_insert(FAR struct inode *node,
int inode_reserve(FAR const char *path, FAR struct inode **inode)
{
- const char *name = path;
+ FAR const char *name = path;
FAR struct inode *left;
FAR struct inode *parent;
diff --git a/nuttx/fs/fs_internal.h b/nuttx/fs/fs_internal.h
index 648f02704..5dd45bc23 100644
--- a/nuttx/fs/fs_internal.h
+++ b/nuttx/fs/fs_internal.h
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/fs_internal.h
*
- * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2012, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -196,12 +196,31 @@ int inode_reserve(FAR const char *path, FAR struct inode **inode);
/* fs_inoderemove.c *********************************************************/
/****************************************************************************
+ * Name: inode_unlink
+ *
+ * Description:
+ * Given a path, remove a the node from the in-memory, inode tree that the
+ * path refers to. This is normally done in preparation to removing or
+ * moving an inode.
+ *
+ * Assumptions/Limitations:
+ * The caller must hold the inode semaphore
+ *
+ ****************************************************************************/
+
+FAR struct inode *inode_unlink(FAR const char *path);
+
+/****************************************************************************
* Name: inode_remove
*
* Description:
- * Remove a node from the in-memory, inode tree
+ * Given a path, remove a the node from the in-memory, inode tree that the
+ * path refers to and free all resources related to the inode. If the
+ * inode is in-use, then it will be unlinked, but will not be freed until
+ * the last reference to the inode is released.
*
- * NOTE: Caller must hold the inode semaphore
+ * Assumptions/Limitations:
+ * The caller must hold the inode semaphore
*
****************************************************************************/
diff --git a/nuttx/fs/fs_rename.c b/nuttx/fs/fs_rename.c
index 6f2d1e432..474a7492e 100644
--- a/nuttx/fs/fs_rename.c
+++ b/nuttx/fs/fs_rename.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/fs_rename.c
*
- * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -75,78 +75,151 @@
int rename(FAR const char *oldpath, FAR const char *newpath)
{
FAR struct inode *oldinode;
- FAR struct inode *newinode;
const char *oldrelpath = NULL;
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+ FAR struct inode *newinode;
const char *newrelpath = NULL;
+#endif
+ int errcode;
int ret;
+ /* Ignore paths that are interpreted as the root directory which has no name
+ * and cannot be moved
+ */
+
+ if (!oldpath || *oldpath == '\0' || oldpath[0] != '/' ||
+ !newpath || *newpath == '\0' || newpath[0] != '/')
+ {
+ return -EINVAL;
+ }
+
/* Get an inode that includes the oldpath */
oldinode = inode_find(oldpath, &oldrelpath);
if (!oldinode)
{
- /* There is no mountpoint that includes in this path */
+ /* There is no inode that includes in this path */
- ret = ENOENT;
+ errcode = ENOENT;
goto errout;
}
+#ifndef CONFIG_DISABLE_MOUNTPOINT
/* Verify that the old inode is a valid mountpoint. */
- if (!INODE_IS_MOUNTPT(oldinode) || !oldinode->u.i_mops)
+ if (INODE_IS_MOUNTPT(oldinode) && oldinode->u.i_mops)
{
- ret = ENXIO;
- goto errout_with_oldinode;
- }
-
- /* Get an inode for the new relpath -- it should like on the same
- * mountpoint
- */
+ /* Get an inode for the new relpath -- it should like on the same
+ * mountpoint
+ */
- newinode = inode_find(newpath, &newrelpath);
- if (!newinode)
- {
- /* There is no mountpoint that includes in this path */
+ newinode = inode_find(newpath, &newrelpath);
+ if (!newinode)
+ {
+ /* There is no mountpoint that includes in this path */
- ret = ENOENT;
- goto errout_with_oldinode;
- }
+ errcode = ENOENT;
+ goto errout_with_oldinode;
+ }
- /* Verify that the two paths lie on the same mountpoint inode */
+ /* Verify that the two paths lie on the same mountpoint inode */
- if (oldinode != newinode)
- {
- ret = EXDEV;
- goto errout_with_newinode;
- }
+ if (oldinode != newinode)
+ {
+ errcode = EXDEV;
+ goto errout_with_newinode;
+ }
- /* Perform the rename operation using the relative paths
- * at the common mountpoint.
- */
+ /* Perform the rename operation using the relative paths
+ * at the common mountpoint.
+ */
- if (oldinode->u.i_mops->rename)
- {
- ret = oldinode->u.i_mops->rename(oldinode, oldrelpath, newrelpath);
- if (ret < 0)
+ if (oldinode->u.i_mops->rename)
{
- ret = -ret;
+ ret = oldinode->u.i_mops->rename(oldinode, oldrelpath, newrelpath);
+ if (ret < 0)
+ {
+ errcode = -ret;
+ goto errout_with_newinode;
+ }
+ }
+ else
+ {
+ errcode = ENOSYS;
goto errout_with_newinode;
}
+
+ /* Successfully renamed */
+
+ inode_release(newinode);
}
else
- {
- ret = ENOSYS;
- goto errout_with_newinode;
+#endif
+ {
+ /* Create a new, empty inode at the destination location */
+
+ inode_semtake();
+ ret = inode_reserve(newpath, &newinode);
+ if (ret < 0)
+ {
+ /* It is an error if a node at newpath already exists in the tree
+ * OR if we fail to allocate memory for the new inode (and possibly
+ * any new intermediate path segments).
+ */
+
+ inode_semgive();
+ errcode = EEXIST;
+ goto errout_with_oldinode;
+ }
+
+ /* Copy the inode state from the old inode to the newly allocated inode */
+
+ newinode->i_child = oldinode->i_child; /* Link to lower level inode */
+ newinode->i_flags = oldinode->i_flags; /* Flags for inode */
+ newinode->u.i_ops = oldinode->u.i_ops; /* Inode operations */
+#ifdef CONFIG_FILE_MODE
+ newinode->i_mode = oldinode->i_mode; /* Access mode flags */
+#endif
+ newinode->i_private = oldinode->i_private; /* Per inode driver private data */
+
+ /* We now have two copies of the inode. One with a reference count of
+ * zero (the new one), and one that may have multiple references
+ * including one by this logic (the old one)
+ *
+ * Remove the old inode. Because we hold a reference count on the
+ * inode, it will not be deleted now. It will be deleted when all of
+ * the references to to the inode have been released (perhaps when
+ * inode_release() is called below). inode_remove() should return
+ * -EBUSY to indicate that the inode was not deleted now.
+ */
+
+ ret = inode_remove(oldpath);
+ if (ret < 0 && ret != -EBUSY)
+ {
+ /* Remove the new node we just recreated */
+
+ (void)inode_remove(newpath);
+ inode_semgive();
+
+ errcode = -ret;
+ goto errout_with_oldinode;
+ }
+
+ /* Remove all of the children from the unlinked inode */
+
+ oldinode->i_child = NULL;
+ inode_semgive();
}
/* Successfully renamed */
inode_release(oldinode);
- inode_release(newinode);
return OK;
+#ifndef CONFIG_DISABLE_MOUNTPOINT
errout_with_newinode:
inode_release(newinode);
+#endif
errout_with_oldinode:
inode_release(oldinode);
errout:
diff --git a/nuttx/include/nuttx/fs/fs.h b/nuttx/include/nuttx/fs/fs.h
index f73b0b0cf..9b6502634 100644
--- a/nuttx/include/nuttx/fs/fs.h
+++ b/nuttx/include/nuttx/fs/fs.h
@@ -208,8 +208,8 @@ union inode_ops_u
struct inode
{
- FAR struct inode *i_peer; /* Pointer to same level inode */
- FAR struct inode *i_child; /* Pointer to lower level inode */
+ FAR struct inode *i_peer; /* Link to same level inode */
+ FAR struct inode *i_child; /* Link to lower level inode */
int16_t i_crefs; /* References to inode */
uint16_t i_flags; /* Flags for inode */
union inode_ops_u u; /* Inode operations */