Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 17 Aug 2014 07:00:48 +0000 (UTC)
From:      Mateusz Guzik <mjg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r270088 - stable/10/sys/kern
Message-ID:  <201408170700.s7H70m4d034361@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mjg
Date: Sun Aug 17 07:00:47 2014
New Revision: 270088
URL: http://svnweb.freebsd.org/changeset/base/270088

Log:
  MFC r268505, r268507:
  
  Avoid relocking filedesc lock when closing fds during fdp destruction.
  
  Don't call bzero nor fdunused from fdfree for such cases. It would do
  unnecessary work and complain that the lock is not taken.
  
  =======
  
  Don't zero fd_nfiles during fdp destruction.
  
  Code trying to take a look has to check fd_refcnt and it is 0 by that time.
  
  This is a follow up to r268505, without this the code would leak memory for
  tables bigger than the default.

Modified:
  stable/10/sys/kern/kern_descrip.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/kern/kern_descrip.c
==============================================================================
--- stable/10/sys/kern/kern_descrip.c	Sun Aug 17 06:58:14 2014	(r270087)
+++ stable/10/sys/kern/kern_descrip.c	Sun Aug 17 07:00:47 2014	(r270088)
@@ -295,18 +295,36 @@ fdunused(struct filedesc *fdp, int fd)
 
 /*
  * Free a file descriptor.
+ *
+ * Avoid some work if fdp is about to be destroyed.
  */
 static inline void
-fdfree(struct filedesc *fdp, int fd)
+_fdfree(struct filedesc *fdp, int fd, int last)
 {
 	struct filedescent *fde;
 
 	fde = &fdp->fd_ofiles[fd];
 	filecaps_free(&fde->fde_caps);
+	if (last)
+		return;
 	bzero(fde, sizeof(*fde));
 	fdunused(fdp, fd);
 }
 
+static inline void
+fdfree(struct filedesc *fdp, int fd)
+{
+
+	_fdfree(fdp, fd, 0);
+}
+
+static inline void
+fdfree_last(struct filedesc *fdp, int fd)
+{
+
+	_fdfree(fdp, fd, 1);
+}
+
 /*
  * System calls on descriptors.
  */
@@ -2044,36 +2062,32 @@ fdescfree(struct thread *td)
 
 	FILEDESC_XLOCK(fdp);
 	i = --fdp->fd_refcnt;
-	FILEDESC_XUNLOCK(fdp);
-	if (i > 0)
+	if (i > 0) {
+		FILEDESC_XUNLOCK(fdp);
 		return;
+	}
+
+	cdir = fdp->fd_cdir;
+	fdp->fd_cdir = NULL;
+	rdir = fdp->fd_rdir;
+	fdp->fd_rdir = NULL;
+	jdir = fdp->fd_jdir;
+	fdp->fd_jdir = NULL;
+	FILEDESC_XUNLOCK(fdp);
 
 	for (i = 0; i <= fdp->fd_lastfile; i++) {
 		fp = fdp->fd_ofiles[i].fde_file;
 		if (fp != NULL) {
-			FILEDESC_XLOCK(fdp);
-			fdfree(fdp, i);
-			FILEDESC_XUNLOCK(fdp);
+			fdfree_last(fdp, i);
 			(void) closef(fp, td);
 		}
 	}
-	FILEDESC_XLOCK(fdp);
 
 	if (fdp->fd_nfiles > NDFILE)
 		free(fdp->fd_ofiles, M_FILEDESC);
 	if (NDSLOTS(fdp->fd_nfiles) > NDSLOTS(NDFILE))
 		free(fdp->fd_map, M_FILEDESC);
 
-	fdp->fd_nfiles = 0;
-
-	cdir = fdp->fd_cdir;
-	fdp->fd_cdir = NULL;
-	rdir = fdp->fd_rdir;
-	fdp->fd_rdir = NULL;
-	jdir = fdp->fd_jdir;
-	fdp->fd_jdir = NULL;
-	FILEDESC_XUNLOCK(fdp);
-
 	if (cdir != NULL)
 		vrele(cdir);
 	if (rdir != NULL)



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