git: 8ba938472706 - stable/13 - vfs: Rename vfs_emptydir() to vn_dir_check_empty()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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);