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---
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

View file

@ -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:

View file

@ -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)

View file

@ -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);
#ifdef CONFIG_FS_ROMFS_CACHE_NODE
ndx = romfs_cachenode(rm, 0, rootoffset, RFNEXT_DIRECTORY,
0, "", &rm->rm_root);
if (ndx < 0)
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
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;
}