zephyr/subsys/fs/fcb/fcb_append.c
Eivind Jølsgard cfa1ba1261 fs: fcb: add option to disable CRC for fcb entries
Add option to disable CRC for fcb entries. This improves the write
throughput significantly at the cost of not detecting corrupted data
in flash. This is beneficial for aplications that needs the extra
write throughput, where error detection is done elsewhere.

Allow the FCB entries in flash to have a valid CRC when CRC is
disabled in the FCB. This allows existing solutions to disable
CRC checking, while keeping the CRC areas intact. Note that this
is a one-way option.

Fixes #53707

Signed-off-by: Eivind Jølsgard <eivind.jolsgard@nordicsemi.no>
2023-01-18 22:18:37 +00:00

141 lines
2.9 KiB
C

/*
* Copyright (c) 2017-2020 Nordic Semiconductor ASA
* Copyright (c) 2015 Runtime Inc
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include <string.h>
#include <zephyr/fs/fcb.h>
#include "fcb_priv.h"
static struct flash_sector *
fcb_new_sector(struct fcb *fcb, int cnt)
{
struct flash_sector *prev;
struct flash_sector *cur;
int i;
prev = NULL;
i = 0;
cur = fcb->f_active.fe_sector;
do {
cur = fcb_getnext_sector(fcb, cur);
if (!prev) {
prev = cur;
}
if (cur == fcb->f_oldest) {
return NULL;
}
} while (i++ < cnt);
return prev;
}
/*
* Take one of the scratch blocks into use, if at all possible.
*/
int
fcb_append_to_scratch(struct fcb *fcb)
{
struct flash_sector *sector;
int rc;
sector = fcb_new_sector(fcb, 0);
if (!sector) {
return -ENOSPC;
}
rc = fcb_sector_hdr_init(fcb, sector, fcb->f_active_id + 1);
if (rc) {
return rc;
}
fcb->f_active.fe_sector = sector;
fcb->f_active.fe_elem_off = fcb_len_in_flash(fcb, sizeof(struct fcb_disk_area));
fcb->f_active_id++;
return 0;
}
int
fcb_append(struct fcb *fcb, uint16_t len, struct fcb_entry *append_loc)
{
struct flash_sector *sector;
struct fcb_entry *active;
int cnt;
int rc;
uint8_t tmp_str[MAX(8, fcb->f_align)];
/* Ensure defined value of padding bytes */
memset(tmp_str, fcb->f_erase_value, sizeof(tmp_str));
cnt = fcb_put_len(fcb, tmp_str, len);
if (cnt < 0) {
return cnt;
}
cnt = fcb_len_in_flash(fcb, cnt);
len = fcb_len_in_flash(fcb, len) + fcb_len_in_flash(fcb, FCB_CRC_SZ);
__ASSERT_NO_MSG(cnt <= sizeof(tmp_str));
rc = k_mutex_lock(&fcb->f_mtx, K_FOREVER);
if (rc) {
return -EINVAL;
}
active = &fcb->f_active;
if (active->fe_elem_off + len + cnt > active->fe_sector->fs_size) {
sector = fcb_new_sector(fcb, fcb->f_scratch_cnt);
if (!sector || (sector->fs_size <
fcb_len_in_flash(fcb, sizeof(struct fcb_disk_area)) + len + cnt)) {
rc = -ENOSPC;
goto err;
}
rc = fcb_sector_hdr_init(fcb, sector, fcb->f_active_id + 1);
if (rc) {
goto err;
}
fcb->f_active.fe_sector = sector;
fcb->f_active.fe_elem_off = fcb_len_in_flash(fcb, sizeof(struct fcb_disk_area));
fcb->f_active_id++;
}
rc = fcb_flash_write(fcb, active->fe_sector, active->fe_elem_off, tmp_str, cnt);
if (rc) {
rc = -EIO;
goto err;
}
append_loc->fe_sector = active->fe_sector;
append_loc->fe_elem_off = active->fe_elem_off;
append_loc->fe_data_off = active->fe_elem_off + cnt;
active->fe_elem_off = append_loc->fe_data_off + len;
k_mutex_unlock(&fcb->f_mtx);
return 0;
err:
k_mutex_unlock(&fcb->f_mtx);
return rc;
}
int
fcb_append_finish(struct fcb *fcb, struct fcb_entry *loc)
{
int rc;
uint8_t em[fcb->f_align];
off_t off;
(void)memset(em, 0xFF, sizeof(em));
rc = fcb_elem_endmarker(fcb, loc, &em[0]);
if (rc) {
return rc;
}
off = loc->fe_data_off + fcb_len_in_flash(fcb, loc->fe_data_len);
rc = fcb_flash_write(fcb, loc->fe_sector, off, em, fcb->f_align);
if (rc) {
return -EIO;
}
return 0;
}