You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2019/10/21 09:30:22 UTC
[mynewt-core] 01/23: Added capability to recognize when a fcb
sector is about to rotate and provide the application an opportunity to
read logs before the rotation.
This is an automated email from the ASF dual-hosted git repository.
marko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit daf09ee90c17f32dd2528b07ed8b77227d8b63f4
Author: Nolan Lau <no...@juul.com>
AuthorDate: Wed Sep 25 21:56:17 2019 -0700
Added capability to recognize when a fcb sector is about to rotate and
provide the application an opportunity to read logs before the rotation.
---
fs/fcb/include/fcb/fcb.h | 21 ++++----
fs/fcb/src/fcb.c | 23 +++++++-
fs/fcb/src/fcb_append.c | 10 +++-
fs/fcb/src/fcb_getnext.c | 57 ++++++++++++++++++++
fs/fcb/src/fcb_rotate.c | 3 +-
sys/log/common/include/log_common/log_common.h | 7 +++
sys/log/full/include/log/log.h | 28 ++++++++++
sys/log/full/src/log.c | 22 ++++++++
sys/log/full/src/log_fcb.c | 75 ++++++++++++++++++++------
9 files changed, 217 insertions(+), 29 deletions(-)
diff --git a/fs/fcb/include/fcb/fcb.h b/fs/fcb/include/fcb/fcb.h
index f198e18..d06a705 100644
--- a/fs/fcb/include/fcb/fcb.h
+++ b/fs/fcb/include/fcb/fcb.h
@@ -60,6 +60,7 @@ struct fcb {
/* Flash circular buffer internal state */
struct os_mutex f_mtx; /* Locking for accessing the FCB data */
struct flash_area *f_oldest;
+ struct flash_area *f_scratch;
struct fcb_entry f_active;
uint16_t f_active_id;
uint8_t f_align; /* writes to flash have to aligned to this */
@@ -68,15 +69,16 @@ struct fcb {
/**
* Error codes.
*/
-#define FCB_OK 0
-#define FCB_ERR_ARGS -1
-#define FCB_ERR_FLASH -2
-#define FCB_ERR_NOVAR -3
-#define FCB_ERR_NOSPACE -4
-#define FCB_ERR_NOMEM -5
-#define FCB_ERR_CRC -6
-#define FCB_ERR_MAGIC -7
-#define FCB_ERR_VERSION -8
+#define FCB_OK 0
+#define FCB_ERR_ARGS -1
+#define FCB_ERR_FLASH -2
+#define FCB_ERR_NOVAR -3
+#define FCB_ERR_NOSPACE -4
+#define FCB_ERR_NOMEM -5
+#define FCB_ERR_CRC -6
+#define FCB_ERR_MAGIC -7
+#define FCB_ERR_VERSION -8
+#define FCB_ERR_NEXT_SECT -9
int fcb_init(struct fcb *fcb);
@@ -100,6 +102,7 @@ int fcb_append_finish(struct fcb *, struct fcb_entry *append_loc);
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);
+int fcb_getnext_sector(struct fcb *fcb, struct fcb_entry *loc);
/**
* Erases the data from oldest sector.
diff --git a/fs/fcb/src/fcb.c b/fs/fcb/src/fcb.c
index 0fe7e1f..40b218b 100644
--- a/fs/fcb/src/fcb.c
+++ b/fs/fcb/src/fcb.c
@@ -32,7 +32,7 @@ fcb_init(struct fcb *fcb)
int max_align = 1;
int align;
int oldest = -1, newest = -1;
- struct flash_area *oldest_fap = NULL, *newest_fap = NULL;
+ struct flash_area *oldest_fap = NULL, *newest_fap = NULL, *scratch_fap = NULL;
struct fcb_disk_area fda;
if (!fcb->f_sectors || fcb->f_sector_cnt - fcb->f_scratch_cnt < 1) {
@@ -56,11 +56,26 @@ fcb_init(struct fcb *fcb)
if (oldest < 0) {
oldest = newest = fda.fd_id;
oldest_fap = newest_fap = fap;
+
+ fap++;
+ if (fap >= &fcb->f_sectors[fcb->f_sector_cnt]) {
+ scratch_fap = &fcb->f_sectors[0];
+ } else {
+ scratch_fap = fap;
+ }
continue;
}
if (FCB_ID_GT(fda.fd_id, newest)) {
newest = fda.fd_id;
newest_fap = fap;
+
+ fap++;
+ if (fap >= &fcb->f_sectors[fcb->f_sector_cnt]) {
+ scratch_fap = &fcb->f_sectors[0];
+ } else {
+ scratch_fap = fap;
+ }
+
} else if (FCB_ID_GT(oldest, fda.fd_id)) {
oldest = fda.fd_id;
oldest_fap = fap;
@@ -76,7 +91,13 @@ fcb_init(struct fcb *fcb)
return rc;
}
newest = oldest = 0;
+ scratch_fap = &fcb->f_sectors[fcb->f_sector_cnt-1];
}
+
+ if (fcb->f_scratch) {
+ fcb->f_scratch = scratch_fap;
+ }
+
fcb->f_align = max_align;
fcb->f_oldest = oldest_fap;
fcb->f_active.fe_area = newest_fap;
diff --git a/fs/fcb/src/fcb_append.c b/fs/fcb/src/fcb_append.c
index 6d1bc86..dcdf2a7 100644
--- a/fs/fcb/src/fcb_append.c
+++ b/fs/fcb/src/fcb_append.c
@@ -36,8 +36,14 @@ fcb_new_area(struct fcb *fcb, int cnt)
if (!rfa) {
rfa = fa;
}
- if (fa == fcb->f_oldest) {
- return NULL;
+ if (fcb->f_scratch) {
+ if (fa == fcb->f_scratch) {
+ return NULL;
+ }
+ } else {
+ if (fa == fcb->f_oldest) {
+ return NULL;
+ }
}
} while (i++ < cnt);
return rfa;
diff --git a/fs/fcb/src/fcb_getnext.c b/fs/fcb/src/fcb_getnext.c
index 6ca08ce..931432d 100644
--- a/fs/fcb/src/fcb_getnext.c
+++ b/fs/fcb/src/fcb_getnext.c
@@ -111,6 +111,48 @@ next_sector:
}
int
+fcb_getnext_nolock_sector(struct fcb *fcb, struct fcb_entry *loc)
+{
+ int rc;
+
+ if (loc->fe_area == NULL) {
+ /*
+ * Find the first one we have in flash.
+ */
+ loc->fe_area = fcb->f_oldest;
+ }
+ if (loc->fe_elem_off == 0) {
+ /*
+ * If offset is zero, we serve the first entry from the area.
+ */
+ loc->fe_elem_off = sizeof(struct fcb_disk_area);
+ rc = fcb_elem_info(fcb, loc);
+ } else {
+ rc = fcb_getnext_in_area(fcb, loc);
+ }
+ switch (rc) {
+ case 0:
+ return 0;
+ case FCB_ERR_CRC:
+ break;
+ default:
+ return FCB_ERR_NEXT_SECT;
+ }
+ while (rc == FCB_ERR_CRC) {
+ rc = fcb_getnext_in_area(fcb, loc);
+ if (rc == 0) {
+ return 0;
+ }
+
+ if (rc != FCB_ERR_CRC) {
+ return FCB_ERR_NEXT_SECT;
+ }
+ }
+
+ return FCB_ERR_NEXT_SECT;
+}
+
+int
fcb_getnext(struct fcb *fcb, struct fcb_entry *loc)
{
int rc;
@@ -124,3 +166,18 @@ fcb_getnext(struct fcb *fcb, struct fcb_entry *loc)
return rc;
}
+
+int
+fcb_getnext_sector(struct fcb *fcb, struct fcb_entry *loc)
+{
+ int rc;
+
+ rc = os_mutex_pend(&fcb->f_mtx, OS_WAIT_FOREVER);
+ if (rc && rc != OS_NOT_STARTED) {
+ return FCB_ERR_ARGS;
+ }
+ rc = fcb_getnext_nolock_sector(fcb, loc);
+ os_mutex_release(&fcb->f_mtx);
+
+ return rc;
+}
diff --git a/fs/fcb/src/fcb_rotate.c b/fs/fcb/src/fcb_rotate.c
index 7135fa6..d9c7bf2 100644
--- a/fs/fcb/src/fcb_rotate.c
+++ b/fs/fcb/src/fcb_rotate.c
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
#include "fcb/fcb.h"
#include "fcb_priv.h"
@@ -49,6 +48,8 @@ fcb_rotate(struct fcb *fcb)
fcb->f_active.fe_elem_off = sizeof(struct fcb_disk_area);
fcb->f_active_id++;
}
+ fcb->f_scratch = fcb->f_oldest;
+
fcb->f_oldest = fcb_getnext_area(fcb, fcb->f_oldest);
out:
os_mutex_release(&fcb->f_mtx);
diff --git a/sys/log/common/include/log_common/log_common.h b/sys/log/common/include/log_common/log_common.h
index 9a42354..356d170 100644
--- a/sys/log/common/include/log_common/log_common.h
+++ b/sys/log/common/include/log_common/log_common.h
@@ -134,6 +134,13 @@ extern struct log_info g_log_info;
*/
typedef void log_append_cb(struct log *log, uint32_t idx);
+/** @typdef log_notify_rotate_cb
+ * @brief Callback that is executed each time we are about to rotate a log.
+ *
+ * @param log The log that is about to rotate
+ */
+typedef void log_notify_rotate_cb(struct log *log);
+
#ifdef __cplusplus
}
#endif
diff --git a/sys/log/full/include/log/log.h b/sys/log/full/include/log/log.h
index 4cf3240..853446f 100644
--- a/sys/log/full/include/log/log.h
+++ b/sys/log/full/include/log/log.h
@@ -114,6 +114,7 @@ struct log_handler {
lh_append_mbuf_func_t log_append_mbuf;
lh_append_mbuf_body_func_t log_append_mbuf_body;
lh_walk_func_t log_walk;
+ lh_walk_func_t log_walk_sector;
lh_flush_func_t log_flush;
#if MYNEWT_VAL(LOG_STORAGE_INFO)
lh_storage_info_func_t log_storage_info;
@@ -213,6 +214,7 @@ struct log {
void *l_arg;
STAILQ_ENTRY(log) l_next;
log_append_cb *l_append_cb;
+ log_notify_rotate_cb *l_notify_erase_done_cb;
uint8_t l_level;
uint16_t l_max_entry_len; /* Log body length; if 0 disables check. */
#if !MYNEWT_VAL(LOG_GLOBAL_IDX)
@@ -597,6 +599,21 @@ int log_walk_body(struct log *log, log_walk_body_func_t walk_body_func,
struct log_offset *log_offset);
int log_flush(struct log *log);
+/**
+ * @brief Walking a section of FCB.
+ *
+ * @param log The log to iterate.
+ * @param walk_body_func The function to apply to each log entry.
+ * @param log_offset Specifies the range of entries to process.
+ * Entries not matching these criteria are
+ * skipped during the walk.
+ *
+ * @return 0 if the walk completed successfully;
+ * nonzero on error or if the walk was aborted.
+ */
+int log_walk_body_section(struct log *log, log_walk_body_func_t walk_body_func,
+ struct log_offset *log_offset);
+
#if MYNEWT_VAL(LOG_MODULE_LEVELS)
/**
* @brief Retrieves the globally configured minimum log level for the specified
@@ -680,6 +697,17 @@ void log_set_max_entry_len(struct log *log, uint16_t max_entry_len);
*/
int log_storage_info(struct log *log, struct log_storage_info *info);
#endif
+
+/**
+ * Assign a callback function to be notified once the log deletes the oldest
+ * data to write in new data.
+ *
+ * @param log The log
+ * @param cb The callback function to be executed.
+ */
+void
+log_set_rotate_done_cb(struct log *log, log_notify_rotate_cb *cb);
+
#if MYNEWT_VAL(LOG_STORAGE_WATERMARK)
/**
* Set watermark on log
diff --git a/sys/log/full/src/log.c b/sys/log/full/src/log.c
index 3b992e7..32bd7ff 100644
--- a/sys/log/full/src/log.c
+++ b/sys/log/full/src/log.c
@@ -458,6 +458,11 @@ log_hdr_len(const struct log_entry_hdr *hdr)
return LOG_BASE_ENTRY_HDR_SIZE;
}
+void
+log_set_rotate_done_cb(struct log *log, log_notify_rotate_cb *cb)
+{
+ log->l_notify_erase_done_cb = cb;
+}
static int
log_chk_type(uint8_t etype)
@@ -916,6 +921,23 @@ log_walk_body(struct log *log, log_walk_body_func_t walk_body_func,
return rc;
}
+int
+log_walk_body_section(struct log *log, log_walk_body_func_t walk_body_func,
+ struct log_offset *log_offset)
+{
+ struct log_walk_body_arg lwba = {
+ .fn = walk_body_func,
+ .arg = log_offset->lo_arg,
+ };
+ int rc;
+
+ log_offset->lo_arg = &lwba;
+ rc = log->l_log->log_walk_sector(log, log_walk_body_fn, log_offset);
+ log_offset->lo_arg = lwba.arg;
+
+ return rc;
+}
+
/**
* Reads from the specified log.
*
diff --git a/sys/log/full/src/log_fcb.c b/sys/log/full/src/log_fcb.c
index c2ffcef..e708b65 100644
--- a/sys/log/full/src/log_fcb.c
+++ b/sys/log/full/src/log_fcb.c
@@ -159,6 +159,11 @@ log_fcb_start_append(struct log *log, int len, struct fcb_entry *loc)
}
#endif
+ /* Check to see if the active region is in the scratch region */
+ if (log->l_notify_erase_done_cb != NULL) {
+ log->l_notify_erase_done_cb(log);
+ }
+
#if MYNEWT_VAL(LOG_FCB_BOOKMARKS)
/* The FCB needs to be rotated. Invalidate all bookmarks. */
log_fcb_clear_bmarks(fcb_log);
@@ -180,8 +185,6 @@ log_fcb_start_append(struct log *log, int len, struct fcb_entry *loc)
fcb_log->fl_watermark_off = fcb->f_oldest->fa_off;
}
#endif
-
-
}
err:
@@ -465,7 +468,6 @@ log_fcb_read_mbuf(struct log *log, const void *dptr, struct os_mbuf *om,
if (rc) {
goto done;
}
-
rc = os_mbuf_append(om, data, read_len);
if (rc) {
goto done;
@@ -528,6 +530,48 @@ log_fcb_walk(struct log *log, log_walk_func_t walk_func,
}
static int
+log_fcb_walk_sector(struct log *log, log_walk_func_t walk_func,
+ struct log_offset *log_offset)
+{
+ struct fcb *fcb;
+ struct fcb_log *fcb_log;
+ struct fcb_entry loc;
+ int rc;
+
+ 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);
+ switch (rc) {
+ case 0:
+ /* Found a starting point. */
+ break;
+ case SYS_ENOENT:
+ /* No entries match the offset criteria; nothing to walk. */
+ return 0;
+ default:
+ return rc;
+ }
+#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.
+ */
+ if (log_offset->lo_ts >= 0) {
+ fcb_log_add_bmark(fcb_log, &loc, log_offset->lo_index);
+ }
+#endif
+ do {
+ rc = walk_func(log, log_offset, &loc, loc.fe_data_len);
+ if (rc != 0) {
+ return rc;
+ }
+ } while (fcb_getnext_sector(fcb, &loc) == 0);
+
+ return 0;
+}
+
+static int
log_fcb_flush(struct log *log)
{
struct fcb_log *fcb_log;
@@ -772,9 +816,7 @@ log_fcb_copy(struct log *log, struct fcb *src_fcb, struct fcb *dst_fcb,
{
struct fcb_entry entry;
int rc;
-
rc = 0;
-
memset(&entry, 0, sizeof(entry));
while (!fcb_getnext(src_fcb, &entry)) {
if (entry.fe_elem_off < offset) {
@@ -860,22 +902,23 @@ err:
}
const struct log_handler log_fcb_handler = {
- .log_type = LOG_TYPE_STORAGE,
- .log_read = log_fcb_read,
- .log_read_mbuf = log_fcb_read_mbuf,
- .log_append = log_fcb_append,
- .log_append_body = log_fcb_append_body,
- .log_append_mbuf = log_fcb_append_mbuf,
+ .log_type = LOG_TYPE_STORAGE,
+ .log_read = log_fcb_read,
+ .log_read_mbuf = log_fcb_read_mbuf,
+ .log_append = log_fcb_append,
+ .log_append_body = log_fcb_append_body,
+ .log_append_mbuf = log_fcb_append_mbuf,
.log_append_mbuf_body = log_fcb_append_mbuf_body,
- .log_walk = log_fcb_walk,
- .log_flush = log_fcb_flush,
+ .log_walk = log_fcb_walk,
+ .log_walk_sector = log_fcb_walk_sector,
+ .log_flush = log_fcb_flush,
#if MYNEWT_VAL(LOG_STORAGE_INFO)
- .log_storage_info = log_fcb_storage_info,
+ .log_storage_info = log_fcb_storage_info,
#endif
#if MYNEWT_VAL(LOG_STORAGE_WATERMARK)
- .log_set_watermark = log_fcb_set_watermark,
+ .log_set_watermark = log_fcb_set_watermark,
#endif
- .log_registered = log_fcb_registered,
+ .log_registered = log_fcb_registered,
};
#endif