From owner-cvs-src@FreeBSD.ORG Sun Jul 4 08:52:36 2004 Return-Path: Delivered-To: cvs-src@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id BD86316A4CE; Sun, 4 Jul 2004 08:52:36 +0000 (GMT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id A2B1F43D3F; Sun, 4 Jul 2004 08:52:36 +0000 (GMT) (envelope-from phk@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.11/8.12.11) with ESMTP id i648qaJN035712; Sun, 4 Jul 2004 08:52:36 GMT (envelope-from phk@repoman.freebsd.org) Received: (from phk@localhost) by repoman.freebsd.org (8.12.11/8.12.11/Submit) id i648qa9w035711; Sun, 4 Jul 2004 08:52:36 GMT (envelope-from phk) Message-Id: <200407040852.i648qa9w035711@repoman.freebsd.org> From: Poul-Henning Kamp Date: Sun, 4 Jul 2004 08:52:36 +0000 (UTC) To: src-committers@FreeBSD.org, cvs-src@FreeBSD.org, cvs-all@FreeBSD.org X-FreeBSD-CVS-Branch: HEAD Subject: cvs commit: src/sys/coda coda_subr.c src/sys/fs/msdosfs msdosfs_vfsops.c src/sys/gnu/ext2fs ext2_vfsops.c src/sys/kern vfs_default.c vfs_mount.c vfs_subr.c src/sys/nfs4client nfs4_vfsops.c src/sys/nfsclient nfs_subs.c nfs_vfsops.c ... X-BeenThere: cvs-src@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: CVS commit messages for the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 04 Jul 2004 08:52:37 -0000 phk 2004-07-04 08:52:36 UTC FreeBSD src repository Modified files: sys/coda coda_subr.c sys/fs/msdosfs msdosfs_vfsops.c sys/gnu/ext2fs ext2_vfsops.c sys/kern vfs_default.c vfs_mount.c vfs_subr.c sys/nfs4client nfs4_vfsops.c sys/nfsclient nfs_subs.c nfs_vfsops.c sys/sys mount.h sys/ufs/ffs ffs_snapshot.c ffs_vfsops.c sys/ufs/ufs ufs_quota.c Log: When we traverse the vnodes on a mountpoint we need to look out for our cached 'next vnode' being removed from this mountpoint. If we find that it was recycled, we restart our traversal from the start of the list. Code to do that is in all local disk filesystems (and a few other places) and looks roughly like this: MNT_ILOCK(mp); loop: for (vp = TAILQ_FIRST(&mp...); (vp = nvp) != NULL; nvp = TAILQ_NEXT(vp,...)) { if (vp->v_mount != mp) goto loop; MNT_IUNLOCK(mp); ... MNT_ILOCK(mp); } MNT_IUNLOCK(mp); The code which takes vnodes off a mountpoint looks like this: MNT_ILOCK(vp->v_mount); ... TAILQ_REMOVE(&vp->v_mount->mnt_nvnodelist, vp, v_nmntvnodes); ... MNT_IUNLOCK(vp->v_mount); ... vp->v_mount = something; (Take a moment and try to spot the locking error before you read on.) On a SMP system, one CPU could have removed nvp from our mountlist but not yet gotten to assign a new value to vp->v_mount while another CPU simultaneously get to the top of the traversal loop where it finds that (vp->v_mount != mp) is not true despite the fact that the vnode has indeed been removed from our mountpoint. Fix: Introduce the macro MNT_VNODE_FOREACH() to traverse the list of vnodes on a mountpoint while taking into account that vnodes may be removed from the list as we go. This saves approx 65 lines of duplicated code. Split the insmntque() which potentially moves a vnode from one mount point to another into delmntque() and insmntque() which does just what the names say. Fix delmntque() to set vp->v_mount to NULL while holding the mountpoint lock. Revision Changes Path 1.29 +2 -5 src/sys/coda/coda_subr.c 1.122 +1 -9 src/sys/fs/msdosfs/msdosfs_vfsops.c 1.123 +2 -14 src/sys/gnu/ext2fs/ext2_vfsops.c 1.94 +1 -9 src/sys/kern/vfs_default.c 1.130 +27 -0 src/sys/kern/vfs_mount.c 1.496 +35 -38 src/sys/kern/vfs_subr.c 1.7 +2 -11 src/sys/nfs4client/nfs4_vfsops.c 1.130 +1 -5 src/sys/nfsclient/nfs_subs.c 1.150 +2 -11 src/sys/nfsclient/nfs_vfsops.c 1.163 +6 -0 src/sys/sys/mount.h 1.83 +1 -8 src/sys/ufs/ffs/ffs_snapshot.c 1.234 +2 -17 src/sys/ufs/ffs/ffs_vfsops.c 1.72 +6 -22 src/sys/ufs/ufs/ufs_quota.c