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 *);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to