romfs:extend romfs to enable write part2

add sparelist api

Signed-off-by: guohao15 <guohao15@xiaomi.com>
This commit is contained in:
guohao15 2024-01-04 20:52:51 +08:00 committed by GUIDINGLI
parent f3840cf141
commit c61734a469
4 changed files with 222 additions and 18 deletions

View file

@ -27,4 +27,11 @@ config FS_ROMFS_CACHE_FILE_NSECTORS
---help--- ---help---
The number of file cache sector 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 endif

View file

@ -1128,7 +1128,7 @@ static int romfs_bind(FAR struct inode *blkdriver, FAR const void *data,
* the ROMF header * the ROMF header
*/ */
ret = romfs_fsconfigure(rm); ret = romfs_fsconfigure(rm, data);
if (ret < 0) if (ret < 0)
{ {
ferr("ERROR: romfs_fsconfigure failed: %d\n", ret); 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 #ifdef CONFIG_FS_ROMFS_CACHE_NODE
romfs_freenode(rm->rm_root); romfs_freenode(rm->rm_root);
#endif
#ifdef CONFIG_FS_ROMFS_WRITEABLE
romfs_free_sparelist(&rm->rm_sparelist);
#endif #endif
nxrmutex_destroy(&rm->rm_lock); nxrmutex_destroy(&rm->rm_lock);
fs_heap_free(rm); 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 */ /* Everything else follows in units of sectors */
buf->f_blocks = SEC_NSECTORS(rm, rm->rm_volsize + SEC_NDXMASK(rm)); buf->f_blocks = SEC_NSECTORS(rm, rm->rm_volsize + SEC_NDXMASK(rm));
buf->f_bfree = 0; buf->f_bfree = rm->rm_hwnsectors - buf->f_blocks;
buf->f_bavail = 0; buf->f_bavail = buf->f_bfree;
buf->f_namelen = NAME_MAX; buf->f_namelen = NAME_MAX;
errout_with_lock: errout_with_lock:

View file

@ -26,6 +26,7 @@
****************************************************************************/ ****************************************************************************/
#include <nuttx/config.h> #include <nuttx/config.h>
#include <nuttx/list.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
@ -116,6 +117,20 @@
* Public Types * 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 represents the overall mountpoint state. An instance of
* this structure is retained as inode private data on each mountpoint that * this structure is retained as inode private data on each mountpoint that
* is mounted with a romfs filesystem. * is mounted with a romfs filesystem.
@ -139,6 +154,9 @@ struct romfs_mountpt_s
uint32_t rm_cachesector; /* Current sector in the rm_buffer */ 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_xipbase; /* Base address of directly accessible media */
FAR uint8_t *rm_buffer; /* Device sector buffer, allocated if rm_xipbase==0 */ 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 /* 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, int romfs_filecacheread(FAR struct romfs_mountpt_s *rm,
FAR struct romfs_file_s *rf, uint32_t sector); FAR struct romfs_file_s *rf, uint32_t sector);
int romfs_hwconfigure(FAR struct romfs_mountpt_s *rm); 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, int romfs_fileconfigure(FAR struct romfs_mountpt_s *rm,
FAR struct romfs_file_s *rf); FAR struct romfs_file_s *rf);
int romfs_checkmount(FAR struct romfs_mountpt_s *rm); 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 #ifdef CONFIG_FS_ROMFS_CACHE_NODE
void romfs_freenode(FAR struct romfs_nodeinfo_s *node); void romfs_freenode(FAR struct romfs_nodeinfo_s *node);
#endif #endif
#ifdef CONFIG_FS_ROMFS_WRITEABLE
void romfs_free_sparelist(FAR struct list_node *list);
#endif
#undef EXTERN #undef EXTERN
#if defined(__cplusplus) #if defined(__cplusplus)

View file

@ -395,6 +395,127 @@ static inline int romfs_searchdir(FAR struct romfs_mountpt_s *rm,
return -ENOENT; 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 * Name: romfs_cachenode
* *
@ -431,6 +552,26 @@ static int romfs_cachenode(FAR struct romfs_mountpt_s *rm,
nodeinfo->rn_next = next; nodeinfo->rn_next = next;
nodeinfo->rn_namesize = nsize; nodeinfo->rn_namesize = nsize;
strlcpy(nodeinfo->rn_name, name, nsize + 1); 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) || if (!IS_DIRECTORY(next) || (strcmp(name, ".") == 0) ||
(strcmp(name, "..") == 0)) (strcmp(name, "..") == 0))
{ {
@ -686,6 +827,27 @@ int romfs_hwconfigure(FAR struct romfs_mountpt_s *rm)
return OK; 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 * 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; FAR const char *name;
int16_t ndx; int ret;
uint32_t rootoffset; uint32_t rootoffset;
/* Then get information about the ROMFS filesystem on the devices managed /* Then get information about the ROMFS filesystem on the devices managed
* by this block driver. Read sector zero which contains the volume header. * by this block driver. Read sector zero which contains the volume header.
*/ */
ndx = romfs_devcacheread(rm, 0); ret = romfs_devcacheread(rm, 0);
if (ndx < 0) if (ret < 0)
{ {
return ndx; return ret;
} }
/* Verify the magic number at that identifies this as a ROMFS filesystem */ /* 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 */ /* 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 */ /* The root directory entry begins right after the header */
name = (FAR const char *)&rm->rm_buffer[ROMFS_VHDR_VOLNAME]; name = (FAR const char *)&rm->rm_buffer[ROMFS_VHDR_VOLNAME];
rootoffset = ROMFS_ALIGNUP(ROMFS_VHDR_VOLNAME + strlen(name) + 1); rootoffset = ROMFS_ALIGNUP(ROMFS_VHDR_VOLNAME + strlen(name) + 1);
#ifdef CONFIG_FS_ROMFS_CACHE_NODE #ifdef CONFIG_FS_ROMFS_WRITEABLE
ndx = romfs_cachenode(rm, 0, rootoffset, RFNEXT_DIRECTORY, ret = romfs_init_sparelist(rm, data && strstr(data, "rw"));
0, "", &rm->rm_root); if (ret < 0)
if (ndx < 0)
{ {
return ret;
}
#endif
#ifdef CONFIG_FS_ROMFS_CACHE_NODE
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); romfs_freenode(rm->rm_root);
return ndx; return ret;
} }
#else #else
rm->rm_rootoffset = rootoffset; rm->rm_rootoffset = rootoffset;
@ -742,7 +915,7 @@ int romfs_fsconfigure(FAR struct romfs_mountpt_s *rm)
/* and return success */ /* and return success */
rm->rm_mounted = true; rm->rm_mounted = true;
return OK; return OK;
} }