mtd_config_fs : optimize nvs
Signed-off-by: xucheng5 <xucheng5@xiaomi.com>
This commit is contained in:
parent
cd80900646
commit
3b79363041
@ -81,11 +81,8 @@
|
||||
|
||||
#define NVS_SPECIAL_ATE_ID 0xffffffff
|
||||
|
||||
#ifdef CONFIG_MTD_WRITE_ALIGN_SIZE
|
||||
#define NVS_ALIGN_SIZE CONFIG_MTD_WRITE_ALIGN_SIZE
|
||||
#else
|
||||
#define NVS_ALIGN_SIZE 4
|
||||
#endif
|
||||
#define NVS_ALIGN_UP(x) (((x) + NVS_ALIGN_SIZE - 1) & ~(NVS_ALIGN_SIZE - 1))
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
@ -116,11 +113,15 @@ begin_packed_struct struct nvs_ate
|
||||
uint16_t key_len; /* Key string len */
|
||||
uint8_t part; /* Part of a multipart data - future extension */
|
||||
uint8_t crc8; /* Crc8 check of the ate entry */
|
||||
#if CONFIG_MTD_WRITE_ALIGN_SIZE > 4
|
||||
uint8_t padding[NVS_ALIGN_SIZE - 4]; /* padding for align */
|
||||
#if CONFIG_MTD_WRITE_ALIGN_SIZE <= 4
|
||||
/* stay compatible with situation which align byte be 1 */
|
||||
|
||||
uint8_t expired[NVS_ALIGN_SIZE];
|
||||
uint8_t reserved[4 - NVS_ALIGN_SIZE];
|
||||
#else
|
||||
uint8_t padding[NVS_ALIGN_UP(12) - 12];
|
||||
uint8_t expired[NVS_ALIGN_SIZE];
|
||||
#endif
|
||||
uint8_t expired; /* 0xFF-newest entry, others-old entry */
|
||||
uint8_t reserved[NVS_ALIGN_SIZE - 1];
|
||||
} end_packed_struct;
|
||||
|
||||
/****************************************************************************
|
||||
@ -163,19 +164,6 @@ static const struct file_operations g_mtdnvs_fops =
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nvs_al_size
|
||||
****************************************************************************/
|
||||
|
||||
static inline size_t nvs_al_size(size_t len)
|
||||
{
|
||||
#ifdef CONFIG_MTD_WRITE_ALIGN_SIZE
|
||||
return (len + (NVS_ALIGN_SIZE - 1U)) & ~(NVS_ALIGN_SIZE - 1U);
|
||||
#else
|
||||
return len;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nvs_fnv_hash
|
||||
****************************************************************************/
|
||||
@ -599,6 +587,40 @@ static int nvs_close_ate_valid(FAR struct nvs_fs *fs,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nvs_flash_write_multi_blk
|
||||
*
|
||||
* Description:
|
||||
* Store multi align block in flash
|
||||
*
|
||||
* Returned Value:
|
||||
* number of bytes at the end of addr which is left to write next time.
|
||||
* zero indicates all bytes were written . On error returns -ERRNO code.
|
||||
****************************************************************************/
|
||||
|
||||
int nvs_flash_write_multi_blk(FAR struct nvs_fs *fs, const uint8_t *addr,
|
||||
size_t size)
|
||||
{
|
||||
size_t blk_cnt;
|
||||
int left;
|
||||
int rc;
|
||||
|
||||
blk_cnt = size / NVS_ALIGN_SIZE;
|
||||
left = size % NVS_ALIGN_SIZE;
|
||||
|
||||
if (blk_cnt)
|
||||
{
|
||||
rc = nvs_flash_data_wrt(fs, addr, size - left);
|
||||
if (rc)
|
||||
{
|
||||
ferr("Write multi data value failed, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nvs_flash_wrt_entry
|
||||
*
|
||||
@ -613,8 +635,9 @@ static int nvs_flash_wrt_entry(FAR struct nvs_fs *fs, uint32_t id,
|
||||
{
|
||||
int rc;
|
||||
struct nvs_ate entry;
|
||||
uint16_t total;
|
||||
uint8_t *tmp;
|
||||
uint16_t left;
|
||||
uint16_t copy_len = 0;
|
||||
uint8_t buf[NVS_ALIGN_SIZE];
|
||||
|
||||
memset(&entry, fs->erasestate, sizeof(entry));
|
||||
entry.id = id;
|
||||
@ -624,37 +647,65 @@ static int nvs_flash_wrt_entry(FAR struct nvs_fs *fs, uint32_t id,
|
||||
|
||||
nvs_ate_crc8_update(&entry);
|
||||
|
||||
/* Let's sew key and data into one, key comes first, then data */
|
||||
/* Let's save key and data into one, key comes first, then data */
|
||||
|
||||
total = nvs_al_size(key_size + len);
|
||||
tmp = kmm_malloc(total);
|
||||
if (tmp == NULL)
|
||||
rc = nvs_flash_write_multi_blk(fs, key, key_size);
|
||||
if (rc < 0)
|
||||
{
|
||||
ferr("malloc size %u failed\n", total);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(tmp, key, key_size);
|
||||
memcpy(tmp + key_size, data, len);
|
||||
memset(tmp + key_size + len, fs->erasestate, total - key_size - len);
|
||||
|
||||
rc = nvs_flash_data_wrt(fs, tmp, total);
|
||||
if (rc)
|
||||
{
|
||||
ferr("Write value failed, rc=%d\n", rc);
|
||||
kmm_free(tmp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (rc)
|
||||
{
|
||||
/* Write align block which inlcude part key + part data */
|
||||
|
||||
left = rc;
|
||||
memset(buf, fs->erasestate, NVS_ALIGN_SIZE);
|
||||
|
||||
copy_len = (left + len) <= NVS_ALIGN_SIZE ?
|
||||
len : (NVS_ALIGN_SIZE - left);
|
||||
|
||||
memcpy(buf, key + key_size - left, left);
|
||||
memcpy(buf + left, data, copy_len);
|
||||
rc = nvs_flash_data_wrt(fs, buf, NVS_ALIGN_SIZE);
|
||||
if (rc)
|
||||
{
|
||||
ferr("Write value failed, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
rc = nvs_flash_write_multi_blk(fs, data + copy_len, len - copy_len);
|
||||
if (rc < 0)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (rc)
|
||||
{
|
||||
/* Add padding at the end of data */
|
||||
|
||||
left = rc;
|
||||
memset(buf, fs->erasestate, NVS_ALIGN_SIZE);
|
||||
memcpy(buf, data + len - left, left);
|
||||
|
||||
rc = nvs_flash_data_wrt(fs, buf, NVS_ALIGN_SIZE);
|
||||
if (rc)
|
||||
{
|
||||
ferr("Write value failed, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/* Last, let's save entry to flash */
|
||||
|
||||
rc = nvs_flash_ate_wrt(fs, &entry);
|
||||
if (rc)
|
||||
{
|
||||
ferr("Write ate failed, rc=%d\n", rc);
|
||||
kmm_free(tmp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
kmm_free(tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -699,7 +750,7 @@ static int nvs_recover_last_ate(FAR struct nvs_fs *fs,
|
||||
|
||||
data_end_addr &= ADDR_BLOCK_MASK;
|
||||
data_end_addr += end_ate.offset +
|
||||
nvs_al_size(end_ate.key_len + end_ate.len);
|
||||
NVS_ALIGN_UP(end_ate.key_len + end_ate.len);
|
||||
*addr = ate_end_addr;
|
||||
}
|
||||
|
||||
@ -945,7 +996,7 @@ static int nvs_gc(FAR struct nvs_fs *fs)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (gc_ate.expired != fs->erasestate)
|
||||
if (gc_ate.expired[0] != fs->erasestate)
|
||||
{
|
||||
/* Deleted or old ate, ignore it */
|
||||
|
||||
@ -971,7 +1022,7 @@ static int nvs_gc(FAR struct nvs_fs *fs)
|
||||
nvs_ate_crc8_update(&gc_ate);
|
||||
|
||||
rc = nvs_flash_block_move(fs, data_addr,
|
||||
nvs_al_size(gc_ate.key_len + gc_ate.len));
|
||||
NVS_ALIGN_UP(gc_ate.key_len + gc_ate.len));
|
||||
if (rc)
|
||||
{
|
||||
return rc;
|
||||
@ -1156,8 +1207,8 @@ static int nvs_startup(FAR struct nvs_fs *fs)
|
||||
/* Complete write of ate was performed */
|
||||
|
||||
fs->data_wra = addr & ADDR_BLOCK_MASK;
|
||||
fs->data_wra += last_ate.offset + nvs_al_size(last_ate.key_len +
|
||||
last_ate.len);
|
||||
fs->data_wra += last_ate.offset +
|
||||
NVS_ALIGN_UP(last_ate.key_len + last_ate.len);
|
||||
finfo("recovered data_wra=0x%" PRIx32 "\n", fs->data_wra);
|
||||
}
|
||||
|
||||
@ -1316,7 +1367,7 @@ static int nvs_startup(FAR struct nvs_fs *fs)
|
||||
|
||||
if (nvs_ate_valid(fs, &second_ate)
|
||||
&& second_ate.id == last_ate.id
|
||||
&& second_ate.expired == fs->erasestate)
|
||||
&& second_ate.expired[0] == fs->erasestate)
|
||||
{
|
||||
finfo("same id at 0x%" PRIx32 ", key_len %" PRIu16 ", "
|
||||
"offset %" PRIu16 "\n",
|
||||
@ -1432,7 +1483,7 @@ static ssize_t nvs_read_entry(FAR struct nvs_fs *fs, FAR const uint8_t *key,
|
||||
{
|
||||
/* It is old or deleted, return -ENOENT */
|
||||
|
||||
if (wlk_ate.expired != fs->erasestate)
|
||||
if (wlk_ate.expired[0] != fs->erasestate)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
@ -1521,13 +1572,14 @@ static ssize_t nvs_write(FAR struct nvs_fs *fs,
|
||||
|
||||
/* Data now contains input data and input key, input key first. */
|
||||
|
||||
data_size = nvs_al_size(key_size + pdata->len);
|
||||
data_size = NVS_ALIGN_UP(key_size + pdata->len);
|
||||
|
||||
/* The maximum data size is block size - 3 ate
|
||||
* where: 1 ate for data, 1 ate for block close, 1 ate for gc done.
|
||||
*/
|
||||
|
||||
finfo("key_size=%zu, len=%zu\n", key_size, pdata->len);
|
||||
finfo("key_size=%zu, len=%zu, data_size = %zu\n", key_size,
|
||||
pdata->len, data_size);
|
||||
|
||||
if ((data_size > (fs->geo.erasesize - 3 * sizeof(struct nvs_ate))) ||
|
||||
((pdata->len > 0) && (pdata->configdata == NULL)))
|
||||
@ -1587,7 +1639,7 @@ static ssize_t nvs_write(FAR struct nvs_fs *fs,
|
||||
{
|
||||
/* If prev ate is expired, it is deleted. */
|
||||
|
||||
if (wlk_ate.expired != fs->erasestate)
|
||||
if (wlk_ate.expired[0] != fs->erasestate)
|
||||
{
|
||||
/* Skip delete entry as it is already the
|
||||
* last one.
|
||||
@ -1611,7 +1663,7 @@ static ssize_t nvs_write(FAR struct nvs_fs *fs,
|
||||
}
|
||||
}
|
||||
else if (pdata->len == wlk_ate.len &&
|
||||
wlk_ate.expired == fs->erasestate)
|
||||
wlk_ate.expired[0] == fs->erasestate)
|
||||
{
|
||||
/* Do not try to compare if lengths are not equal
|
||||
* or prev one is deleted.
|
||||
@ -1658,7 +1710,7 @@ static ssize_t nvs_write(FAR struct nvs_fs *fs,
|
||||
/* Nvs is changed after gc, we will look for the old ate.
|
||||
*/
|
||||
|
||||
if (prev_found && wlk_ate.expired == fs->erasestate)
|
||||
if (prev_found && wlk_ate.expired[0] == fs->erasestate)
|
||||
{
|
||||
finfo("prev entry exists, search for it\n");
|
||||
|
||||
@ -1701,7 +1753,7 @@ static ssize_t nvs_write(FAR struct nvs_fs *fs,
|
||||
* already expired)
|
||||
*/
|
||||
|
||||
if (prev_found && wlk_ate.expired == fs->erasestate)
|
||||
if (prev_found && wlk_ate.expired[0] == fs->erasestate)
|
||||
{
|
||||
rc = nvs_expire_ate(fs, hist_addr);
|
||||
finfo("expir prev entry, %" PRIx32 ", rc %d\n",
|
||||
@ -1871,7 +1923,7 @@ static int nvs_next(FAR struct nvs_fs *fs,
|
||||
|
||||
if (nvs_ate_valid(fs, &step_ate)
|
||||
&& step_ate.id != NVS_SPECIAL_ATE_ID
|
||||
&& step_ate.expired == fs->erasestate)
|
||||
&& step_ate.expired[0] == fs->erasestate)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user