git: 37b9fb169686 - main - Add descrip_check_write_mp() helper

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Thu, 29 Dec 2022 20:56:23 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=37b9fb169686e867987c8a1a9868f81137b9df2b

commit 37b9fb169686e867987c8a1a9868f81137b9df2b
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2022-12-28 18:13:01 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2022-12-29 20:55:39 +0000

    Add descrip_check_write_mp() helper
    
    ... which verifies that given file table does not have file descriptors
    referencing vnodes on the specified mount point.  It is up to the caller
    to ensure that the check is not racy.
    
    Reviewed by:    mckusick
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D37896
---
 sys/kern/kern_descrip.c | 23 +++++++++++++++++++++++
 sys/sys/filedesc.h      |  2 ++
 2 files changed, 25 insertions(+)

diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 63a7f8b2a6d7..0be59e930dd4 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -4172,6 +4172,29 @@ mountcheckdirs(struct vnode *olddp, struct vnode *newdp)
 		vrele(olddp);
 }
 
+int
+descrip_check_write_mp(struct filedesc *fdp, struct mount *mp)
+{
+	struct file *fp;
+	struct vnode *vp;
+	int error, i;
+
+	error = 0;
+	FILEDESC_SLOCK(fdp);
+	FILEDESC_FOREACH_FP(fdp, i, fp) {
+		if (fp->f_type != DTYPE_VNODE ||
+		    (atomic_load_int(&fp->f_flag) & FWRITE) == 0)
+			continue;
+		vp = fp->f_vnode;
+		if (vp->v_mount == mp) {
+			error = EDEADLK;
+			break;
+		}
+	}
+	FILEDESC_SUNLOCK(fdp);
+	return (error);
+}
+
 struct filedesc_to_leader *
 filedesc_to_leader_alloc(struct filedesc_to_leader *old, struct filedesc *fdp,
     struct proc *leader)
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index 52bd3c97a9ac..ffea8d7e0195 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -225,6 +225,7 @@ enum {
 #define	falloc(td, resultfp, resultfd, flags) \
 	falloc_caps(td, resultfp, resultfd, flags, NULL)
 
+struct mount;
 struct thread;
 
 static __inline void
@@ -241,6 +242,7 @@ void	filecaps_free(struct filecaps *fcaps);
 
 int	closef(struct file *fp, struct thread *td);
 void	closef_nothread(struct file *fp);
+int	descrip_check_write_mp(struct filedesc *fdp, struct mount *mp);
 int	dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode,
 	    int openerror, int *indxp);
 int	falloc_caps(struct thread *td, struct file **resultfp, int *resultfd,