Date: Fri, 17 Jun 2016 17:33:25 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r301996 - in head/sys: kern sys Message-ID: <201606171733.u5HHXPCt005753@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Fri Jun 17 17:33:25 2016 New Revision: 301996 URL: https://svnweb.freebsd.org/changeset/base/301996 Log: Add VFS interface to flush specified amount of free vnodes belonging to mount points with the given filesystem type, specified by mount vfs_ops pointer. Based on patch by: mckusick Reviewed by: avg, mckusick Tested by: allanjude, madpilot Sponsored by: The FreeBSD Foundation Approved by: re (gjb) Modified: head/sys/kern/vfs_subr.c head/sys/sys/vnode.h Modified: head/sys/kern/vfs_subr.c ============================================================================== --- head/sys/kern/vfs_subr.c Fri Jun 17 17:09:22 2016 (r301995) +++ head/sys/kern/vfs_subr.c Fri Jun 17 17:33:25 2016 (r301996) @@ -107,7 +107,6 @@ static void v_incr_usecount(struct vnode static void v_incr_usecount_locked(struct vnode *); static void v_incr_devcount(struct vnode *); static void v_decr_devcount(struct vnode *); -static void vnlru_free(int); static void vgonel(struct vnode *); static void vfs_knllock(void *arg); static void vfs_knlunlock(void *arg); @@ -942,15 +941,23 @@ relock_mnt: return done; } +static int max_vnlru_free = 10000; /* limit on vnode free requests per call */ +SYSCTL_INT(_debug, OID_AUTO, max_vnlru_free, CTLFLAG_RW, &max_vnlru_free, + 0, + "limit on vnode free requests per call to the vnlru_free routine"); + /* * Attempt to reduce the free list by the requested amount. */ static void -vnlru_free(int count) +vnlru_free_locked(int count, struct vfsops *mnt_op) { struct vnode *vp; + struct mount *mp; mtx_assert(&vnode_free_list_mtx, MA_OWNED); + if (count > max_vnlru_free) + count = max_vnlru_free; for (; count > 0; count--) { vp = TAILQ_FIRST(&vnode_free_list); /* @@ -966,10 +973,17 @@ vnlru_free(int count) KASSERT((vp->v_iflag & VI_ACTIVE) == 0, ("Mangling active vnode")); TAILQ_REMOVE(&vnode_free_list, vp, v_actfreelist); + /* - * Don't recycle if we can't get the interlock. + * Don't recycle if our vnode is from different type + * of mount point. Note that mp is type-safe, the + * check does not reach unmapped address even if + * vnode is reclaimed. + * Don't recycle if we can't get the interlock without + * blocking. */ - if (!VI_TRYLOCK(vp)) { + if ((mnt_op != NULL && (mp = vp->v_mount) != NULL && + mp->mnt_op != mnt_op) || !VI_TRYLOCK(vp)) { TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_actfreelist); continue; } @@ -1001,6 +1015,16 @@ vnlru_free(int count) } } +void +vnlru_free(int count, struct vfsops *mnt_op) +{ + + mtx_lock(&vnode_free_list_mtx); + vnlru_free_locked(count, mnt_op); + mtx_unlock(&vnode_free_list_mtx); +} + + /* XXX some names and initialization are bad for limits and watermarks. */ static int vspace(void) @@ -1046,8 +1070,8 @@ vnlru_proc(void) * try to reduce it by discarding from the free list. */ if (numvnodes > desiredvnodes && freevnodes > 0) - vnlru_free(ulmin(numvnodes - desiredvnodes, - freevnodes)); + vnlru_free_locked(ulmin(numvnodes - desiredvnodes, + freevnodes), NULL); /* * Sleep if the vnode cache is in a good state. This is * when it is not over-full and has space for about a 4% @@ -1237,7 +1261,7 @@ getnewvnode_wait(int suspended) } /* Post-adjust like the pre-adjust in getnewvnode(). */ if (numvnodes + 1 > desiredvnodes && freevnodes > 1) - vnlru_free(1); + vnlru_free_locked(1, NULL); return (numvnodes >= desiredvnodes ? ENFILE : 0); } @@ -1254,8 +1278,8 @@ getnewvnode_reserve(u_int count) /* XXX no longer so quick, but this part is not racy. */ mtx_lock(&vnode_free_list_mtx); if (numvnodes + count > desiredvnodes && freevnodes > wantfreevnodes) - vnlru_free(ulmin(numvnodes + count - desiredvnodes, - freevnodes - wantfreevnodes)); + vnlru_free_locked(ulmin(numvnodes + count - desiredvnodes, + freevnodes - wantfreevnodes), NULL); mtx_unlock(&vnode_free_list_mtx); td = curthread; @@ -1337,7 +1361,7 @@ getnewvnode(const char *tag, struct moun if (numvnodes + 1 <= desiredvnodes) ; else if (freevnodes > 0) - vnlru_free(1); + vnlru_free_locked(1, NULL); else { error = getnewvnode_wait(mp != NULL && (mp->mnt_kern_flag & MNTK_SUSPEND)); Modified: head/sys/sys/vnode.h ============================================================================== --- head/sys/sys/vnode.h Fri Jun 17 17:09:22 2016 (r301995) +++ head/sys/sys/vnode.h Fri Jun 17 17:33:25 2016 (r301996) @@ -603,6 +603,7 @@ struct nstat; struct ucred; struct uio; struct vattr; +struct vfsops; struct vnode; typedef int (*vn_get_ino_t)(struct mount *, void *, int, struct vnode **); @@ -738,6 +739,7 @@ void vfs_timestamp(struct timespec *); void vfs_write_resume(struct mount *mp, int flags); int vfs_write_suspend(struct mount *mp, int flags); int vfs_write_suspend_umnt(struct mount *mp); +void vnlru_free(int, struct vfsops *); int vop_stdbmap(struct vop_bmap_args *); int vop_stdfsync(struct vop_fsync_args *); int vop_stdgetwritemount(struct vop_getwritemount_args *);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201606171733.u5HHXPCt005753>