Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 25 Feb 2017 10:38:18 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r314253 - in head/sys: fs/nfsserver kern sys ufs/ffs
Message-ID:  <201702251038.v1PAcIwH090194@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sat Feb 25 10:38:18 2017
New Revision: 314253
URL: https://svnweb.freebsd.org/changeset/base/314253

Log:
  Do not leak mount references for dying threads.
  
  Thread might create a condition for delayed SU cleanup, which creates
  a reference to the mount point in td_su, but exit without returning
  through userret(), e.g. when terminating due to single-threading or
  process exit.  In this case, td_su reference is not dropped and mount
  point cannot be freed.
  
  Handle the situation by clearing td_su also in the thread destructor
  and in exit1().  softdep_ast_cleanup() has to receive the thread as
  argument, since e.g. thread destructor is executed in different
  context.
  
  Reported and tested by:	pho
  Sponsored by:	The FreeBSD Foundation
  MFC after:	2 weeks

Modified:
  head/sys/fs/nfsserver/nfs_nfsdkrpc.c
  head/sys/kern/kern_exit.c
  head/sys/kern/kern_thread.c
  head/sys/kern/subr_trap.c
  head/sys/sys/proc.h
  head/sys/sys/systm.h
  head/sys/ufs/ffs/ffs_softdep.c

Modified: head/sys/fs/nfsserver/nfs_nfsdkrpc.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdkrpc.c	Sat Feb 25 10:32:49 2017	(r314252)
+++ head/sys/fs/nfsserver/nfs_nfsdkrpc.c	Sat Feb 25 10:38:18 2017	(r314253)
@@ -304,8 +304,7 @@ nfssvc_program(struct svc_req *rqst, SVC
 	svc_freereq(rqst);
 
 out:
-	if (softdep_ast_cleanup != NULL)
-		softdep_ast_cleanup();
+	td_softdep_cleanup(curthread);
 	NFSEXITCODE(0);
 }
 

Modified: head/sys/kern/kern_exit.c
==============================================================================
--- head/sys/kern/kern_exit.c	Sat Feb 25 10:32:49 2017	(r314252)
+++ head/sys/kern/kern_exit.c	Sat Feb 25 10:38:18 2017	(r314253)
@@ -207,8 +207,7 @@ exit1(struct thread *td, int rval, int s
 	/*
 	 * Deref SU mp, since the thread does not return to userspace.
 	 */
-	if (softdep_ast_cleanup != NULL)
-		softdep_ast_cleanup();
+	td_softdep_cleanup(td);
 
 	/*
 	 * MUST abort all other threads before proceeding past here.

Modified: head/sys/kern/kern_thread.c
==============================================================================
--- head/sys/kern/kern_thread.c	Sat Feb 25 10:32:49 2017	(r314252)
+++ head/sys/kern/kern_thread.c	Sat Feb 25 10:38:18 2017	(r314253)
@@ -192,6 +192,8 @@ thread_dtor(void *mem, int size, void *a
 #endif
 	/* Free all OSD associated to this thread. */
 	osd_thread_exit(td);
+	td_softdep_cleanup(td);
+	MPASS(td->td_su == NULL);
 
 	EVENTHANDLER_INVOKE(thread_dtor, td);
 	tid_free(td->td_tid);

Modified: head/sys/kern/subr_trap.c
==============================================================================
--- head/sys/kern/subr_trap.c	Sat Feb 25 10:32:49 2017	(r314252)
+++ head/sys/kern/subr_trap.c	Sat Feb 25 10:38:18 2017	(r314253)
@@ -86,7 +86,7 @@ __FBSDID("$FreeBSD$");
 
 #include <security/mac/mac_framework.h>
 
-void (*softdep_ast_cleanup)(void);
+void (*softdep_ast_cleanup)(struct thread *);
 
 /*
  * Define the code needed before returning to user mode, for trap and
@@ -128,8 +128,8 @@ userret(struct thread *td, struct trapfr
 #ifdef KTRACE
 	KTRUSERRET(td);
 #endif
-	if (softdep_ast_cleanup != NULL)
-		softdep_ast_cleanup();
+	td_softdep_cleanup(td);
+	MPASS(td->td_su == NULL);
 
 	/*
 	 * If this thread tickled GEOM, we need to wait for the giggling to

Modified: head/sys/sys/proc.h
==============================================================================
--- head/sys/sys/proc.h	Sat Feb 25 10:32:49 2017	(r314252)
+++ head/sys/sys/proc.h	Sat Feb 25 10:38:18 2017	(r314253)
@@ -1114,6 +1114,15 @@ td_get_sched(struct thread *td)
 	return ((struct td_sched *)&td[1]);
 }
 
+extern void (*softdep_ast_cleanup)(struct thread *);
+static __inline void
+td_softdep_cleanup(struct thread *td)
+{
+
+	if (td->td_su != NULL && softdep_ast_cleanup != NULL)
+		softdep_ast_cleanup(td);
+}
+
 #endif	/* _KERNEL */
 
 #endif	/* !_SYS_PROC_H_ */

Modified: head/sys/sys/systm.h
==============================================================================
--- head/sys/sys/systm.h	Sat Feb 25 10:32:49 2017	(r314252)
+++ head/sys/sys/systm.h	Sat Feb 25 10:38:18 2017	(r314253)
@@ -452,8 +452,6 @@ void free_unr(struct unrhdr *uh, u_int i
 
 void	intr_prof_stack_use(struct thread *td, struct trapframe *frame);
 
-extern void (*softdep_ast_cleanup)(void);
-
 void counted_warning(unsigned *counter, const char *msg);
 
 __NULLABILITY_PRAGMA_POP

Modified: head/sys/ufs/ffs/ffs_softdep.c
==============================================================================
--- head/sys/ufs/ffs/ffs_softdep.c	Sat Feb 25 10:32:49 2017	(r314252)
+++ head/sys/ufs/ffs/ffs_softdep.c	Sat Feb 25 10:38:18 2017	(r314253)
@@ -902,7 +902,7 @@ static	int pagedep_find(struct pagedep_h
 static	void pause_timer(void *);
 static	int request_cleanup(struct mount *, int);
 static	void schedule_cleanup(struct mount *);
-static void softdep_ast_cleanup_proc(void);
+static void softdep_ast_cleanup_proc(struct thread *);
 static	int process_worklist_item(struct mount *, int, int);
 static	void process_removes(struct vnode *);
 static	void process_truncates(struct vnode *);
@@ -13445,15 +13445,13 @@ schedule_cleanup(struct mount *mp)
 }
 
 static void
-softdep_ast_cleanup_proc(void)
+softdep_ast_cleanup_proc(struct thread *td)
 {
-	struct thread *td;
 	struct mount *mp;
 	struct ufsmount *ump;
 	int error;
 	bool req;
 
-	td = curthread;
 	while ((mp = td->td_su) != NULL) {
 		td->td_su = NULL;
 		error = vfs_busy(mp, MBF_NOWAIT);
@@ -13491,6 +13489,10 @@ softdep_ast_cleanup_proc(void)
 		}
 		vfs_unbusy(mp);
 	}
+	if ((mp = td->td_su) != NULL) {
+		td->td_su = NULL;
+		vfs_rel(mp);
+	}
 }
 
 /*



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