git: 507f8523f5f6 - main - makefs: zfs dataset mountpoints are considered non-empty

From: Toomas Soome <tsoome_at_FreeBSD.org>
Date: Tue, 29 Jul 2025 21:01:54 UTC
The branch main has been updated by tsoome:

URL: https://cgit.FreeBSD.org/src/commit/?id=507f8523f5f6795ad40dc6c13c84e480925f48c0

commit 507f8523f5f6795ad40dc6c13c84e480925f48c0
Author:     Toomas Soome <tsoome@FreeBSD.org>
AuthorDate: 2025-07-25 21:01:46 +0000
Commit:     Toomas Soome <tsoome@FreeBSD.org>
CommitDate: 2025-07-29 21:01:26 +0000

    makefs: zfs dataset mountpoints are considered non-empty
    
    The dataset mountpoints get link count and size calculated by
    content of dataset root directory, but this will break libzfs
    dir_is_empty_stat() test.
    
    For fix, we need to check if the directory is mountpoint for
    dataset, and calculate the link count and size accordingly.
    
    Reviewed by:    markj
    Differential revision:  https://reviews.freebsd.org/D51593
---
 usr.sbin/makefs/zfs/fs.c | 42 +++++++++++++++++++++++++++---------------
 1 file changed, 27 insertions(+), 15 deletions(-)

diff --git a/usr.sbin/makefs/zfs/fs.c b/usr.sbin/makefs/zfs/fs.c
index 0194089a357d..75f6e30e1500 100644
--- a/usr.sbin/makefs/zfs/fs.c
+++ b/usr.sbin/makefs/zfs/fs.c
@@ -384,22 +384,34 @@ fs_populate_sattrs(struct fs_populate_arg *arg, const fsnode *cur,
 		links = 1; /* .. */
 		objsize = 1; /* .. */
 
-		/*
-		 * The size of a ZPL directory is the number of entries
-		 * (including "." and ".."), and the link count is the number of
-		 * entries which are directories (including "." and "..").
-		 */
-		for (fsnode *c = fsnode_isroot(cur) ? cur->next : cur->child;
-		    c != NULL; c = c->next) {
-			switch (c->type) {
-			case S_IFDIR:
-				links++;
-				/* FALLTHROUGH */
-			case S_IFREG:
-			case S_IFLNK:
-				objsize++;
-				break;
+		if ((cur->inode->flags & FI_ROOT) == 0 ) {
+			/*
+			 * The size of a ZPL directory is the number of entries
+			 * (including "." and ".."), and the link count is the
+			 * number of entries which are directories
+			 * (including "." and "..").
+			 */
+			for (fsnode *c =
+			    fsnode_isroot(cur) ? cur->next : cur->child;
+			    c != NULL; c = c->next) {
+				switch (c->type) {
+				case S_IFDIR:
+					links++;
+					/* FALLTHROUGH */
+				case S_IFREG:
+				case S_IFLNK:
+					objsize++;
+					break;
+				}
 			}
+		} else {
+			/*
+			 * Root directory children do belong to
+			 * different dataset and this directory is
+			 * empty in the current objset.
+			 */
+			links++;        /* . */
+			objsize++;      /* . */
 		}
 
 		/* The root directory is its own parent. */