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/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 696717b28b add munmap logic to pseudofs
696717b28b is described below

commit 696717b28b28585a2aa3359572b67082a9ec175b
Author: ThomasNS <thomas.narayana-sw...@wandercraft.eu>
AuthorDate: Mon Oct 9 21:38:58 2023 +0200

    add munmap logic to pseudofs
---
 fs/vfs/fs_pseudofile.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 71 insertions(+), 5 deletions(-)

diff --git a/fs/vfs/fs_pseudofile.c b/fs/vfs/fs_pseudofile.c
index 0e3528162a..f39f2e5162 100644
--- a/fs/vfs/fs_pseudofile.c
+++ b/fs/vfs/fs_pseudofile.c
@@ -66,6 +66,10 @@ static off_t   pseudofile_seek(FAR struct file *filep, off_t 
offset,
                                int whence);
 static int     pseudofile_mmap(FAR struct file *filep,
                                FAR struct mm_map_entry_s *map);
+static int     pseudofile_munmap(FAR struct task_group_s *group,
+                                 FAR struct mm_map_entry_s *map,
+                                 FAR void *start,
+                                 size_t length);
 static int     pseudofile_truncate(FAR struct file *filep, off_t length);
 #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
 static int     pseudofile_unlink(FAR struct inode *inode);
@@ -309,14 +313,76 @@ static int pseudofile_mmap(FAR struct file *filep,
   FAR struct inode *node = filep->f_inode;
   FAR struct fs_pseudofile_s *pf = node->i_private;
 
-  if (map->offset >= 0 && map->offset < node->i_size &&
-      map->length != 0 && map->offset + map->length <= node->i_size)
+  /* Keep the inode when mmapped, increase refcount */
+
+  int ret = inode_addref(node);
+  if (ret >= 0)
     {
-      map->vaddr = pf->content + map->offset;
-      return OK;
+      if (map->offset >= 0 && map->offset < node->i_size &&
+          map->length != 0 && map->offset + map->length <= node->i_size)
+        {
+          map->vaddr = pf->content + map->offset;
+          map->munmap = pseudofile_munmap;
+          map->priv.p = (FAR void *)node;
+          ret = mm_map_add(get_current_mm(), map);
+        }
+      else
+        {
+          ret = -EINVAL;
+        }
+
+      if (ret < 0)
+        {
+          inode_release(node);
+        }
     }
 
-  return -EINVAL;
+  return ret;
+}
+
+static int pseudofile_munmap(FAR struct task_group_s *group,
+                             FAR struct mm_map_entry_s *map,
+                             FAR void *start,
+                             size_t length)
+{
+  FAR struct inode *inode = (FAR struct inode *)map->priv.p;
+
+  /* If the file has been unlinked previously, delete the contents.
+   * The inode is released after this call, hence checking if i_crefs <= 1.
+   */
+
+  int ret = inode_lock();
+  if (ret >= 0)
+    {
+      if (inode->i_parent == NULL &&
+          inode->i_crefs <= 1)
+        {
+          /* Delete the inode metadata */
+
+          if (inode->i_private)
+            {
+              kmm_free(inode->i_private);
+            }
+
+          inode->i_private = NULL;
+          ret = OK;
+        }
+
+      inode_unlock();
+    }
+
+  /* Unkeep the inode when unmapped, decrease refcount */
+
+  if (ret == OK)
+    {
+      inode_release(inode);
+
+      /* Remove the mapping. */
+
+      ret = mm_map_remove(get_group_mm(group), map);
+    }
+
+  return ret;
 }
 
 static int pseudofile_truncate(FAR struct file *filep, off_t length)

Reply via email to