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

janc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git


The following commit(s) were added to refs/heads/master by this push:
     new 597956000 sys/log: Add optional support for sector bookmarks to 
optimize reading logs
597956000 is described below

commit 59795600024aadbf4dde7caa7593e10aaf849c80
Author: Vipul Rahane <[email protected]>
AuthorDate: Thu Mar 13 07:58:00 2025 -0700

    sys/log: Add optional support for sector bookmarks to optimize reading logs
    
    - Add sector bookmarks for reading optimization
    - CLI: Add '-b' option in log_shell for reading bookmarks
    - CLI: Add '-i' option in log_shell for reading logs from given index
---
 fs/fcb/include/fcb/fcb.h                           |  22 ++
 fs/fcb/src/fcb.c                                   |   2 +-
 fs/fcb/src/fcb_getnext.c                           |  11 +-
 fs/fcb/src/fcb_priv.h                              |   1 -
 sys/log/full/include/log/log_fcb.h                 |  70 +++-
 .../src/log_test_fcb_bookmarks_util.c              |   2 +-
 .../src/log_test_fcb_bookmarks_util.c              |   2 +-
 sys/log/full/selftest/fcb_bookmarks_mixed/pkg.yml  |  29 ++
 .../src/log_test_fcb_bookmarks.c                   |  38 +++
 .../src/log_test_fcb_bookmarks.h                   |  43 +++
 .../src/log_test_fcb_bookmarks_util.c              |  42 ++-
 .../src/testcases/s0_l10_b10_p100.c                |  32 ++
 .../src/testcases/s0_l1_b0_p100.c                  |  32 ++
 .../src/testcases/s0_l1_b5_p100.c                  |  32 ++
 .../src/testcases/s10_l10_b10_p100.c               |  32 ++
 .../full/selftest/fcb_bookmarks_mixed/syscfg.yml   |  22 ++
 sys/log/full/src/log_fcb.c                         |  65 +++-
 sys/log/full/src/log_fcb2.c                        |  22 +-
 sys/log/full/src/log_fcb_bmark.c                   | 375 +++++++++++++++++++--
 sys/log/full/src/log_shell.c                       |  86 ++++-
 sys/log/full/syscfg.yml                            |  13 +
 21 files changed, 894 insertions(+), 79 deletions(-)

diff --git a/fs/fcb/include/fcb/fcb.h b/fs/fcb/include/fcb/fcb.h
index 7f97b9ee1..16d97305a 100644
--- a/fs/fcb/include/fcb/fcb.h
+++ b/fs/fcb/include/fcb/fcb.h
@@ -168,6 +168,28 @@ typedef int (*fcb_walk_cb)(struct fcb_entry *loc, void 
*arg);
 int fcb_walk(struct fcb *, struct flash_area *, fcb_walk_cb cb, void *cb_arg);
 int fcb_getnext(struct fcb *, struct fcb_entry *loc);
 
+/**
+ * Get first entry in the provided flash area
+ *
+ * @param fcb Pointer to FCB
+ * @param fap Optional pointer to flash area
+ * @param loc Pointer to first FCB entry in the provided flash area
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int fcb_getnext_in_area(struct fcb *fcb, struct flash_area *fap,
+                        struct fcb_entry *loc);
+
+/**
+ * Get next area pointer from the FCB pointer
+ *
+ * @param fcb Pointer to the FCB
+ * @param fap Pointer to the flash_area
+ *
+ * @return Pointer to the flash_area that comes next
+ */
+struct flash_area *fcb_getnext_area(struct fcb *fcb, struct flash_area *fap);
+
 #if MYNEWT_VAL_FCB_BIDIRECTIONAL
 /**
  * Call 'cb' for every element in flash circular buffer moving
diff --git a/fs/fcb/src/fcb.c b/fs/fcb/src/fcb.c
index 967f5b460..89856ef69 100644
--- a/fs/fcb/src/fcb.c
+++ b/fs/fcb/src/fcb.c
@@ -90,7 +90,7 @@ fcb_init(struct fcb *fcb)
     assert((fcb->f_align & (fcb->f_align - 1)) == 0);
 
     while (1) {
-        rc = fcb_getnext_in_area(fcb, &fcb->f_active);
+        rc = fcb_getnext_in_area(fcb, NULL, &fcb->f_active);
         if (rc == FCB_ERR_NOVAR) {
             rc = FCB_OK;
             break;
diff --git a/fs/fcb/src/fcb_getnext.c b/fs/fcb/src/fcb_getnext.c
index 196a9c457..fe2278a8a 100644
--- a/fs/fcb/src/fcb_getnext.c
+++ b/fs/fcb/src/fcb_getnext.c
@@ -63,10 +63,19 @@ fcb_start_offset(struct fcb *fcb)
 }
 
 int
-fcb_getnext_in_area(struct fcb *fcb, struct fcb_entry *loc)
+fcb_getnext_in_area(struct fcb *fcb, struct flash_area *fap,
+                    struct fcb_entry *loc)
 {
     int rc;
 
+    /* If a flash area is specified, find first entry in that area */
+    if (fap) {
+        loc->fe_area = fap;
+        loc->fe_elem_off = fcb_len_in_flash(fcb, sizeof(struct fcb_disk_area));
+        loc->fe_elem_ix = 0;
+        loc->fe_data_len = 0;
+    }
+
     rc = fcb_elem_info(fcb, loc);
     if (rc == 0 || rc == FCB_ERR_CRC) {
         do {
diff --git a/fs/fcb/src/fcb_priv.h b/fs/fcb/src/fcb_priv.h
index 352aa969a..064a435d0 100644
--- a/fs/fcb/src/fcb_priv.h
+++ b/fs/fcb/src/fcb_priv.h
@@ -47,7 +47,6 @@ fcb_len_in_flash(struct fcb *fcb, uint16_t len)
     return (len + (fcb->f_align - 1)) & ~(fcb->f_align - 1);
 }
 
-int fcb_getnext_in_area(struct fcb *fcb, struct fcb_entry *loc);
 struct flash_area *fcb_getnext_area(struct fcb *fcb, struct flash_area *fap);
 int fcb_getnext_nolock(struct fcb *fcb, struct fcb_entry *loc);
 
diff --git a/sys/log/full/include/log/log_fcb.h 
b/sys/log/full/include/log/log_fcb.h
index ff81fcc28..7eca59b8c 100644
--- a/sys/log/full/include/log/log_fcb.h
+++ b/sys/log/full/include/log/log_fcb.h
@@ -46,14 +46,29 @@ struct log_fcb_bset {
     /** Array of bookmarks. */
     struct log_fcb_bmark *lfs_bmarks;
 
+    /** Enable sector bookmarks */
+    bool lfs_en_sect_bmarks;
+
     /** The maximum number of bookmarks. */
     int lfs_cap;
 
+    /** The maximum number of sector bookmarks. */
+    int lfs_sect_cap;
+
+    /** The number of currently used non-sector bookmarks. */
+    int lfs_non_sect_size;
+
     /** The number of currently usable bookmarks. */
     int lfs_size;
 
-    /** The index where the next bookmark will get written. */
-    int lfs_next;
+    /** The index where the next non-sector bmark will get written */
+    uint32_t lfs_next_non_sect;
+
+    /** The sector interval at which to insert sector bookmarks */
+    int lfs_sect_bmark_itvl;
+
+    /** The index where the next sector bmark will get written */
+    uint32_t lfs_next_sect;
 };
 
 /**
@@ -72,6 +87,7 @@ struct fcb_log {
 #if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
     struct log_fcb_bset fl_bset;
 #endif
+    struct log *fl_log;
 };
 
 #elif MYNEWT_VAL(LOG_FCB2)
@@ -87,6 +103,7 @@ struct fcb_log {
 #if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
     struct log_fcb_bset fl_bset;
 #endif
+    struct log *fl_log;
 };
 #endif
 
@@ -103,19 +120,35 @@ struct fcb_log {
  * the log is walked, the starting point of the walk is added to the set of
  * bookmarks.
  *
- * FCB rotation invalidates all bookmarks.  It is up to the client code to
+ * FCB rotation invalidates all bookmarks. It is up to the client code to
  * clear a log's bookmarks whenever rotation occurs.
  */
 
 /**
  * @brief Configures an fcb_log to use the specified buffer for bookmarks.
+ *        If sector bookmarks are enabled, buffer should be big enough
+ *        to accommodate bookmarks for the entire flash area that is allocated
+ *        for the FCB log, i,e; sizeof(struct log_fcb_bmark) *
+ *        my_log.fl_fcb.f_sector_cnt + MYNEWT_VAL(LOG_FCB_NUM_ABS_BOOKMARKS)
  *
  * @param fcb_log               The log to configure.
  * @param buf                   The buffer to use for bookmarks.
- * @param bmark_count           The bookmark capacity of the supplied buffer.
+ * @param avl_bmark_cnt         The bookmark capacity of the supplied buffer,
+ *                              available bookmark count
+ * @param en_sect_bmarks        Enable sector bookmarks
+ *
+ * @return 0 on success, non-zero on failure
  */
-void log_fcb_init_bmarks(struct fcb_log *fcb_log,
-                         struct log_fcb_bmark *buf, int bmark_count);
+int log_fcb_init_bmarks(struct fcb_log *fcb_log,
+                        struct log_fcb_bmark *buf, int avl_bmark_cnt,
+                        bool en_sect_bmarks);
+
+/** @brief Remove bookmarks which point to oldest FCB/FCB2 area. This is
+ * meant to get called just before the area is rotated out.
+ *
+ * @param fcb_log               The fcb_log to operate on.
+ */
+void log_fcb_rotate_bmarks(struct fcb_log *fcb_log);
 
 /**
  * @brief Erases all bookmarks from the supplied fcb_log.
@@ -125,12 +158,14 @@ void log_fcb_init_bmarks(struct fcb_log *fcb_log,
 void log_fcb_clear_bmarks(struct fcb_log *fcb_log);
 
 /**
- * @brief Remove bookmarks which point to oldest FCB/FCB2 area. This is
- * meant to get called just before the area is rotated out.
+ * @brief Get bookmarks for a particular log
  *
- * @param fcb_log               The fcb_log to operate on.
+ * @param log Pointer to the log we want to read bookmarks from
+ * @param bmarks_size Pointer to the variable we want to read bookmarks into
+ *
+ * @return Pointer to the bookmarks array for the provided log
  */
-void log_fcb_rotate_bmarks(struct fcb_log *fcb_log);
+struct log_fcb_bmark *log_fcb_get_bmarks(struct log *log, uint32_t 
*bmarks_size);
 
 /**
  * @brief Searches an fcb_log for the closest bookmark that comes before or at
@@ -138,12 +173,14 @@ void log_fcb_rotate_bmarks(struct fcb_log *fcb_log);
  *
  * @param fcb_log               The log to search.
  * @param index                 The index to look for.
+ * @param min_diff              If bookmark was found, fill it up with the 
difference
+ *                              else it will return -1.
  *
  * @return                      The closest bookmark on success;
  *                              NULL if the log has no applicable bookmarks.
  */
 const struct log_fcb_bmark *
-log_fcb_closest_bmark(const struct fcb_log *fcb_log, uint32_t index);
+log_fcb_closest_bmark(const struct fcb_log *fcb_log, uint32_t index, int 
*min_diff);
 
 /**
  * Inserts a bookmark into the provided log.
@@ -151,13 +188,16 @@ log_fcb_closest_bmark(const struct fcb_log *fcb_log, 
uint32_t index);
  * @param fcb_log               The log to insert a bookmark into.
  * @param entry                 The entry the bookmark should point to.
  * @param index                 The log entry index of the bookmark.
+ * @paran sect_bmark            Bool indicating it is a sector bookmark.
+ *
+ * @return                      non-zero on failure, 0 on success
  */
 #if MYNEWT_VAL(LOG_FCB)
-void log_fcb_add_bmark(struct fcb_log *fcb_log, const struct fcb_entry *entry,
-                       uint32_t index);
+int log_fcb_add_bmark(struct fcb_log *fcb_log, struct fcb_entry *entry,
+                      uint32_t index, bool sect_bmark);
 #elif MYNEWT_VAL(LOG_FCB2)
-void log_fcb_add_bmark(struct fcb_log *fcb_log, const struct fcb2_entry *entry,
-                       uint32_t index);
+int log_fcb_add_bmark(struct fcb_log *fcb_log, struct fcb2_entry *entry,
+                      uint32_t index, bool sect_bmark);
 #endif
 #endif
 
diff --git 
a/sys/log/full/selftest/fcb2_bookmarks/src/log_test_fcb_bookmarks_util.c 
b/sys/log/full/selftest/fcb2_bookmarks/src/log_test_fcb_bookmarks_util.c
index c8d5c8ce9..25c40152d 100644
--- a/sys/log/full/selftest/fcb2_bookmarks/src/log_test_fcb_bookmarks_util.c
+++ b/sys/log/full/selftest/fcb2_bookmarks/src/log_test_fcb_bookmarks_util.c
@@ -220,7 +220,7 @@ ltfbu_init(const struct ltfbu_cfg *cfg)
     TEST_ASSERT_FATAL(rc == 0);
 
     if (cfg->bmark_count > 0) {
-        log_fcb_init_bmarks(&ltfbu_fcb_log, ltfbu_bmarks, cfg->bmark_count);
+        log_fcb_init_bmarks(&ltfbu_fcb_log, ltfbu_bmarks, cfg->bmark_count, 
false);
     }
 
     log_register("log", &ltfbu_log, &log_fcb_handler, &ltfbu_fcb_log,
diff --git 
a/sys/log/full/selftest/fcb_bookmarks/src/log_test_fcb_bookmarks_util.c 
b/sys/log/full/selftest/fcb_bookmarks/src/log_test_fcb_bookmarks_util.c
index 854f99b2e..3e416cdcc 100644
--- a/sys/log/full/selftest/fcb_bookmarks/src/log_test_fcb_bookmarks_util.c
+++ b/sys/log/full/selftest/fcb_bookmarks/src/log_test_fcb_bookmarks_util.c
@@ -231,7 +231,7 @@ ltfbu_init(const struct ltfbu_cfg *cfg)
     TEST_ASSERT_FATAL(rc == 0);
 
     if (cfg->bmark_count > 0) {
-        log_fcb_init_bmarks(&ltfbu_fcb_log, ltfbu_bmarks, cfg->bmark_count);
+        log_fcb_init_bmarks(&ltfbu_fcb_log, ltfbu_bmarks, cfg->bmark_count, 
false);
     }
 
     log_register("log", &ltfbu_log, &log_fcb_handler, &ltfbu_fcb_log,
diff --git a/sys/log/full/selftest/fcb_bookmarks_mixed/pkg.yml 
b/sys/log/full/selftest/fcb_bookmarks_mixed/pkg.yml
new file mode 100644
index 000000000..07266232c
--- /dev/null
+++ b/sys/log/full/selftest/fcb_bookmarks_mixed/pkg.yml
@@ -0,0 +1,29 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+pkg.name: sys/log/full/selftest/fcb_bookmarks_mixed
+pkg.type: unittest
+pkg.description: "Log unit tests; flash-alignment=8."
+pkg.author: "Apache Mynewt <[email protected]>"
+pkg.homepage: "http://mynewt.apache.org/";
+pkg.keywords:
+
+pkg.deps:
+    - "@apache-mynewt-core/sys/console/stub"
+    - "@apache-mynewt-core/sys/log/full"
+    - "@apache-mynewt-core/sys/log/full/selftest/util"
+    - "@apache-mynewt-core/test/testutil"
diff --git 
a/sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks.c 
b/sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks.c
new file mode 100644
index 000000000..5ed58ae8f
--- /dev/null
+++ b/sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks.c
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "os/mynewt.h"
+#include "log_test_util/log_test_util.h"
+#include "log_test_fcb_bookmarks.h"
+
+TEST_SUITE(log_test_suite_fcb_bookmarks)
+{
+    log_test_case_fcb_bookmarks_s0_l1_b0_p100();
+    log_test_case_fcb_bookmarks_s0_l1_b5_p100();
+    log_test_case_fcb_bookmarks_s0_l10_b10_p100();
+    log_test_case_fcb_bookmarks_s10_l10_b10_p100();
+}
+
+int
+main(int argc, char **argv)
+{
+    log_test_suite_fcb_bookmarks();
+
+    return tu_any_failed;
+}
diff --git 
a/sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks.h 
b/sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks.h
new file mode 100644
index 000000000..441d842ce
--- /dev/null
+++ b/sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks.h
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_LOG_TEST_FCB_BOOKMARKS_
+#define H_LOG_TEST_FCB_BOOKMARKS_
+
+#include "os/mynewt.h"
+#include "testutil/testutil.h"
+
+struct ltfbu_cfg {
+    int skip_mod;
+    int body_len;
+    int bmark_count;
+    int pop_count;
+};
+
+void ltfbu_populate_log(int count);
+void ltfbu_verify_log(uint32_t start_idx);
+void ltfbu_init(const struct ltfbu_cfg *cfg);
+void ltfbu_test_once(const struct ltfbu_cfg *cfg);
+
+TEST_CASE_DECL(log_test_case_fcb_bookmarks_s0_l1_b0_p100);
+TEST_CASE_DECL(log_test_case_fcb_bookmarks_s0_l1_b5_p100);
+TEST_CASE_DECL(log_test_case_fcb_bookmarks_s0_l10_b10_p100);
+TEST_CASE_DECL(log_test_case_fcb_bookmarks_s10_l10_b10_p100);
+
+#endif
diff --git 
a/sys/log/full/selftest/fcb_bookmarks/src/log_test_fcb_bookmarks_util.c 
b/sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks_util.c
similarity index 86%
copy from sys/log/full/selftest/fcb_bookmarks/src/log_test_fcb_bookmarks_util.c
copy to 
sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks_util.c
index 854f99b2e..3464d2504 100644
--- a/sys/log/full/selftest/fcb_bookmarks/src/log_test_fcb_bookmarks_util.c
+++ 
b/sys/log/full/selftest/fcb_bookmarks_mixed/src/log_test_fcb_bookmarks_util.c
@@ -48,7 +48,21 @@ static struct flash_area ltfbu_fcb_areas[] = {
     [1] = {
         .fa_off = 1 * LTFBU_SECTOR_SIZE,
         .fa_size = LTFBU_SECTOR_SIZE,
+    },
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+    [2] = {
+        .fa_off = 2 * LTFBU_SECTOR_SIZE,
+        .fa_size = LTFBU_SECTOR_SIZE,
+    },
+    [3] = {
+        .fa_off = 3 * LTFBU_SECTOR_SIZE,
+        .fa_size = LTFBU_SECTOR_SIZE,
+    },
+    [4] = {
+        .fa_off = 4 * LTFBU_SECTOR_SIZE,
+        .fa_size = LTFBU_SECTOR_SIZE,
     }
+ #endif
 };
 
 static int
@@ -136,6 +150,13 @@ ltfbu_write_entry(void)
 
     memset(body, idx, ltfbu_cfg.body_len);
 
+#if 0
+    printf("log entry: ");
+    for (int i = 0; i < ltfbu_cfg.body_len; i++) {
+        printf("%2x", body[i]);
+    }
+    printf("\n");
+#endif
     rc = log_append_body(&ltfbu_log, 0, 255, LOG_ETYPE_BINARY, body,
                          ltfbu_cfg.body_len);
     TEST_ASSERT_FATAL(rc == 0);
@@ -230,12 +251,9 @@ ltfbu_init(const struct ltfbu_cfg *cfg)
     rc = fcb_init(&ltfbu_fcb_log.fl_fcb);
     TEST_ASSERT_FATAL(rc == 0);
 
-    if (cfg->bmark_count > 0) {
-        log_fcb_init_bmarks(&ltfbu_fcb_log, ltfbu_bmarks, cfg->bmark_count);
-    }
-
     log_register("log", &ltfbu_log, &log_fcb_handler, &ltfbu_fcb_log,
                  LOG_SYSLEVEL);
+    
 }
 
 void
@@ -243,6 +261,7 @@ ltfbu_test_once(const struct ltfbu_cfg *cfg)
 {
     uint32_t start_idx;
     int i;
+    int rc = 0;
 
     ltfbu_init(cfg);
 
@@ -253,12 +272,21 @@ ltfbu_test_once(const struct ltfbu_cfg *cfg)
      *     a. All expected entries are visited.
      *     b. No extra entries are visited.
      *
-     * This procedure is repeated three times to ensure that the FCB is rotated
+     * This procedure is repeated six times to ensure that the FCB is rotated
      * between walks.
      */
-    for (i = 0; i < 3; i++) {
-        ltfbu_populate_log(cfg->pop_count);
+    ltfbu_populate_log(cfg->pop_count);
+
+    if (cfg->bmark_count > 0) {
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+        rc = log_fcb_init_bmarks(&ltfbu_fcb_log, ltfbu_bmarks, 
cfg->bmark_count, true);
+#else
+        rc = log_fcb_init_bmarks(&ltfbu_fcb_log, ltfbu_bmarks, 
cfg->bmark_count, false);
+#endif
+        TEST_ASSERT_FATAL(rc == 0);
+    }
 
+    for (i = 0; i < 6; i++) {
         start_idx = 0;
         while (start_idx < ltfbu_entry_idxs[ltfbu_num_entry_idxs - 1]) {
             ltfbu_verify_log(start_idx);
diff --git 
a/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l10_b10_p100.c 
b/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l10_b10_p100.c
new file mode 100644
index 000000000..4555d4f54
--- /dev/null
+++ b/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l10_b10_p100.c
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "log_test_util/log_test_util.h"
+#include "log_test_fcb_bookmarks.h"
+
+TEST_CASE_SELF(log_test_case_fcb_bookmarks_s0_l10_b10_p100)
+{
+    struct ltfbu_cfg cfg = {
+        .skip_mod = 0,
+        .body_len = 10,
+        .bmark_count = 10,
+        .pop_count = 100,
+    };
+    ltfbu_test_once(&cfg);
+}
diff --git 
a/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l1_b0_p100.c 
b/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l1_b0_p100.c
new file mode 100644
index 000000000..d21126407
--- /dev/null
+++ b/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l1_b0_p100.c
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "log_test_util/log_test_util.h"
+#include "log_test_fcb_bookmarks.h"
+
+TEST_CASE_SELF(log_test_case_fcb_bookmarks_s0_l1_b0_p100)
+{
+    struct ltfbu_cfg cfg = {
+        .skip_mod = 0,
+        .body_len = 10,
+        .bmark_count = 0,
+        .pop_count = 100,
+    };
+    ltfbu_test_once(&cfg);
+}
diff --git 
a/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l1_b5_p100.c 
b/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l1_b5_p100.c
new file mode 100644
index 000000000..13c097d97
--- /dev/null
+++ b/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s0_l1_b5_p100.c
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "log_test_util/log_test_util.h"
+#include "log_test_fcb_bookmarks.h"
+
+TEST_CASE_SELF(log_test_case_fcb_bookmarks_s0_l1_b5_p100)
+{
+    struct ltfbu_cfg cfg = {
+        .skip_mod = 0,
+        .body_len = 10,
+        .bmark_count = 5,
+        .pop_count = 100,
+    };
+    ltfbu_test_once(&cfg);
+}
diff --git 
a/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s10_l10_b10_p100.c 
b/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s10_l10_b10_p100.c
new file mode 100644
index 000000000..b8296d38d
--- /dev/null
+++ b/sys/log/full/selftest/fcb_bookmarks_mixed/src/testcases/s10_l10_b10_p100.c
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "log_test_util/log_test_util.h"
+#include "log_test_fcb_bookmarks.h"
+
+TEST_CASE_SELF(log_test_case_fcb_bookmarks_s10_l10_b10_p100)
+{
+    struct ltfbu_cfg cfg = {
+        .skip_mod = 10,
+        .body_len = 10,
+        .bmark_count = 10,
+        .pop_count = 100,
+    };
+    ltfbu_test_once(&cfg);
+}
diff --git a/sys/log/full/selftest/fcb_bookmarks_mixed/syscfg.yml 
b/sys/log/full/selftest/fcb_bookmarks_mixed/syscfg.yml
new file mode 100644
index 000000000..da0698b62
--- /dev/null
+++ b/sys/log/full/selftest/fcb_bookmarks_mixed/syscfg.yml
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+syscfg.vals:
+    LOG_FCB: 1
+    LOG_FCB_BOOKMARKS: 1
+    LOG_FCB_SECTOR_BOOKMARKS: 1
diff --git a/sys/log/full/src/log_fcb.c b/sys/log/full/src/log_fcb.c
index 05dd29e3b..529e8f473 100644
--- a/sys/log/full/src/log_fcb.c
+++ b/sys/log/full/src/log_fcb.c
@@ -53,7 +53,9 @@ fcb_get_fa_hdr(struct fcb *fcb, struct log *log, struct 
fcb_entry *fcb_entry, st
  * given offset is found, start walking from there.
  */
 static int
-fcb_walk_back_find_start(struct fcb *fcb, struct log *log, struct log_offset 
*log_offset, struct fcb_entry *fcb_entry)
+fcb_walk_back_find_start(struct fcb *fcb, struct log *log,
+                         struct log_offset *log_offset,
+                         struct fcb_entry *fcb_entry)
 {
     struct flash_area *fap;
     struct log_entry_hdr hdr;
@@ -111,6 +113,10 @@ found_ent:
  *
  * The "index" field corresponds to a log entry index.
  *
+ * If bookmark is found with the minimum difference in indices, min_diff 
contains
+ * the difference else it will contain -1 if no bookmark is found. min_diff is 0
+ * means an exact match.
+ *
  * If bookmarks are enabled, this function uses them in the search.
  *
  * @return                      0 if an entry was found
@@ -119,7 +125,7 @@ found_ent:
  */
 static int
 log_fcb_find_gte(struct log *log, struct log_offset *log_offset,
-                 struct fcb_entry *out_entry)
+                 struct fcb_entry *out_entry, int *min_diff)
 {
 #if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
     const struct log_fcb_bmark *bmark;
@@ -166,7 +172,7 @@ log_fcb_find_gte(struct log *log, struct log_offset 
*log_offset,
     }
 
 #if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
-    bmark = log_fcb_closest_bmark(fcb_log, log_offset->lo_index);
+    bmark = log_fcb_closest_bmark(fcb_log, log_offset->lo_index, min_diff);
     if (bmark != NULL) {
         *out_entry = bmark->lfb_entry;
         bmark_found = true;
@@ -209,6 +215,10 @@ log_fcb_start_append(struct log *log, int len, struct 
fcb_entry *loc)
     struct fcb_log *fcb_log;
     struct flash_area *old_fa;
     int rc = 0;
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+    int active_id;
+    uint32_t idx;
+#endif
 #if MYNEWT_VAL(LOG_STATS)
     int cnt;
 #endif
@@ -216,6 +226,10 @@ log_fcb_start_append(struct log *log, int len, struct 
fcb_entry *loc)
     fcb_log = (struct fcb_log *)log->l_arg;
     fcb = &fcb_log->fl_fcb;
 
+    /* Cache active ID before appending */
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+    active_id = fcb->f_active_id;
+#endif
     while (1) {
         rc = fcb_append(fcb, len, loc);
         if (rc == 0) {
@@ -250,8 +264,10 @@ log_fcb_start_append(struct log *log, int len, struct 
fcb_entry *loc)
             log->l_rotate_notify_cb(log);
         }
 
-#if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
-        /* The FCB needs to be rotated. */
+#if MYNEWT_VAL(LOG_FCB_BOOKMARKS) && !MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+        /* The FCB needs to be rotated. For sector bookmarks
+         * we just re-initialize the bookmarks
+         */
         log_fcb_rotate_bmarks(fcb_log);
 #endif
 
@@ -260,6 +276,15 @@ log_fcb_start_append(struct log *log, int len, struct 
fcb_entry *loc)
             goto err;
         }
 
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+        /* The FCB needs to be rotated, reinit previously allocated
+         * bookmarks
+         */
+        log_fcb_init_bmarks(fcb_log, fcb_log->fl_bset.lfs_bmarks,
+                            fcb_log->fl_bset.lfs_cap,
+                            fcb_log->fl_bset.lfs_en_sect_bmarks);
+#endif
+
 #if MYNEWT_VAL(LOG_STORAGE_WATERMARK)
         /*
          * FCB was rotated successfully so let's check if watermark was within
@@ -273,6 +298,20 @@ log_fcb_start_append(struct log *log, int len, struct 
fcb_entry *loc)
 #endif
     }
 
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+    /* Add bookmark if entry is added to a new sector */
+    if (!rc && log->l_log->log_type != LOG_TYPE_STREAM) {
+        if (fcb->f_active_id != active_id) {
+#if MYNEWT_VAL(LOG_GLOBAL_IDX)
+            idx = g_log_info.li_next_index;
+#else
+            idx = log->l_idx;
+#endif
+            log_fcb_add_bmark(fcb_log, loc, idx, true);
+        }
+    }
+#endif
+
 err:
     return (rc);
 }
@@ -582,12 +621,13 @@ log_fcb_walk_impl(struct log *log, log_walk_func_t 
walk_func,
     struct flash_area *fap;
     int rc;
     struct fcb_entry_cache cache;
+    int min_diff = -1;
 
     fcb_log = log->l_arg;
     fcb = &fcb_log->fl_fcb;
 
     /* Locate the starting point of the walk. */
-    rc = log_fcb_find_gte(log, log_offset, &loc);
+    rc = log_fcb_find_gte(log, log_offset, &loc, &min_diff);
     switch (rc) {
     case 0:
         /* Found a starting point. */
@@ -611,9 +651,12 @@ log_fcb_walk_impl(struct log *log, log_walk_func_t 
walk_func,
 #if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
     /* If a minimum index was specified (i.e., we are not just retrieving the
      * last entry), add a bookmark pointing to this walk's start location.
+     * Only add a bmark if the index is non-zero and an exactly matching bmark
+     * was not found. If an exactly matching bmark was found, min_diff is 0,
+     * else it stays -1 or is great than 0.
      */
-    if (log_offset->lo_ts >= 0) {
-        log_fcb_add_bmark(fcb_log, &loc, log_offset->lo_index);
+    if ((log_offset->lo_ts >= 0 && log_offset->lo_index > 0) && min_diff != 0) 
{
+        log_fcb_add_bmark(fcb_log, &loc, log_offset->lo_index, false);
     }
 #endif
 
@@ -674,15 +717,15 @@ log_fcb_flush(struct log *log)
 static int
 log_fcb_registered(struct log *log)
 {
+    struct fcb_log *fl = (struct fcb_log *)log->l_arg;
+
+    fl->fl_log = log;
 #if MYNEWT_VAL(LOG_STORAGE_WATERMARK)
-    struct fcb_log *fl;
 #if MYNEWT_VAL(LOG_PERSIST_WATERMARK)
     struct fcb *fcb;
     struct fcb_entry loc;
 #endif
 
-    fl = (struct fcb_log *)log->l_arg;
-
 #if MYNEWT_VAL(LOG_PERSIST_WATERMARK)
     fcb = &fl->fl_fcb;
 
diff --git a/sys/log/full/src/log_fcb2.c b/sys/log/full/src/log_fcb2.c
index b307acfe9..2bb2e604e 100644
--- a/sys/log/full/src/log_fcb2.c
+++ b/sys/log/full/src/log_fcb2.c
@@ -46,7 +46,10 @@ static int log_fcb2_rtr_erase(struct log *log);
  *
  * The "index" field corresponds to a log entry index.
  *
- * If bookmarks are enabled, this function uses them in the search.
+ *
+ * If bookmark is found with the minimum difference in indexes, min_diff 
contains
+ * the difference else it will contain -1 if no bookmark is found. min_diff is 0
+ * means an exact match.
  *
  * @return                      0 if an entry was found
  *                              SYS_ENOENT if there are no suitable entries.
@@ -54,7 +57,7 @@ static int log_fcb2_rtr_erase(struct log *log);
  */
 static int
 log_fcb2_find_gte(struct log *log, struct log_offset *log_offset,
-                  struct fcb2_entry *out_entry)
+                  struct fcb2_entry *out_entry, int *min_diff)
 {
 #if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
     const struct log_fcb_bmark *bmark;
@@ -67,6 +70,7 @@ log_fcb2_find_gte(struct log *log, struct log_offset 
*log_offset,
     fcb_log = log->l_arg;
     fcb = &fcb_log->fl_fcb;
 
+    (void)min_diff;
     /* Attempt to read the last entry.  If this fails, the FCB is empty. */
     memset(out_entry, 0, sizeof(*out_entry));
     rc = fcb2_getprev(fcb, out_entry);
@@ -103,7 +107,7 @@ log_fcb2_find_gte(struct log *log, struct log_offset 
*log_offset,
         return SYS_EUNKNOWN;
     }
 #if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
-    bmark = log_fcb_closest_bmark(fcb_log, log_offset->lo_index);
+    bmark = log_fcb_closest_bmark(fcb_log, log_offset->lo_index, min_diff);
     if (bmark != NULL) {
         *out_entry = bmark->lfb_entry;
     }
@@ -476,12 +480,13 @@ log_fcb2_walk(struct log *log, log_walk_func_t walk_func,
     struct fcb_log *fcb_log;
     struct fcb2_entry loc;
     int rc;
+    int min_diff = -1;
 
     fcb_log = log->l_arg;
     fcb = &fcb_log->fl_fcb;
 
     /* Locate the starting point of the walk. */
-    rc = log_fcb2_find_gte(log, log_off, &loc);
+    rc = log_fcb2_find_gte(log, log_off, &loc, &min_diff);
     switch (rc) {
     case 0:
         /* Found a starting point. */
@@ -497,8 +502,8 @@ log_fcb2_walk(struct log *log, log_walk_func_t walk_func,
     /* If a minimum index was specified (i.e., we are not just retrieving the
      * last entry), add a bookmark pointing to this walk's start location.
      */
-    if (log_off->lo_ts >= 0) {
-        log_fcb_add_bmark(fcb_log, &loc, log_off->lo_index);
+    if ((log_off->lo_ts >= 0 && log_off->lo_index > 0) && min_diff != 0) {
+        log_fcb_add_bmark(fcb_log, &loc, log_off->lo_index, false);
     }
 #endif
 
@@ -537,14 +542,15 @@ log_fcb2_registered(struct log *log)
 {
     struct fcb2 *fcb;
     int i;
-    struct fcb_log *fl;
+    struct fcb_log *fl = (struct fcb_log *)log->l_arg;
+
 #if MYNEWT_VAL(LOG_STORAGE_WATERMARK)
 #if MYNEWT_VAL(LOG_PERSIST_WATERMARK)
     struct fcb2_entry loc;
 #endif
 #endif
+    fl->fl_log = log;
 
-    fl = (struct fcb_log *)log->l_arg;
     fcb = &fl->fl_fcb;
 
     for (i = 0; i < fcb->f_range_cnt; i++) {
diff --git a/sys/log/full/src/log_fcb_bmark.c b/sys/log/full/src/log_fcb_bmark.c
index e9282771a..2a210aa94 100644
--- a/sys/log/full/src/log_fcb_bmark.c
+++ b/sys/log/full/src/log_fcb_bmark.c
@@ -22,17 +22,152 @@
 #include "os/mynewt.h"
 
 #if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
-
+#include "log/log.h"
 #include "log/log_fcb.h"
 
-void
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+static int
+log_fcb_init_sector_bmarks(struct fcb_log *fcb_log)
+{
+    int rc = 0;
+    int i = 0;
+    int j = 0;
+    struct log_fcb_bset *bset = &fcb_log->fl_bset;
+    struct log_entry_hdr ueh = {0};
+#if MYNEWT_VAL(LOG_FCB)
+    struct fcb_entry loc = {0};
+    struct flash_area *fa = NULL;
+
+    rc = fcb_getnext(&fcb_log->fl_fcb, &loc);
+    if (rc) {
+        return SYS_EOK;
+    }
+#else
+    struct flash_sector_range *range = NULL;
+    struct fcb2_entry loc = {0};
+
+    rc = fcb2_getnext(&fcb_log->fl_fcb, &loc);
+    if (rc) {
+        return SYS_EOK;
+    }
+#endif
+
+    /* Start adding a bookmark from the end of array just before
+     * non-sector bookmarks
+     */
+    bset->lfs_next_sect = bset->lfs_sect_cap - 1;
+    for (i = 0; i < bset->lfs_sect_cap; i++) {
+        rc = log_read_hdr(fcb_log->fl_log, &loc, &ueh);
+        if (rc) {
+            /* Read failed, don't add a bookmark, done adding bookmarks */
+            rc = SYS_EOK;
+            break;
+        }
+
+        rc = log_fcb_add_bmark(fcb_log, &loc, ueh.ue_index, true);
+        if (rc) {
+            return rc;
+        }
+
+#if MYNEWT_VAL(LOG_FCB)
+        j = 0;
+        fa = loc.fe_area;
+        /* Keep skipping sectors until lfs_sect_bmark_itvl is reached */
+        do {
+            fa = fcb_getnext_area(&fcb_log->fl_fcb, fa);
+            if (!fa) {
+                break;
+            }
+            j++;
+        } while (j < bset->lfs_sect_bmark_itvl);
+
+        if (!fa) {
+            break;
+        }
+
+        /* First entry in the next area */
+        rc = fcb_getnext_in_area(&fcb_log->fl_fcb, fa, &loc);
+        if (rc) {
+            rc = SYS_EOK;
+            break;
+        }
+#else
+        j = 0;
+
+        /* Keep skipping rangess until lfs_sect_bmark_itvl is reached */
+        do {
+            /* Get next range */
+            range = fcb2_getnext_range(&fcb_log->fl_fcb, &loc);
+            if (!range) {
+                break;
+            }
+            j++;
+        } while (j < bset->lfs_sect_bmark_itvl);
+
+        if (!range) {
+            break;
+        }
+
+        /* First entry in the next area */
+        rc = fcb2_getnext_in_area(&fcb_log->fl_fcb, range, &loc);
+        if (rc) {
+            rc = SYS_EOK;
+            break;
+        }
+#endif
+    }
+
+    return rc;
+}
+#endif
+
+int
 log_fcb_init_bmarks(struct fcb_log *fcb_log,
-                    struct log_fcb_bmark *buf, int bmark_count)
+                    struct log_fcb_bmark *buf, int avl_bmark_cnt,
+                    bool en_sect_bmarks)
 {
-    fcb_log->fl_bset = (struct log_fcb_bset) {
+    struct log_fcb_bset *bset = &fcb_log->fl_bset;
+    /* Required bookmark count */
+    int reqd_bmark_cnt = MYNEWT_VAL(LOG_FCB_NUM_ABS_BOOKMARKS);
+
+    (void)reqd_bmark_cnt;
+    if (!bset || !buf || !avl_bmark_cnt) {
+        return SYS_EINVAL;
+    }
+
+    memset(buf, 0, sizeof(struct log_fcb_bmark) * avl_bmark_cnt);
+
+    *bset = (struct log_fcb_bset) {
         .lfs_bmarks = buf,
-        .lfs_cap = bmark_count,
+        .lfs_cap = avl_bmark_cnt,
+        .lfs_en_sect_bmarks = en_sect_bmarks
     };
+
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+    if (en_sect_bmarks) {
+        /* Default sector bookmark interval is 1 */
+        bset->lfs_sect_bmark_itvl = 1;
+        reqd_bmark_cnt += fcb_log->fl_fcb.f_sector_cnt;
+        /* Make sure we have allocated the exact number of bookmarks
+         * compare available bookmark count Vs required bookmark count
+         */
+        if (avl_bmark_cnt < reqd_bmark_cnt) {
+            /* Not enough space allocated for sector bookmarks,
+             * add bookmarks at sector intervals
+             */
+            bset->lfs_sect_bmark_itvl =
+                fcb_log->fl_fcb.f_sector_cnt / avl_bmark_cnt;
+            bset->lfs_sect_cap = avl_bmark_cnt -
+                                 MYNEWT_VAL(LOG_FCB_NUM_ABS_BOOKMARKS);
+        } else {
+            bset->lfs_sect_cap = fcb_log->fl_fcb.f_sector_cnt;
+        }
+
+        return log_fcb_init_sector_bmarks(fcb_log);
+    }
+#endif
+
+    return 0;
 }
 
 void
@@ -61,7 +196,6 @@ log_fcb_rotate_bmarks(struct fcb_log *fcb_log)
             i--;
         }
         bset->lfs_size--;
-        bset->lfs_next = bset->lfs_size;
     }
 }
 
@@ -69,28 +203,93 @@ void
 log_fcb_clear_bmarks(struct fcb_log *fcb_log)
 {
     fcb_log->fl_bset.lfs_size = 0;
-    fcb_log->fl_bset.lfs_next = 0;
+    fcb_log->fl_bset.lfs_next_non_sect = 0;
+    fcb_log->fl_bset.lfs_non_sect_size = 0;
+    memset(fcb_log->fl_bset.lfs_bmarks, 0,
+           sizeof(struct log_fcb_bmark) *
+           fcb_log->fl_bset.lfs_cap);
+}
+
+struct log_fcb_bmark *
+log_fcb_get_bmarks(struct log *log, uint32_t *bmarks_size)
+{
+    struct fcb_log *fcb_log = (struct fcb_log *)log->l_arg;
+
+    *bmarks_size = fcb_log->fl_bset.lfs_cap;
+
+    return fcb_log->fl_bset.lfs_bmarks;
 }
 
 const struct log_fcb_bmark *
-log_fcb_closest_bmark(const struct fcb_log *fcb_log, uint32_t index)
+log_fcb_closest_bmark(const struct fcb_log *fcb_log, uint32_t index,
+                      int *min_diff)
 {
     const struct log_fcb_bmark *closest;
     const struct log_fcb_bmark *bmark;
-    uint32_t min_diff;
     uint32_t diff;
-    int i;
+    int i = 0;
+    uint32_t start_idx = 0;
 
-    min_diff = UINT32_MAX;
+    *min_diff = -1;
     closest = NULL;
 
-    for (i = 0; i < fcb_log->fl_bset.lfs_size; i++) {
+    if (!fcb_log->fl_bset.lfs_bmarks) {
+        return closest;
+    }
+
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+#if MYNEWT_VAL(LOG_FCB)
+    /* Reason for this is that we want to iterate to the end of the
+     * bmarks sector section of the array where a bookmark is valid,
+     * this is only for the case where the sector bookmarks have not
+     * been fully filled up, if they are filled up, we can iterate
+     * normally to the end of the array
+     */
+    if (!fcb_log->fl_bset.lfs_bmarks[i].lfb_entry.fe_area &&
+        fcb_log->fl_bset.lfs_next_sect < (fcb_log->fl_bset.lfs_sect_cap - 1)) {
+        start_idx = fcb_log->fl_bset.lfs_next_sect + 1;
+    }
+#endif
+#endif
+
+    /* This works for both sector as well as non-sector bmarks
+     * because we calculate the min diff and iterate to the end
+     * of the bmarks array keeping track of min diff
+     */
+    for (i = start_idx; i < (start_idx + fcb_log->fl_bset.lfs_size); i++) {
         bmark = &fcb_log->fl_bset.lfs_bmarks[i];
+#if MYNEWT_VAL(LOG_FCB)
+        if (!fcb_log->fl_bset.lfs_bmarks[i].lfb_entry.fe_area) {
+#if !MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+            /* Empty non-sector bookmark, nothing more to do
+             * Previous closest bookmark is the closest one */
+            break;
+#endif
+        }
+#elif MYNEWT_VAL(LOG_FCB2)
+        if (!fcb_log->fl_bset.lfs_bmarks[i].lfb_entry.fe_range) {
+#if !MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+            /* Empty non-sector bookmark, nothing more to do
+             * Previous closest bookmark is the closest one */
+            break;
+#endif
+        }
+#endif
         if (bmark->lfb_index <= index) {
             diff = index - bmark->lfb_index;
-            if (diff < min_diff) {
-                min_diff = diff;
+            if (diff < *min_diff) {
+                *min_diff = diff;
                 closest = bmark;
+                MODLOG_DEBUG(LOG_MODULE_DEFAULT,
+                             "index: %u, closest bmark idx: %u, \n",
+                             (unsigned int)index,
+                             (unsigned int)bmark->lfb_index);
+                /* We found the exact match, no need to keep searching for a
+                 * better match
+                 */
+                if (*min_diff == 0) {
+                    break;
+                }
             }
         }
     }
@@ -98,37 +297,151 @@ log_fcb_closest_bmark(const struct fcb_log *fcb_log, 
uint32_t index)
     return closest;
 }
 
-#if MYNEWT_VAL(LOG_FCB)
-void
-log_fcb_add_bmark(struct fcb_log *fcb_log, const struct fcb_entry *entry,
-                  uint32_t index)
-#elif MYNEWT_VAL(LOG_FCB2)
-void
-log_fcb_add_bmark(struct fcb_log *fcb_log, const struct fcb2_entry *entry,
-                  uint32_t index)
-#endif
+#if MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+static int
+log_fcb_insert_sect_bmark(struct fcb_log *fcb_log, struct fcb_entry *entry,
+                          uint32_t index)
 {
     struct log_fcb_bset *bset;
 
     bset = &fcb_log->fl_bset;
 
-    if (bset->lfs_cap == 0) {
-        return;
+    if (bset->lfs_size < fcb_log->fl_bset.lfs_sect_cap) {
+        bset->lfs_bmarks[bset->lfs_next_sect] = (struct log_fcb_bmark) {
+            .lfb_entry = *entry,
+            .lfb_index = index,
+        };
+
+        bset->lfs_size++;
+        bset->lfs_next_sect--;
+        if (bset->lfs_next_sect >= fcb_log->fl_bset.lfs_sect_cap) {
+            bset->lfs_next_sect = fcb_log->fl_bset.lfs_sect_cap - 1;
+        }
     }
 
-    bset->lfs_bmarks[bset->lfs_next] = (struct log_fcb_bmark) {
+    return 0;
+}
+#endif
+
+#if MYNEWT_VAL(LOG_FCB)
+static int
+log_fcb_replace_non_sect_bmark(struct fcb_log *fcb_log, struct fcb_entry 
*entry,
+                               uint32_t index, int pos)
+#elif MYNEWT_VAL(LOG_FCB2)
+static int
+log_fcb_replace_non_sect_bmark(struct fcb_log *fcb_log, struct fcb2_entry 
*entry,
+                               uint32_t index, int pos)
+#endif
+{
+    int i = 0;
+    struct log_fcb_bset *bset = &fcb_log->fl_bset;
+
+#if MYNEWT_VAL(LOG_FCB) && MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+    if (bset->lfs_en_sect_bmarks) {
+        for (i = bset->lfs_sect_cap;
+             i < (bset->lfs_non_sect_size + bset->lfs_sect_cap);
+             i++) {
+            if (index == bset->lfs_bmarks[i].lfb_index) {
+                /* If index matches, no need to replace */
+                return SYS_EALREADY;
+            }
+        }
+    } else
+#endif
+    {
+        for (i = 0; i < bset->lfs_non_sect_size; i++) {
+            if (index == bset->lfs_bmarks[i].lfb_index) {
+                /* If index matches, no need to replace */
+                return SYS_EALREADY;
+            }
+        }
+    }
+
+    bset->lfs_bmarks[pos] = (struct log_fcb_bmark) {
         .lfb_entry = *entry,
         .lfb_index = index,
     };
 
-    if (bset->lfs_size < bset->lfs_cap) {
-        bset->lfs_size++;
+    return SYS_EOK;
+}
+
+#if MYNEWT_VAL(LOG_FCB)
+int
+log_fcb_add_bmark(struct fcb_log *fcb_log, struct fcb_entry *entry,
+                  uint32_t index, bool sect_bmark)
+#elif MYNEWT_VAL(LOG_FCB2)
+int
+log_fcb_add_bmark(struct fcb_log *fcb_log, struct fcb2_entry *entry,
+                  uint32_t index, bool sect_bmark)
+#endif
+{
+    struct log_fcb_bset *bset = &fcb_log->fl_bset;
+    int rc = 0;
+
+    if (bset->lfs_cap == 0) {
+        return SYS_ENOMEM;
     }
 
-    bset->lfs_next++;
-    if (bset->lfs_next >= bset->lfs_cap) {
-        bset->lfs_next = 0;
+#if MYNEWT_VAL(LOG_FCB) && MYNEWT_VAL(LOG_FCB_SECTOR_BOOKMARKS)
+    if (sect_bmark & bset->lfs_en_sect_bmarks) {
+        rc = log_fcb_insert_sect_bmark(fcb_log, entry, index);
+        if (rc) {
+            MODLOG_DEBUG(LOG_MODULE_DEFAULT, "insert bmark failure: %u\n",
+                         index);
+        }
+        MODLOG_DEBUG(LOG_MODULE_DEFAULT, "insert bmark index: %u, pos: %u\n",
+                     index, bset->lfs_next_sect);
+    } else {
+        /* Replace oldest non-sector bmark */
+        rc = log_fcb_replace_non_sect_bmark(fcb_log, entry, index,
+                                            bset->lfs_next_non_sect +
+                                            (bset->lfs_en_sect_bmarks ?
+                                             bset->lfs_sect_cap : 0));
+        if (rc == SYS_EOK) {
+            MODLOG_DEBUG(LOG_MODULE_DEFAULT, "replace bmark index: %u, pos: 
%u\n",
+                         index, bset->lfs_next_non_sect +
+                         (bset->lfs_en_sect_bmarks ?
+                          bset->lfs_sect_cap : 0));
+
+            if (bset->lfs_non_sect_size < 
MYNEWT_VAL(LOG_FCB_NUM_ABS_BOOKMARKS)) {
+                bset->lfs_non_sect_size++;
+                bset->lfs_size++;
+            }
+
+            bset->lfs_next_non_sect = (bset->lfs_next_non_sect + 1) %
+                                      MYNEWT_VAL(LOG_FCB_NUM_ABS_BOOKMARKS);
+        }
     }
+#else
+    if (!sect_bmark) {
+        if (bset->lfs_size >= MYNEWT_VAL(LOG_FCB_NUM_ABS_BOOKMARKS)) {
+            /* Replace oldest non-sector bmark */
+            rc = log_fcb_replace_non_sect_bmark(fcb_log, entry, index,
+                                                bset->lfs_next_non_sect);
+            if (rc == SYS_EOK) {
+                MODLOG_DEBUG(LOG_MODULE_DEFAULT, "replace bmark index: %u, 
pos: %u\n",
+                             index, bset->lfs_next_non_sect);
+                bset->lfs_next_non_sect = (bset->lfs_next_non_sect + 1) %
+                                          
MYNEWT_VAL(LOG_FCB_NUM_ABS_BOOKMARKS);
+            }
+        } else {
+            rc = log_fcb_replace_non_sect_bmark(fcb_log, entry, index,
+                                                bset->lfs_size);
+            if (rc == SYS_EOK) {
+                MODLOG_DEBUG(LOG_MODULE_DEFAULT, "replace bmark index: %u, 
pos: %u\n",
+                             index, bset->lfs_size);
+                if (!bset->lfs_size) {
+                    /* First non-sector bmark position */
+                    bset->lfs_next_non_sect = 0;
+                }
+                bset->lfs_size++;
+            }
+        }
+
+        assert(bset->lfs_size <= MYNEWT_VAL(LOG_FCB_NUM_ABS_BOOKMARKS));
+    }
+#endif
+    return SYS_EOK;
 }
 
 #endif /* MYNEWT_VAL(LOG_FCB_BOOKMARKS) */
diff --git a/sys/log/full/src/log_shell.c b/sys/log/full/src/log_shell.c
index a10c08eb1..c33be9eae 100644
--- a/sys/log/full/src/log_shell.c
+++ b/sys/log/full/src/log_shell.c
@@ -51,6 +51,8 @@ struct walk_arg {
     uint32_t count_limit;
     /* Entry number */
     uint32_t count;
+    /* Entry index */
+    uint32_t idx;
 };
 
 static int
@@ -172,11 +174,22 @@ shell_log_dump_cmd(int argc, char **argv)
     bool clear_log;
     bool reverse = false;
     bool dump_logs = true;
+    bool dump_bmarks = false;
+    uint32_t bmarks_size = 0;
+    struct log_fcb_bmark *bmarks = NULL;
     struct walk_arg arg = {};
     int i;
-    int rc;
+    int rc = 0;
+    int start = -1;
+    int end = -1;
 
     clear_log = false;
+    (void)dump_bmarks;
+    (void)bmarks;
+    (void)bmarks_size;
+    (void)start;
+    (void)end;
+
     for (i = 1; i < argc; ++i) {
         if (0 == strcmp(argv[i], "-l")) {
             list_only = true;
@@ -208,6 +221,22 @@ shell_log_dump_cmd(int argc, char **argv)
             dump_logs = false;
             continue;
         }
+        if (0 == strcmp(argv[i], "-b")) {
+            dump_logs = false;
+            dump_bmarks = true;
+            continue;
+        }
+        if (0 == strcmp(argv[i], "-i")) {
+            if (i + 1 < argc) {
+                arg.idx = parse_ll_bounds(argv[i + 1], 0, UINT32_MAX, &rc);
+                if (rc) {
+                    arg.idx = 0;
+                }
+                log_offset.lo_arg = &arg;
+            }
+            ++i;
+            continue;
+        }
         if (0 == strcmp(argv[i], "-r")) {
             reverse = true;
             continue;
@@ -251,6 +280,57 @@ shell_log_dump_cmd(int argc, char **argv)
             continue;
         }
 
+#if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
+        if (dump_bmarks) {
+            bmarks = log_fcb_get_bmarks(log, &bmarks_size);
+            for (i = 0; i < bmarks_size; i++) {
+#if MYNEWT_VAL(LOG_FCB)
+                if (!bmarks[i].lfb_entry.fe_area) {
+                    if (start == -1) {
+                        start = i;
+                    }
+                    end = i;
+                    continue;
+                }
+                if (start != -1) {
+                    console_printf("bookmarks unused: %d to %d\n", start, end);
+                    start = -1;
+                    end = -1;
+                }
+                console_printf("%u: index:%lu fa_off:%x fe_elem_off:%lx\n", i,
+                               bmarks[i].lfb_index,
+                               (uintptr_t)bmarks[i].lfb_entry.fe_area->fa_off,
+                               bmarks[i].lfb_entry.fe_elem_off);
+#else
+                if (!bmarks[i].lfb_entry.fe_range) {
+                    if (start == -1) {
+                        start = i;
+                    }
+                    end = i;
+                    continue;
+                }
+                if (start != -1) {
+                    console_printf("bookmarks unused: %d to %d\n", start, end);
+                    start = -1;
+                    end = -1;
+                }
+                console_printf("%u: index:%lu fa_off:%x fe_sector:%x 
fe_data_off:%lx\n", i,
+                               bmarks[i].lfb_index,
+                               
(uintptr_t)bmarks[i].lfb_entry.fe_range->fsr_flash_area.fa_off,
+                               (uintptr_t)bmarks[i].lfb_entry.fe_sector,
+                               bmarks[i].lfb_entry.fe_data_off);
+#endif
+            }
+
+            if (start != -1) {
+                console_printf("bookmarks unused: %d to %d\n", start, end);
+                start = -1;
+                end = -1;
+            }
+            goto err;
+        }
+#endif
+
         if (clear_log) {
             console_printf("Clearing log %s\n", log->l_name);
             rc = log_flush(log);
@@ -278,11 +358,13 @@ shell_log_dump_cmd(int argc, char **argv)
 
             if (dump_logs) {
                 arg.count = 0;
+                log_offset.lo_index = arg.idx;
                 rc = log_walk_body(log, shell_log_dump_entry, &log_offset);
-            } else {
+            } else if (!dump_bmarks) {
                 /* Measure time for log_walk */
                 shell_log_count = 0;
                 os_time_t start = os_time_get();
+                log_offset.lo_index = arg.idx;
                 rc = log_walk_body(log, shell_log_count_entry, &log_offset);
                 os_time_t end = os_time_get();
                 console_printf("Log %s %d entries walked in %d ms\n", 
log->l_name,
diff --git a/sys/log/full/syscfg.yml b/sys/log/full/syscfg.yml
index dc35b6c54..7170e91ed 100644
--- a/sys/log/full/syscfg.yml
+++ b/sys/log/full/syscfg.yml
@@ -179,6 +179,19 @@ syscfg.defs:
             the global index to be sequentially increasing for persisted logs.
         value: 0
 
+    LOG_FCB_NUM_ABS_BOOKMARKS:
+        description: >
+            Number of absolute bookmarks excluding sector bookmarks
+        value: 2
+
+    LOG_FCB_SECTOR_BOOKMARKS:
+        description: >
+            Enable sector bookmarks
+        value: 0
+        restrictions:
+            - LOG_FCB_BOOKMARKS
+            - LOG_FCB
+
 syscfg.vals.CONSOLE_TICKS:
     LOG_CONSOLE_PRETTY_WITH_TIMESTAMP: 0
 

Reply via email to