From 6bce3f23d0aa045d61c0ec8d27100eb186a33375 Mon Sep 17 00:00:00 2001 From: Olivier Certner Date: Sun, 23 Apr 2023 09:47:58 +0200 Subject: [PATCH] vfs: Export get_next_dirent() as vn_dir_next_dirent() Move internal-to-'vfs_default.c' get_next_dirent() to 'vfs_vnops.c' and export it for use by other parts of the VFS. This is a preparatory change for using it in vfs_emptydir(). No functional change. Reviewed by: kib MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D39755 --- sys/kern/vfs_default.c | 73 +++--------------------------------------- sys/kern/vfs_vnops.c | 62 +++++++++++++++++++++++++++++++++++ sys/sys/vnode.h | 3 ++ 3 files changed, 69 insertions(+), 69 deletions(-) diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index ee1310215621..7da4f7b62cff 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -75,15 +75,9 @@ __FBSDID("$FreeBSD$"); static int vop_nolookup(struct vop_lookup_args *); static int vop_norename(struct vop_rename_args *); static int vop_nostrategy(struct vop_strategy_args *); -static int get_next_dirent(struct vnode *vp, struct dirent **dpp, - char *dirbuf, int dirbuflen, off_t *off, - char **cpos, int *len, int *eofflag, - struct thread *td); static int dirent_exists(struct vnode *vp, const char *dirname, struct thread *td); -#define DIRENT_MINSIZE (sizeof(struct dirent) - (MAXNAMLEN+1) + 4) - static int vop_stdis_text(struct vop_is_text_args *ap); static int vop_stdunset_text(struct vop_unset_text_args *ap); static int vop_stdadd_writecount(struct vop_add_writecount_args *ap); @@ -281,65 +275,6 @@ vop_nostrategy (struct vop_strategy_args *ap) return (EOPNOTSUPP); } -static int -get_next_dirent(struct vnode *vp, struct dirent **dpp, char *dirbuf, - int dirbuflen, off_t *off, char **cpos, int *len, - int *eofflag, struct thread *td) -{ - int error, reclen; - struct uio uio; - struct iovec iov; - struct dirent *dp; - - KASSERT(VOP_ISLOCKED(vp), ("vp %p is not locked", vp)); - KASSERT(vp->v_type == VDIR, ("vp %p is not a directory", vp)); - - if (*len == 0) { - iov.iov_base = dirbuf; - iov.iov_len = dirbuflen; - - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = *off; - uio.uio_resid = dirbuflen; - uio.uio_segflg = UIO_SYSSPACE; - uio.uio_rw = UIO_READ; - uio.uio_td = td; - - *eofflag = 0; - -#ifdef MAC - error = mac_vnode_check_readdir(td->td_ucred, vp); - if (error == 0) -#endif - error = VOP_READDIR(vp, &uio, td->td_ucred, eofflag, - NULL, NULL); - if (error) - return (error); - - *off = uio.uio_offset; - - *cpos = dirbuf; - *len = (dirbuflen - uio.uio_resid); - - if (*len == 0) - return (ENOENT); - } - - dp = (struct dirent *)(*cpos); - reclen = dp->d_reclen; - *dpp = dp; - - /* check for malformed directory.. */ - if (reclen < DIRENT_MINSIZE) - return (EINVAL); - - *cpos += reclen; - *len -= reclen; - - return (0); -} - /* * Check if a named file exists in a given directory vnode. */ @@ -369,8 +304,8 @@ dirent_exists(struct vnode *vp, const char *dirname, struct thread *td) off = 0; len = 0; do { - error = get_next_dirent(vp, &dp, dirbuf, dirbuflen, &off, - &cpos, &len, &eofflag, td); + error = vn_dir_next_dirent(vp, &dp, dirbuf, dirbuflen, &off, + &cpos, &len, &eofflag, td); if (error) goto out; @@ -808,8 +743,8 @@ vop_stdvptocnp(struct vop_vptocnp_args *ap) len = 0; do { /* call VOP_READDIR of parent */ - error = get_next_dirent(*dvp, &dp, dirbuf, dirbuflen, &off, - &cpos, &len, &eofflag, td); + error = vn_dir_next_dirent(*dvp, &dp, dirbuf, dirbuflen, &off, + &cpos, &len, &eofflag, td); if (error) goto out; diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 581d620e348e..ad9b0c8864b0 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -3736,6 +3737,67 @@ vn_fspacectl(struct file *fp, int cmd, off_t *offset, off_t *length, int flags, return (error); } +#define DIRENT_MINSIZE (sizeof(struct dirent) - (MAXNAMLEN+1) + 4) + +int +vn_dir_next_dirent(struct vnode *vp, struct dirent **dpp, char *dirbuf, + int dirbuflen, off_t *off, char **cpos, int *len, + int *eofflag, struct thread *td) +{ + int error, reclen; + struct uio uio; + struct iovec iov; + struct dirent *dp; + + KASSERT(VOP_ISLOCKED(vp), ("vp %p is not locked", vp)); + KASSERT(vp->v_type == VDIR, ("vp %p is not a directory", vp)); + + if (*len == 0) { + iov.iov_base = dirbuf; + iov.iov_len = dirbuflen; + + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = *off; + uio.uio_resid = dirbuflen; + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_rw = UIO_READ; + uio.uio_td = td; + + *eofflag = 0; + +#ifdef MAC + error = mac_vnode_check_readdir(td->td_ucred, vp); + if (error == 0) +#endif + error = VOP_READDIR(vp, &uio, td->td_ucred, eofflag, + NULL, NULL); + if (error) + return (error); + + *off = uio.uio_offset; + + *cpos = dirbuf; + *len = (dirbuflen - uio.uio_resid); + + if (*len == 0) + return (ENOENT); + } + + dp = (struct dirent *)(*cpos); + reclen = dp->d_reclen; + *dpp = dp; + + /* check for malformed directory.. */ + if (reclen < DIRENT_MINSIZE) + return (EINVAL); + + *cpos += reclen; + *len -= reclen; + + return (0); +} + static u_long vn_lock_pair_pause_cnt; SYSCTL_ULONG(_debug, OID_AUTO, vn_lock_pair_pause, CTLFLAG_RD, &vn_lock_pair_pause_cnt, 0, diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index fa889826867e..282f75bcdd71 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -1099,6 +1099,9 @@ void vfs_hash_remove(struct vnode *vp); int vfs_kqfilter(struct vop_kqfilter_args *); struct dirent; +int vn_dir_next_dirent(struct vnode *vp, struct dirent **dpp, char *dirbuf, + int dirbuflen, off_t *off, char **cpos, int *len, + int *eofflag, struct thread *td); int vfs_read_dirent(struct vop_readdir_args *ap, struct dirent *dp, off_t off); int vfs_emptydir(struct vnode *vp);