Date: Sun, 21 Oct 2012 12:33:38 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r241812 - in stable/9/sys: kern sys Message-ID: <201210211233.q9LCXcu2075717@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Sun Oct 21 12:33:38 2012 New Revision: 241812 URL: http://svn.freebsd.org/changeset/base/241812 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. Modified: stable/9/sys/kern/kern_thread.c stable/9/sys/kern/subr_trap.c stable/9/sys/kern/vfs_subr.c stable/9/sys/sys/proc.h stable/9/sys/sys/vnode.h Directory Properties: stable/9/sys/ (props changed) Modified: stable/9/sys/kern/kern_thread.c ============================================================================== --- stable/9/sys/kern/kern_thread.c Sun Oct 21 12:17:22 2012 (r241811) +++ stable/9/sys/kern/kern_thread.c Sun Oct 21 12:33:38 2012 (r241812) @@ -207,6 +207,7 @@ thread_init(void *mem, int size, int fla td->td_sleepqueue = sleepq_alloc(); td->td_turnstile = turnstile_alloc(); td->td_rlqe = NULL; + td->td_vp_reserv = 0; EVENTHANDLER_INVOKE(thread_init, td); td->td_sched = (struct td_sched *)&td[1]; umtx_thread_init(td); Modified: stable/9/sys/kern/subr_trap.c ============================================================================== --- stable/9/sys/kern/subr_trap.c Sun Oct 21 12:17:22 2012 (r241811) +++ stable/9/sys/kern/subr_trap.c Sun Oct 21 12:33:38 2012 (r241812) @@ -139,6 +139,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/9/sys/kern/vfs_subr.c ============================================================================== --- stable/9/sys/kern/vfs_subr.c Sun Oct 21 12:17:22 2012 (r241811) +++ stable/9/sys/kern/vfs_subr.c Sun Oct 21 12:33:38 2012 (r241812) @@ -935,34 +935,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 */ @@ -970,16 +958,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/9/sys/sys/proc.h ============================================================================== --- stable/9/sys/sys/proc.h Sun Oct 21 12:17:22 2012 (r241811) +++ stable/9/sys/sys/proc.h Sun Oct 21 12:33:38 2012 (r241812) @@ -316,6 +316,7 @@ struct thread { struct vm_page **td_ma; /* (k) uio pages held */ int td_ma_cnt; /* (k) size of *td_ma */ struct rl_q_entry *td_rlqe; /* (k) Associated range lock entry. */ + u_int td_vp_reserv; /* (k) Count of reserved vnodes. */ }; struct mtx *thread_lock_block(struct thread *); Modified: stable/9/sys/sys/vnode.h ============================================================================== --- stable/9/sys/sys/vnode.h Sun Oct 21 12:17:22 2012 (r241811) +++ stable/9/sys/sys/vnode.h Sun Oct 21 12:33:38 2012 (r241812) @@ -603,6 +603,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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201210211233.q9LCXcu2075717>