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

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

commit c61734a469215a46ece9531a7b9222a681847422
Author: guohao15 <[email protected]>
AuthorDate: Thu Jan 4 20:52:51 2024 +0800

    romfs:extend romfs to enable write part2
    
    add sparelist api
    
    Signed-off-by: guohao15 <[email protected]>
---
 fs/romfs/Kconfig        |   7 ++
 fs/romfs/fs_romfs.c     |   9 ++-
 fs/romfs/fs_romfs.h     |  23 +++++-
 fs/romfs/fs_romfsutil.c | 199 ++++++++++++++++++++++++++++++++++++++++++++----
 4 files changed, 221 insertions(+), 17 deletions(-)

diff --git a/fs/romfs/Kconfig b/fs/romfs/Kconfig
index 427cf3bf85..ff0566ce82 100644
--- a/fs/romfs/Kconfig
+++ b/fs/romfs/Kconfig
@@ -27,4 +27,11 @@ config FS_ROMFS_CACHE_FILE_NSECTORS
        ---help---
                The number of file cache sector
 
+config FS_ROMFS_WRITEABLE
+       bool "Enable write extended feature in romfs"
+       default n
+       depends on FS_ROMFS_CACHE_NODE
+       ---help---
+               Enable write extended feature in romfs
+
 endif
diff --git a/fs/romfs/fs_romfs.c b/fs/romfs/fs_romfs.c
index 463852b379..25f6f6deda 100644
--- a/fs/romfs/fs_romfs.c
+++ b/fs/romfs/fs_romfs.c
@@ -1128,7 +1128,7 @@ static int romfs_bind(FAR struct inode *blkdriver, FAR 
const void *data,
    * the ROMF header
    */
 
-  ret = romfs_fsconfigure(rm);
+  ret = romfs_fsconfigure(rm, data);
   if (ret < 0)
     {
       ferr("ERROR: romfs_fsconfigure failed: %d\n", ret);
@@ -1238,6 +1238,9 @@ static int romfs_unbind(FAR void *handle, FAR struct 
inode **blkdriver,
 
 #ifdef CONFIG_FS_ROMFS_CACHE_NODE
       romfs_freenode(rm->rm_root);
+#endif
+#ifdef CONFIG_FS_ROMFS_WRITEABLE
+      romfs_free_sparelist(&rm->rm_sparelist);
 #endif
       nxrmutex_destroy(&rm->rm_lock);
       fs_heap_free(rm);
@@ -1296,8 +1299,8 @@ static int romfs_statfs(FAR struct inode *mountpt, FAR 
struct statfs *buf)
   /* Everything else follows in units of sectors */
 
   buf->f_blocks  = SEC_NSECTORS(rm, rm->rm_volsize + SEC_NDXMASK(rm));
-  buf->f_bfree   = 0;
-  buf->f_bavail  = 0;
+  buf->f_bfree   = rm->rm_hwnsectors - buf->f_blocks;
+  buf->f_bavail  = buf->f_bfree;
   buf->f_namelen = NAME_MAX;
 
 errout_with_lock:
diff --git a/fs/romfs/fs_romfs.h b/fs/romfs/fs_romfs.h
index f0af14fcc5..b066d0adf2 100644
--- a/fs/romfs/fs_romfs.h
+++ b/fs/romfs/fs_romfs.h
@@ -26,6 +26,7 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
+#include <nuttx/list.h>
 
 #include <stdint.h>
 #include <stdbool.h>
@@ -116,6 +117,20 @@
  * Public Types
  ****************************************************************************/
 
+#ifdef CONFIG_FS_ROMFS_WRITEABLE
+/* This structure represents the spare list.  An instance of this
+ * structure is retained as file header and file data size on each mountpoint
+ * that is mounted with a romfs filesystem.
+ */
+
+struct romfs_sparenode_s
+{
+  struct list_node node;
+  uint32_t start;
+  uint32_t end;
+};
+#endif
+
 /* This structure represents the overall mountpoint state.  An instance of
  * this structure is retained as inode private data on each mountpoint that
  * is mounted with a romfs filesystem.
@@ -139,6 +154,9 @@ struct romfs_mountpt_s
   uint32_t rm_cachesector;        /* Current sector in the rm_buffer */
   FAR uint8_t *rm_xipbase;        /* Base address of directly accessible media 
*/
   FAR uint8_t *rm_buffer;         /* Device sector buffer, allocated if 
rm_xipbase==0 */
+#ifdef CONFIG_FS_ROMFS_WRITEABLE
+  struct list_node rm_sparelist;  /* The list of spare space */
+#endif
 };
 
 /* This structure represents on open file under the mountpoint.  An instance
@@ -194,7 +212,7 @@ int  romfs_hwread(FAR struct romfs_mountpt_s *rm, FAR 
uint8_t *buffer,
 int  romfs_filecacheread(FAR struct romfs_mountpt_s *rm,
                          FAR struct romfs_file_s *rf, uint32_t sector);
 int  romfs_hwconfigure(FAR struct romfs_mountpt_s *rm);
-int  romfs_fsconfigure(FAR struct romfs_mountpt_s *rm);
+int  romfs_fsconfigure(FAR struct romfs_mountpt_s *rm, FAR const void *data);
 int  romfs_fileconfigure(FAR struct romfs_mountpt_s *rm,
                          FAR struct romfs_file_s *rf);
 int  romfs_checkmount(FAR struct romfs_mountpt_s *rm);
@@ -212,6 +230,9 @@ int  romfs_datastart(FAR struct romfs_mountpt_s *rm,
 #ifdef CONFIG_FS_ROMFS_CACHE_NODE
 void romfs_freenode(FAR struct romfs_nodeinfo_s *node);
 #endif
+#ifdef CONFIG_FS_ROMFS_WRITEABLE
+void romfs_free_sparelist(FAR struct list_node *list);
+#endif
 
 #undef EXTERN
 #if defined(__cplusplus)
diff --git a/fs/romfs/fs_romfsutil.c b/fs/romfs/fs_romfsutil.c
index 84310ec04f..16dd0d1045 100644
--- a/fs/romfs/fs_romfsutil.c
+++ b/fs/romfs/fs_romfsutil.c
@@ -395,6 +395,127 @@ static inline int romfs_searchdir(FAR struct 
romfs_mountpt_s *rm,
   return -ENOENT;
 }
 
+#ifdef CONFIG_FS_ROMFS_WRITEABLE
+/****************************************************************************
+ * Name: romfs_alloc_sparenode
+ *
+ * Description:
+ *   Allocate the spare node
+ *
+ ****************************************************************************/
+
+static FAR struct romfs_sparenode_s *
+romfs_alloc_sparenode(uint32_t start, uint32_t end)
+{
+  FAR struct romfs_sparenode_s *node;
+  node = kmm_malloc(sizeof(struct romfs_sparenode_s));
+  if (node == NULL)
+    {
+      ferr("romfs_alloc_sparenode: no memory\n");
+      return NULL;
+    }
+
+  node->start = start;
+  node->end = end;
+  return node;
+}
+
+/****************************************************************************
+ * Name: romfs_init_sparelist
+ *
+ * Description:
+ *   Init the sparelist
+ *
+ ****************************************************************************/
+
+static int romfs_init_sparelist(FAR struct romfs_mountpt_s *rm, bool rw)
+{
+  FAR struct romfs_sparenode_s *node;
+
+  list_initialize(&rm->rm_sparelist);
+  if (!rw)
+    {
+      return 0;
+    }
+
+  node = romfs_alloc_sparenode(0, rm->rm_hwsectorsize *
+                               rm->rm_hwnsectors);
+  if (node == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  list_add_head(&rm->rm_sparelist, &node->node);
+  rm->rm_volsize = 0;
+  return 0;
+}
+
+/****************************************************************************
+ * Name: romfs_alloc_spareregion
+ *
+ * Description:
+ *   Allocate the spare region
+ *
+ ****************************************************************************/
+
+static int romfs_alloc_spareregion(FAR struct list_node *list,
+                                   uint32_t start, uint32_t end)
+{
+  FAR struct romfs_sparenode_s *node;
+
+  list_for_every_entry(list, node, struct romfs_sparenode_s, node)
+    {
+      /* Find the node that start ~ end
+       * is in node->start ~ node->end
+       */
+
+      if (start == node->start && end == node->end)
+        {
+          /* Delete the node */
+
+          list_delete(&node->node);
+          kmm_free(node);
+          return 0;
+        }
+      else if (start == node->start)
+        {
+          /* Update the node */
+
+          node->start = end;
+          return 0;
+        }
+      else if (end == node->end)
+        {
+          /* Update the node */
+
+          node->end = start;
+          return 0;
+        }
+      else if (start > node->start && end < node->end)
+        {
+          /* Split the node */
+
+          FAR struct romfs_sparenode_s *new;
+          new = romfs_alloc_sparenode(end, node->end);
+          if (new == NULL)
+            {
+              return -ENOMEM;
+            }
+
+          node->end = start;
+          list_add_after(&node->node, &new->node);
+          return 0;
+        }
+    }
+
+  /* Not found */
+
+  ferr("No space for start %" PRIu32 ", end %" PRIu32 "\n", start,
+        end);
+  return -ENOENT;
+}
+#endif
+
 /****************************************************************************
  * Name: romfs_cachenode
  *
@@ -431,6 +552,26 @@ static int romfs_cachenode(FAR struct romfs_mountpt_s *rm,
   nodeinfo->rn_next       = next;
   nodeinfo->rn_namesize   = nsize;
   strlcpy(nodeinfo->rn_name, name, nsize + 1);
+
+#ifdef CONFIG_FS_ROMFS_WRITEABLE
+  if (!list_is_empty(&rm->rm_sparelist))
+    {
+      uint32_t totalsize = ROMFS_ALIGNUP(ROMFS_FHDR_NAME + nsize + 1);
+      if (offset == origoffset)
+        {
+          totalsize += size;
+        }
+
+      rm->rm_volsize += totalsize;
+      ret = romfs_alloc_spareregion(&rm->rm_sparelist, offset,
+                                    offset + totalsize);
+      if (ret < 0)
+        {
+          return ret;
+        }
+    }
+#endif
+
   if (!IS_DIRECTORY(next) || (strcmp(name, ".") == 0) ||
       (strcmp(name, "..") == 0))
     {
@@ -686,6 +827,27 @@ int romfs_hwconfigure(FAR struct romfs_mountpt_s *rm)
   return OK;
 }
 
+/****************************************************************************
+ * Name: romfs_free_sparelist
+ *
+ * Description:
+ *   Free the sparelist
+ *
+ ****************************************************************************/
+#ifdef CONFIG_FS_ROMFS_WRITEABLE
+void romfs_free_sparelist(FAR struct list_node *list)
+{
+  FAR struct romfs_sparenode_s *node;
+  FAR struct romfs_sparenode_s *tmp;
+
+  list_for_every_entry_safe(list, node, tmp, struct romfs_sparenode_s, node)
+    {
+      list_delete(&node->node);
+      kmm_free(node);
+    }
+}
+#endif
+
 /****************************************************************************
  * Name: romfs_fsconfigure
  *
@@ -697,20 +859,20 @@ int romfs_hwconfigure(FAR struct romfs_mountpt_s *rm)
  *
  ****************************************************************************/
 
-int romfs_fsconfigure(FAR struct romfs_mountpt_s *rm)
+int romfs_fsconfigure(FAR struct romfs_mountpt_s *rm, FAR const void *data)
 {
   FAR const char *name;
-  int16_t         ndx;
+  int             ret;
   uint32_t        rootoffset;
 
   /* Then get information about the ROMFS filesystem on the devices managed
    * by this block driver. Read sector zero which contains the volume header.
    */
 
-  ndx = romfs_devcacheread(rm, 0);
-  if (ndx < 0)
+  ret = romfs_devcacheread(rm, 0);
+  if (ret < 0)
     {
-      return ndx;
+      return ret;
     }
 
   /* Verify the magic number at that identifies this as a ROMFS filesystem */
@@ -722,19 +884,30 @@ int romfs_fsconfigure(FAR struct romfs_mountpt_s *rm)
 
   /* Then extract the values we need from the header and return success */
 
-  rm->rm_volsize    = romfs_devread32(rm, ROMFS_VHDR_SIZE);
+  rm->rm_volsize = romfs_devread32(rm, ROMFS_VHDR_SIZE);
 
   /* The root directory entry begins right after the header */
 
-  name              = (FAR const char *)&rm->rm_buffer[ROMFS_VHDR_VOLNAME];
-  rootoffset        = ROMFS_ALIGNUP(ROMFS_VHDR_VOLNAME + strlen(name) + 1);
+  name = (FAR const char *)&rm->rm_buffer[ROMFS_VHDR_VOLNAME];
+  rootoffset = ROMFS_ALIGNUP(ROMFS_VHDR_VOLNAME + strlen(name) + 1);
+#ifdef CONFIG_FS_ROMFS_WRITEABLE
+  ret = romfs_init_sparelist(rm, data && strstr(data, "rw"));
+  if (ret < 0)
+    {
+      return ret;
+    }
+#endif
+
 #ifdef CONFIG_FS_ROMFS_CACHE_NODE
-  ndx               = romfs_cachenode(rm, 0, rootoffset, RFNEXT_DIRECTORY,
-                                      0, "", &rm->rm_root);
-  if (ndx < 0)
+  ret = romfs_cachenode(rm, 0, rootoffset, RFNEXT_DIRECTORY,
+                        0, "", &rm->rm_root);
+  if (ret < 0)
     {
+#  ifdef CONFIG_FS_ROMFS_WRITEABLE
+      romfs_free_sparelist(&rm->rm_sparelist);
+#  endif
       romfs_freenode(rm->rm_root);
-      return ndx;
+      return ret;
     }
 #else
   rm->rm_rootoffset = rootoffset;
@@ -742,7 +915,7 @@ int romfs_fsconfigure(FAR struct romfs_mountpt_s *rm)
 
   /* and return success */
 
-  rm->rm_mounted    = true;
+  rm->rm_mounted = true;
   return OK;
 }
 

Reply via email to