mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 06:18:40 +08:00
romfs:extend romfs to enable write part2
add sparelist api Signed-off-by: guohao15 <guohao15@xiaomi.com>
This commit is contained in:
parent
f3840cf141
commit
c61734a469
4 changed files with 222 additions and 18 deletions
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue