fs: Convert FCB to use sectors (not areas)

Prior to this commit: `struct fcb` contained a pointer to an array of
`struct flash_area`.  Each entry in the array represented a flash sector
that the fcb comprised.

After commit: `struct fcb` contains a pointer to an array of `struct
flash_sector`, not `struct flash_area`.

Rationale: The FCB needs to know which sectors it occupies for its
rotate operation.  However, the `flash_area` type is meant to represent
a collection of sectors, not a single sector.  `struct flash_area`
contains information that the fcb does not need (e.g., area ID and
device ID).  Furthermore, the flash_map API provides a means of
converting a flash area ID to an array of sectors
(`flash_area_get_sectors()`), but no way to convert to an array of
areas.

Signed-off-by: Christopher Collins <ccollins@apache.org>
This commit is contained in:
Christopher Collins 2018-01-26 14:07:10 -08:00 committed by Anas Nashif
commit e3cd915d8f
8 changed files with 208 additions and 104 deletions

View file

@ -12,30 +12,134 @@
#include "fcb_priv.h"
#include "string.h"
const struct flash_area *
fcb_open_flash(const struct fcb *fcb)
{
const struct flash_area *fa;
int rc;
rc = flash_area_open(fcb->f_area_id, &fa);
if (rc != 0) {
return NULL;
}
return fa;
}
u8_t
fcb_get_align(const struct fcb *fcb)
{
const struct flash_area *fa;
u8_t align;
fa = fcb_open_flash(fcb);
if (fa == NULL) {
return 0;
}
align = flash_area_align(fa);
flash_area_close(fa);
return align;
}
int
fcb_flash_read(const struct fcb *fcb, const struct flash_sector *sector,
off_t off, void *dst, size_t len)
{
const struct flash_area *fa;
int rc;
if (off + len > sector->fs_size) {
return FCB_ERR_ARGS;
}
fa = fcb_open_flash(fcb);
if (fa == NULL) {
return FCB_ERR_FLASH;
}
rc = flash_area_read(fa, sector->fs_off + off, dst, len);
flash_area_close(fa);
if (rc != 0) {
return FCB_ERR_FLASH;
}
return 0;
}
int
fcb_flash_write(const struct fcb *fcb, const struct flash_sector *sector,
off_t off, const void *src, size_t len)
{
const struct flash_area *fa;
int rc;
if (off + len > sector->fs_size) {
return FCB_ERR_ARGS;
}
fa = fcb_open_flash(fcb);
if (fa == NULL) {
return FCB_ERR_FLASH;
}
rc = flash_area_write(fa, sector->fs_off + off, src, len);
flash_area_close(fa);
if (rc != 0) {
return FCB_ERR_FLASH;
}
return 0;
}
int
fcb_erase_sector(const struct fcb *fcb, const struct flash_sector *sector)
{
const struct flash_area *fa;
int rc;
fa = fcb_open_flash(fcb);
if (fa == NULL) {
return FCB_ERR_FLASH;
}
rc = flash_area_erase(fa, sector->fs_off, sector->fs_size);
flash_area_close(fa);
if (rc != 0) {
return FCB_ERR_FLASH;
}
return 0;
}
int
fcb_init(struct fcb *fcb)
{
struct flash_area *fap;
struct flash_sector *sector;
int rc;
int i;
int max_align = 1;
int align;
u8_t align;
int oldest = -1, newest = -1;
struct flash_area *oldest_fap = NULL, *newest_fap = NULL;
struct flash_sector *oldest_sector = NULL, *newest_sector = NULL;
struct fcb_disk_area fda;
if (!fcb->f_sectors || fcb->f_sector_cnt - fcb->f_scratch_cnt < 1) {
return FCB_ERR_ARGS;
}
align = fcb_get_align(fcb);
if (align == 0) {
return FCB_ERR_ARGS;
}
/* Fill last used, first used */
for (i = 0; i < fcb->f_sector_cnt; i++) {
fap = &fcb->f_sectors[i];
align = flash_area_align(fap);
if (align > max_align) {
max_align = flash_area_align(fap);
}
rc = fcb_sector_hdr_read(fcb, fap, &fda);
sector = &fcb->f_sectors[i];
rc = fcb_sector_hdr_read(fcb, sector, &fda);
if (rc < 0) {
return rc;
}
@ -44,36 +148,36 @@ fcb_init(struct fcb *fcb)
}
if (oldest < 0) {
oldest = newest = fda.fd_id;
oldest_fap = newest_fap = fap;
oldest_sector = newest_sector = sector;
continue;
}
if (FCB_ID_GT(fda.fd_id, newest)) {
newest = fda.fd_id;
newest_fap = fap;
newest_sector = sector;
} else if (FCB_ID_GT(oldest, fda.fd_id)) {
oldest = fda.fd_id;
oldest_fap = fap;
oldest_sector = sector;
}
}
if (oldest < 0) {
/*
* No initialized areas.
*/
oldest_fap = newest_fap = &fcb->f_sectors[0];
rc = fcb_sector_hdr_init(fcb, oldest_fap, 0);
oldest_sector = newest_sector = &fcb->f_sectors[0];
rc = fcb_sector_hdr_init(fcb, oldest_sector, 0);
if (rc) {
return rc;
}
newest = oldest = 0;
}
fcb->f_align = max_align;
fcb->f_oldest = oldest_fap;
fcb->f_active.fe_area = newest_fap;
fcb->f_align = align;
fcb->f_oldest = oldest_sector;
fcb->f_active.fe_sector = newest_sector;
fcb->f_active.fe_elem_off = sizeof(struct fcb_disk_area);
fcb->f_active_id = newest;
while (1) {
rc = fcb_getnext_in_area(fcb, &fcb->f_active);
rc = fcb_getnext_in_sector(fcb, &fcb->f_active);
if (rc == FCB_ERR_NOVAR) {
rc = FCB_OK;
break;
@ -90,11 +194,11 @@ int
fcb_free_sector_cnt(struct fcb *fcb)
{
int i;
struct flash_area *fa;
struct flash_sector *fa;
fa = fcb->f_active.fe_area;
fa = fcb->f_active.fe_sector;
for (i = 0; i < fcb->f_sector_cnt; i++) {
fa = fcb_getnext_area(fcb, fa);
fa = fcb_getnext_sector(fcb, fa);
if (fa == fcb->f_oldest) {
break;
}
@ -105,7 +209,7 @@ fcb_free_sector_cnt(struct fcb *fcb)
int
fcb_is_empty(struct fcb *fcb)
{
return (fcb->f_active.fe_area == fcb->f_oldest &&
return (fcb->f_active.fe_sector == fcb->f_oldest &&
fcb->f_active.fe_elem_off == sizeof(struct fcb_disk_area));
}
@ -150,7 +254,7 @@ fcb_get_len(u8_t *buf, u16_t *len)
* Initialize erased sector for use.
*/
int
fcb_sector_hdr_init(struct fcb *fcb, struct flash_area *fap, u16_t id)
fcb_sector_hdr_init(struct fcb *fcb, struct flash_sector *sector, u16_t id)
{
struct fcb_disk_area fda;
int rc;
@ -160,8 +264,8 @@ fcb_sector_hdr_init(struct fcb *fcb, struct flash_area *fap, u16_t id)
fda._pad = 0xff;
fda.fd_id = id;
rc = flash_area_write(fap, 0, &fda, sizeof(fda));
if (rc) {
rc = fcb_flash_write(fcb, sector, 0, &fda, sizeof fda);
if (rc != 0) {
return FCB_ERR_FLASH;
}
return 0;
@ -173,7 +277,7 @@ fcb_sector_hdr_init(struct fcb *fcb, struct flash_area *fap, u16_t id)
* Returns 0 if sector is unused;
* Returns 1 if sector has data.
*/
int fcb_sector_hdr_read(struct fcb *fcb, struct flash_area *fap,
int fcb_sector_hdr_read(struct fcb *fcb, struct flash_sector *sector,
struct fcb_disk_area *fdap)
{
struct fcb_disk_area fda;
@ -182,7 +286,7 @@ int fcb_sector_hdr_read(struct fcb *fcb, struct flash_area *fap,
if (!fdap) {
fdap = &fda;
}
rc = flash_area_read(fap, 0, fdap, sizeof(*fdap));
rc = fcb_flash_read(fcb, sector, 0, fdap, sizeof(*fdap));
if (rc) {
return FCB_ERR_FLASH;
}

View file

@ -10,26 +10,26 @@
#include "fcb.h"
#include "fcb_priv.h"
static struct flash_area *
fcb_new_area(struct fcb *fcb, int cnt)
static struct flash_sector *
fcb_new_sector(struct fcb *fcb, int cnt)
{
struct flash_area *fa;
struct flash_area *rfa;
struct flash_sector *prev;
struct flash_sector *cur;
int i;
rfa = NULL;
prev = NULL;
i = 0;
fa = fcb->f_active.fe_area;
cur = fcb->f_active.fe_sector;
do {
fa = fcb_getnext_area(fcb, fa);
if (!rfa) {
rfa = fa;
cur = fcb_getnext_sector(fcb, cur);
if (!prev) {
prev = cur;
}
if (fa == fcb->f_oldest) {
if (cur == fcb->f_oldest) {
return NULL;
}
} while (i++ < cnt);
return rfa;
return prev;
}
/*
@ -38,18 +38,18 @@ fcb_new_area(struct fcb *fcb, int cnt)
int
fcb_append_to_scratch(struct fcb *fcb)
{
struct flash_area *fa;
struct flash_sector *sector;
int rc;
fa = fcb_new_area(fcb, 0);
if (!fa) {
sector = fcb_new_sector(fcb, 0);
if (!sector) {
return FCB_ERR_NOSPACE;
}
rc = fcb_sector_hdr_init(fcb, fa, fcb->f_active_id + 1);
rc = fcb_sector_hdr_init(fcb, sector, fcb->f_active_id + 1);
if (rc) {
return rc;
}
fcb->f_active.fe_area = fa;
fcb->f_active.fe_sector = sector;
fcb->f_active.fe_elem_off = sizeof(struct fcb_disk_area);
fcb->f_active_id++;
return FCB_OK;
@ -58,8 +58,8 @@ fcb_append_to_scratch(struct fcb *fcb)
int
fcb_append(struct fcb *fcb, u16_t len, struct fcb_entry *append_loc)
{
struct flash_sector *sector;
struct fcb_entry *active;
struct flash_area *fa;
u8_t tmp_str[2];
int cnt;
int rc;
@ -76,29 +76,28 @@ fcb_append(struct fcb *fcb, u16_t len, struct fcb_entry *append_loc)
return FCB_ERR_ARGS;
}
active = &fcb->f_active;
if (active->fe_elem_off + len + cnt > active->fe_area->fa_size) {
fa = fcb_new_area(fcb, fcb->f_scratch_cnt);
if (!fa || (fa->fa_size <
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 <
sizeof(struct fcb_disk_area) + len + cnt)) {
rc = FCB_ERR_NOSPACE;
goto err;
}
rc = fcb_sector_hdr_init(fcb, fa, fcb->f_active_id + 1);
rc = fcb_sector_hdr_init(fcb, sector, fcb->f_active_id + 1);
if (rc) {
goto err;
}
fcb->f_active.fe_area = fa;
fcb->f_active.fe_sector = sector;
fcb->f_active.fe_elem_off = sizeof(struct fcb_disk_area);
fcb->f_active_id++;
}
rc = flash_area_write(active->fe_area, active->fe_elem_off, tmp_str,
cnt);
rc = fcb_flash_write(fcb, active->fe_sector, active->fe_elem_off, tmp_str, cnt);
if (rc) {
rc = FCB_ERR_FLASH;
goto err;
}
append_loc->fe_area = active->fe_area;
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;
@ -125,7 +124,7 @@ fcb_append_finish(struct fcb *fcb, struct fcb_entry *loc)
}
off = loc->fe_data_off + fcb_len_in_flash(fcb, loc->fe_data_len);
rc = flash_area_write(loc->fe_area, off, &crc8, sizeof(crc8));
rc = fcb_flash_write(fcb, loc->fe_sector, off, &crc8, sizeof(crc8));
if (rc) {
return FCB_ERR_FLASH;
}

View file

@ -11,7 +11,7 @@
#include "fcb_priv.h"
/*
* Given offset in flash area, fill in rest of the fcb_entry, and crc8 over
* Given offset in flash sector, fill in rest of the fcb_entry, and crc8 over
* the data.
*/
int
@ -26,10 +26,10 @@ fcb_elem_crc8(struct fcb *fcb, struct fcb_entry *loc, u8_t *c8p)
u32_t end;
int rc;
if (loc->fe_elem_off + 2 > loc->fe_area->fa_size) {
if (loc->fe_elem_off + 2 > loc->fe_sector->fs_size) {
return FCB_ERR_NOVAR;
}
rc = flash_area_read(loc->fe_area, loc->fe_elem_off, tmp_str, 2);
rc = fcb_flash_read(fcb, loc->fe_sector, loc->fe_elem_off, tmp_str, 2);
if (rc) {
return FCB_ERR_FLASH;
}
@ -52,7 +52,7 @@ fcb_elem_crc8(struct fcb *fcb, struct fcb_entry *loc, u8_t *c8p)
blk_sz = sizeof(tmp_str);
}
rc = flash_area_read(loc->fe_area, off, tmp_str, blk_sz);
rc = fcb_flash_read(fcb, loc->fe_sector, off, tmp_str, blk_sz);
if (rc) {
return FCB_ERR_FLASH;
}
@ -76,7 +76,7 @@ int fcb_elem_info(struct fcb *fcb, struct fcb_entry *loc)
}
off = loc->fe_data_off + fcb_len_in_flash(fcb, loc->fe_data_len);
rc = flash_area_read(loc->fe_area, off, &fl_crc8, sizeof(fl_crc8));
rc = fcb_flash_read(fcb, loc->fe_sector, off, &fl_crc8, sizeof(fl_crc8));
if (rc) {
return FCB_ERR_FLASH;
}

View file

@ -11,7 +11,7 @@
#include "fcb_priv.h"
int
fcb_getnext_in_area(struct fcb *fcb, struct fcb_entry *loc)
fcb_getnext_in_sector(struct fcb *fcb, struct fcb_entry *loc)
{
int rc;
@ -30,14 +30,14 @@ fcb_getnext_in_area(struct fcb *fcb, struct fcb_entry *loc)
return rc;
}
struct flash_area *
fcb_getnext_area(struct fcb *fcb, struct flash_area *fap)
struct flash_sector *
fcb_getnext_sector(struct fcb *fcb, struct flash_sector *sector)
{
fap++;
if (fap >= &fcb->f_sectors[fcb->f_sector_cnt]) {
fap = &fcb->f_sectors[0];
sector++;
if (sector >= &fcb->f_sectors[fcb->f_sector_cnt]) {
sector = &fcb->f_sectors[0];
}
return fap;
return sector;
}
int
@ -45,15 +45,15 @@ fcb_getnext_nolock(struct fcb *fcb, struct fcb_entry *loc)
{
int rc;
if (loc->fe_area == NULL) {
if (loc->fe_sector == NULL) {
/*
* Find the first one we have in flash.
*/
loc->fe_area = fcb->f_oldest;
loc->fe_sector = fcb->f_oldest;
}
if (loc->fe_elem_off == 0) {
/*
* If offset is zero, we serve the first entry from the area.
* If offset is zero, we serve the first entry from the sector.
*/
loc->fe_elem_off = sizeof(struct fcb_disk_area);
rc = fcb_elem_info(fcb, loc);
@ -66,7 +66,7 @@ fcb_getnext_nolock(struct fcb *fcb, struct fcb_entry *loc)
goto next_sector;
}
} else {
rc = fcb_getnext_in_area(fcb, loc);
rc = fcb_getnext_in_sector(fcb, loc);
if (rc == 0) {
return 0;
}
@ -75,7 +75,7 @@ fcb_getnext_nolock(struct fcb *fcb, struct fcb_entry *loc)
}
}
while (rc == FCB_ERR_CRC) {
rc = fcb_getnext_in_area(fcb, loc);
rc = fcb_getnext_in_sector(fcb, loc);
if (rc == 0) {
return 0;
}
@ -85,10 +85,10 @@ fcb_getnext_nolock(struct fcb *fcb, struct fcb_entry *loc)
* Moving to next sector.
*/
next_sector:
if (loc->fe_area == fcb->f_active.fe_area) {
if (loc->fe_sector == fcb->f_active.fe_sector) {
return FCB_ERR_NOVAR;
}
loc->fe_area = fcb_getnext_area(fcb, loc->fe_area);
loc->fe_sector = fcb_getnext_sector(fcb, loc->fe_sector);
loc->fe_elem_off = sizeof(struct fcb_disk_area);
rc = fcb_elem_info(fcb, loc);
switch (rc) {

View file

@ -35,16 +35,20 @@ static inline int fcb_len_in_flash(struct fcb *fcb, u16_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);
const struct flash_area *fcb_open_flash(const struct fcb *fcb);
u8_t fcb_get_align(const struct fcb *fcb);
int fcb_erase_sector(const struct fcb *fcb, const struct flash_sector *sector);
int fcb_getnext_in_sector(struct fcb *fcb, struct fcb_entry *loc);
struct flash_sector *fcb_getnext_sector(struct fcb *fcb, struct flash_sector *sector);
int fcb_getnext_nolock(struct fcb *fcb, struct fcb_entry *loc);
int fcb_elem_info(struct fcb *fcb, struct fcb_entry *loc);
int fcb_elem_crc8(struct fcb *fcb, struct fcb_entry *loc, u8_t *crc8p);
int fcb_sector_hdr_init(struct fcb *fcb, struct flash_area *fap, u16_t id);
int fcb_sector_hdr_read(struct fcb *fcb, struct flash_area *fap,
struct fcb_disk_area *fdap);
int fcb_sector_hdr_init(struct fcb *fcb, struct flash_sector *sector, u16_t id);
int fcb_sector_hdr_read(struct fcb *fcb, struct flash_sector *sector,
struct fcb_disk_area *fdap);
#ifdef __cplusplus
}

View file

@ -11,7 +11,7 @@
int
fcb_rotate(struct fcb *fcb)
{
struct flash_area *fap;
struct flash_sector *sector;
int rc = 0;
rc = k_mutex_lock(&fcb->f_mtx, K_FOREVER);
@ -19,26 +19,26 @@ fcb_rotate(struct fcb *fcb)
return FCB_ERR_ARGS;
}
rc = flash_area_erase(fcb->f_oldest, 0, fcb->f_oldest->fa_size);
rc = fcb_erase_sector(fcb, fcb->f_oldest);
if (rc) {
rc = FCB_ERR_FLASH;
goto out;
}
if (fcb->f_oldest == fcb->f_active.fe_area) {
if (fcb->f_oldest == fcb->f_active.fe_sector) {
/*
* Need to create a new active area, as we're wiping
* the current.
*/
fap = fcb_getnext_area(fcb, fcb->f_oldest);
rc = fcb_sector_hdr_init(fcb, fap, fcb->f_active_id + 1);
sector = fcb_getnext_sector(fcb, fcb->f_oldest);
rc = fcb_sector_hdr_init(fcb, sector, fcb->f_active_id + 1);
if (rc) {
goto out;
}
fcb->f_active.fe_area = fap;
fcb->f_active.fe_sector = sector;
fcb->f_active.fe_elem_off = sizeof(struct fcb_disk_area);
fcb->f_active_id++;
}
fcb->f_oldest = fcb_getnext_area(fcb, fcb->f_oldest);
fcb->f_oldest = fcb_getnext_sector(fcb, fcb->f_oldest);
out:
k_mutex_unlock(&fcb->f_mtx);
return rc;

View file

@ -9,16 +9,17 @@
#include "fcb_priv.h"
/*
* Call 'cb' for every element in flash circular buffer. If fap is specified,
* only elements with that flash_area are reported.
* Call 'cb' for every element in flash circular buffer. If sector is specified,
* only elements with that flash_sector are reported.
*/
int
fcb_walk(struct fcb *fcb, struct flash_area *fap, fcb_walk_cb cb, void *cb_arg)
fcb_walk(struct fcb *fcb, struct flash_sector *sector, fcb_walk_cb cb,
void *cb_arg)
{
struct fcb_entry loc;
int rc;
loc.fe_area = fap;
loc.fe_sector = sector;
loc.fe_elem_off = 0;
rc = k_mutex_lock(&fcb->f_mtx, K_FOREVER);
@ -27,7 +28,7 @@ fcb_walk(struct fcb *fcb, struct flash_area *fap, fcb_walk_cb cb, void *cb_arg)
}
while ((rc = fcb_getnext_nolock(fcb, &loc)) != FCB_ERR_NOVAR) {
k_mutex_unlock(&fcb->f_mtx);
if (fap && loc.fe_area != fap) {
if (sector && loc.fe_sector != sector) {
return 0;
}
rc = cb(&loc, cb_arg);