git: 8ba938472706 - stable/13 - vfs: Rename vfs_emptydir() to vn_dir_check_empty()

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Fri, 05 May 2023 06:38:59 UTC
The branch stable/13 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=8ba9384727065435f699f29524980c89a9263e12

commit 8ba9384727065435f699f29524980c89a9263e12
Author:     Olivier Certner <olce.freebsd@certner.fr>
AuthorDate: 2023-04-28 09:00:11 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2023-05-05 06:20:58 +0000

    vfs: Rename vfs_emptydir() to vn_dir_check_empty()
    
    (cherry picked from commit 2544b8e00ca1afea64b00a6ddaf7b584244ade90)
---
 sys/kern/vfs_mount.c |  2 +-
 sys/kern/vfs_subr.c  | 90 ---------------------------------------------------
 sys/kern/vfs_vnops.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 sys/sys/vnode.h      |  2 +-
 4 files changed, 93 insertions(+), 92 deletions(-)

diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 32d24fb16526..d5b137e7ffab 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -979,7 +979,7 @@ vfs_domount_first(
 			error = ENOTDIR;
 	}
 	if (error == 0 && (fsflags & MNT_EMPTYDIR) != 0)
-		error = vfs_emptydir(vp);
+		error = vn_dir_check_empty(vp);
 	if (error == 0) {
 		VI_LOCK(vp);
 		if ((vp->v_iflag & VI_MOUNT) == 0 && vp->v_mountedhere == NULL)
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index dbedc16f555b..2002f3b81937 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -6443,96 +6443,6 @@ filt_vfsvnode(struct knote *kn, long hint)
 	return (res);
 }
 
-/*
- * Returns whether the directory is empty or not.
- * If it is empty, the return value is 0; otherwise
- * the return value is an error value (which may
- * be ENOTEMPTY).
- */
-int
-vfs_emptydir(struct vnode *vp)
-{
-	struct thread *const td = curthread;
-	char *dirbuf;
-	size_t dirbuflen, len;
-	off_t off;
-	int eofflag, error;
-	struct dirent *dp;
-	struct vattr va;
-
-	ASSERT_VOP_LOCKED(vp, "vfs_emptydir");
-	VNASSERT(vp->v_type == VDIR, vp, ("vp is not a directory"));
-
-	error = VOP_GETATTR(vp, &va, td->td_ucred);
-	if (error != 0)
-		return (error);
-
-	dirbuflen = max(DEV_BSIZE, GENERIC_MAXDIRSIZ);
-	if (dirbuflen < va.va_blocksize)
-		dirbuflen = va.va_blocksize;
-	dirbuf = malloc(dirbuflen, M_TEMP, M_WAITOK);
-
-	len = 0;
-	off = 0;
-	eofflag = 0;
-
-	for (;;) {
-		error = vn_dir_next_dirent(vp, td, dirbuf, dirbuflen,
-		    &dp, &len, &off, &eofflag);
-		if (error != 0)
-			goto end;
-
-		if (len == 0) {
-			/* EOF */
-			error = 0;
-			goto end;
-		}
-
-		/*
-		 * Skip whiteouts. Unionfs operates on filesystems only and not
-		 * on hierarchies, so these whiteouts would be shadowed on the
-		 * system hierarchy but not for a union using the filesystem of
-		 * their directories as the upper layer. Additionally, unionfs
-		 * currently transparently exposes union-specific metadata of
-		 * its upper layer, meaning that whiteouts can be seen through
-		 * the union view in empty directories. Taking into account
-		 * these whiteouts would then prevent mounting another
-		 * filesystem on such effectively empty directories.
-		 */
-		if (dp->d_type == DT_WHT)
-			continue;
-
-		/*
-		 * Any file in the directory which is not '.' or '..' indicates
-		 * the directory is not empty.
-		 */
-		switch (dp->d_namlen) {
-		case 2:
-			if (dp->d_name[1] != '.') {
-				/* Can't be '..' (nor '.') */
-				error = ENOTEMPTY;
-				goto end;
-			}
-			/* FALLTHROUGH */
-		case 1:
-			if (dp->d_name[0] != '.') {
-				/* Can't be '..' nor '.' */
-				error = ENOTEMPTY;
-				goto end;
-			}
-			break;
-
-		default:
-			error = ENOTEMPTY;
-			goto end;
-		}
-	}
-
-end:
-	free(dirbuf, M_TEMP);
-	return (error);
-}
-
 int
 vfs_read_dirent(struct vop_readdir_args *ap, struct dirent *dp, off_t off)
 {
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 8ad66be142b2..dfaa6868c567 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -3757,6 +3757,97 @@ out:
 	return (error);
 }
 
+/*
+ * Checks whether a directory is empty or not.
+ *
+ * If the directory is empty, returns 0, and if it is not, ENOTEMPTY.  Other
+ * values are genuine errors preventing the check.
+ */
+int
+vn_dir_check_empty(struct vnode *vp)
+{
+	struct thread *const td = curthread;
+	char *dirbuf;
+	size_t dirbuflen, len;
+	off_t off;
+	int eofflag, error;
+	struct dirent *dp;
+	struct vattr va;
+
+	ASSERT_VOP_LOCKED(vp, "vfs_emptydir");
+	VNPASS(vp->v_type == VDIR, vp);
+
+	error = VOP_GETATTR(vp, &va, td->td_ucred);
+	if (error != 0)
+		return (error);
+
+	dirbuflen = max(DEV_BSIZE, GENERIC_MAXDIRSIZ);
+	if (dirbuflen < va.va_blocksize)
+		dirbuflen = va.va_blocksize;
+	dirbuf = malloc(dirbuflen, M_TEMP, M_WAITOK);
+
+	len = 0;
+	off = 0;
+	eofflag = 0;
+
+	for (;;) {
+		error = vn_dir_next_dirent(vp, td, dirbuf, dirbuflen,
+		    &dp, &len, &off, &eofflag);
+		if (error != 0)
+			goto end;
+
+		if (len == 0) {
+			/* EOF */
+			error = 0;
+			goto end;
+		}
+
+		/*
+		 * Skip whiteouts.  Unionfs operates on filesystems only and
+		 * not on hierarchies, so these whiteouts would be shadowed on
+		 * the system hierarchy but not for a union using the
+		 * filesystem of their directories as the upper layer.
+		 * Additionally, unionfs currently transparently exposes
+		 * union-specific metadata of its upper layer, meaning that
+		 * whiteouts can be seen through the union view in empty
+		 * directories.  Taking into account these whiteouts would then
+		 * prevent mounting another filesystem on such effectively
+		 * empty directories.
+		 */
+		if (dp->d_type == DT_WHT)
+			continue;
+
+		/*
+		 * Any file in the directory which is not '.' or '..' indicates
+		 * the directory is not empty.
+		 */
+		switch (dp->d_namlen) {
+		case 2:
+			if (dp->d_name[1] != '.') {
+				/* Can't be '..' (nor '.') */
+				error = ENOTEMPTY;
+				goto end;
+			}
+			/* FALLTHROUGH */
+		case 1:
+			if (dp->d_name[0] != '.') {
+				/* Can't be '..' nor '.' */
+				error = ENOTEMPTY;
+				goto end;
+			}
+			break;
+
+		default:
+			error = ENOTEMPTY;
+			goto end;
+		}
+	}
+
+end:
+	free(dirbuf, M_TEMP);
+	return (error);
+}
+
 
 static u_long vn_lock_pair_pause_cnt;
 SYSCTL_ULONG(_debug, OID_AUTO, vn_lock_pair_pause, CTLFLAG_RD,
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 7b15cb95f63f..543eb06f2f16 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -1099,8 +1099,8 @@ struct dirent;
 int vn_dir_next_dirent(struct vnode *vp, struct thread *td,
     char *dirbuf, size_t dirbuflen,
     struct dirent **dpp, size_t *len, off_t *off, int *eofflag);
+int vn_dir_check_empty(struct vnode *vp);
 int vfs_read_dirent(struct vop_readdir_args *ap, struct dirent *dp, off_t off);
-int vfs_emptydir(struct vnode *vp);
 
 int vfs_unixify_accmode(accmode_t *accmode);