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

acassis 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 0cf3e49a129 fs/shm: Copy the data of a shm object page by page in the 
kernel build.
0cf3e49a129 is described below

commit 0cf3e49a129243f1fc22cdd388dee93cb9badb31
Author: Marco Casaroli <[email protected]>
AuthorDate: Wed Oct 21 17:09:53 2026 +0200

    fs/shm: Copy the data of a shm object page by page in the kernel build.
    
    In the kernel build, a shm object is a list of single pages from the
    page pool.  shmfs_read() and shmfs_write() copied the data at the first
    page plus the file position.  After the first page, this is correct
    only if the pages of the object are contiguous, and it uses the
    physical address as the kernel address.
    
    Copy the data page by page through the kernel address of each page
    (up_addrenv_page_vaddr()).  The flat and protected builds keep the
    object in one block of memory and do not change.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 fs/shm/shmfs.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 57 insertions(+), 2 deletions(-)

diff --git a/fs/shm/shmfs.c b/fs/shm/shmfs.c
index 37191f8ae41..63aacbff1b4 100644
--- a/fs/shm/shmfs.c
+++ b/fs/shm/shmfs.c
@@ -25,6 +25,9 @@
  ****************************************************************************/
 
 #include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/param.h>
 
 #include <nuttx/fs/ioctl.h>
 #include <nuttx/mm/map.h>
@@ -84,6 +87,58 @@ const struct file_operations g_shmfs_operations =
  * Private Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: shmfs_copy
+ *
+ * Description:
+ *   Copy data between a buffer and a memory object.  In the kernel build
+ *   the object is a list of single pages from the page pool, which are not
+ *   always contiguous: copy page by page through the kernel address of
+ *   each page.  In the other builds the object is one block of memory.
+ *
+ ****************************************************************************/
+
+static void shmfs_copy(FAR struct shmfs_object_s *sho, off_t pos,
+                       FAR char *buffer, size_t len, bool write)
+{
+#ifdef CONFIG_BUILD_KERNEL
+  FAR uintptr_t *pages = (FAR uintptr_t *)&sho->paddr;
+  FAR char *vaddr;
+  size_t offset;
+  size_t n;
+
+  while (len > 0)
+    {
+      offset = pos % MM_PGSIZE;
+      n      = MIN(len, MM_PGSIZE - offset);
+      vaddr  = (FAR char *)up_addrenv_page_vaddr(pages[pos / MM_PGSIZE]) +
+               offset;
+
+      if (write)
+        {
+          memcpy(vaddr, buffer, n);
+        }
+      else
+        {
+          memcpy(buffer, vaddr, n);
+        }
+
+      pos    += n;
+      buffer += n;
+      len    -= n;
+    }
+#else
+  if (write)
+    {
+      memcpy((FAR char *)sho->paddr + pos, buffer, len);
+    }
+  else
+    {
+      memcpy(buffer, (FAR char *)sho->paddr + pos, len);
+    }
+#endif
+}
+
 /****************************************************************************
  * Name: shmfs_read
  ****************************************************************************/
@@ -121,7 +176,7 @@ static ssize_t shmfs_read(FAR struct file *filep, FAR char 
*buffer,
 
   if (sho->paddr != NULL)
     {
-      memcpy(buffer, (FAR char *)sho->paddr + startpos, nread);
+      shmfs_copy(sho, startpos, buffer, nread, false);
       filep->f_pos += nread;
     }
   else
@@ -165,7 +220,7 @@ static ssize_t shmfs_write(FAR struct file *filep, FAR 
const char *buffer,
 
   if (sho->paddr != NULL)
     {
-      memcpy((FAR char *)sho->paddr + startpos, buffer, nwritten);
+      shmfs_copy(sho, startpos, (FAR char *)buffer, nwritten, true);
       filep->f_pos += nwritten;
     }
   else

Reply via email to