svn commit: r301996 - in head/sys: kern sys
Konstantin Belousov
kib at FreeBSD.org
Fri Jun 17 17:33:27 UTC 2016
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 *);
More information about the svn-src-all
mailing list