Date: Wed, 1 Jul 2015 06:54:26 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r284993 - in stable/10/sys: kern ufs/ffs Message-ID: <201507010654.t616sQXT028048@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Wed Jul 1 06:54:25 2015 New Revision: 284993 URL: https://svnweb.freebsd.org/changeset/base/284993 Log: MFC r284495: Keep a vnode which is freed but still owing inactivation, on the active list. This closes a race where such vnode is not msync-ed until reboot. Modified: stable/10/sys/kern/vfs_subr.c stable/10/sys/ufs/ffs/ffs_vfsops.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/kern/vfs_subr.c ============================================================================== --- stable/10/sys/kern/vfs_subr.c Wed Jul 1 03:49:35 2015 (r284992) +++ stable/10/sys/kern/vfs_subr.c Wed Jul 1 06:54:25 2015 (r284993) @@ -173,6 +173,11 @@ static int reassignbufcalls; SYSCTL_INT(_vfs, OID_AUTO, reassignbufcalls, CTLFLAG_RW, &reassignbufcalls, 0, "Number of calls to reassignbuf"); +static u_long free_owe_inact; +SYSCTL_ULONG(_vfs, OID_AUTO, free_owe_inact, CTLFLAG_RD, &free_owe_inact, 0, + "Number of times free vnodes kept on active list due to VFS " + "owing inactivation"); + /* * Cache for the mount type id assigned to NFS. This is used for * special checks in nfs/nfs_nqlease.c and vm/vnode_pager.c. @@ -2361,11 +2366,8 @@ vholdl(struct vnode *vp) CTR2(KTR_VFS, "%s: vp %p", __func__, vp); #ifdef INVARIANTS /* getnewvnode() calls v_incr_usecount() without holding interlock. */ - if (vp->v_type != VNON || vp->v_data != NULL) { + if (vp->v_type != VNON || vp->v_data != NULL) ASSERT_VI_LOCKED(vp, "vholdl"); - VNASSERT(vp->v_holdcnt > 0 || (vp->v_iflag & VI_FREE) != 0, - vp, ("vholdl: free vnode is held")); - } #endif vp->v_holdcnt++; if ((vp->v_iflag & VI_FREE) == 0) @@ -2434,23 +2436,29 @@ vdropl(struct vnode *vp) VNASSERT(vp->v_holdcnt == 0, vp, ("vdropl: freeing when we shouldn't")); active = vp->v_iflag & VI_ACTIVE; - vp->v_iflag &= ~VI_ACTIVE; - mp = vp->v_mount; - mtx_lock(&vnode_free_list_mtx); - if (active) { - TAILQ_REMOVE(&mp->mnt_activevnodelist, vp, - v_actfreelist); - mp->mnt_activevnodelistsize--; - } - if (vp->v_iflag & VI_AGE) { - TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_actfreelist); + if ((vp->v_iflag & VI_OWEINACT) == 0) { + vp->v_iflag &= ~VI_ACTIVE; + mp = vp->v_mount; + mtx_lock(&vnode_free_list_mtx); + if (active) { + TAILQ_REMOVE(&mp->mnt_activevnodelist, vp, + v_actfreelist); + mp->mnt_activevnodelistsize--; + } + if (vp->v_iflag & VI_AGE) { + TAILQ_INSERT_HEAD(&vnode_free_list, vp, + v_actfreelist); + } else { + TAILQ_INSERT_TAIL(&vnode_free_list, vp, + v_actfreelist); + } + freevnodes++; + vp->v_iflag &= ~VI_AGE; + vp->v_iflag |= VI_FREE; + mtx_unlock(&vnode_free_list_mtx); } else { - TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_actfreelist); + atomic_add_long(&free_owe_inact, 1); } - freevnodes++; - vp->v_iflag &= ~VI_AGE; - vp->v_iflag |= VI_FREE; - mtx_unlock(&vnode_free_list_mtx); VI_UNLOCK(vp); return; } Modified: stable/10/sys/ufs/ffs/ffs_vfsops.c ============================================================================== --- stable/10/sys/ufs/ffs/ffs_vfsops.c Wed Jul 1 03:49:35 2015 (r284992) +++ stable/10/sys/ufs/ffs/ffs_vfsops.c Wed Jul 1 06:54:25 2015 (r284993) @@ -1409,6 +1409,14 @@ ffs_statfs(mp, sbp) return (0); } +static bool +sync_doupdate(struct inode *ip) +{ + + return ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | + IN_UPDATE)) != 0); +} + /* * For a lazy sync, we only care about access times, quotas and the * superblock. Other filesystem changes are already converted to @@ -1442,15 +1450,15 @@ ffs_sync_lazy(mp) * Test also all the other timestamp flags too, to pick up * any other cases that could be missed. */ - if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | - IN_UPDATE)) == 0) { + if (!sync_doupdate(ip) && (vp->v_iflag & VI_OWEINACT) == 0) { VI_UNLOCK(vp); continue; } if ((error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, td)) != 0) continue; - error = ffs_update(vp, 0); + if (sync_doupdate(ip)) + error = ffs_update(vp, 0); if (error != 0) allerror = error; vput(vp);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201507010654.t616sQXT028048>