From owner-svn-src-all@freebsd.org Sat Feb 25 10:38:20 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 4CCCFCEB96D; Sat, 25 Feb 2017 10:38:20 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 0A79B6AB; Sat, 25 Feb 2017 10:38:19 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v1PAcJPY090201; Sat, 25 Feb 2017 10:38:19 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v1PAcIwH090194; Sat, 25 Feb 2017 10:38:18 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201702251038.v1PAcIwH090194@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Sat, 25 Feb 2017 10:38:18 +0000 (UTC) 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 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 25 Feb 2017 10:38:20 -0000 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 -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); + } } /*