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 410fdf60bbf fs/vfs: Add CONFIG_FS_UIO to option out vector I/O
410fdf60bbf is described below

commit 410fdf60bbf4f37d56b7c68503c9f39e727b469b
Author: Swatantra Yadav <[email protected]>
AuthorDate: Fri Oct 23 01:48:46 2026 +0530

    fs/vfs: Add CONFIG_FS_UIO to option out vector I/O
    
    Provide a hidden Kconfig option CONFIG_FS_UIO (selected by subsystems
    such as drivers/serial that implement vector I/O). When disabled,
    file_read() and file_write() invoke the underlying driver read/write
    operations directly, avoiding struct iovec stack allocations and
    omitting fs_uio.c.
    
    POSIX readv() and writev() remain available via read/write fallback
    loops and are automatically stripped by the linker (--gc-sections)
    when unreferenced, preserving full POSIX compliance while saving
    memory on constrained targets.
    
    Signed-off-by: Swatantra Yadav <[email protected]>
---
 drivers/serial/Kconfig |   1 +
 fs/Kconfig             |   3 ++
 fs/vfs/CMakeLists.txt  |   5 ++-
 fs/vfs/Make.defs       |   6 ++-
 fs/vfs/fs_read.c       | 116 +++++++++++++++++++++++++++++++++++++++++++++----
 fs/vfs/fs_write.c      | 107 +++++++++++++++++++++++++++++++++++++++++----
 6 files changed, 218 insertions(+), 20 deletions(-)

diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 399c398627c..3b368991099 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -19,6 +19,7 @@ config ARCH_HAVE_8BIT_SERIAL_BUFSIZE
 menuconfig SERIAL
        bool "Serial Driver Support"
        default y
+       select FS_UIO
        ---help---
                Front-end character drivers for chip-specific UARTs.  This 
provide
                some TTY-like functionality and are commonly used (but not 
required
diff --git a/fs/Kconfig b/fs/Kconfig
index 2a37d1f30a2..2b58a632dbf 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -17,6 +17,9 @@ config DISABLE_MOUNTPOINT
        bool "Disable support for mount points"
        default n
 
+config FS_UIO
+       bool
+
 config FS_LARGEFILE
        bool "Large File Support"
        default n
diff --git a/fs/vfs/CMakeLists.txt b/fs/vfs/CMakeLists.txt
index 9d1d2127c2a..cff84c164c9 100644
--- a/fs/vfs/CMakeLists.txt
+++ b/fs/vfs/CMakeLists.txt
@@ -45,7 +45,6 @@ set(SRCS
     fs_stat.c
     fs_sendfile.c
     fs_statfs.c
-    fs_uio.c
     fs_unlink.c
     fs_write.c
     fs_fsync.c
@@ -53,6 +52,10 @@ set(SRCS
     fs_truncate.c
     fs_link.c)
 
+if(CONFIG_FS_UIO)
+  list(APPEND SRCS fs_uio.c)
+endif()
+
 if(NOT CONFIG_DISABLE_DIRECTORY_OPERATIONS)
   list(APPEND SRCS fs_dir.c)
 endif()
diff --git a/fs/vfs/Make.defs b/fs/vfs/Make.defs
index 0b2b02bfcf5..89012c6a7bb 100644
--- a/fs/vfs/Make.defs
+++ b/fs/vfs/Make.defs
@@ -26,9 +26,13 @@ CSRCS += fs_chstat.c fs_close.c fs_dup.c fs_dup2.c fs_dup3.c 
fs_fcntl.c
 CSRCS += fs_epoll.c fs_fchstat.c fs_fstat.c fs_fstatfs.c fs_ioctl.c fs_lseek.c
 CSRCS += fs_mkdir.c fs_open.c fs_poll.c fs_pread.c fs_pwrite.c fs_read.c
 CSRCS += fs_rename.c fs_rmdir.c fs_select.c fs_sendfile.c fs_stat.c
-CSRCS += fs_statfs.c fs_uio.c fs_unlink.c fs_write.c fs_fsync.c
+CSRCS += fs_statfs.c fs_unlink.c fs_write.c fs_fsync.c
 CSRCS += fs_syncfs.c fs_truncate.c fs_link.c
 
+ifeq ($(CONFIG_FS_UIO),y)
+CSRCS += fs_uio.c
+endif
+
 ifneq ($(CONFIG_DISABLE_DIRECTORY_OPERATIONS),y)
 CSRCS += fs_dir.c
 endif
diff --git a/fs/vfs/fs_read.c b/fs/vfs/fs_read.c
index 0ffc1e9715e..584c043bc86 100644
--- a/fs/vfs/fs_read.c
+++ b/fs/vfs/fs_read.c
@@ -32,6 +32,7 @@
 #include <sched.h>
 #include <assert.h>
 #include <errno.h>
+#include <limits.h>
 
 #include <nuttx/cancelpt.h>
 
@@ -219,6 +220,7 @@ ssize_t file_readv(FAR struct file *filep,
 
       FS_PROFILE_START(start_time);
 
+#ifdef CONFIG_FS_UIO
       if (inode->u.i_ops->readv)
         {
           struct uio uio;
@@ -229,7 +231,9 @@ ssize_t file_readv(FAR struct file *filep,
               ret = inode->u.i_ops->readv(filep, &uio);
             }
         }
-      else if (inode->u.i_ops->read)
+      else
+#endif
+      if (inode->u.i_ops->read)
         {
           ret = file_readv_compat(filep, iov, iovcnt);
         }
@@ -274,12 +278,82 @@ ssize_t file_readv(FAR struct file *filep,
 
 ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
 {
+#ifdef CONFIG_FS_UIO
   struct iovec iov;
 
   iov.iov_base = buf;
   iov.iov_len = nbytes;
 
   return file_readv(filep, &iov, 1);
+#else
+  FAR struct inode *inode = filep->f_inode;
+  ssize_t ret = -EBADF;
+
+  DEBUGASSERT(filep);
+
+  /* Was this file opened for read access? */
+
+  if ((filep->f_oflags & O_ACCMODE) == O_WRONLY)
+    {
+      /* No.. File is not read-able */
+
+      return -EACCES;
+    }
+
+  if (nbytes == 0)
+    {
+      return 0;
+    }
+
+  if (nbytes > SSIZE_MAX)
+    {
+      return -EINVAL;
+    }
+
+  /* -------------------- DO NOT REMOVE --------------------
+   * Only for kernel builds with CONFIG_ARCH_TEXT_VBASE == 0.
+   * In this case we have to allow the NULL buffer otherwise
+   * kernel builds will fail to load elf binaries found at 0.
+   */
+
+#if !defined(CONFIG_BUILD_KERNEL) || CONFIG_ARCH_TEXT_VBASE != 0
+  if (buf == NULL)
+    {
+      return -EFAULT;
+    }
+#endif
+
+  /* Is a driver or mountpoint registered? If so, does it support the read
+   * method?
+   * If yes, then let it perform the read.
+   */
+
+  if (inode != NULL && inode->u.i_ops)
+    {
+      clock_t start_time;
+
+      FS_PROFILE_START(start_time);
+
+      if (inode->u.i_ops->read)
+        {
+          ret = inode->u.i_ops->read(filep, buf, nbytes);
+        }
+
+      FS_PROFILE_STOP(start_time, g_fs_profile.total_read_time,
+                      g_fs_profile.reads);
+    }
+
+  /* Return the number of bytes read (or possibly an error code) */
+
+#ifdef CONFIG_FS_NOTIFY
+  if (ret > 0)
+    {
+      notify_read(filep);
+    }
+#endif
+
+  return ret;
+#endif
 }
 
 /****************************************************************************
@@ -348,11 +422,23 @@ ssize_t nx_readv(int fd, FAR const struct iovec *iov, int 
iovcnt)
 
 ssize_t nx_read(int fd, FAR void *buf, size_t nbytes)
 {
-  struct iovec iov;
+  FAR struct file *filep;
+  ssize_t ret;
 
-  iov.iov_base = buf;
-  iov.iov_len = nbytes;
-  return nx_readv(fd, &iov, 1);
+  /* First, get the file structure.  Note that on failure,
+   * file_get() will return the errno.
+   */
+
+  ret = file_get(fd, &filep);
+  if (ret >= 0)
+    {
+      /* Then let file_read do all of the work. */
+
+      ret = file_read(filep, buf, nbytes);
+      file_put(filep);
+    }
+
+  return ret;
 }
 
 /****************************************************************************
@@ -412,9 +498,21 @@ ssize_t readv(int fd, FAR const struct iovec *iov, int 
iovcnt)
 
 ssize_t read(int fd, FAR void *buf, size_t nbytes)
 {
-  struct iovec iov;
+  ssize_t ret;
 
-  iov.iov_base = buf;
-  iov.iov_len = nbytes;
-  return readv(fd, &iov, 1);
+  /* read() is a cancellation point */
+
+  enter_cancellation_point();
+
+  /* Let nx_read() do the real work */
+
+  ret = nx_read(fd, buf, nbytes);
+  if (ret < 0)
+    {
+      set_errno(-ret);
+      ret = ERROR;
+    }
+
+  leave_cancellation_point();
+  return ret;
 }
diff --git a/fs/vfs/fs_write.c b/fs/vfs/fs_write.c
index b61483e82fb..399e0c3ceae 100644
--- a/fs/vfs/fs_write.c
+++ b/fs/vfs/fs_write.c
@@ -32,6 +32,7 @@
 #include <sched.h>
 #include <errno.h>
 #include <assert.h>
+#include <limits.h>
 
 #include <nuttx/cancelpt.h>
 
@@ -192,6 +193,7 @@ ssize_t file_writev(FAR struct file *filep,
 
       FS_PROFILE_START(start_time);
 
+#ifdef CONFIG_FS_UIO
       if (inode->u.i_ops->writev)
         {
           struct uio uio;
@@ -202,7 +204,9 @@ ssize_t file_writev(FAR struct file *filep,
               ret = inode->u.i_ops->writev(filep, &uio);
             }
         }
-      else if (inode->u.i_ops->write)
+      else
+#endif
+      if (inode->u.i_ops->write)
         {
           ret = file_writev_compat(filep, iov, iovcnt);
         }
@@ -249,12 +253,73 @@ ssize_t file_writev(FAR struct file *filep,
 ssize_t file_write(FAR struct file *filep, FAR const void *buf,
                    size_t nbytes)
 {
+#ifdef CONFIG_FS_UIO
   struct iovec iov;
 
   iov.iov_base = (FAR void *)buf;
   iov.iov_len = nbytes;
 
   return file_writev(filep, &iov, 1);
+#else
+  FAR struct inode *inode = filep->f_inode;
+  ssize_t ret = -EBADF;
+
+  DEBUGASSERT(filep);
+
+  /* Was this file opened for write access? */
+
+  if ((filep->f_oflags & O_ACCMODE) == O_RDONLY)
+    {
+      /* No.. File is not writable */
+
+      return -EACCES;
+    }
+
+  if (nbytes == 0)
+    {
+      return 0;
+    }
+
+  if (nbytes > SSIZE_MAX)
+    {
+      return -EINVAL;
+    }
+
+  if (buf == NULL)
+    {
+      return -EFAULT;
+    }
+
+  /* Is a driver registered? Does it support the write method?
+   * If yes, then let the driver perform the write.
+   */
+
+  if (inode != NULL && inode->u.i_ops)
+    {
+      clock_t start_time;
+
+      FS_PROFILE_START(start_time);
+
+      if (inode->u.i_ops->write)
+        {
+          ret = inode->u.i_ops->write(filep, buf, nbytes);
+        }
+
+      FS_PROFILE_STOP(start_time, g_fs_profile.total_write_time,
+                      g_fs_profile.writes);
+    }
+
+  /* Return the number of bytes written (or possibly an error code) */
+
+#ifdef CONFIG_FS_NOTIFY
+  if (ret > 0)
+    {
+      notify_write(filep);
+    }
+#endif
+
+  return ret;
+#endif
 }
 
 /****************************************************************************
@@ -333,11 +398,23 @@ ssize_t nx_writev(int fd, FAR const struct iovec *iov, 
int iovcnt)
 
 ssize_t nx_write(int fd, FAR const void *buf, size_t nbytes)
 {
-  struct iovec iov;
+  FAR struct file *filep;
+  ssize_t ret;
 
-  iov.iov_base = (void *)buf;
-  iov.iov_len = nbytes;
-  return nx_writev(fd, &iov, 1);
+  /* First, get the file structure.  Note that on failure,
+   * file_get() will return the errno.
+   */
+
+  ret = file_get(fd, &filep);
+  if (ret >= 0)
+    {
+      /* Then let file_write do all of the work. */
+
+      ret = file_write(filep, buf, nbytes);
+      file_put(filep);
+    }
+
+  return ret;
 }
 
 /****************************************************************************
@@ -459,9 +536,21 @@ ssize_t writev(int fd, FAR const struct iovec *iov, int 
iovcnt)
 
 ssize_t write(int fd, FAR const void *buf, size_t nbytes)
 {
-  struct iovec iov;
+  ssize_t ret;
 
-  iov.iov_base = (void *)buf;
-  iov.iov_len = nbytes;
-  return writev(fd, &iov, 1);
+  /* write() is a cancellation point */
+
+  enter_cancellation_point();
+
+  /* Let nx_write() do all of the work */
+
+  ret = nx_write(fd, buf, nbytes);
+  if (ret < 0)
+    {
+      set_errno(-ret);
+      ret = ERROR;
+    }
+
+  leave_cancellation_point();
+  return ret;
 }

Reply via email to