Răsfoiți Sursa

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.
Christopher Haster 1 an în urmă
părinte
comite
2d62d2f4c9
1 a modificat fișierele cu 5 adăugiri și 4 ștergeri
  1. 5 4
      lfs.c

+ 5 - 4
lfs.c

@@ -2128,13 +2128,14 @@ static int lfs_dir_splittingcompact(lfs_t *lfs, lfs_mdir_t *dir,
             // And we cap at half a block to avoid degenerate cases with
             // nearly-full metadata blocks.
             //
+            lfs_size_t metadata_max = (lfs->cfg->metadata_max)
+                    ? lfs->cfg->metadata_max
+                    : lfs->cfg->block_size;
             if (end - split < 0xff
                     && size <= lfs_min(
-                        lfs->cfg->block_size - 40,
+                        metadata_max - 40,
                         lfs_alignup(
-                            (lfs->cfg->metadata_max
-                                ? lfs->cfg->metadata_max
-                                : lfs->cfg->block_size)/2,
+                            metadata_max/2,
                             lfs->cfg->prog_size))) {
                 break;
             }