diff --git a/include/zephyr/fs/nvs.h b/include/zephyr/fs/nvs.h index df70b64f58bce..f654933166f9e 100644 --- a/include/zephyr/fs/nvs.h +++ b/include/zephyr/fs/nvs.h @@ -48,7 +48,7 @@ struct nvs_fs { /** Data write address */ uint32_t data_wra; /** File system is split into sectors, each sector must be multiple of erase-block-size */ - uint16_t sector_size; + uint32_t sector_size; /** Number of sectors in the file system */ uint16_t sector_count; /** Flag indicating if the file system is initialized */ diff --git a/subsys/fs/nvs/nvs.c b/subsys/fs/nvs/nvs.c index 2e553fdbf554f..8a710d570fb12 100644 --- a/subsys/fs/nvs/nvs.c +++ b/subsys/fs/nvs/nvs.c @@ -1025,6 +1025,13 @@ int nvs_mount(struct nvs_fs *fs) return -EINVAL; } + /* check that sector size is not greater than max */ + if (fs->sector_size > NVS_MAX_SECTOR_SIZE) { + LOG_ERR("Sector size %u too large, maximum is %zu", + fs->sector_size, NVS_MAX_SECTOR_SIZE); + return -EINVAL; + } + /* check that sector size is a multiple of pagesize */ rc = flash_get_page_info_by_offs(fs->flash_device, fs->offset, &info); if (rc) { diff --git a/subsys/fs/nvs/nvs_priv.h b/subsys/fs/nvs/nvs_priv.h index 53f109ee13201..0c302d132f6ca 100644 --- a/subsys/fs/nvs/nvs_priv.h +++ b/subsys/fs/nvs/nvs_priv.h @@ -21,6 +21,8 @@ extern "C" { #define ADDR_SECT_SHIFT 16 #define ADDR_OFFS_MASK 0x0000FFFF +#define NVS_MAX_SECTOR_SIZE KB(64) + /* * Status return values */ diff --git a/tests/subsys/fs/nvs/boards/native_sim_64kb_erase_block.overlay b/tests/subsys/fs/nvs/boards/native_sim_64kb_erase_block.overlay new file mode 100644 index 0000000000000..2079b50ceab20 --- /dev/null +++ b/tests/subsys/fs/nvs/boards/native_sim_64kb_erase_block.overlay @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&flash0 { + erase-block-size = <0x10000>; + + /* + * Delete old partitions that were not aligned on 64kb addresses and + * create new ones that are aligned. + */ + /delete-node/ partitions; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x00010000>; + }; + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x00070000>; + }; + slot1_partition: partition@80000 { + label = "image-1"; + reg = <0x00080000 0x00070000>; + }; + scratch_partition: partition@f0000 { + label = "image-scratch"; + reg = <0x000f0000 0x00020000>; + }; + storage_partition: partition@110000 { + label = "storage"; + reg = <0x00110000 0x00050000>; + }; + }; +}; diff --git a/tests/subsys/fs/nvs/src/main.c b/tests/subsys/fs/nvs/src/main.c index 1747a7ba4aafb..d900c5aa99bf9 100644 --- a/tests/subsys/fs/nvs/src/main.c +++ b/tests/subsys/fs/nvs/src/main.c @@ -96,7 +96,14 @@ ZTEST_SUITE(nvs, NULL, setup, before, after, NULL); ZTEST_F(nvs, test_nvs_mount) { int err; + size_t orig_sector_size = fixture->fs.sector_size; + fixture->fs.sector_size = KB(128); + err = nvs_mount(&fixture->fs); + zassert_true(err == -EINVAL, + "nvs_mount did not return expected err for invalid sector_size"); + + fixture->fs.sector_size = orig_sector_size; err = nvs_mount(&fixture->fs); zassert_true(err == 0, "nvs_mount call failure: %d", err); } @@ -307,7 +314,7 @@ static void write_content(uint16_t max_id, uint16_t begin, uint16_t end, for (uint16_t i = begin; i < end; i++) { uint8_t id = (i % max_id); - uint8_t id_data = id + max_id * (i / max_id); + uint8_t id_data = id + max_id * ((i % 256) / max_id); memset(buf, id_data, sizeof(buf)); @@ -346,13 +353,25 @@ ZTEST_F(nvs, test_nvs_gc_3sectors) const uint16_t max_id = 10; /* 50th write will trigger 1st GC. */ - const uint16_t max_writes = 51; + uint16_t max_writes = 51; /* 75th write will trigger 2st GC. */ - const uint16_t max_writes_2 = 51 + 25; + uint16_t max_writes_2 = 51 + 25; /* 100th write will trigger 3st GC. */ - const uint16_t max_writes_3 = 51 + 25 + 25; + uint16_t max_writes_3 = 51 + 25 + 25; /* 125th write will trigger 4st GC. */ - const uint16_t max_writes_4 = 51 + 25 + 25 + 25; + uint16_t max_writes_4 = 51 + 25 + 25 + 25; + + if (fixture->fs.sector_size == KB(64)) { + /* write 1637 will trigger 1st GC. */ + /* write 3274 will trigger 2nd GC. */ + max_writes = 3275; + /* write 4911 will trigger 3rd GC. */ + max_writes_2 = 3275 + 1637; + /* write 6548 will trigger 4th GC. */ + max_writes_3 = 3275 + 1637 + 1637; + /* write 8185 will trigger 5th GC. */ + max_writes_4 = 3275 + 1637 + 1637 + 1637; + } fixture->fs.sector_count = 3; @@ -361,7 +380,7 @@ ZTEST_F(nvs, test_nvs_gc_3sectors) zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 0, "unexpected write sector"); - /* Trigger 1st GC */ + /* Trigger 1st and 2nd GC */ write_content(max_id, 0, max_writes, &fixture->fs); /* sector sequence: empty,closed, write */ @@ -376,7 +395,7 @@ ZTEST_F(nvs, test_nvs_gc_3sectors) "unexpected write sector"); check_content(max_id, &fixture->fs); - /* Trigger 2nd GC */ + /* Trigger 3rd GC */ write_content(max_id, max_writes, max_writes_2, &fixture->fs); /* sector sequence: write, empty, closed */ @@ -391,7 +410,7 @@ ZTEST_F(nvs, test_nvs_gc_3sectors) "unexpected write sector"); check_content(max_id, &fixture->fs); - /* Trigger 3rd GC */ + /* Trigger 4th GC */ write_content(max_id, max_writes_2, max_writes_3, &fixture->fs); /* sector sequence: closed, write, empty */ @@ -406,7 +425,7 @@ ZTEST_F(nvs, test_nvs_gc_3sectors) "unexpected write sector"); check_content(max_id, &fixture->fs); - /* Trigger 4th GC */ + /* Trigger 5th GC */ write_content(max_id, max_writes_3, max_writes_4, &fixture->fs); /* sector sequence: empty,closed, write */ diff --git a/tests/subsys/fs/nvs/testcase.yaml b/tests/subsys/fs/nvs/testcase.yaml index c796cda1307b0..34b28ab30e623 100644 --- a/tests/subsys/fs/nvs/testcase.yaml +++ b/tests/subsys/fs/nvs/testcase.yaml @@ -28,3 +28,6 @@ tests: - CONFIG_NVS_LOOKUP_CACHE=y - CONFIG_NVS_LOOKUP_CACHE_SIZE=64 platform_allow: native_sim + filesystem.nvs.64kb_erase_block: + extra_args: DTC_OVERLAY_FILE=boards/native_sim_64kb_erase_block.overlay + platform_allow: native_sim