Changed mkgbmap/rmgbmap to error if NOENT/EXIST

This more closely matches behavior of functions like mkdir and remove,
even though mkgbmap/rmgbmap operate on a special object and not files.

Besides, returning an error is more useful as users are always free to
ignore said error.

Adds what appears to be one literal to mkgbmap (curiously not rmgbmap?
snuck into alignment?):

                 code          stack          ctx
  before:       35968           2280          660
  after:        35968 (+0.0%)   2280 (+0.0%)  660 (+0.0%)

                 code          stack          ctx
  gbmap before: 38824           2296          772
  gbmap after:  38828 (+0.0%)   2296 (+0.0%)  772 (+0.0%)
This commit is contained in:
Christopher Haster
2025-11-15 02:10:42 -06:00
parent 867d201bce
commit ad2e8b3498
2 changed files with 298 additions and 4 deletions

8
lfs3.c
View File

@ -16540,9 +16540,9 @@ failed:;
// enable the global on-disk block-map
#if !defined(LFS3_RDONLY) && defined(LFS3_GBMAP) && !defined(LFS3_YES_GBMAP)
int lfs3_fs_mkgbmap(lfs3_t *lfs3) {
// do nothing if we already have a gbmap
// error if we already have a gbmap
if (lfs3_f_isgbmap(lfs3->flags)) {
return 0;
return LFS3_ERR_EXIST;
}
// prepare our filesystem for writing
@ -16599,9 +16599,9 @@ failed:;
// disable the global on-disk block-map
#if !defined(LFS3_RDONLY) && defined(LFS3_GBMAP) && !defined(LFS3_YES_GBMAP)
int lfs3_fs_rmgbmap(lfs3_t *lfs3) {
// do nothing if we already don't have a gbmap
// error if we already don't have a gbmap
if (!lfs3_f_isgbmap(lfs3->flags)) {
return 0;
return LFS3_ERR_NOENT;
}
// prepare our filesystem for writing

View File

@ -1167,3 +1167,297 @@ code = '''
lfs3_unmount(&lfs3) => 0;
'''
# test that removing a non-existant gbmap errors
[cases.test_gbmap_rmgbmap_noent]
ifndef = 'LFS3_YES_GBMAP'
defines.COUNT = [
'BLOCK_COUNT',
'BLOCK_COUNT-1',
'BLOCK_COUNT/2',
'BLOCK_COUNT/4',
'5',
'3',
]
defines.SIZE = [
'BLOCK_SIZE',
'2*BLOCK_SIZE',
'8*BLOCK_SIZE',
]
defines.N = ['5', 'BLOCK_COUNT/2']
defines.WRAPAROUND = 3
# REMOUNT=0 => don't remount
# REMOUNT=1 => remount after
# REMOUNT=2 => remount before
# REMOUNT=3 => remount both after and before
defines.REMOUNT = [0, 1, 2, 3]
if = [
'COUNT >= 3',
'COUNT >= 2*N*SIZE/BLOCK_SIZE',
]
code = '''
// test various block counts
struct lfs3_cfg cfg = *CFG;
cfg.block_count = COUNT;
lfs3_t lfs3;
// note the lack of gbmap flag
lfs3_format(&lfs3, LFS3_F_RDWR, &cfg) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0;
// check that we were formatted without the gbmap
struct lfs3_fsinfo fsinfo;
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(!(fsinfo.flags & LFS3_I_GBMAP));
// create n files repeatedly until we're sure we've wrapped around
// a few times
uint32_t prng = 42;
uint32_t prng_ = prng;
for (lfs3_size_t i = 0;
i < (WRAPAROUND*COUNT)
/ (N*(SIZE/BLOCK_SIZE));
i++) {
prng = prng_;
for (lfs3_size_t n = 0; n < N; n++) {
char name[256];
sprintf(name, "file%08d", n);
uint8_t wbuf[SIZE];
for (lfs3_size_t j = 0; j < SIZE; j++) {
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
}
lfs3_file_t file;
lfs3_file_open(&lfs3, &file, name,
LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0;
lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE;
lfs3_file_close(&lfs3, &file) => 0;
}
}
// remount before?
if (REMOUNT & 2) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0;
}
// now try to remove the gbmap
lfs3_fs_rmgbmap(&lfs3) => LFS3_ERR_NOENT;
// remount after?
if (REMOUNT & 1) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0;
}
// we should no longer have a gbmap
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(!(fsinfo.flags & LFS3_I_GBMAP));
// create n files repeatedly until we're sure we've wrapped around
// a few times
for (lfs3_size_t i = 0;
i < (WRAPAROUND*COUNT)
/ (N*(SIZE/BLOCK_SIZE));
i++) {
prng = prng_;
for (lfs3_size_t n = 0; n < N; n++) {
char name[256];
sprintf(name, "file%08d", n);
uint8_t wbuf[SIZE];
for (lfs3_size_t j = 0; j < SIZE; j++) {
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
}
lfs3_file_t file;
lfs3_file_open(&lfs3, &file, name,
LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0;
lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE;
lfs3_file_close(&lfs3, &file) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0;
}
// check that our file writes worked
prng_ = prng;
for (lfs3_size_t i = 0; i < N; i++) {
// check with stat
char name[256];
sprintf(name, "file%08d", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_REG);
assert(info.size == SIZE);
// try reading the file, note we reset prng above
uint8_t wbuf[SIZE];
for (lfs3_size_t j = 0; j < SIZE; j++) {
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
}
lfs3_file_t file;
uint8_t rbuf[SIZE];
lfs3_file_open(&lfs3, &file, name, LFS3_O_RDONLY) => 0;
lfs3_file_read(&lfs3, &file, rbuf, SIZE) => SIZE;
assert(memcmp(rbuf, wbuf, SIZE) == 0);
lfs3_file_close(&lfs3, &file) => 0;
}
}
lfs3_unmount(&lfs3) => 0;
'''
# test that making an existant gbmap errors
[cases.test_gbmap_mkgbmap_exist]
ifndef = 'LFS3_YES_GBMAP'
defines.COUNT = [
'BLOCK_COUNT',
'BLOCK_COUNT-1',
'BLOCK_COUNT/2',
'BLOCK_COUNT/4',
'5',
'3',
]
defines.SIZE = [
'BLOCK_SIZE',
'2*BLOCK_SIZE',
'8*BLOCK_SIZE',
]
defines.N = ['5', 'BLOCK_COUNT/2']
defines.WRAPAROUND = 3
# REMOUNT=0 => don't remount
# REMOUNT=1 => remount after
# REMOUNT=2 => remount before
# REMOUNT=3 => remount both after and before
defines.REMOUNT = [0, 1, 2, 3]
if = [
'COUNT >= 3',
'COUNT >= 2*N*SIZE/BLOCK_SIZE',
]
code = '''
// test various block counts
struct lfs3_cfg cfg = *CFG;
cfg.block_count = COUNT;
lfs3_t lfs3;
// note the gbmap flag
lfs3_format(&lfs3, LFS3_F_RDWR | LFS3_F_GBMAP, &cfg) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0;
// check that we were formatted with the gbmap
struct lfs3_fsinfo fsinfo;
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags & LFS3_I_GBMAP);
// create n files repeatedly until we're sure we've wrapped around
// a few times
uint32_t prng = 42;
uint32_t prng_ = prng;
for (lfs3_size_t i = 0;
i < (WRAPAROUND*COUNT)
/ (N*(SIZE/BLOCK_SIZE));
i++) {
prng = prng_;
for (lfs3_size_t n = 0; n < N; n++) {
char name[256];
sprintf(name, "file%08d", n);
uint8_t wbuf[SIZE];
for (lfs3_size_t j = 0; j < SIZE; j++) {
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
}
lfs3_file_t file;
lfs3_file_open(&lfs3, &file, name,
LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0;
lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE;
lfs3_file_close(&lfs3, &file) => 0;
}
}
// remount before?
if (REMOUNT & 2) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0;
}
// now make the gbmap
lfs3_fs_mkgbmap(&lfs3) => LFS3_ERR_EXIST;
// remount after?
if (REMOUNT & 1) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0;
}
// we should now have a gbmap
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
assert(fsinfo.flags & LFS3_I_GBMAP);
// create n files repeatedly until we're sure we've wrapped around
// a few times
for (lfs3_size_t i = 0;
i < (WRAPAROUND*COUNT)
/ (N*(SIZE/BLOCK_SIZE));
i++) {
prng = prng_;
for (lfs3_size_t n = 0; n < N; n++) {
char name[256];
sprintf(name, "file%08d", n);
uint8_t wbuf[SIZE];
for (lfs3_size_t j = 0; j < SIZE; j++) {
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
}
lfs3_file_t file;
lfs3_file_open(&lfs3, &file, name,
LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0;
lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE;
lfs3_file_close(&lfs3, &file) => 0;
}
}
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfs3_unmount(&lfs3) => 0;
lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0;
}
// check that our file writes worked
prng_ = prng;
for (lfs3_size_t i = 0; i < N; i++) {
// check with stat
char name[256];
sprintf(name, "file%08d", i);
struct lfs3_info info;
lfs3_stat(&lfs3, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS3_TYPE_REG);
assert(info.size == SIZE);
// try reading the file, note we reset prng above
uint8_t wbuf[SIZE];
for (lfs3_size_t j = 0; j < SIZE; j++) {
wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26);
}
lfs3_file_t file;
uint8_t rbuf[SIZE];
lfs3_file_open(&lfs3, &file, name, LFS3_O_RDONLY) => 0;
lfs3_file_read(&lfs3, &file, rbuf, SIZE) => SIZE;
assert(memcmp(rbuf, wbuf, SIZE) == 0);
lfs3_file_close(&lfs3, &file) => 0;
}
}
lfs3_unmount(&lfs3) => 0;
'''