This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 786701c752 fs/mnemofs: Add master node and r/w methods Adds master 
node and r/w methods to mnemofs
786701c752 is described below

commit 786701c75273242f6222985b25a67fbce19c22d0
Author: Saurav Pal <[email protected]>
AuthorDate: Mon Jul 15 13:51:22 2024 +0000

    fs/mnemofs: Add master node and r/w methods
    Adds master node and r/w methods to mnemofs
    
    Signed-off-by: Saurav Pal <[email protected]>
---
 fs/mnemofs/mnemofs.h        |  44 ++++++++
 fs/mnemofs/mnemofs_master.c | 249 +++++++++++++++++++++++++++++++++++++++++++-
 fs/mnemofs/mnemofs_rw.c     |  34 +++++-
 3 files changed, 321 insertions(+), 6 deletions(-)

diff --git a/fs/mnemofs/mnemofs.h b/fs/mnemofs/mnemofs.h
index 7511d22203..df1d1040b3 100644
--- a/fs/mnemofs/mnemofs.h
+++ b/fs/mnemofs/mnemofs.h
@@ -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 */
 
 /****************************************************************************
diff --git a/fs/mnemofs/mnemofs_master.c b/fs/mnemofs/mnemofs_master.c
index b971671b1a..3f94720aa8 100644
--- a/fs/mnemofs/mnemofs_master.c
+++ b/fs/mnemofs/mnemofs_master.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;
+
+  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;
 
-  return OK;
+errout:
+  return ret;
 }
diff --git a/fs/mnemofs/mnemofs_rw.c b/fs/mnemofs/mnemofs_rw.c
index 306051d5b2..4a01e8aec9 100644
--- a/fs/mnemofs/mnemofs_rw.c
+++ b/fs/mnemofs/mnemofs_rw.c
@@ -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;
+
+  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 OK;
+  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;
+
+  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 OK;
+  return ret;
 }
 
 int mfs_erase_blk(FAR const struct mfs_sb_s * const sb, const off_t blk)

Reply via email to