From owner-svn-src-all@freebsd.org Wed Nov 2 09:43:21 2016 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 0AAD4C2A005; Wed, 2 Nov 2016 09:43:21 +0000 (UTC) (envelope-from trasz@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 AE7161CF8; Wed, 2 Nov 2016 09:43:20 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id uA29hJdf033035; Wed, 2 Nov 2016 09:43:19 GMT (envelope-from trasz@FreeBSD.org) Received: (from trasz@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id uA29hJda033034; Wed, 2 Nov 2016 09:43:19 GMT (envelope-from trasz@FreeBSD.org) Message-Id: <201611020943.uA29hJda033034@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: trasz set sender to trasz@FreeBSD.org using -f From: Edward Tomasz Napierala Date: Wed, 2 Nov 2016 09:43:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r308209 - head/sys/kern 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: Wed, 02 Nov 2016 09:43:21 -0000 Author: trasz Date: Wed Nov 2 09:43:19 2016 New Revision: 308209 URL: https://svnweb.freebsd.org/changeset/base/308209 Log: Fix getfsstat(2) with MNT_WAIT to not skip filesystems that are in the process of being unmounted. Previously it would skip them, even if the unmount eventually failed eg due to the filesystem being busy. This behaviour broke autounmountd(8) - if you tried to manually unmount a mounted filesystem, using 'automount -u', and the autounmountd attempted to refresh the filesystem list in that very moment, it would conclude that the filesystem got unmounted and not try to unmount it afterwards. Reviewed by: kib@ Tested by: pho@ MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D8030 Modified: head/sys/kern/vfs_syscalls.c Modified: head/sys/kern/vfs_syscalls.c ============================================================================== --- head/sys/kern/vfs_syscalls.c Wed Nov 2 08:46:04 2016 (r308208) +++ head/sys/kern/vfs_syscalls.c Wed Nov 2 09:43:19 2016 (r308209) @@ -446,16 +446,19 @@ kern_getfsstat(struct thread *td, struct size_t *countp, enum uio_seg bufseg, int flags) { struct mount *mp, *nmp; - struct statfs *sfsp, *sp, sb; + struct statfs *sfsp, *sp, sb, *tofree; size_t count, maxcount; int error; +restart: maxcount = bufsize / sizeof(struct statfs); - if (bufsize == 0) + if (bufsize == 0) { sfsp = NULL; - else if (bufseg == UIO_USERSPACE) + tofree = NULL; + } else if (bufseg == UIO_USERSPACE) { sfsp = *buf; - else /* if (bufseg == UIO_SYSSPACE) */ { + tofree = NULL; + } else /* if (bufseg == UIO_SYSSPACE) */ { count = 0; mtx_lock(&mountlist_mtx); TAILQ_FOREACH(mp, &mountlist, mnt_list) { @@ -464,8 +467,8 @@ kern_getfsstat(struct thread *td, struct mtx_unlock(&mountlist_mtx); if (maxcount > count) maxcount = count; - sfsp = *buf = malloc(maxcount * sizeof(struct statfs), M_TEMP, - M_WAITOK); + tofree = sfsp = *buf = malloc(maxcount * sizeof(struct statfs), + M_TEMP, M_WAITOK); } count = 0; mtx_lock(&mountlist_mtx); @@ -480,9 +483,24 @@ kern_getfsstat(struct thread *td, struct continue; } #endif - if (vfs_busy(mp, MBF_NOWAIT | MBF_MNTLSTLOCK)) { - nmp = TAILQ_NEXT(mp, mnt_list); - continue; + if (flags == MNT_WAIT) { + if (vfs_busy(mp, MBF_MNTLSTLOCK) != 0) { + /* + * If vfs_busy() failed, and MBF_NOWAIT + * wasn't passed, then the mp is gone. + * Furthermore, because of MBF_MNTLSTLOCK, + * the mountlist_mtx was dropped. We have + * no other choice than to start over. + */ + mtx_unlock(&mountlist_mtx); + free(tofree, M_TEMP); + goto restart; + } + } else { + if (vfs_busy(mp, MBF_NOWAIT | MBF_MNTLSTLOCK) != 0) { + nmp = TAILQ_NEXT(mp, mnt_list); + continue; + } } if (sfsp && count < maxcount) { sp = &mp->mnt_stat;