svn commit: r249310 - in stable/8/sys: kern sys
Steven Hartland
smh at FreeBSD.org
Tue Apr 9 15:35:28 UTC 2013
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);
More information about the svn-src-stable-8
mailing list