Author: smh
Date: Tue Apr  9 15:35:26 2013
New Revision: 249310
URL: http://svnweb.freebsd.org/changeset/base/249310

Log:
  MFC r241556:
  Add a KPI to allow to reserve some amount of space in the numvnodes
  counter, without actually allocating the vnodes.
  
  For KBI stability, the td_vp_reserv was moved to the end of struct thread.
  
  Reviewed by:  avg
  Approved by:  avg (co-mentor)

Modified:
  stable/8/sys/kern/kern_thread.c
  stable/8/sys/kern/subr_trap.c
  stable/8/sys/kern/vfs_subr.c
  stable/8/sys/sys/proc.h
  stable/8/sys/sys/vnode.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/kern/   (props changed)
  stable/8/sys/sys/   (props changed)

Modified: stable/8/sys/kern/kern_thread.c
==============================================================================
--- stable/8/sys/kern/kern_thread.c     Tue Apr  9 15:15:52 2013        
(r249309)
+++ stable/8/sys/kern/kern_thread.c     Tue Apr  9 15:35:26 2013        
(r249310)
@@ -159,6 +159,7 @@ thread_init(void *mem, int size, int fla
 
        td->td_sleepqueue = sleepq_alloc();
        td->td_turnstile = turnstile_alloc();
+       td->td_vp_reserv = 0;
        EVENTHANDLER_INVOKE(thread_init, td);
        td->td_sched = (struct td_sched *)&td[1];
        umtx_thread_init(td);

Modified: stable/8/sys/kern/subr_trap.c
==============================================================================
--- stable/8/sys/kern/subr_trap.c       Tue Apr  9 15:15:52 2013        
(r249309)
+++ stable/8/sys/kern/subr_trap.c       Tue Apr  9 15:35:26 2013        
(r249310)
@@ -132,6 +132,8 @@ userret(struct thread *td, struct trapfr
        sched_userret(td);
        KASSERT(td->td_locks == 0,
            ("userret: Returning with %d locks held.", td->td_locks));
+       KASSERT(td->td_vp_reserv == 0,
+           ("userret: Returning while holding vnode reservation"));
 #ifdef VIMAGE
        /* Unfortunately td_vnet_lpush needs VNET_DEBUG. */
        VNET_ASSERT(curvnet == NULL,

Modified: stable/8/sys/kern/vfs_subr.c
==============================================================================
--- stable/8/sys/kern/vfs_subr.c        Tue Apr  9 15:15:52 2013        
(r249309)
+++ stable/8/sys/kern/vfs_subr.c        Tue Apr  9 15:35:26 2013        
(r249310)
@@ -977,34 +977,22 @@ vtryrecycle(struct vnode *vp)
 }
 
 /*
- * Return the next vnode from the free list.
+ * Wait for available vnodes.
  */
-int
-getnewvnode(const char *tag, struct mount *mp, struct vop_vector *vops,
-    struct vnode **vpp)
+static int
+getnewvnode_wait(int suspended)
 {
-       struct vnode *vp = NULL;
-       struct bufobj *bo;
 
-       CTR3(KTR_VFS, "%s: mp %p with tag %s", __func__, mp, tag);
-       mtx_lock(&vnode_free_list_mtx);
-       /*
-        * Lend our context to reclaim vnodes if they've exceeded the max.
-        */
-       if (freevnodes > wantfreevnodes)
-               vnlru_free(1);
-       /*
-        * Wait for available vnodes.
-        */
+       mtx_assert(&vnode_free_list_mtx, MA_OWNED);
        if (numvnodes > desiredvnodes) {
-               if (mp != NULL && (mp->mnt_kern_flag & MNTK_SUSPEND)) {
+               if (suspended) {
                        /*
                         * File system is beeing suspended, we cannot risk a
                         * deadlock here, so allocate new vnode anyway.
                         */
                        if (freevnodes > wantfreevnodes)
                                vnlru_free(freevnodes - wantfreevnodes);
-                       goto alloc;
+                       return (0);
                }
                if (vnlruproc_sig == 0) {
                        vnlruproc_sig = 1;      /* avoid unnecessary wakeups */
@@ -1012,16 +1000,76 @@ getnewvnode(const char *tag, struct moun
                }
                msleep(&vnlruproc_sig, &vnode_free_list_mtx, PVFS,
                    "vlruwk", hz);
-#if 0  /* XXX Not all VFS_VGET/ffs_vget callers check returns. */
-               if (numvnodes > desiredvnodes) {
-                       mtx_unlock(&vnode_free_list_mtx);
-                       return (ENFILE);
+       }
+       return (numvnodes > desiredvnodes ? ENFILE : 0);
+}
+
+void
+getnewvnode_reserve(u_int count)
+{
+       struct thread *td;
+
+       td = curthread;
+       mtx_lock(&vnode_free_list_mtx);
+       while (count > 0) {
+               if (getnewvnode_wait(0) == 0) {
+                       count--;
+                       td->td_vp_reserv++;
+                       numvnodes++;
                }
-#endif
        }
-alloc:
+       mtx_unlock(&vnode_free_list_mtx);
+}
+
+void
+getnewvnode_drop_reserve(void)
+{
+       struct thread *td;
+
+       td = curthread;
+       mtx_lock(&vnode_free_list_mtx);
+       KASSERT(numvnodes >= td->td_vp_reserv, ("reserve too large"));
+       numvnodes -= td->td_vp_reserv;
+       mtx_unlock(&vnode_free_list_mtx);
+       td->td_vp_reserv = 0;
+}
+
+/*
+ * Return the next vnode from the free list.
+ */
+int
+getnewvnode(const char *tag, struct mount *mp, struct vop_vector *vops,
+    struct vnode **vpp)
+{
+       struct vnode *vp;
+       struct bufobj *bo;
+       struct thread *td;
+       int error;
+
+       CTR3(KTR_VFS, "%s: mp %p with tag %s", __func__, mp, tag);
+       vp = NULL;
+       td = curthread;
+       if (td->td_vp_reserv > 0) {
+               td->td_vp_reserv -= 1;
+               goto alloc;
+       }
+       mtx_lock(&vnode_free_list_mtx);
+       /*
+        * Lend our context to reclaim vnodes if they've exceeded the max.
+        */
+       if (freevnodes > wantfreevnodes)
+               vnlru_free(1);
+       error = getnewvnode_wait(mp != NULL && (mp->mnt_kern_flag &
+           MNTK_SUSPEND));
+#if 0  /* XXX Not all VFS_VGET/ffs_vget callers check returns. */
+       if (error != 0) {
+               mtx_unlock(&vnode_free_list_mtx);
+               return (error);
+       }
+#endif
        numvnodes++;
        mtx_unlock(&vnode_free_list_mtx);
+alloc:
        vp = (struct vnode *) uma_zalloc(vnode_zone, M_WAITOK|M_ZERO);
        /*
         * Setup locks.

Modified: stable/8/sys/sys/proc.h
==============================================================================
--- stable/8/sys/sys/proc.h     Tue Apr  9 15:15:52 2013        (r249309)
+++ stable/8/sys/sys/proc.h     Tue Apr  9 15:35:26 2013        (r249310)
@@ -308,6 +308,7 @@ struct thread {
        struct rusage_ext td_rux;       /* (t) Internal rusage information. */
        struct vm_map_entry *td_map_def_user; /* (k) Deferred entries. */
        pid_t           td_dbg_forked;  /* (c) Child pid for debugger. */
+       u_int           td_vp_reserv;   /* (k) Count of reserved vnodes. */
 };
 
 struct mtx *thread_lock_block(struct thread *);

Modified: stable/8/sys/sys/vnode.h
==============================================================================
--- stable/8/sys/sys/vnode.h    Tue Apr  9 15:15:52 2013        (r249309)
+++ stable/8/sys/sys/vnode.h    Tue Apr  9 15:35:26 2013        (r249310)
@@ -604,6 +604,8 @@ void        cvtstat(struct stat *st, struct ost
 void   cvtnstat(struct stat *sb, struct nstat *nsb);
 int    getnewvnode(const char *tag, struct mount *mp, struct vop_vector *vops,
            struct vnode **vpp);
+void   getnewvnode_reserve(u_int count);
+void   getnewvnode_drop_reserve(void);
 int    insmntque1(struct vnode *vp, struct mount *mp,
            void (*dtr)(struct vnode *, void *), void *dtr_arg);
 int    insmntque(struct vnode *vp, struct mount *mp);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to