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

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


The following commit(s) were added to refs/heads/master by this push:
     new c9c04d74bcf fs/inode: Avoid temp buffer for simple absolute paths
c9c04d74bcf is described below

commit c9c04d74bcf2eedc04a90b3de7e7f4a39722e4a1
Author: chao an <[email protected]>
AuthorDate: Tue Oct 27 16:00:53 2026 +0800

    fs/inode: Avoid temp buffer for simple absolute paths
    
    Skip the PATH_MAX temporary buffer allocation when inode search is given a
    simple absolute path that already needs no root prefixing or 
canonicalization.
    This keeps common VFS lookups from copying paths only to normalize them back
    to the same string, while preserving the existing mutable-buffer path for
    nofollow and non-canonical cases.
    
    Signed-off-by: chao an <[email protected]>
---
 fs/inode/fs_inodesearch.c | 74 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 68 insertions(+), 6 deletions(-)

diff --git a/fs/inode/fs_inodesearch.c b/fs/inode/fs_inodesearch.c
index add1fd532e1..4c40790303d 100644
--- a/fs/inode/fs_inodesearch.c
+++ b/fs/inode/fs_inodesearch.c
@@ -325,12 +325,19 @@ static int _inode_canonicalize(FAR char *path, FAR char 
*dst_min)
 
 /****************************************************************************
  * Name: _inode_checkpath
+ *
+ * Description:
+ *   Check path length constraints.  Returns 1 if the path is already a
+ *   simple absolute path that needs no canonicalization.
  ****************************************************************************/
 
-static int _inode_checkpath(const char *path)
+static int _inode_checkpath(FAR const char *path)
 {
+  bool is_simple = true;
   int namelen = 0;
   int pathlen = 0;
+  bool dot = false;
+  bool dotdot = false;
 
   if (*path == '\0')
     {
@@ -339,25 +346,67 @@ static int _inode_checkpath(const char *path)
 
   /* Check each segment of the path */
 
-  while (*path != '\0' && pathlen < PATH_MAX)
+  while (pathlen < PATH_MAX)
     {
-      if (*path == '/')
+      if (*path == '/' || *path == '\0')
         {
+          if (is_simple && pathlen > 0 &&
+              !(pathlen == 1 && namelen == 0 && *path == '\0'))
+            {
+              if (namelen == 0 || dot || dotdot)
+                {
+                  is_simple = false;
+                }
+            }
+
+          if (*path == '\0')
+            {
+              break;
+            }
+
           namelen = 0;
+          dot = false;
+          dotdot = false;
         }
       else
         {
+          if (pathlen == 0)
+            {
+              is_simple = false;
+            }
+
           if (++namelen > NAME_MAX)
             {
               return -ENAMETOOLONG;
             }
+
+          if (namelen == 1)
+            {
+              dot = *path == '.';
+              dotdot = dot;
+            }
+          else if (namelen == 2)
+            {
+              dot = false;
+              dotdot = dotdot && *path == '.';
+            }
+          else
+            {
+              dot = false;
+              dotdot = false;
+            }
         }
 
       path++;
       pathlen++;
     }
 
-  return pathlen >= PATH_MAX ? -ENAMETOOLONG : OK;
+  if (pathlen >= PATH_MAX)
+    {
+      return -ENAMETOOLONG;
+    }
+
+  return is_simple;
 }
 
 #ifdef CONFIG_FS_CHROOT
@@ -432,8 +481,9 @@ void inode_search_release(FAR struct inode_search_s *desc)
  * Description:
  *   Initialize a search descriptor and make 'path' host-absolute: join
  *   $PWD if it is relative, prepend the chroot jail if one is installed,
- *   and canonicalize "." / "..".  On success desc->path points at
- *   desc->buffer.
+ *   and canonicalize "." / "..".  For simple absolute paths that already
+ *   need no expansion or canonicalization, desc->path may point directly at
+ *   the caller-provided path and desc->buffer will remain NULL.
  *
  ****************************************************************************/
 
@@ -473,6 +523,18 @@ int inode_search_setup(FAR struct inode_search_s *desc,
     }
 #endif
 
+  /* Fast path for the common case where the caller already passes a simple
+   * absolute path.  Avoid allocating a PATH_MAX temporary buffer and copying
+   * the string only to canonicalize it back to the same value.  Keep the
+   * existing buffer path for nofollow searches so symbolic-link target
+   * handling can continue to rely on a mutable path buffer.
+   */
+
+  if (root == NULL && !nofollow && ret > 0)
+    {
+      return OK;
+    }
+
   /* For a relative path the absolute form is "<cwd>/<path>".  That
    * concatenation can exceed PATH_MAX even when the relative path
    * itself is within PATH_MAX: a relative path of PATH_MAX-1 bytes

Reply via email to