svn commit: r314253 - in head/sys: fs/nfsserver kern sys ufs/ffs
Konstantin Belousov
kib at FreeBSD.org
Sat Feb 25 10:38:20 UTC 2017
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);
+ }
}
/*
More information about the svn-src-all
mailing list