Skip to content

Commit 2d62d2f

Browse files
committed
Fixed metadata_max==prog_size commit->end calculation
The inconsistency here between the use of block_size vs metadata_max was suspicious. Turns out there's a bug when metadata_max == prog_size. We correctly use metadata_max for the block_size/2 check, but we weren't using it for the block_size-40 check. The second check seems unnecessary after the first, but it protects against running out of space in a commit for commit-related metadata (checksums, tail pointers, etc) when we can't program half-blocks. Turns out this is also needed when limiting metadata_max to a single prog, otherwise we risk erroring with LFS_ERR_NOSPC early. Found by ajheck, dpkristensen, NLLK, and likely others.
1 parent 1f82c0f commit 2d62d2f

File tree

1 file changed

+5
-4
lines changed

1 file changed

+5
-4
lines changed

lfs.c

+5-4
Original file line numberDiff line numberDiff line change
@@ -2128,13 +2128,14 @@ static int lfs_dir_splittingcompact(lfs_t *lfs, lfs_mdir_t *dir,
21282128
// And we cap at half a block to avoid degenerate cases with
21292129
// nearly-full metadata blocks.
21302130
//
2131+
lfs_size_t metadata_max = (lfs->cfg->metadata_max)
2132+
? lfs->cfg->metadata_max
2133+
: lfs->cfg->block_size;
21312134
if (end - split < 0xff
21322135
&& size <= lfs_min(
2133-
lfs->cfg->block_size - 40,
2136+
metadata_max - 40,
21342137
lfs_alignup(
2135-
(lfs->cfg->metadata_max
2136-
? lfs->cfg->metadata_max
2137-
: lfs->cfg->block_size)/2,
2138+
metadata_max/2,
21382139
lfs->cfg->prog_size))) {
21392140
break;
21402141
}

0 commit comments

Comments
 (0)