Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 17 Dec 2020 18:52:30 +0000 (UTC)
From:      Mateusz Guzik <mjg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r368732 - head/sys/kern
Message-ID:  <202012171852.0BHIqUBA042267@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mjg
Date: Thu Dec 17 18:52:30 2020
New Revision: 368732
URL: https://svnweb.freebsd.org/changeset/base/368732

Log:
  fd: reimplement close_range to avoid spurious relocking

Modified:
  head/sys/kern/kern_descrip.c

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c	Thu Dec 17 18:52:04 2020	(r368731)
+++ head/sys/kern/kern_descrip.c	Thu Dec 17 18:52:30 2020	(r368732)
@@ -307,6 +307,7 @@ fdfree(struct filedesc *fdp, int fd)
 {
 	struct filedescent *fde;
 
+	FILEDESC_XLOCK_ASSERT(fdp);
 	fde = &fdp->fd_ofiles[fd];
 #ifdef CAPABILITIES
 	seqc_write_begin(&fde->fde_seqc);
@@ -1367,12 +1368,10 @@ int
 kern_close_range(struct thread *td, u_int lowfd, u_int highfd)
 {
 	struct filedesc *fdp;
-	int fd, ret, lastfile;
+	const struct fdescenttbl *fdt;
+	struct file *fp;
+	int fd;
 
-	ret = 0;
-	fdp = td->td_proc->p_fd;
-	FILEDESC_SLOCK(fdp);
-
 	/*
 	 * Check this prior to clamping; closefrom(3) with only fd 0, 1, and 2
 	 * open should not be a usage error.  From a close_range() perspective,
@@ -1380,30 +1379,36 @@ kern_close_range(struct thread *td, u_int lowfd, u_int
 	 * be a usage error as all fd above 3 are in-fact already closed.
 	 */
 	if (highfd < lowfd) {
-		ret = EINVAL;
-		goto out;
+		return (EINVAL);
 	}
 
-	/*
-	 * If lastfile == -1, we're dealing with either a fresh file
-	 * table or one in which every fd has been closed.  Just return
-	 * successful; there's nothing left to do.
-	 */
-	lastfile = fdlastfile(fdp);
-	if (lastfile == -1)
-		goto out;
-	/* Clamped to [lowfd, lastfile] */
-	highfd = MIN(highfd, lastfile);
-	for (fd = lowfd; fd <= highfd; fd++) {
-		if (fdp->fd_ofiles[fd].fde_file != NULL) {
-			FILEDESC_SUNLOCK(fdp);
-			(void)kern_close(td, fd);
-			FILEDESC_SLOCK(fdp);
+	fdp = td->td_proc->p_fd;
+	FILEDESC_XLOCK(fdp);
+	fdt = atomic_load_ptr(&fdp->fd_files);
+	highfd = MIN(highfd, fdt->fdt_nfiles - 1);
+	fd = lowfd;
+	if (__predict_false(fd > highfd)) {
+		goto out_locked;
+	}
+	for (;;) {
+		fp = fdt->fdt_ofiles[fd].fde_file;
+		if (fp == NULL) {
+			if (fd == highfd)
+				goto out_locked;
+		} else {
+			fdfree(fdp, fd);
+			(void) closefp(fdp, fd, fp, td, true, true);
+			if (fd == highfd)
+				goto out_unlocked;
+			FILEDESC_XLOCK(fdp);
+			fdt = atomic_load_ptr(&fdp->fd_files);
 		}
+		fd++;
 	}
-out:
-	FILEDESC_SUNLOCK(fdp);
-	return (ret);
+out_locked:
+	FILEDESC_XUNLOCK(fdp);
+out_unlocked:
+	return (0);
 }
 
 #ifndef _SYS_SYSPROTO_H_



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202012171852.0BHIqUBA042267>