Download raw body.
Remove fd_checkclosed
All,
fd_checkclosed() is only used in two places, both as a best‑effort race detector rather than a strong synchronization point. In sys_fcntl()’s F_SETLK/F_SETLKW path, it is called after VOP_ADVLOCK() to see if close() or dup2() won the race and then issue a compensating F_UNLCK if so. In kqueue_kqfilter(), fd filters use it to check whether knote_fdclose() might have missed the knote while it was being attached.
In both cases, the caller already holds a reference on the struct file obtained earlier from fd_getfile(). This patch converts the check to a direct atomic grab and then removing the helper.
There is no intended semantic change beyond avoiding an extra mutex acquisition around what is already documented as a racy snapshot in both call sites.
—
Tim Leslie
diff --git a/share/man/man9/file.9 b/share/man/man9/file.9
--- a/share/man/man9/file.9
+++ b/share/man/man9/file.9
@@ -32,7 +32,6 @@
.Nm FRELE ,
.Nm fd_getfile ,
.Nm fd_getfile_mode ,
-.Nm fd_checkclosed ,
.Nm getsock ,
.Nm getvnode
.Nd an overview of file descriptor handling
@@ -52,8 +51,6 @@
.Ft struct file *
.Fn fd_getfile_mode "struct filedesc *fdp" "int fd" "int mode"
.Ft int
-.Fn fd_checkclosed "struct filedesc *fdp" "int fd" "struct file *fp"
-.Ft int
.Fn getsock "struct proc *p" "int fd" "struct file **fpp"
.In sys/file.h
.In sys/filedesc.h
@@ -112,13 +109,6 @@ is like
.Fn fd_getfile
but also checks if the file has been opened with the given mode.
.Pp
-.Fn fd_checkclosed
-checks if file descriptor
-.Fa fd
-has been closed and no longer points to file
-.Fa fp .
-The file must have been retrieved from the descriptor previously.
-.Pp
The files are extracted from the process context using the
function
.Fn getsock
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -262,18 +262,6 @@ fd_getfile_mode(struct filedesc *fdp, int fd, int mode)
return (fp);
}
-int
-fd_checkclosed(struct filedesc *fdp, int fd, struct file *fp)
-{
- int closed;
-
- mtx_enter(&fdp->fd_fplock);
- KASSERT(fd < fdp->fd_nfiles);
- closed = (fdp->fd_ofiles[fd] != fp);
- mtx_leave(&fdp->fd_fplock);
- return (closed);
-}
-
/*
* System calls on descriptors.
*/
@@ -571,7 +559,7 @@ restart:
goto out;
}
- if (fd_checkclosed(fdp, fd, fp)) {
+ if (READ_ONCE(fdp->fd_ofiles[fd]) != fp) {
/*
* We have lost the race with close() or dup2();
* unlock, pretend that we've won the race and that
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -1501,7 +1501,7 @@ again:
* ran before kn appeared in kq_knlist.
*/
if ((fops->f_flags & FILTEROP_ISFD) &&
- fd_checkclosed(fdp, kev->ident, kn->kn_fp)) {
+ READ_ONCE(fdp->fd_ofiles[kev->ident]) != kn->kn_fp) {
/*
* Drop the knote silently without error
* because another thread might already have
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -148,7 +148,6 @@ void fdprepforexec(struct proc *);
struct file *fd_iterfile(struct file *, struct proc *);
struct file *fd_getfile(struct filedesc *, int);
struct file *fd_getfile_mode(struct filedesc *, int, int);
-int fd_checkclosed(struct filedesc *, int, struct file *);
int closef(struct file *, struct proc *);
int getsock(struct proc *, int, struct file **);
Remove fd_checkclosed