fs/mnemofs: Add master node and r/w methods
Adds master node and r/w methods to mnemofs Signed-off-by: Saurav Pal <resyfer.dev@gmail.com>
This commit is contained in:
parent
baf52268cc
commit
786701c752
3 changed files with 321 additions and 6 deletions
|
@ -1303,6 +1303,27 @@ void mfs_lru_updatedsz(FAR struct mfs_sb_s * const sb,
|
|||
|
||||
/* mnemofs_master.c */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mfs_mn_init
|
||||
*
|
||||
* Description:
|
||||
* Initialize master node by reading from the flash.
|
||||
*
|
||||
* Input Parameters:
|
||||
* sb - Superblock instance of the device.
|
||||
* jrnl_blk - First block of the journal.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 - OK
|
||||
* < 0 - Error
|
||||
*
|
||||
* Assumptions/Limitations:
|
||||
* The journal will have to be initialized before this.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int mfs_mn_init(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mfs_mn_fmt
|
||||
*
|
||||
|
@ -1324,6 +1345,29 @@ void mfs_lru_updatedsz(FAR struct mfs_sb_s * const sb,
|
|||
|
||||
int mfs_mn_fmt(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mfs_mn_move
|
||||
*
|
||||
* Description:
|
||||
* Move the master node.
|
||||
*
|
||||
* Input Parameters:
|
||||
* sb - Superblock instance of the device.
|
||||
* root - New location of the root of the file system.
|
||||
* root_sz - New size of the CTZ list of the root of the file syste.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 - OK
|
||||
* < 0 - Error
|
||||
*
|
||||
* Assumptions/Limitations:
|
||||
* This is called when the root is updated to a new location.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int mfs_mn_move(FAR struct mfs_sb_s * const sb, struct mfs_ctz_s root,
|
||||
const mfs_t root_sz);
|
||||
|
||||
/* mnemofs_fsobj.c */
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -97,6 +97,11 @@
|
|||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
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,
|
||||
FAR struct mfs_mn_s *mn, FAR uint8_t *hash);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
@ -109,13 +114,253 @@
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ser_mn
|
||||
*
|
||||
* Description:
|
||||
* Serialize master node.
|
||||
*
|
||||
* Input Parameters:
|
||||
* mn - Master node.
|
||||
* out - Out buffer.
|
||||
*
|
||||
* Returned Value:
|
||||
* Pointer to the end of the serialized data in `out`.
|
||||
*
|
||||
* Assumptions/Limitations:
|
||||
* Out should contain enough space for `mn` and 1 byte extra for the hash.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static FAR char *ser_mn(const struct mfs_mn_s mn, FAR char * const out)
|
||||
{
|
||||
FAR char *tmp = out;
|
||||
|
||||
tmp = mfs_ser_mfs(mn.jrnl_blk, tmp);
|
||||
tmp = mfs_ser_mfs(mn.mblk_idx, tmp);
|
||||
tmp = mfs_ser_ctz(&mn.root_ctz, tmp);
|
||||
tmp = mfs_ser_mfs(mn.root_sz, tmp);
|
||||
tmp = mfs_ser_timespec(&mn.ts, tmp);
|
||||
tmp = mfs_ser_8(mfs_arrhash(out, tmp - out), tmp);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ser_mn
|
||||
*
|
||||
* Description:
|
||||
* Deserialize master node.
|
||||
*
|
||||
* Input Parameters:
|
||||
* in - In buffer.
|
||||
* mn - Master node to populate.
|
||||
* hash - Stored hash (of serialized data) to populate.
|
||||
*
|
||||
* Returned Value:
|
||||
* Pointer to the end of the serialized data in `in`.
|
||||
*
|
||||
* Assumptions/Limitations:
|
||||
* In should contain enough space for `mn` and 1 byte extra for the hash.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static FAR const char *deser_mn(FAR const char * const in,
|
||||
FAR struct mfs_mn_s *mn, FAR uint8_t *hash)
|
||||
{
|
||||
FAR const char *tmp = in;
|
||||
|
||||
tmp = mfs_deser_mfs(tmp, &mn->jrnl_blk);
|
||||
tmp = mfs_deser_mfs(tmp, &mn->mblk_idx);
|
||||
tmp = mfs_deser_ctz(tmp, &mn->root_ctz);
|
||||
tmp = mfs_deser_mfs(tmp, &mn->root_sz);
|
||||
tmp = mfs_deser_timespec(tmp, &mn->ts);
|
||||
tmp = mfs_deser_8(tmp, hash);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int mfs_mn_init(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk)
|
||||
{
|
||||
int ret = OK;
|
||||
mfs_t i = 0;
|
||||
mfs_t mblk1;
|
||||
mfs_t mblk2;
|
||||
mfs_t jrnl_blk_tmp;
|
||||
bool found = false;
|
||||
uint8_t hash;
|
||||
struct mfs_mn_s mn;
|
||||
const mfs_t sz = sizeof(struct mfs_mn_s) - sizeof(mn.pg);
|
||||
char buftmp[4];
|
||||
char buf[sz + 1];
|
||||
|
||||
mblk1 = mfs_jrnl_blkidx2blk(sb, MFS_JRNL(sb).n_blks);
|
||||
mblk2 = mfs_jrnl_blkidx2blk(sb, MFS_JRNL(sb).n_blks + 1);
|
||||
|
||||
mn.jrnl_blk = mn.jrnl_blk;
|
||||
mn.mblk_idx = 0;
|
||||
mn.pg = MFS_BLK2PG(sb, mblk1);
|
||||
|
||||
for (i = 0; i < MFS_PGINBLK(sb); i++)
|
||||
{
|
||||
mfs_read_page(sb, buftmp, 4, mn.pg, 0);
|
||||
mfs_deser_mfs(buftmp, &jrnl_blk_tmp);
|
||||
|
||||
if (jrnl_blk_tmp == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (jrnl_blk_tmp != jrnl_blk)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
found = true;
|
||||
mn.mblk_idx++;
|
||||
mn.pg++;
|
||||
}
|
||||
|
||||
if (found == false)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (i == MFS_PGINBLK(sb))
|
||||
{
|
||||
ret = -ENOSPC;
|
||||
goto errout;
|
||||
}
|
||||
else
|
||||
{
|
||||
mn.mblk_idx--;
|
||||
mn.pg--;
|
||||
}
|
||||
|
||||
mfs_read_page(sb, buf, sz + 1, mn.pg, 0);
|
||||
|
||||
/* Deserialize. */
|
||||
|
||||
deser_mn(buf, &mn, &hash);
|
||||
if (hash != mfs_arrhash(buf, sz))
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* FUTURE TODO: Recovery in case of hash not matching, or page not
|
||||
* readable.
|
||||
*/
|
||||
|
||||
MFS_MN(sb) = mn;
|
||||
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mfs_mn_fmt(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk)
|
||||
{
|
||||
/* TODO */
|
||||
int ret = OK;
|
||||
mfs_t pg;
|
||||
mfs_t mblk1;
|
||||
mfs_t mblk2;
|
||||
struct mfs_mn_s mn;
|
||||
const mfs_t sz = sizeof(struct mfs_mn_s) - sizeof(mn.pg);
|
||||
char buf[sz + 1];
|
||||
struct timespec ts;
|
||||
|
||||
return OK;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
|
||||
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);
|
||||
if (predict_false(pg == 0))
|
||||
{
|
||||
ret = -ENOSPC;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
finfo("Root formatted to be at Page %u", pg);
|
||||
|
||||
mn.root_ctz.idx_e = 0;
|
||||
mn.root_ctz.pg_e = pg;
|
||||
mn.jrnl_blk = jrnl_blk;
|
||||
mn.mblk_idx = 0;
|
||||
mn.pg = MFS_BLK2PG(sb, mblk1);
|
||||
mn.root_sz = 0;
|
||||
mn.ts = ts;
|
||||
mn.root_st_atim = ts;
|
||||
mn.root_st_ctim = ts;
|
||||
mn.root_st_mtim = ts;
|
||||
mn.root_mode = 0777 | S_IFDIR;
|
||||
|
||||
/* Serialize. */
|
||||
|
||||
ser_mn(mn, buf);
|
||||
|
||||
ret = mfs_write_page(sb, buf, sz, MFS_BLK2PG(sb, mblk1), 0);
|
||||
if (predict_false(ret < 0))
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = mfs_write_page(sb, buf, sz, MFS_BLK2PG(sb, mblk2), 0);
|
||||
if (predict_false(ret < 0))
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
|
||||
MFS_MN(sb) = mn;
|
||||
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).ts.tv_nsec);
|
||||
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mfs_mn_move(FAR struct mfs_sb_s * const sb, struct mfs_ctz_s root,
|
||||
const mfs_t root_sz)
|
||||
{
|
||||
int ret = OK;
|
||||
mfs_t mblk1;
|
||||
mfs_t mblk2;
|
||||
struct mfs_mn_s mn;
|
||||
const mfs_t sz = sizeof(struct mfs_mn_s) - sizeof(mn.pg);
|
||||
char buf[sz + 1];
|
||||
|
||||
if (MFS_MN(sb).mblk_idx == MFS_PGINBLK(sb) - 1)
|
||||
{
|
||||
/* TODO: Move journal. Master blocks are full. */
|
||||
}
|
||||
|
||||
mblk1 = mfs_jrnl_blkidx2blk(sb, MFS_JRNL(sb).n_blks);
|
||||
mblk2 = mfs_jrnl_blkidx2blk(sb, MFS_JRNL(sb).n_blks + 1);
|
||||
mn = MFS_MN(sb);
|
||||
|
||||
mn.root_ctz = root;
|
||||
mn.root_sz = root_sz;
|
||||
mn.mblk_idx++;
|
||||
mn.pg++;
|
||||
|
||||
ser_mn(mn, buf);
|
||||
|
||||
ret = mfs_write_page(sb, buf, sz + 1, mn.pg, 0);
|
||||
if (predict_false(ret < 0))
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
|
||||
MFS_MN(sb) = mn;
|
||||
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -93,22 +93,48 @@ int mfs_markbadblk(FAR const struct mfs_sb_s * const sb, mfs_t blk)
|
|||
return MTD_ISBAD(MFS_MTD(sb), blk);
|
||||
}
|
||||
|
||||
/* NOTE: These functions do not update the block allocator's state nor do
|
||||
* they enforce it.
|
||||
*/
|
||||
|
||||
ssize_t mfs_write_page(FAR const struct mfs_sb_s * const sb,
|
||||
FAR const char *data, const mfs_t datalen,
|
||||
const off_t page, const mfs_t pgoff)
|
||||
{
|
||||
/* TODO */
|
||||
int ret = OK;
|
||||
|
||||
return OK;
|
||||
mempcpy(MFS_RWBUF(sb) + pgoff, data, datalen);
|
||||
|
||||
ret = MTD_BWRITE(MFS_MTD(sb), page, 1, MFS_RWBUF(sb));
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_reset;
|
||||
}
|
||||
|
||||
errout_with_reset:
|
||||
memset(MFS_RWBUF(sb), 0, MFS_PGSZ(sb));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t mfs_read_page(FAR const struct mfs_sb_s * const sb,
|
||||
FAR char *data, const mfs_t datalen, const off_t page,
|
||||
const mfs_t pgoff)
|
||||
{
|
||||
/* TODO */
|
||||
int ret = OK;
|
||||
|
||||
return OK;
|
||||
ret = MTD_BREAD(MFS_MTD(sb), page, 1, MFS_RWBUF(sb));
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_reset;
|
||||
}
|
||||
|
||||
memcpy(data, MFS_RWBUF(sb) + pgoff, datalen);
|
||||
|
||||
errout_with_reset:
|
||||
memset(MFS_RWBUF(sb), 0, MFS_PGSZ(sb));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mfs_erase_blk(FAR const struct mfs_sb_s * const sb, const off_t blk)
|
||||
|
|
Loading…
Reference in a new issue