mirror of
https://github.com/apache/nuttx.git
synced 2026-03-27 02:29:15 +08:00
fs/mnemofs: Fix journal log rw issue, read size issue
Fixes the journal log read and write size and overlap issues, along with read return value issue. Signed-off-by: Saurav Pal <resyfer.dev@gmail.com>
This commit is contained in:
committed by
Alan Carvalho de Assis
parent
9d396bf89e
commit
daa3168cfb
@@ -295,7 +295,7 @@ int nand_ram_eraseblock(FAR struct nand_raw_s *raw, off_t block)
|
|||||||
for (i = start_page; i < end_page; i++)
|
for (i = start_page; i < end_page; i++)
|
||||||
{
|
{
|
||||||
nand_ram_flash_spare[i].n_erase++;
|
nand_ram_flash_spare[i].n_erase++;
|
||||||
nand_ram_flash_spare[i].free = 1;
|
nand_ram_flash_spare[i].free = NAND_RAM_PAGE_FREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
NAND_RAM_LOG("[LOWER %lu | %s] Done\n", nand_ram_ins_i, "eraseblock");
|
NAND_RAM_LOG("[LOWER %lu | %s] Done\n", nand_ram_ins_i, "eraseblock");
|
||||||
@@ -331,12 +331,11 @@ int nand_ram_rawread(FAR struct nand_raw_s *raw, off_t block,
|
|||||||
struct nand_ram_data_s *read_page_data;
|
struct nand_ram_data_s *read_page_data;
|
||||||
struct nand_ram_spare_s *read_page_spare;
|
struct nand_ram_spare_s *read_page_spare;
|
||||||
|
|
||||||
|
ret = OK;
|
||||||
read_page = (block << NAND_RAM_LOG_PAGES_PER_BLOCK) + page;
|
read_page = (block << NAND_RAM_LOG_PAGES_PER_BLOCK) + page;
|
||||||
read_page_data = nand_ram_flash_data + read_page;
|
read_page_data = nand_ram_flash_data + read_page;
|
||||||
read_page_spare = nand_ram_flash_spare + read_page;
|
read_page_spare = nand_ram_flash_spare + read_page;
|
||||||
|
|
||||||
ret = OK;
|
|
||||||
|
|
||||||
nxmutex_lock(&nand_ram_dev_mut);
|
nxmutex_lock(&nand_ram_dev_mut);
|
||||||
nand_ram_ins_i++;
|
nand_ram_ins_i++;
|
||||||
|
|
||||||
@@ -362,7 +361,8 @@ int nand_ram_rawread(FAR struct nand_raw_s *raw, off_t block,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy(data, (const void *)read_page_data, NAND_RAM_PAGE_SIZE);
|
memcpy(data, (const void *)read_page_data->page,
|
||||||
|
NAND_RAM_PAGE_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,12 +407,11 @@ int nand_ram_rawwrite(FAR struct nand_raw_s *raw, off_t block,
|
|||||||
struct nand_ram_data_s *write_page_data;
|
struct nand_ram_data_s *write_page_data;
|
||||||
struct nand_ram_spare_s *write_page_spare;
|
struct nand_ram_spare_s *write_page_spare;
|
||||||
|
|
||||||
|
ret = OK;
|
||||||
write_page = (block << NAND_RAM_LOG_PAGES_PER_BLOCK) + page;
|
write_page = (block << NAND_RAM_LOG_PAGES_PER_BLOCK) + page;
|
||||||
write_page_data = nand_ram_flash_data + write_page;
|
write_page_data = nand_ram_flash_data + write_page;
|
||||||
write_page_spare = nand_ram_flash_spare + write_page;
|
write_page_spare = nand_ram_flash_spare + write_page;
|
||||||
|
|
||||||
ret = OK;
|
|
||||||
|
|
||||||
nxmutex_lock(&nand_ram_dev_mut);
|
nxmutex_lock(&nand_ram_dev_mut);
|
||||||
nand_ram_ins_i++;
|
nand_ram_ins_i++;
|
||||||
|
|
||||||
@@ -429,16 +428,17 @@ int nand_ram_rawwrite(FAR struct nand_raw_s *raw, off_t block,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nand_ram_flash_spare[write_page].n_write++;
|
nand_ram_flash_spare[write_page].n_write++;
|
||||||
|
nand_ram_flash_spare[write_page].free = NAND_RAM_PAGE_WRITTEN;
|
||||||
|
|
||||||
memset((void *)write_page_data, 0, NAND_RAM_PAGE_SIZE);
|
memset((void *)write_page_data->page, 0, NAND_RAM_PAGE_SIZE);
|
||||||
if (data != NULL)
|
if (data != NULL)
|
||||||
{
|
{
|
||||||
memcpy((void *)write_page_data, data, NAND_RAM_PAGE_SIZE);
|
memcpy((void *)write_page_data->page, data, NAND_RAM_PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spare != NULL)
|
if (spare != NULL)
|
||||||
{
|
{
|
||||||
memcpy((void *)write_page_spare, data, NAND_RAM_PAGE_SIZE);
|
memcpy((void *)write_page_spare, data, NAND_RAM_SPARE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
NAND_RAM_LOG("[LOWER %lu | %s] Done\n", nand_ram_ins_i, "rawwrite");
|
NAND_RAM_LOG("[LOWER %lu | %s] Done\n", nand_ram_ins_i, "rawwrite");
|
||||||
|
|||||||
@@ -214,10 +214,6 @@ const struct mountpt_operations g_mnemofs_operations =
|
|||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Public Functions
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mnemofs_open
|
* Name: mnemofs_open
|
||||||
*
|
*
|
||||||
@@ -393,8 +389,7 @@ static int mnemofs_open(FAR struct file *filep, FAR const char *relpath,
|
|||||||
f->com->off = f->com->sz;
|
f->com->off = f->com->sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
finfo("[TMP1] %p %p", &sb->of, &f->list);
|
list_add_tail(&MFS_OFILES(sb), &f->list);
|
||||||
list_add_tail(&sb->of, &f->list);
|
|
||||||
filep->f_priv = f;
|
filep->f_priv = f;
|
||||||
|
|
||||||
nxmutex_unlock(&MFS_LOCK(sb));
|
nxmutex_unlock(&MFS_LOCK(sb));
|
||||||
@@ -471,23 +466,31 @@ static int mnemofs_close(FAR struct file *filep)
|
|||||||
|
|
||||||
/* Flushing in-memory data to on-flash journal. */
|
/* Flushing in-memory data to on-flash journal. */
|
||||||
|
|
||||||
ret = mfs_lru_ctzflush(sb, f->com->path, f->com->depth);
|
finfo("Original refcount is %u.", f->com->refcount);
|
||||||
if (predict_false(ret < 0))
|
|
||||||
{
|
|
||||||
finfo("Error while flushing file. Ret: %d.", ret);
|
|
||||||
goto errout_with_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
f->com->refcount--;
|
f->com->refcount--;
|
||||||
|
|
||||||
if (f->com->refcount == 0)
|
if (f->com->refcount == 0)
|
||||||
{
|
{
|
||||||
|
ret = mnemofs_flush(sb);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
finfo("Error while flushing. Ret: %d.", ret);
|
||||||
|
goto errout_with_lock;
|
||||||
|
}
|
||||||
|
|
||||||
kmm_free(f->com->path);
|
kmm_free(f->com->path);
|
||||||
kmm_free(f->com);
|
kmm_free(f->com);
|
||||||
|
|
||||||
finfo("Refcount is 0, open file structure freed.");
|
finfo("Open file structure freed.");
|
||||||
|
|
||||||
|
ret = mnemofs_flush(sb);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
goto errout_with_fcom;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errout_with_fcom:
|
||||||
list_delete(&f->list);
|
list_delete(&f->list);
|
||||||
kmm_free(f);
|
kmm_free(f);
|
||||||
filep->f_priv = NULL;
|
filep->f_priv = NULL;
|
||||||
@@ -524,14 +527,14 @@ errout:
|
|||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* 0 - OK
|
* 0 - OK
|
||||||
* < 0 - Error
|
* <= 0 - Bytes read.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t mnemofs_read(FAR struct file *filep, FAR char *buffer,
|
static ssize_t mnemofs_read(FAR struct file *filep, FAR char *buffer,
|
||||||
size_t buflen)
|
size_t buflen)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
ssize_t ret = 0;
|
||||||
FAR struct inode *inode;
|
FAR struct inode *inode;
|
||||||
FAR struct mfs_sb_s *sb;
|
FAR struct mfs_sb_s *sb;
|
||||||
FAR struct mfs_ofd_s *f;
|
FAR struct mfs_ofd_s *f;
|
||||||
@@ -567,6 +570,11 @@ static ssize_t mnemofs_read(FAR struct file *filep, FAR char *buffer,
|
|||||||
|
|
||||||
/* Read data in CTZ from the current offset. */
|
/* Read data in CTZ from the current offset. */
|
||||||
|
|
||||||
|
buflen = MIN(buflen, f->com->sz - f->com->off); /* TODO: Need to consider
|
||||||
|
* if this needs to be
|
||||||
|
* lower down the chain.
|
||||||
|
*/
|
||||||
|
|
||||||
ret = mfs_lru_rdfromoff(sb, f->com->off, f->com->path, f->com->depth,
|
ret = mfs_lru_rdfromoff(sb, f->com->off, f->com->path, f->com->depth,
|
||||||
buffer, buflen);
|
buffer, buflen);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@@ -575,6 +583,8 @@ static ssize_t mnemofs_read(FAR struct file *filep, FAR char *buffer,
|
|||||||
goto errout_with_lock;
|
goto errout_with_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = buflen;
|
||||||
|
|
||||||
/* Update offset. */
|
/* Update offset. */
|
||||||
|
|
||||||
f->com->off += buflen;
|
f->com->off += buflen;
|
||||||
@@ -602,14 +612,14 @@ errout:
|
|||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* 0 - OK
|
* 0 - OK
|
||||||
* < 0 - Error
|
* <= 0 - Bytes written.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t mnemofs_write(FAR struct file *filep, FAR const char *buffer,
|
static ssize_t mnemofs_write(FAR struct file *filep, FAR const char *buffer,
|
||||||
size_t buflen)
|
size_t buflen)
|
||||||
{
|
{
|
||||||
int ret = OK;
|
ssize_t ret = OK;
|
||||||
FAR struct inode *inode;
|
FAR struct inode *inode;
|
||||||
FAR struct mfs_sb_s *sb;
|
FAR struct mfs_sb_s *sb;
|
||||||
FAR struct mfs_ofd_s *f;
|
FAR struct mfs_ofd_s *f;
|
||||||
@@ -655,6 +665,7 @@ static ssize_t mnemofs_write(FAR struct file *filep, FAR const char *buffer,
|
|||||||
|
|
||||||
f->com->off += buflen;
|
f->com->off += buflen;
|
||||||
f->com->sz = MAX(f->com->sz, f->com->off);
|
f->com->sz = MAX(f->com->sz, f->com->off);
|
||||||
|
ret = buflen;
|
||||||
|
|
||||||
finfo("Offset updated to %u and size to %u", f->com->off, f->com->sz);
|
finfo("Offset updated to %u and size to %u", f->com->off, f->com->sz);
|
||||||
|
|
||||||
@@ -688,7 +699,7 @@ errout:
|
|||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* 0 - OK
|
* 0 - OK
|
||||||
* < 0 - Error
|
* <= 0 - Final position.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
@@ -752,6 +763,7 @@ static off_t mnemofs_seek(FAR struct file *filep, off_t offset, int whence)
|
|||||||
}
|
}
|
||||||
|
|
||||||
f->com->off = pos;
|
f->com->off = pos;
|
||||||
|
ret = pos;
|
||||||
|
|
||||||
finfo("Final position %u.", pos);
|
finfo("Final position %u.", pos);
|
||||||
|
|
||||||
@@ -933,7 +945,7 @@ static int mnemofs_sync(FAR struct file *filep)
|
|||||||
f = filep->f_priv;
|
f = filep->f_priv;
|
||||||
DEBUGASSERT(f != NULL);
|
DEBUGASSERT(f != NULL);
|
||||||
|
|
||||||
ret = mfs_lru_ctzflush(sb, f->com->path, f->com->depth);
|
ret = mnemofs_flush(sb);
|
||||||
|
|
||||||
nxmutex_unlock(&MFS_LOCK(sb));
|
nxmutex_unlock(&MFS_LOCK(sb));
|
||||||
finfo("Lock released.");
|
finfo("Lock released.");
|
||||||
@@ -1014,7 +1026,8 @@ static int mnemofs_dup(FAR const struct file *oldp, FAR struct file *newp)
|
|||||||
|
|
||||||
/* Add the new upper half to the list of open fds. */
|
/* Add the new upper half to the list of open fds. */
|
||||||
|
|
||||||
list_add_tail(&sb->of, &nf->list);
|
list_add_tail(&MFS_OFILES(sb), &nf->list);
|
||||||
|
newp->f_priv = nf;
|
||||||
finfo("New file descriptor added to the end of the list of open files.");
|
finfo("New file descriptor added to the end of the list of open files.");
|
||||||
|
|
||||||
nxmutex_unlock(&MFS_LOCK(sb));
|
nxmutex_unlock(&MFS_LOCK(sb));
|
||||||
@@ -1467,6 +1480,9 @@ static int mnemofs_bind(FAR struct inode *driver, FAR const void *data,
|
|||||||
bool format = false;
|
bool format = false;
|
||||||
FAR char buf[8];
|
FAR char buf[8];
|
||||||
mfs_t i = 0;
|
mfs_t i = 0;
|
||||||
|
mfs_t mnblk1;
|
||||||
|
mfs_t mnblk2;
|
||||||
|
mfs_t jrnl_blk;
|
||||||
FAR struct mfs_sb_s *sb = NULL;
|
FAR struct mfs_sb_s *sb = NULL;
|
||||||
struct mtd_geometry_s geo;
|
struct mtd_geometry_s geo;
|
||||||
|
|
||||||
@@ -1522,16 +1538,17 @@ static int mnemofs_bind(FAR struct inode *driver, FAR const void *data,
|
|||||||
sb->n_blks = geo.neraseblocks;
|
sb->n_blks = geo.neraseblocks;
|
||||||
sb->pg_in_blk = MFS_BLKSZ(sb) / sb->pg_sz;
|
sb->pg_in_blk = MFS_BLKSZ(sb) / sb->pg_sz;
|
||||||
#ifdef CONFIG_MNEMOFS_JOURNAL_NBLKS
|
#ifdef CONFIG_MNEMOFS_JOURNAL_NBLKS
|
||||||
sb->j_nblks = CONFIG_MNEMOFS_JOURNAL_NBLKS;
|
MFS_JRNL(sb).n_blks = CONFIG_MNEMOFS_JOURNAL_NBLKS;
|
||||||
#else
|
#else
|
||||||
sb->j_nblks = MIN(5, MFS_NBLKS(sb) / 2);
|
MFS_JRNL(sb).n_blks = MIN(5, MFS_NBLKS(sb) / 2);
|
||||||
#endif
|
#endif
|
||||||
sb->log_blk_sz = log2(MFS_BLKSZ(sb));
|
sb->log_blk_sz = log2(MFS_BLKSZ(sb));
|
||||||
sb->log_pg_sz = log2(sb->pg_sz);
|
sb->log_pg_sz = log2(sb->pg_sz);
|
||||||
sb->log_pg_in_blk = log2(sb->pg_in_blk);
|
sb->log_pg_in_blk = log2(sb->pg_in_blk);
|
||||||
sb->log_n_blks = log2(MFS_NBLKS(sb));
|
sb->log_n_blks = log2(MFS_NBLKS(sb));
|
||||||
|
MFS_FLUSH(sb) = false;
|
||||||
|
|
||||||
list_initialize(&sb->of);
|
list_initialize(&MFS_OFILES(sb));
|
||||||
|
|
||||||
sb->rw_buf = kmm_zalloc(MFS_PGSZ(sb));
|
sb->rw_buf = kmm_zalloc(MFS_PGSZ(sb));
|
||||||
if (predict_false(sb->rw_buf == NULL))
|
if (predict_false(sb->rw_buf == NULL))
|
||||||
@@ -1542,8 +1559,6 @@ static int mnemofs_bind(FAR struct inode *driver, FAR const void *data,
|
|||||||
/* TODO: Print the super block in Block 0. */
|
/* TODO: Print the super block in Block 0. */
|
||||||
|
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
mfs_ba_init(sb);
|
|
||||||
mfs_lru_init(sb);
|
|
||||||
|
|
||||||
if (!strncmp(data, "autoformat", 11))
|
if (!strncmp(data, "autoformat", 11))
|
||||||
{
|
{
|
||||||
@@ -1575,6 +1590,9 @@ static int mnemofs_bind(FAR struct inode *driver, FAR const void *data,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
finfo("Device already formatted.\n");
|
finfo("Device already formatted.\n");
|
||||||
|
|
||||||
|
mfs_ba_init(sb);
|
||||||
|
mfs_lru_init(sb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1587,8 +1605,19 @@ static int mnemofs_bind(FAR struct inode *driver, FAR const void *data,
|
|||||||
finfo("Force format.\n");
|
finfo("Force format.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = mfs_jrnl_fmt(sb, 0, 0);
|
mfs_ba_fmt(sb);
|
||||||
if (ret != OK)
|
mfs_lru_init(sb);
|
||||||
|
|
||||||
|
mnblk1 = 0;
|
||||||
|
mnblk2 = 0;
|
||||||
|
ret = mfs_jrnl_fmt(sb, &mnblk1, &mnblk2, &jrnl_blk);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
goto errout_with_sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mfs_mn_fmt(sb, mnblk1, mnblk2, jrnl_blk);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
{
|
{
|
||||||
goto errout_with_sb;
|
goto errout_with_sb;
|
||||||
}
|
}
|
||||||
@@ -1755,7 +1784,7 @@ static int mnemofs_unlink(FAR struct inode *mountpt, FAR const char *relpath)
|
|||||||
goto errout_with_lock;
|
goto errout_with_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
mfs_pitr_rm(sb, path, depth);
|
mfs_pitr_rm(sb, path, depth, true);
|
||||||
|
|
||||||
mfs_free_patharr(path);
|
mfs_free_patharr(path);
|
||||||
|
|
||||||
@@ -1941,7 +1970,7 @@ static int mnemofs_rmdir(FAR struct inode *mountpt, FAR const char *relpath)
|
|||||||
|
|
||||||
mfs_pitr_free(&pitr);
|
mfs_pitr_free(&pitr);
|
||||||
|
|
||||||
mfs_pitr_rm(sb, path, depth);
|
mfs_pitr_rm(sb, path, depth, true);
|
||||||
|
|
||||||
errout_with_pitr:
|
errout_with_pitr:
|
||||||
mfs_free_patharr(path);
|
mfs_free_patharr(path);
|
||||||
@@ -2061,7 +2090,7 @@ static int mnemofs_rename(FAR struct inode *mountpt,
|
|||||||
|
|
||||||
mfs_pitr_reset(&npitr);
|
mfs_pitr_reset(&npitr);
|
||||||
|
|
||||||
mfs_pitr_rm(sb, npath, ndepth);
|
mfs_pitr_rm(sb, npath, ndepth, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
mfs_pitr_adv_tochild(&npitr, npath);
|
mfs_pitr_adv_tochild(&npitr, npath);
|
||||||
@@ -2133,6 +2162,9 @@ static int mnemofs_stat(FAR struct inode *mountpt, FAR const char *relpath,
|
|||||||
|
|
||||||
finfo("Lock acquired.");
|
finfo("Lock acquired.");
|
||||||
|
|
||||||
|
finfo("Master node: Root (%u, %u), Size %u", MFS_MN(sb).root_ctz.idx_e,
|
||||||
|
MFS_MN(sb).root_ctz.pg_e, MFS_MN(sb).root_sz);
|
||||||
|
|
||||||
ret_flags = mfs_get_patharr(sb, relpath, &path, &depth);
|
ret_flags = mfs_get_patharr(sb, relpath, &path, &depth);
|
||||||
if ((ret_flags & MFS_EXIST) == 0)
|
if ((ret_flags & MFS_EXIST) == 0)
|
||||||
{
|
{
|
||||||
@@ -2187,3 +2219,59 @@ errout:
|
|||||||
finfo("Ret %d", ret);
|
finfo("Ret %d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int mnemofs_flush(FAR struct mfs_sb_s *sb)
|
||||||
|
{
|
||||||
|
int ret = OK;
|
||||||
|
bool change;
|
||||||
|
|
||||||
|
/* Emtpy the LRU, and maybe the journal as well. */
|
||||||
|
|
||||||
|
finfo("Flush operation started.");
|
||||||
|
|
||||||
|
for (; ; )
|
||||||
|
{
|
||||||
|
change = false;
|
||||||
|
if (!mfs_lru_isempty(sb))
|
||||||
|
{
|
||||||
|
finfo("LRU needs to be flushed.");
|
||||||
|
|
||||||
|
change = true;
|
||||||
|
ret = mfs_lru_flush(sb);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mfs_jrnl_isempty(sb) &&
|
||||||
|
MFS_JRNL(sb).log_cblkidx >= MFS_JRNL_LIM(sb))
|
||||||
|
{
|
||||||
|
finfo("Journal needs to be flushed.");
|
||||||
|
|
||||||
|
change = true;
|
||||||
|
|
||||||
|
ret = mfs_jrnl_flush(sb);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!change)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
finfo("Finished Iteration.");
|
||||||
|
}
|
||||||
|
|
||||||
|
errout:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Superblock still doesn't exist. Plus bug fixes. */
|
||||||
@@ -86,14 +86,17 @@
|
|||||||
#define MFS_RWBUF(sb) ((sb)->rw_buf)
|
#define MFS_RWBUF(sb) ((sb)->rw_buf)
|
||||||
#define MFS_BA(sb) ((sb)->ba_state)
|
#define MFS_BA(sb) ((sb)->ba_state)
|
||||||
#define MFS_NBLKS(sb) ((sb)->n_blks)
|
#define MFS_NBLKS(sb) ((sb)->n_blks)
|
||||||
|
#define MFS_OFILES(sb) ((sb)->of)
|
||||||
|
#define MFS_FLUSH(sb) ((sb)->flush)
|
||||||
#define MFS_NPGS(sb) (MFS_NBLKS(sb) * MFS_PGINBLK(sb))
|
#define MFS_NPGS(sb) (MFS_NBLKS(sb) * MFS_PGINBLK(sb))
|
||||||
|
|
||||||
#define MFS_HASHSZ 16
|
#define MFS_HASHSZ 16
|
||||||
#define MFS_CTZ_SZ(l) ((l)->sz)
|
#define MFS_CTZ_SZ(l) ((l)->sz)
|
||||||
#define MFS_DIRENTSZ(dirent) ((mfs_t) (sizeof(struct mfs_dirent_s) \
|
#define MFS_DIRENTSZ(dirent) ((2 * 2) + 4 + (16 * 3) + 8 + 1 \
|
||||||
+ (dirent)->namelen))
|
+ (dirent)->namelen)
|
||||||
|
|
||||||
#define MFS_JRNL_LIM(sb) (MFS_JRNL(sb).n_blks) /* TODO: 50-75% */
|
#define MFS_JRNL_LIM(sb) (MFS_JRNL(sb).n_blks / 2)
|
||||||
|
#define MFS_TRAVERSE_INITSZ 8
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Types
|
* Public Types
|
||||||
@@ -149,7 +152,7 @@ struct mfs_mn_s
|
|||||||
{
|
{
|
||||||
mfs_t pg; /* Only mblk1's pg will be used here. */
|
mfs_t pg; /* Only mblk1's pg will be used here. */
|
||||||
mfs_t jrnl_blk; /* Start of journal. */
|
mfs_t jrnl_blk; /* Start of journal. */
|
||||||
mfs_t mblk_idx;
|
mfs_t mblk_idx; /* Index for next MN entry inside blk. */
|
||||||
struct mfs_ctz_s root_ctz;
|
struct mfs_ctz_s root_ctz;
|
||||||
mfs_t root_sz;
|
mfs_t root_sz;
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
@@ -170,7 +173,7 @@ struct mfs_jrnl_state_s
|
|||||||
mfs_t log_sblkidx; /* First jrnl blk index. TODO: jrnlarr > 1 blk. */
|
mfs_t log_sblkidx; /* First jrnl blk index. TODO: jrnlarr > 1 blk. */
|
||||||
mfs_t jrnlarr_pg;
|
mfs_t jrnlarr_pg;
|
||||||
mfs_t jrnlarr_pgoff;
|
mfs_t jrnlarr_pgoff;
|
||||||
uint16_t n_blks;
|
uint16_t n_blks; /* TODO: Does not include the master node. */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mfs_sb_s
|
struct mfs_sb_s
|
||||||
@@ -185,15 +188,14 @@ struct mfs_sb_s
|
|||||||
uint8_t log_blk_sz;
|
uint8_t log_blk_sz;
|
||||||
mfs_t n_blks;
|
mfs_t n_blks;
|
||||||
uint8_t log_n_blks;
|
uint8_t log_n_blks;
|
||||||
mfs_t n_lru;
|
|
||||||
uint16_t pg_in_blk;
|
uint16_t pg_in_blk;
|
||||||
uint8_t log_pg_in_blk;
|
uint8_t log_pg_in_blk;
|
||||||
uint8_t j_nblks;
|
|
||||||
struct mfs_mn_s mn; /* Master Node */
|
struct mfs_mn_s mn; /* Master Node */
|
||||||
struct mfs_jrnl_state_s j_state; /* Journal State */
|
struct mfs_jrnl_state_s j_state; /* Journal State */
|
||||||
struct mfs_ba_state_s ba_state; /* Block Allocator State */
|
struct mfs_ba_state_s ba_state; /* Block Allocator State */
|
||||||
struct list_node lru;
|
struct list_node lru;
|
||||||
struct list_node of; /* open files. */
|
struct list_node of; /* open files. */
|
||||||
|
bool flush;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This is for *dir VFS methods. */
|
/* This is for *dir VFS methods. */
|
||||||
@@ -417,6 +419,10 @@ static inline mfs_t mfs_popcnt(mfs_t x)
|
|||||||
* Public Function Prototypes
|
* Public Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* mnemofs.c */
|
||||||
|
|
||||||
|
int mnemofs_flush(FAR struct mfs_sb_s *sb);
|
||||||
|
|
||||||
/* mnemofs_journal.c */
|
/* mnemofs_journal.c */
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -459,7 +465,8 @@ int mfs_jrnl_init(FAR struct mfs_sb_s * const sb, mfs_t blk);
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2);
|
int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t *blk1, mfs_t *blk2,
|
||||||
|
FAR mfs_t *jrnl_blk);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mfs_jrnl_free
|
* Name: mfs_jrnl_free
|
||||||
@@ -551,7 +558,7 @@ int mfs_jrnl_updatedinfo(FAR const struct mfs_sb_s * const sb,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int mfs_jrnl_wrlog(FAR struct mfs_sb_s * const sb,
|
int mfs_jrnl_wrlog(FAR struct mfs_sb_s * const sb,
|
||||||
const struct mfs_node_s node,
|
FAR const struct mfs_node_s *node,
|
||||||
const struct mfs_ctz_s loc_new, const mfs_t sz_new);
|
const struct mfs_ctz_s loc_new, const mfs_t sz_new);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -572,8 +579,41 @@ int mfs_jrnl_wrlog(FAR struct mfs_sb_s * const sb,
|
|||||||
|
|
||||||
int mfs_jrnl_flush(FAR struct mfs_sb_s * const sb);
|
int mfs_jrnl_flush(FAR struct mfs_sb_s * const sb);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mfs_jrnl_isempty
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Check if the journal is empty.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* sb - Superblock instance of the device.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* True is the journal is empty, false otherwise.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
bool mfs_jrnl_isempty(FAR const struct mfs_sb_s * const sb);
|
||||||
|
|
||||||
/* mnemofs_blkalloc.c */
|
/* mnemofs_blkalloc.c */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mfs_ba_init
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Formats and initializes the block allocator.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* sb - Superblock instance of the device.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* 0 - OK
|
||||||
|
* -ENOMEM - No memory left.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int mfs_ba_fmt(FAR struct mfs_sb_s * const sb);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mfs_ba_init
|
* Name: mfs_ba_init
|
||||||
*
|
*
|
||||||
@@ -1172,7 +1212,7 @@ int mfs_ctz_rdfromoff(FAR const struct mfs_sb_s * const sb,
|
|||||||
mfs_t len, FAR char * buf);
|
mfs_t len, FAR char * buf);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mfs_ctz_wrtnode_new
|
* Name: mfs_ctz_wrtnode
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Write an LRU node to the flash. It also adds a log of it to the journal.
|
* Write an LRU node to the flash. It also adds a log of it to the journal.
|
||||||
@@ -1192,7 +1232,37 @@ int mfs_ctz_rdfromoff(FAR const struct mfs_sb_s * const sb,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int mfs_ctz_wrtnode(FAR struct mfs_sb_s * const sb,
|
int mfs_ctz_wrtnode(FAR struct mfs_sb_s * const sb,
|
||||||
const struct mfs_node_s * const node);
|
FAR const struct mfs_node_s * const node,
|
||||||
|
FAR struct mfs_ctz_s *new_loc);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mfs_ctz_travel
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* From CTZ block at page `pg_src` and index `idx_src`, give the page
|
||||||
|
* number of index `idx_dest`.
|
||||||
|
*
|
||||||
|
* The source is preferably the last CTZ block in the CTZ list, but it can
|
||||||
|
* realistically be any CTZ block in the CTZ list whos position is known.
|
||||||
|
* However, `idx_dest <= idx_src` has to be followed. Takes O(log(n))
|
||||||
|
* complexity to travel.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* sb - Superblock instance of the device.
|
||||||
|
* idx_src - Index of the source ctz block.
|
||||||
|
* pg_src - Page number of the source ctz block.
|
||||||
|
* idx_dest - Index of the destination ctz block.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The page number corresponding to `idx_dest`.
|
||||||
|
*
|
||||||
|
* Assumptions/Limitations:
|
||||||
|
* `idx_dest <= idx_src`.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
mfs_t mfs_ctz_travel(FAR const struct mfs_sb_s * const sb,
|
||||||
|
mfs_t idx_src, mfs_t pg_src, mfs_t idx_dest);
|
||||||
|
|
||||||
/* mnemofs_lru.c */
|
/* mnemofs_lru.c */
|
||||||
|
|
||||||
@@ -1325,7 +1395,10 @@ int mfs_lru_updatedinfo(FAR const struct mfs_sb_s * const sb,
|
|||||||
|
|
||||||
int mfs_lru_updatectz(FAR struct mfs_sb_s * sb,
|
int mfs_lru_updatectz(FAR struct mfs_sb_s * sb,
|
||||||
FAR struct mfs_path_s * const path, const mfs_t depth,
|
FAR struct mfs_path_s * const path, const mfs_t depth,
|
||||||
const struct mfs_ctz_s new_ctz);
|
const struct mfs_ctz_s new_ctz, mfs_t new_sz);
|
||||||
|
|
||||||
|
bool mfs_lru_isempty(FAR struct mfs_sb_s * const sb);
|
||||||
|
int mfs_lru_flush(FAR struct mfs_sb_s * const sb);
|
||||||
|
|
||||||
/* mnemofs_master.c */
|
/* mnemofs_master.c */
|
||||||
|
|
||||||
@@ -1369,7 +1442,8 @@ int mfs_mn_init(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk);
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int mfs_mn_fmt(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk);
|
int mfs_mn_fmt(FAR struct mfs_sb_s * const sb, const mfs_t blk1,
|
||||||
|
const mfs_t blk2, const mfs_t jrnl_blk);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mfs_mn_move
|
* Name: mfs_mn_move
|
||||||
@@ -1394,6 +1468,10 @@ int mfs_mn_fmt(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk);
|
|||||||
int mfs_mn_move(FAR struct mfs_sb_s * const sb, struct mfs_ctz_s root,
|
int mfs_mn_move(FAR struct mfs_sb_s * const sb, struct mfs_ctz_s root,
|
||||||
const mfs_t root_sz);
|
const mfs_t root_sz);
|
||||||
|
|
||||||
|
int mfs_mn_sync(FAR struct mfs_sb_s *sb,
|
||||||
|
FAR struct mfs_path_s * const new_loc,
|
||||||
|
const mfs_t blk1, const mfs_t blk2, const mfs_t jrnl_blk);
|
||||||
|
|
||||||
/* mnemofs_fsobj.c */
|
/* mnemofs_fsobj.c */
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -1817,7 +1895,10 @@ int mfs_pitr_rmdirent(FAR struct mfs_sb_s * const sb,
|
|||||||
|
|
||||||
int mfs_pitr_rm(FAR struct mfs_sb_s * const sb,
|
int mfs_pitr_rm(FAR struct mfs_sb_s * const sb,
|
||||||
FAR struct mfs_path_s * const path,
|
FAR struct mfs_path_s * const path,
|
||||||
const mfs_t depth);
|
const mfs_t depth, bool rm_child);
|
||||||
|
|
||||||
|
int mfs_pitr_traversefs(FAR struct mfs_sb_s * sb, const struct mfs_ctz_s ctz,
|
||||||
|
int type);
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -236,11 +236,11 @@ static int is_pg_writeable(FAR struct mfs_sb_s * const sb, mfs_t pg,
|
|||||||
|
|
||||||
static int is_blk_writeable(FAR struct mfs_sb_s * const sb, const mfs_t blk)
|
static int is_blk_writeable(FAR struct mfs_sb_s * const sb, const mfs_t blk)
|
||||||
{
|
{
|
||||||
|
int blkbad_status;
|
||||||
|
mfs_t i;
|
||||||
|
mfs_t pg = MFS_BLK2PG(sb, blk);
|
||||||
mfs_t idx;
|
mfs_t idx;
|
||||||
uint8_t off;
|
uint8_t off;
|
||||||
mfs_t pg = MFS_BLK2PG(sb, blk);
|
|
||||||
mfs_t i;
|
|
||||||
int blkbad_status;
|
|
||||||
|
|
||||||
/* Bad block check. */
|
/* Bad block check. */
|
||||||
|
|
||||||
@@ -279,12 +279,12 @@ static int is_blk_writeable(FAR struct mfs_sb_s * const sb, const mfs_t blk)
|
|||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int mfs_ba_init(FAR struct mfs_sb_s * const sb)
|
int mfs_ba_fmt(FAR struct mfs_sb_s * const sb)
|
||||||
{
|
{
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
uint8_t log;
|
uint8_t log;
|
||||||
|
|
||||||
/* We need at least 5 blocks, as one is occupied by superblock, at least
|
/* We need at least 5 blocks, as one is occupied by superblock, at least
|
||||||
* one for the journal, 2 for journal's master blocks, and at least one for
|
* one for the journal, 2 for journal's master blocks, and at least one for
|
||||||
* actual data.
|
* actual data.
|
||||||
*/
|
*/
|
||||||
@@ -326,8 +326,6 @@ int mfs_ba_init(FAR struct mfs_sb_s * const sb)
|
|||||||
goto errout_with_k_del;
|
goto errout_with_k_del;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Fill MFS_BA(sb).bmap_upgs after tree traversal. */
|
|
||||||
|
|
||||||
finfo("mnemofs: Block Allocator initialized, starting at page %d.\n",
|
finfo("mnemofs: Block Allocator initialized, starting at page %d.\n",
|
||||||
MFS_BLK2PG(sb, MFS_BA(sb).s_blk));
|
MFS_BLK2PG(sb, MFS_BA(sb).s_blk));
|
||||||
return ret;
|
return ret;
|
||||||
@@ -339,6 +337,33 @@ errout:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mfs_ba_init(FAR struct mfs_sb_s * const sb)
|
||||||
|
{
|
||||||
|
/* TODO: Ensure journal and master node are initialized before this. */
|
||||||
|
|
||||||
|
int ret = OK;
|
||||||
|
|
||||||
|
ret = mfs_ba_fmt(sb);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Traverse the FS tree. */
|
||||||
|
|
||||||
|
ret = mfs_pitr_traversefs(sb, MFS_MN(sb).root_ctz, MFS_ISDIR);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
goto errout_with_ba;
|
||||||
|
}
|
||||||
|
|
||||||
|
errout_with_ba:
|
||||||
|
mfs_ba_free(sb);
|
||||||
|
|
||||||
|
errout:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void mfs_ba_free(FAR struct mfs_sb_s * const sb)
|
void mfs_ba_free(FAR struct mfs_sb_s * const sb)
|
||||||
{
|
{
|
||||||
kmm_free(MFS_BA(sb).k_del);
|
kmm_free(MFS_BA(sb).k_del);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -85,6 +85,7 @@ static const char *next_child(FAR const char *relpath);
|
|||||||
static const char *last_child(FAR const char *relpath);
|
static const char *last_child(FAR const char *relpath);
|
||||||
static FAR char *mfs_ser_dirent(FAR const struct mfs_dirent_s * const x,
|
static FAR char *mfs_ser_dirent(FAR const struct mfs_dirent_s * const x,
|
||||||
FAR char * const out);
|
FAR char * const out);
|
||||||
|
|
||||||
static FAR const char *mfs_deser_dirent(FAR const char * const in,
|
static FAR const char *mfs_deser_dirent(FAR const char * const in,
|
||||||
FAR struct mfs_dirent_s * const x);
|
FAR struct mfs_dirent_s * const x);
|
||||||
|
|
||||||
@@ -285,11 +286,87 @@ static FAR const char *mfs_deser_dirent(FAR const char * const in,
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int pitr_traverse(FAR struct mfs_sb_s *sb, FAR struct mfs_path_s *path,
|
||||||
|
mfs_t depth, FAR mfs_t *cap)
|
||||||
|
{
|
||||||
|
int ret = OK;
|
||||||
|
mfs_t i;
|
||||||
|
mfs_t pg;
|
||||||
|
struct mfs_pitr_s pitr;
|
||||||
|
struct mfs_ctz_s ctz;
|
||||||
|
FAR struct mfs_dirent_s *dirent = NULL;
|
||||||
|
|
||||||
|
/* TODO: Double traversal can be made faster into a single traversal. */
|
||||||
|
|
||||||
|
ctz = path[depth - 1].ctz;
|
||||||
|
|
||||||
|
if (ctz.idx_e == 0 && ctz.pg_e == 0)
|
||||||
|
{
|
||||||
|
/* Not a valid one. TODO: Does this happens? */
|
||||||
|
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = ctz.idx_e; i > 0; i--)
|
||||||
|
{
|
||||||
|
mfs_ba_markusedpg(sb, pg);
|
||||||
|
|
||||||
|
pg = mfs_ctz_travel(sb, i, pg, i - 1);
|
||||||
|
if (pg == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(path + depth, 0, *cap - depth);
|
||||||
|
|
||||||
|
if (depth == *cap)
|
||||||
|
{
|
||||||
|
*cap = (*cap * 3) / 2; /* Don't want to double it for memory. */
|
||||||
|
|
||||||
|
path = kmm_realloc(path, (*cap) * sizeof(struct mfs_path_s));
|
||||||
|
if (predict_false(path == NULL))
|
||||||
|
{
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mfs_pitr_init(sb, path, depth, &pitr, true);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
mfs_pitr_readdirent(sb, path, &pitr, &dirent);
|
||||||
|
if (dirent == NULL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (S_ISDIR(dirent->mode))
|
||||||
|
{
|
||||||
|
path[(depth + 1) - 1].ctz = dirent->ctz;
|
||||||
|
|
||||||
|
ret = pitr_traverse(sb, path, depth + 1, cap);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
mfs_free_dirent(dirent);
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mfs_pitr_adv_bydirent(&pitr, dirent);
|
||||||
|
mfs_free_dirent(dirent);
|
||||||
|
}
|
||||||
|
|
||||||
|
errout:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Function Prototypes
|
* Public Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
FAR const char * mfs_path2childname(FAR const char *relpath)
|
FAR const char *mfs_path2childname(FAR const char *relpath)
|
||||||
{
|
{
|
||||||
FAR const char *last = relpath + strlen(relpath) - 1;
|
FAR const char *last = relpath + strlen(relpath) - 1;
|
||||||
|
|
||||||
@@ -317,7 +394,7 @@ mfs_t mfs_get_fsz(FAR struct mfs_sb_s * const sb,
|
|||||||
{
|
{
|
||||||
sz = MFS_MN(sb).root_sz; /* Updated size. */
|
sz = MFS_MN(sb).root_sz; /* Updated size. */
|
||||||
|
|
||||||
/* Journal updated to the root creates a new master node entry. TODO
|
/* Journal updated to the root creates a new master node entry. TODO
|
||||||
* this and moving of the journal.
|
* this and moving of the journal.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -362,11 +439,6 @@ bool mfs_searchfopen(FAR const struct mfs_sb_s * const sb,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Ensure when an LRU's delta is flushed to the journal, the
|
|
||||||
* new location is updated in the LRU AND the open files, if it is
|
|
||||||
* open.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (mfs_path_eq(&ofd->com->path[depth - 1], &path[depth - 1]))
|
if (mfs_path_eq(&ofd->com->path[depth - 1], &path[depth - 1]))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@@ -400,7 +472,7 @@ int mfs_pitr_rmdirent(FAR struct mfs_sb_s * const sb,
|
|||||||
|
|
||||||
int mfs_pitr_rm(FAR struct mfs_sb_s * const sb,
|
int mfs_pitr_rm(FAR struct mfs_sb_s * const sb,
|
||||||
FAR struct mfs_path_s * const path,
|
FAR struct mfs_path_s * const path,
|
||||||
const mfs_t depth)
|
const mfs_t depth, bool rm_child)
|
||||||
{
|
{
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
struct mfs_pitr_s pitr;
|
struct mfs_pitr_s pitr;
|
||||||
@@ -408,7 +480,23 @@ int mfs_pitr_rm(FAR struct mfs_sb_s * const sb,
|
|||||||
|
|
||||||
mfs_pitr_init(sb, path, depth, &pitr, true);
|
mfs_pitr_init(sb, path, depth, &pitr, true);
|
||||||
mfs_pitr_readdirent(sb, path, &pitr, &dirent);
|
mfs_pitr_readdirent(sb, path, &pitr, &dirent);
|
||||||
|
|
||||||
ret = mfs_pitr_rmdirent(sb, path, depth, &pitr, dirent);
|
ret = mfs_pitr_rmdirent(sb, path, depth, &pitr, dirent);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rm_child)
|
||||||
|
{
|
||||||
|
ret = mfs_lru_del(sb, 0, path[depth - 1].sz, path, depth);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errout:
|
||||||
mfs_free_dirent(dirent);
|
mfs_free_dirent(dirent);
|
||||||
mfs_pitr_free(&pitr);
|
mfs_pitr_free(&pitr);
|
||||||
|
|
||||||
@@ -558,9 +646,9 @@ int mfs_pitr_readdirent(FAR const struct mfs_sb_s * const sb,
|
|||||||
*dirent = d;
|
*dirent = d;
|
||||||
DEBUGASSERT(pitr->depth == 0 || strcmp(d->name, ""));
|
DEBUGASSERT(pitr->depth == 0 || strcmp(d->name, ""));
|
||||||
finfo("Read direntry at %u offset, %u depth for CTZ (%u, %u). " \
|
finfo("Read direntry at %u offset, %u depth for CTZ (%u, %u). " \
|
||||||
"Direntry name: \"%s\" with name length %u.",
|
"Direntry name: \"%.*s\" with name length %u and size %u.",
|
||||||
pitr->c_off, pitr->depth, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e,
|
pitr->c_off, pitr->depth, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e,
|
||||||
d->name, d->namelen);
|
d->namelen, d->name, d->namelen, d->sz);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -614,10 +702,10 @@ static int search_ctz_by_name(FAR const struct mfs_sb_s * const sb,
|
|||||||
/* Applies LRU updates. */
|
/* Applies LRU updates. */
|
||||||
|
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
|
bool found = false;
|
||||||
uint16_t name_hash;
|
uint16_t name_hash;
|
||||||
struct mfs_pitr_s pitr;
|
struct mfs_pitr_s pitr;
|
||||||
FAR struct mfs_dirent_s *nd;
|
FAR struct mfs_dirent_s *nd;
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
*dirent = NULL;
|
*dirent = NULL;
|
||||||
|
|
||||||
@@ -864,7 +952,7 @@ int mfs_pitr_appenddirent(FAR struct mfs_sb_s * const sb,
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TOFO: If the parent directory is newly formed (ie. size is 0), then
|
/* TODO: If the parent directory is newly formed (ie. size is 0), then
|
||||||
* allocate space for it. This can be done better. Just allocate page when
|
* allocate space for it. This can be done better. Just allocate page when
|
||||||
* its created and added first to LRU, and then add a check to ensure it
|
* its created and added first to LRU, and then add a check to ensure it
|
||||||
* doesn't get re-allocated when written. A field like "new" would be
|
* doesn't get re-allocated when written. A field like "new" would be
|
||||||
@@ -892,11 +980,11 @@ int mfs_pitr_appendnew(FAR struct mfs_sb_s * const sb,
|
|||||||
/* Depth is depth of the child to be appended. */
|
/* Depth is depth of the child to be appended. */
|
||||||
|
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
struct timespec ts;
|
|
||||||
FAR const char *cur = last_child(relpath);
|
FAR const char *cur = last_child(relpath);
|
||||||
FAR const char *next = next_child(cur);
|
FAR const char *next = next_child(cur);
|
||||||
FAR struct mfs_dirent_s *d = NULL;
|
|
||||||
const mfs_t len = *next == 0 ? next - cur : next - cur - 1;
|
const mfs_t len = *next == 0 ? next - cur : next - cur - 1;
|
||||||
|
struct timespec ts;
|
||||||
|
FAR struct mfs_dirent_s *d = NULL;
|
||||||
|
|
||||||
DEBUGASSERT(depth > 0);
|
DEBUGASSERT(depth > 0);
|
||||||
|
|
||||||
@@ -942,3 +1030,34 @@ errout_with_d:
|
|||||||
errout:
|
errout:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Only for initialization of the block allocator. */
|
||||||
|
|
||||||
|
int mfs_pitr_traversefs(FAR struct mfs_sb_s * sb, const struct mfs_ctz_s ctz,
|
||||||
|
int type)
|
||||||
|
{
|
||||||
|
/* type takes in MFS_ISFILE & MFS_ISDIR. */
|
||||||
|
|
||||||
|
int ret = OK;
|
||||||
|
mfs_t capacity;
|
||||||
|
FAR struct mfs_path_s *path = NULL;
|
||||||
|
|
||||||
|
capacity = MFS_TRAVERSE_INITSZ;
|
||||||
|
path = kmm_zalloc(capacity * sizeof(struct mfs_path_s));
|
||||||
|
if (predict_false(path == NULL))
|
||||||
|
{
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
path[0].off = 0;
|
||||||
|
path[0].ctz = MFS_MN(sb).root_ctz;
|
||||||
|
path[0].sz = MFS_MN(sb).root_sz;
|
||||||
|
|
||||||
|
ret = pitr_traverse(sb, path, 0, &capacity);
|
||||||
|
|
||||||
|
mfs_free_patharr(path);
|
||||||
|
|
||||||
|
errout:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
@@ -483,13 +483,13 @@ errout:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2)
|
int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, FAR mfs_t *blk1,
|
||||||
|
FAR mfs_t *blk2, FAR mfs_t *jrnl_blk)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
mfs_t sz;
|
mfs_t sz;
|
||||||
mfs_t pg;
|
mfs_t pg;
|
||||||
mfs_t mn;
|
|
||||||
mfs_t blk;
|
mfs_t blk;
|
||||||
mfs_t n_pgs;
|
mfs_t n_pgs;
|
||||||
mfs_t rem_sz;
|
mfs_t rem_sz;
|
||||||
@@ -509,26 +509,26 @@ int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blk1 == 0 && blk2 == 0)
|
if (*blk1 == 0 && *blk2 == 0)
|
||||||
{
|
{
|
||||||
blk1 = mfs_ba_getblk(sb);
|
*blk1 = mfs_ba_getblk(sb);
|
||||||
if (predict_false(blk1 == 0))
|
if (predict_false(blk1 == 0))
|
||||||
{
|
{
|
||||||
ret = -ENOSPC;
|
ret = -ENOSPC;
|
||||||
goto errout_with_buf;
|
goto errout_with_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
finfo("Allocated Master Block 1: %d.", blk1);
|
finfo("Allocated Master Block 1: %d.", *blk1);
|
||||||
|
|
||||||
blk2 = mfs_ba_getblk(sb);
|
*blk2 = mfs_ba_getblk(sb);
|
||||||
if (predict_false(blk2 == 0))
|
if (predict_false(blk2 == 0))
|
||||||
{
|
{
|
||||||
ret = -ENOSPC;
|
ret = -ENOSPC;
|
||||||
goto errout_with_buf;
|
goto errout_with_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
finfo("Allocated Master Block 1: %d.", blk2);
|
finfo("Allocated Master Block 1: %d.", *blk2);
|
||||||
finfo("New locations for Master Blocks %d & %d.", blk1, blk2);
|
finfo("New locations for Master Blocks %d & %d.", *blk1, *blk2);
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = buf;
|
tmp = buf;
|
||||||
@@ -548,8 +548,8 @@ int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2)
|
|||||||
finfo("Allocated Journal Block %d at Block %d.", i, alloc_blk);
|
finfo("Allocated Journal Block %d at Block %d.", i, alloc_blk);
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = mfs_ser_mfs(blk1, tmp);
|
tmp = mfs_ser_mfs(*blk1, tmp);
|
||||||
tmp = mfs_ser_mfs(blk2, tmp);
|
tmp = mfs_ser_mfs(*blk2, tmp);
|
||||||
|
|
||||||
finfo("All Journal Blocks allocated.");
|
finfo("All Journal Blocks allocated.");
|
||||||
|
|
||||||
@@ -576,26 +576,15 @@ int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2)
|
|||||||
finfo("Written magic sequence, size and journal array into the journal.");
|
finfo("Written magic sequence, size and journal array into the journal.");
|
||||||
|
|
||||||
MFS_JRNL(sb).n_logs = 0;
|
MFS_JRNL(sb).n_logs = 0;
|
||||||
|
MFS_JRNL(sb).n_blks = CONFIG_MNEMOFS_JOURNAL_NBLKS;
|
||||||
MFS_JRNL(sb).log_cpg = pg;
|
MFS_JRNL(sb).log_cpg = pg;
|
||||||
MFS_JRNL(sb).log_cblkidx = 0;
|
MFS_JRNL(sb).log_cblkidx = 0;
|
||||||
MFS_JRNL(sb).log_spg = MFS_JRNL(sb).log_cpg;
|
MFS_JRNL(sb).log_spg = MFS_JRNL(sb).log_cpg;
|
||||||
MFS_JRNL(sb).log_sblkidx = MFS_JRNL(sb).log_cblkidx;
|
MFS_JRNL(sb).log_sblkidx = MFS_JRNL(sb).log_cblkidx;
|
||||||
MFS_JRNL(sb).jrnlarr_pg = MFS_BLK2PG(sb, blk);
|
MFS_JRNL(sb).jrnlarr_pg = MFS_BLK2PG(sb, blk);
|
||||||
MFS_JRNL(sb).jrnlarr_pgoff = MFS_JRNL_SUFFIXSZ;
|
MFS_JRNL(sb).jrnlarr_pgoff = MFS_JRNL_SUFFIXSZ;
|
||||||
MFS_JRNL(sb).n_blks = CONFIG_MNEMOFS_JOURNAL_NBLKS;
|
MFS_JRNL(sb).mblk1 = *blk1;
|
||||||
MFS_JRNL(sb).mblk1 = blk1;
|
MFS_JRNL(sb).mblk2 = *blk2;
|
||||||
MFS_JRNL(sb).mblk2 = blk2;
|
|
||||||
|
|
||||||
/* Master node */
|
|
||||||
|
|
||||||
mn = mfs_mn_fmt(sb, blk);
|
|
||||||
if (predict_false(mn == 0))
|
|
||||||
{
|
|
||||||
ret = -ENOSPC;
|
|
||||||
goto errout_with_buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: Write master node's location in blk1, blk2. */
|
|
||||||
|
|
||||||
errout_with_buf:
|
errout_with_buf:
|
||||||
kmm_free(buf);
|
kmm_free(buf);
|
||||||
@@ -707,7 +696,7 @@ errout:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mfs_jrnl_wrlog(FAR struct mfs_sb_s * const sb,
|
int mfs_jrnl_wrlog(FAR struct mfs_sb_s * const sb,
|
||||||
const struct mfs_node_s node,
|
FAR const struct mfs_node_s *node,
|
||||||
const struct mfs_ctz_s loc_new, const mfs_t sz_new)
|
const struct mfs_ctz_s loc_new, const mfs_t sz_new)
|
||||||
{
|
{
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
@@ -718,7 +707,7 @@ int mfs_jrnl_wrlog(FAR struct mfs_sb_s * const sb,
|
|||||||
mfs_t jrnl_blk;
|
mfs_t jrnl_blk;
|
||||||
FAR char *buf = NULL;
|
FAR char *buf = NULL;
|
||||||
FAR char *tmp = NULL;
|
FAR char *tmp = NULL;
|
||||||
const mfs_t log_sz = sizeof(mfs_t) + MFS_LOGSZ(node.depth);
|
const mfs_t log_sz = sizeof(mfs_t) + MFS_LOGSZ(node->depth);
|
||||||
struct jrnl_log_s log;
|
struct jrnl_log_s log;
|
||||||
|
|
||||||
buf = kmm_zalloc(log_sz); /* For size before log. */
|
buf = kmm_zalloc(log_sz); /* For size before log. */
|
||||||
@@ -730,16 +719,16 @@ int mfs_jrnl_wrlog(FAR struct mfs_sb_s * const sb,
|
|||||||
|
|
||||||
/* Serialize */
|
/* Serialize */
|
||||||
|
|
||||||
log.depth = node.depth;
|
log.depth = node->depth;
|
||||||
log.sz_new = node.depth;
|
log.sz_new = sz_new;
|
||||||
log.loc_new = loc_new;
|
log.loc_new = loc_new;
|
||||||
log.st_mtim_new = node.st_mtim;
|
log.st_mtim_new = node->st_mtim;
|
||||||
log.st_atim_new = node.st_atim;
|
log.st_atim_new = node->st_atim;
|
||||||
log.st_ctim_new = node.st_ctim;
|
log.st_ctim_new = node->st_ctim;
|
||||||
log.path = node.path; /* Fine as temporarily usage. */
|
log.path = node->path; /* Fine as temporarily usage. */
|
||||||
|
|
||||||
tmp = buf;
|
tmp = buf;
|
||||||
tmp = mfs_ser_mfs(log_sz - sizeof(mfs_t), tmp);
|
tmp = mfs_ser_mfs(log_sz - sizeof(mfs_t), tmp); /* First 4 bytes have sz */
|
||||||
tmp = ser_log(&log, tmp);
|
tmp = ser_log(&log, tmp);
|
||||||
|
|
||||||
/* Store */
|
/* Store */
|
||||||
@@ -820,7 +809,200 @@ errout:
|
|||||||
|
|
||||||
int mfs_jrnl_flush(FAR struct mfs_sb_s * const sb)
|
int mfs_jrnl_flush(FAR struct mfs_sb_s * const sb)
|
||||||
{
|
{
|
||||||
/* TODO */
|
/* When a file or a directory is deleted.
|
||||||
|
*
|
||||||
|
* It will be modified to an entry in the LRU which details the deletion
|
||||||
|
* of all bytes from the child... as in, offset 0, deleted bytes is the
|
||||||
|
* size of the file.
|
||||||
|
*
|
||||||
|
* The new "location" can be used as (0, 0) to signify a deletion, even in
|
||||||
|
* its journal log.
|
||||||
|
*
|
||||||
|
* Also ensure if the size gets updated to 0.
|
||||||
|
*
|
||||||
|
* Then the flush operation problem will be solved for removal of files or
|
||||||
|
* directories.
|
||||||
|
*
|
||||||
|
* Move operation will not empty the child, but only the parent from the
|
||||||
|
* old parent.
|
||||||
|
*/
|
||||||
|
|
||||||
return OK;
|
/* Time complexity is going to be horrendous. Hint: O(n^2). HOWEVER, as
|
||||||
|
* littlefs points out....if n is constant, it's essentially a O(k), or
|
||||||
|
* O(1) :D
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TODO: Need to consider how the LRU and Journal interact with each other
|
||||||
|
* for newly created fs object's entries.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* We're using updatectz to update the LRU inside the journal. Think
|
||||||
|
* about how that might affect the iteration attempts.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ret = OK;
|
||||||
|
mfs_t blkidx = MFS_JRNL(sb).log_sblkidx;
|
||||||
|
mfs_t log_itr = 0;
|
||||||
|
mfs_t pg_in_blk = MFS_JRNL(sb).log_spg \
|
||||||
|
% MFS_PGINBLK(sb);
|
||||||
|
mfs_t tmp_blkidx;
|
||||||
|
mfs_t tmp_pg_in_blk;
|
||||||
|
mfs_t mn_blk1;
|
||||||
|
mfs_t mn_blk2;
|
||||||
|
mfs_t i;
|
||||||
|
mfs_t jrnl_blk;
|
||||||
|
mfs_t blk;
|
||||||
|
struct jrnl_log_s log;
|
||||||
|
struct jrnl_log_s tmp_log;
|
||||||
|
FAR struct mfs_path_s *path = NULL;
|
||||||
|
struct mfs_jrnl_state_s j_state;
|
||||||
|
struct mfs_mn_s mn_state;
|
||||||
|
|
||||||
|
while (log_itr < MFS_JRNL(sb).n_logs)
|
||||||
|
{
|
||||||
|
ret = jrnl_rdlog(sb, &blkidx, &pg_in_blk, &log);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
DEBUGASSERT(ret != -ENOSPC); /* While condition is sufficient. */
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log.loc_new.pg_e == 0 && log.loc_new.idx_e == 0)
|
||||||
|
{
|
||||||
|
/* Entry is deleted, do not bother with it. */
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_blkidx = blkidx;
|
||||||
|
tmp_pg_in_blk = pg_in_blk;
|
||||||
|
|
||||||
|
path = kmm_zalloc(log.depth * sizeof(struct mfs_path_s));
|
||||||
|
if (predict_false(path == NULL))
|
||||||
|
{
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(path, log.path, log.depth * sizeof(struct mfs_path_s));
|
||||||
|
path[log.depth - 1].ctz = log.loc_new;
|
||||||
|
|
||||||
|
for (; ; )
|
||||||
|
{
|
||||||
|
ret = jrnl_rdlog(sb, &tmp_blkidx, &tmp_pg_in_blk, &tmp_log);
|
||||||
|
if (ret == -ENOSPC)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
jrnl_log_free(&log);
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp_log.depth > log.depth)
|
||||||
|
{
|
||||||
|
jrnl_log_free(&tmp_log);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mfs_path_eq(&path[tmp_log.depth - 1],
|
||||||
|
&tmp_log.path[tmp_log.depth - 1]))
|
||||||
|
{
|
||||||
|
jrnl_log_free(&tmp_log);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
path[tmp_log.depth - 1] = tmp_log.path[tmp_log.depth - 1];
|
||||||
|
|
||||||
|
if (tmp_log.loc_new.pg_e == 0 && tmp_log.loc_new.idx_e == 0)
|
||||||
|
{
|
||||||
|
/* Entry is deleted, do not bother with it. */
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log.depth == 1)
|
||||||
|
{
|
||||||
|
MFS_MN(sb).root_ctz = path[log.depth - 1].ctz;
|
||||||
|
MFS_MN(sb).root_sz = path[log.depth - 1].sz;
|
||||||
|
|
||||||
|
/* TODO: Other parameters. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = mfs_lru_updatectz(sb, path, log.depth,
|
||||||
|
path[log.depth - 1].ctz,
|
||||||
|
path[log.depth - 1].sz);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
mfs_free_patharr(path);
|
||||||
|
jrnl_log_free(&log);
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mfs_free_patharr(path);
|
||||||
|
jrnl_log_free(&log);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MFS_MN(sb).mblk_idx == MFS_PGINBLK(sb))
|
||||||
|
{
|
||||||
|
mn_blk1 = 0;
|
||||||
|
mn_blk2 = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* FUTURE TODO: Save the two block numbers in master node structure to
|
||||||
|
* be faster.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mn_blk1 = mfs_jrnl_blkidx2blk(sb, MFS_JRNL(sb).n_blks);
|
||||||
|
mn_blk2 = mfs_jrnl_blkidx2blk(sb, MFS_JRNL(sb).n_blks + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reallocate journal. */
|
||||||
|
|
||||||
|
j_state = MFS_JRNL(sb);
|
||||||
|
mn_state = MFS_MN(sb);
|
||||||
|
|
||||||
|
ret = mfs_jrnl_fmt(sb, &mn_blk1, &mn_blk2, &jrnl_blk);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
MFS_JRNL(sb) = j_state;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write master node entry. */
|
||||||
|
|
||||||
|
ret = mfs_mn_sync(sb, &path[0], mn_blk1, mn_blk2, jrnl_blk);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
MFS_MN(sb) = mn_state;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mark all old blocks of journal (and master blocks) as deletable. */
|
||||||
|
|
||||||
|
for (i = 0; i < MFS_JRNL(sb).n_blks + 2; i++)
|
||||||
|
{
|
||||||
|
blk = mfs_jrnl_blkidx2blk(sb, i);
|
||||||
|
mfs_ba_blkmarkdel(sb, blk);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete outdated blocks. */
|
||||||
|
|
||||||
|
ret = mfs_ba_delmarked(sb);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
errout:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mfs_jrnl_isempty(FAR const struct mfs_sb_s * const sb)
|
||||||
|
{
|
||||||
|
return MFS_JRNL(sb).n_logs == 0;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -100,7 +100,7 @@
|
|||||||
static FAR char *ser_mn(const struct mfs_mn_s mn,
|
static FAR char *ser_mn(const struct mfs_mn_s mn,
|
||||||
FAR char * const out);
|
FAR char * const out);
|
||||||
static FAR const char *deser_mn(FAR const char * const in,
|
static FAR const char *deser_mn(FAR const char * const in,
|
||||||
FAR struct mfs_mn_s *mn, FAR uint8_t *hash);
|
FAR struct mfs_mn_s *mn, FAR uint16_t *hash);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
@@ -141,7 +141,9 @@ static FAR char *ser_mn(const struct mfs_mn_s mn, FAR char * const out)
|
|||||||
tmp = mfs_ser_ctz(&mn.root_ctz, tmp);
|
tmp = mfs_ser_ctz(&mn.root_ctz, tmp);
|
||||||
tmp = mfs_ser_mfs(mn.root_sz, tmp);
|
tmp = mfs_ser_mfs(mn.root_sz, tmp);
|
||||||
tmp = mfs_ser_timespec(&mn.ts, tmp);
|
tmp = mfs_ser_timespec(&mn.ts, tmp);
|
||||||
tmp = mfs_ser_8(mfs_arrhash(out, tmp - out), tmp);
|
tmp = mfs_ser_16(mfs_hash(out, tmp - out), tmp);
|
||||||
|
|
||||||
|
/* TODO: Update this, and the make a macro for size of MN. */
|
||||||
|
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -166,7 +168,7 @@ static FAR char *ser_mn(const struct mfs_mn_s mn, FAR char * const out)
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static FAR const char *deser_mn(FAR const char * const in,
|
static FAR const char *deser_mn(FAR const char * const in,
|
||||||
FAR struct mfs_mn_s *mn, FAR uint8_t *hash)
|
FAR struct mfs_mn_s *mn, FAR uint16_t *hash)
|
||||||
{
|
{
|
||||||
FAR const char *tmp = in;
|
FAR const char *tmp = in;
|
||||||
|
|
||||||
@@ -175,7 +177,9 @@ static FAR const char *deser_mn(FAR const char * const in,
|
|||||||
tmp = mfs_deser_ctz(tmp, &mn->root_ctz);
|
tmp = mfs_deser_ctz(tmp, &mn->root_ctz);
|
||||||
tmp = mfs_deser_mfs(tmp, &mn->root_sz);
|
tmp = mfs_deser_mfs(tmp, &mn->root_sz);
|
||||||
tmp = mfs_deser_timespec(tmp, &mn->ts);
|
tmp = mfs_deser_timespec(tmp, &mn->ts);
|
||||||
tmp = mfs_deser_8(tmp, hash);
|
tmp = mfs_deser_16(tmp, hash);
|
||||||
|
|
||||||
|
/* TODO: Update this, and the make a macro for size of MN. */
|
||||||
|
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -192,7 +196,7 @@ int mfs_mn_init(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk)
|
|||||||
mfs_t mblk2;
|
mfs_t mblk2;
|
||||||
mfs_t jrnl_blk_tmp;
|
mfs_t jrnl_blk_tmp;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
uint8_t hash;
|
uint16_t hash;
|
||||||
struct mfs_mn_s mn;
|
struct mfs_mn_s mn;
|
||||||
const mfs_t sz = sizeof(struct mfs_mn_s) - sizeof(mn.pg);
|
const mfs_t sz = sizeof(struct mfs_mn_s) - sizeof(mn.pg);
|
||||||
char buftmp[4];
|
char buftmp[4];
|
||||||
@@ -200,7 +204,6 @@ int mfs_mn_init(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk)
|
|||||||
|
|
||||||
mblk1 = mfs_jrnl_blkidx2blk(sb, MFS_JRNL(sb).n_blks);
|
mblk1 = mfs_jrnl_blkidx2blk(sb, MFS_JRNL(sb).n_blks);
|
||||||
mblk2 = mfs_jrnl_blkidx2blk(sb, MFS_JRNL(sb).n_blks + 1);
|
mblk2 = mfs_jrnl_blkidx2blk(sb, MFS_JRNL(sb).n_blks + 1);
|
||||||
|
|
||||||
mn.jrnl_blk = mn.jrnl_blk;
|
mn.jrnl_blk = mn.jrnl_blk;
|
||||||
mn.mblk_idx = 0;
|
mn.mblk_idx = 0;
|
||||||
mn.pg = MFS_BLK2PG(sb, mblk1);
|
mn.pg = MFS_BLK2PG(sb, mblk1);
|
||||||
@@ -238,7 +241,6 @@ int mfs_mn_init(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mn.mblk_idx--;
|
|
||||||
mn.pg--;
|
mn.pg--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +249,7 @@ int mfs_mn_init(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk)
|
|||||||
/* Deserialize. */
|
/* Deserialize. */
|
||||||
|
|
||||||
deser_mn(buf, &mn, &hash);
|
deser_mn(buf, &mn, &hash);
|
||||||
if (hash != mfs_arrhash(buf, sz))
|
if (hash != mfs_hash(buf, sz))
|
||||||
{
|
{
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -263,12 +265,11 @@ errout:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mfs_mn_fmt(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk)
|
int mfs_mn_fmt(FAR struct mfs_sb_s * const sb, const mfs_t mblk1,
|
||||||
|
const mfs_t mblk2, const mfs_t jrnl_blk)
|
||||||
{
|
{
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
mfs_t pg;
|
mfs_t pg;
|
||||||
mfs_t mblk1;
|
|
||||||
mfs_t mblk2;
|
|
||||||
struct mfs_mn_s mn;
|
struct mfs_mn_s mn;
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
const mfs_t sz = sizeof(struct mfs_mn_s) - sizeof(mn.pg);
|
const mfs_t sz = sizeof(struct mfs_mn_s) - sizeof(mn.pg);
|
||||||
@@ -278,9 +279,6 @@ int mfs_mn_fmt(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk)
|
|||||||
|
|
||||||
memset(buf, 0, sz + 1);
|
memset(buf, 0, sz + 1);
|
||||||
|
|
||||||
mblk1 = mfs_jrnl_blkidx2blk(sb, MFS_JRNL(sb).n_blks);
|
|
||||||
mblk2 = mfs_jrnl_blkidx2blk(sb, MFS_JRNL(sb).n_blks + 1);
|
|
||||||
|
|
||||||
pg = mfs_ba_getpg(sb);
|
pg = mfs_ba_getpg(sb);
|
||||||
if (predict_false(pg == 0))
|
if (predict_false(pg == 0))
|
||||||
{
|
{
|
||||||
@@ -318,6 +316,7 @@ int mfs_mn_fmt(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mn.mblk_idx = 1;
|
||||||
MFS_MN(sb) = mn;
|
MFS_MN(sb) = mn;
|
||||||
finfo("Master node written. Now at page %d, timestamp %lld.%.9ld.",
|
finfo("Master node written. Now at page %d, timestamp %lld.%.9ld.",
|
||||||
MFS_MN(sb).pg, (long long)MFS_MN(sb).ts.tv_sec,
|
MFS_MN(sb).pg, (long long)MFS_MN(sb).ts.tv_sec,
|
||||||
@@ -348,7 +347,7 @@ int mfs_mn_move(FAR struct mfs_sb_s * const sb, struct mfs_ctz_s root,
|
|||||||
|
|
||||||
mn.root_ctz = root;
|
mn.root_ctz = root;
|
||||||
mn.root_sz = root_sz;
|
mn.root_sz = root_sz;
|
||||||
mn.mblk_idx++;
|
mn.mblk_idx++; /* TODO */
|
||||||
mn.pg++;
|
mn.pg++;
|
||||||
|
|
||||||
ser_mn(mn, buf);
|
ser_mn(mn, buf);
|
||||||
@@ -364,3 +363,55 @@ int mfs_mn_move(FAR struct mfs_sb_s * const sb, struct mfs_ctz_s root,
|
|||||||
errout:
|
errout:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mfs_mn_sync(FAR struct mfs_sb_s *sb,
|
||||||
|
FAR struct mfs_path_s * const new_loc,
|
||||||
|
const mfs_t blk1, const mfs_t blk2, const mfs_t jrnl_blk)
|
||||||
|
{
|
||||||
|
int ret = OK;
|
||||||
|
struct timespec ts;
|
||||||
|
struct mfs_mn_s mn;
|
||||||
|
const mfs_t sz = sizeof(struct mfs_mn_s) - sizeof(mn.pg);
|
||||||
|
char buf[sz + 1];
|
||||||
|
|
||||||
|
mn = MFS_MN(sb);
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
|
|
||||||
|
if (mn.mblk_idx == MFS_PGINBLK(sb))
|
||||||
|
{
|
||||||
|
/* New blocks have been already allocated by the journal. */
|
||||||
|
|
||||||
|
mn.mblk_idx = 0;
|
||||||
|
mn.pg = MFS_BLK2PG(sb, blk1);
|
||||||
|
}
|
||||||
|
|
||||||
|
mn.ts = ts;
|
||||||
|
mn.root_sz = new_loc->sz;
|
||||||
|
mn.root_ctz = new_loc->ctz;
|
||||||
|
mn.root_mode = 0777 | S_IFDIR;
|
||||||
|
|
||||||
|
/* TODO: Root timestamps. */
|
||||||
|
|
||||||
|
/* Serialize. */
|
||||||
|
|
||||||
|
ser_mn(mn, buf);
|
||||||
|
|
||||||
|
ret = mfs_write_page(sb, buf, sz, MFS_BLK2PG(sb, blk1) + mn.mblk_idx, 0);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mfs_write_page(sb, buf, sz, MFS_BLK2PG(sb, blk2) + mn.mblk_idx, 0);
|
||||||
|
if (predict_false(ret < 0))
|
||||||
|
{
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
mn.mblk_idx++;
|
||||||
|
MFS_MN(sb) = mn;
|
||||||
|
|
||||||
|
errout:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
@@ -53,6 +53,8 @@
|
|||||||
* Included Files
|
* Included Files
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
#include "mnemofs.h"
|
#include "mnemofs.h"
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -118,10 +120,10 @@ ssize_t mfs_write_page(FAR const struct mfs_sb_s * const sb,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mempcpy(MFS_RWBUF(sb) + pgoff, data, datalen);
|
memcpy(MFS_RWBUF(sb) + pgoff, data, MIN(datalen, MFS_PGSZ(sb) - pgoff));
|
||||||
|
|
||||||
ret = MTD_BWRITE(MFS_MTD(sb), page, 1, MFS_RWBUF(sb));
|
ret = MTD_BWRITE(MFS_MTD(sb), page, 1, MFS_RWBUF(sb));
|
||||||
if (ret < 0)
|
if (predict_false(ret < 0))
|
||||||
{
|
{
|
||||||
goto errout_with_reset;
|
goto errout_with_reset;
|
||||||
}
|
}
|
||||||
@@ -144,12 +146,12 @@ ssize_t mfs_read_page(FAR const struct mfs_sb_s * const sb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = MTD_BREAD(MFS_MTD(sb), page, 1, MFS_RWBUF(sb));
|
ret = MTD_BREAD(MFS_MTD(sb), page, 1, MFS_RWBUF(sb));
|
||||||
if (ret < 0)
|
if (predict_false(ret < 0))
|
||||||
{
|
{
|
||||||
goto errout_with_reset;
|
goto errout_with_reset;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(data, MFS_RWBUF(sb) + pgoff, datalen);
|
memcpy(data, MFS_RWBUF(sb) + pgoff, MIN(datalen, MFS_PGSZ(sb) - pgoff));
|
||||||
|
|
||||||
errout_with_reset:
|
errout_with_reset:
|
||||||
memset(MFS_RWBUF(sb), 0, MFS_PGSZ(sb));
|
memset(MFS_RWBUF(sb), 0, MFS_PGSZ(sb));
|
||||||
|
|||||||
Reference in New Issue
Block a user