git: 4f816f5b11ca - main - makefs: Fix space accounting for the root DSL directory

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Tue, 16 Aug 2022 15:03:15 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=4f816f5b11ca7a5db965455d11d1db19162cfca6

commit 4f816f5b11ca7a5db965455d11d1db19162cfca6
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2022-08-16 14:15:53 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2022-08-16 15:02:51 +0000

    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
---
 usr.sbin/makefs/zfs/dsl.c    | 21 +++++++++++++++------
 usr.sbin/makefs/zfs/objset.c |  6 ++++--
 usr.sbin/makefs/zfs/zfs.h    |  2 +-
 3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/usr.sbin/makefs/zfs/dsl.c b/usr.sbin/makefs/zfs/dsl.c
index 1d20f5f3891a..223f5941ef69 100644
--- a/usr.sbin/makefs/zfs/dsl.c
+++ b/usr.sbin/makefs/zfs/dsl.c
@@ -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
diff --git a/usr.sbin/makefs/zfs/objset.c b/usr.sbin/makefs/zfs/objset.c
index fdb17167a607..edd0b66d6147 100644
--- a/usr.sbin/makefs/zfs/objset.c
+++ b/usr.sbin/makefs/zfs/objset.c
@@ -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);
 }
diff --git a/usr.sbin/makefs/zfs/zfs.h b/usr.sbin/makefs/zfs/zfs.h
index 7ad3151dd8a2..6b743b40b3ab 100644
--- a/usr.sbin/makefs/zfs/zfs.h
+++ b/usr.sbin/makefs/zfs/zfs.h
@@ -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 */