makefs: fix calculation of file sizes

When a new FS image is created we need to calculate how much space each
file is going to consume.
Fix two bugs in that logic:

1) Count the space needed for indirect blocks for large files.
1) Normally the trailing data of a file is written to a block of frag
   size, 4 kB by default.

However for files that use indirect blocks a full block is allocated,
32kB by default.  Take that into account.

Adjust size calculations to match what is done in ffs_mkfs routine:

* Depending on the UFS version the superblock is stored at a different
  offset. Take that into account.
* Add the cylinder group block size.
* All of the above has to be aligned to the block size.

Finally, Remove "ncg" variable. It's always 1 and it was used to
multiply stuff.

PR:		229929
Reviewed by:	mckusick
MFC after:	2 weeks
Sponsored by:	Semihalf
Submitted by:	Kornel Dulęba <mindal@semihalf.com>
Differential Revision:	https://reviews.freebsd.org/D35131
Differential Revision:	https://reviews.freebsd.org/D35132
This commit is contained in:
Alan Somers 2022-05-16 16:32:10 -06:00
parent c1e0431c22
commit ecdc04d006
2 changed files with 30 additions and 21 deletions

View File

@ -324,7 +324,6 @@ ffs_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts)
static void
ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts)
{
int32_t ncg = 1;
#ifdef notyet
int32_t spc, nspf, ncyl, fssize;
#endif
@ -395,22 +394,26 @@ ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts)
fsopts->size =
fsopts->size * (100 + fsopts->freeblockpc) / 100;
/* add space needed for superblocks */
/*
* The old SBOFF (SBLOCK_UFS1) is used here because makefs is
* typically used for small filesystems where space matters.
* XXX make this an option.
* Add space needed for superblock, cylblock and to store inodes.
* All of those segments are aligned to the block size.
* XXX: This has to match calculations done in ffs_mkfs.
*/
fsopts->size += (SBLOCK_UFS1 + SBLOCKSIZE) * ncg;
/* add space needed to store inodes, x3 for blockmaps, etc */
if (ffs_opts->version == 1)
fsopts->size += ncg * DINODE1_SIZE *
roundup(fsopts->inodes / ncg,
ffs_opts->bsize / DINODE1_SIZE);
else
fsopts->size += ncg * DINODE2_SIZE *
roundup(fsopts->inodes / ncg,
ffs_opts->bsize / DINODE2_SIZE);
if (ffs_opts->version == 1) {
fsopts->size +=
roundup(SBLOCK_UFS1 + SBLOCKSIZE, ffs_opts->bsize);
fsopts->size += roundup(SBLOCKSIZE, ffs_opts->bsize);
fsopts->size += ffs_opts->bsize;
fsopts->size += DINODE1_SIZE *
roundup(fsopts->inodes, ffs_opts->bsize / DINODE1_SIZE);
} else {
fsopts->size +=
roundup(SBLOCK_UFS2 + SBLOCKSIZE, ffs_opts->bsize);
fsopts->size += roundup(SBLOCKSIZE, ffs_opts->bsize);
fsopts->size += ffs_opts->bsize;
fsopts->size += DINODE2_SIZE *
roundup(fsopts->inodes, ffs_opts->bsize / DINODE2_SIZE);
}
/* add minfree */
if (ffs_opts->minfree > 0)
@ -620,12 +623,19 @@ ffs_size_dir(fsnode *root, fsinfo_t *fsopts)
e, tmpdir.d_namlen, this, curdirsize); \
} while (0);
/*
* XXX this needs to take into account extra space consumed
* by indirect blocks, etc.
*/
#define ADDSIZE(x) do { \
fsopts->size += roundup((x), ffs_opts->fsize); \
if ((size_t)(x) < UFS_NDADDR * (size_t)ffs_opts->bsize) { \
fsopts->size += roundup((x), ffs_opts->fsize); \
} else { \
/* Count space consumed by indirecttion blocks. */ \
fsopts->size += ffs_opts->bsize * \
(howmany((x), UFS_NDADDR * ffs_opts->bsize) - 1); \
/* \
* If the file is big enough to use indirect blocks, \
* we allocate bsize block for trailing data. \
*/ \
fsopts->size += roundup((x), ffs_opts->bsize); \
} \
} while (0);
curdirsize = 0;

View File

@ -57,7 +57,6 @@ check_ffs_image_contents()
atf_test_case autocalculate_image_size cleanup
autocalculate_image_size_body()
{
atf_expect_fail "PR 229929 makefs(8) can underestimate image size"
create_test_inputs
atf_check -e empty -o save:$TEST_SPEC_FILE -s exit:0 \