makefs: Fix space accounting for the root DSL directory

Space used by the MOS is summed after all on-disk data structures are
finalized, so the MOS DSL directory represents a special case when
counting bytes used for each directory.  The DSL layer failed to update
the MOS DSL directory's parent, the root directory, accordingly, so the
root directory reported less space used than was used in reality.  Be
careful to update the root directory after the MOS is finalized.

PR:		265849
Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Mark Johnston 2022-08-16 10:15:53 -04:00
parent 187084dddd
commit 4f816f5b11
3 changed files with 20 additions and 9 deletions

View File

@ -425,11 +425,11 @@ dsl_dir_alloc(zfs_opt_t *zfs, const char *name)
}
void
dsl_dir_size_set(zfs_dsl_dir_t *dir, uint64_t bytes)
dsl_dir_size_add(zfs_dsl_dir_t *dir, uint64_t bytes)
{
dir->phys->dd_used_bytes = bytes;
dir->phys->dd_compressed_bytes = bytes;
dir->phys->dd_uncompressed_bytes = bytes;
dir->phys->dd_used_bytes += bytes;
dir->phys->dd_compressed_bytes += bytes;
dir->phys->dd_uncompressed_bytes += bytes;
}
/*
@ -515,9 +515,18 @@ dsl_dir_finalize(zfs_opt_t *zfs, zfs_dsl_dir_t *dir, void *arg __unused)
headds->phys->ds_uncompressed_bytes = bytes;
headds->phys->ds_compressed_bytes = bytes;
STAILQ_FOREACH(cdir, &dir->children, next)
STAILQ_FOREACH(cdir, &dir->children, next) {
/*
* The root directory needs a special case: the amount of
* space used for the MOS isn't known until everything else is
* finalized, so it can't be accounted in the MOS directory's
* parent until then.
*/
if (dir == zfs->rootdsldir && cdir == zfs->mosdsldir)
continue;
bytes += cdir->phys->dd_used_bytes;
dsl_dir_size_set(dir, bytes);
}
dsl_dir_size_add(dir, bytes);
}
void

View File

@ -180,9 +180,11 @@ objset_write(zfs_opt_t *zfs, zfs_objset_t *os)
vdev_spacemap_write(zfs);
/*
* We've finished allocating space, account for it in $MOS.
* We've finished allocating space, account for it in $MOS and
* in the parent directory.
*/
dsl_dir_size_set(zfs->mosdsldir, os->space);
dsl_dir_size_add(zfs->mosdsldir, os->space);
dsl_dir_size_add(zfs->rootdsldir, os->space);
}
_objset_write(zfs, os, c, dnodeloc);
}

View File

@ -123,7 +123,7 @@ char *dsl_dir_get_mountpoint(zfs_opt_t *, zfs_dsl_dir_t *);
bool dsl_dir_has_dataset(zfs_dsl_dir_t *);
bool dsl_dir_dataset_has_objset(zfs_dsl_dir_t *);
void dsl_dir_dataset_write(zfs_opt_t *, zfs_objset_t *, zfs_dsl_dir_t *);
void dsl_dir_size_set(zfs_dsl_dir_t *, uint64_t);
void dsl_dir_size_add(zfs_dsl_dir_t *, uint64_t);
void dsl_write(zfs_opt_t *);
/* fs.c */