Date: Fri, 23 Aug 2013 17:27:13 +0000 (UTC) From: Alan Cox <alc@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r254719 - head/sys/vm Message-ID: <201308231727.r7NHRDUI077451@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: alc Date: Fri Aug 23 17:27:12 2013 New Revision: 254719 URL: http://svnweb.freebsd.org/changeset/base/254719 Log: Addendum to r254141: The call to vm_radix_insert() in vm_page_cache() can reclaim the last preexisting cached page in the object, resulting in a call to vdrop(). Detect this scenario so that the vnode's hold count is correctly maintained. Otherwise, we panic. Reported by: scottl Tested by: pho Discussed with: attilio, jeff, kib Modified: head/sys/vm/vm_page.c head/sys/vm/vm_radix.c head/sys/vm/vm_radix.h Modified: head/sys/vm/vm_page.c ============================================================================== --- head/sys/vm/vm_page.c Fri Aug 23 17:03:43 2013 (r254718) +++ head/sys/vm/vm_page.c Fri Aug 23 17:27:12 2013 (r254719) @@ -2558,6 +2558,15 @@ vm_page_cache(vm_page_t m) vm_page_free(m); return; } + + /* + * The above call to vm_radix_insert() could reclaim the one pre- + * existing cached page from this object, resulting in a call to + * vdrop(). + */ + if (!cache_was_empty) + cache_was_empty = vm_radix_is_singleton(&object->cache); + m->flags |= PG_CACHED; cnt.v_cache_count++; PCPU_INC(cnt.v_tcached); Modified: head/sys/vm/vm_radix.c ============================================================================== --- head/sys/vm/vm_radix.c Fri Aug 23 17:03:43 2013 (r254718) +++ head/sys/vm/vm_radix.c Fri Aug 23 17:27:12 2013 (r254719) @@ -432,6 +432,21 @@ restart: } /* + * Returns TRUE if the specified radix tree contains a single leaf and FALSE + * otherwise. + */ +boolean_t +vm_radix_is_singleton(struct vm_radix *rtree) +{ + struct vm_radix_node *rnode; + + rnode = vm_radix_getroot(rtree); + if (rnode == NULL) + return (FALSE); + return (vm_radix_isleaf(rnode)); +} + +/* * Returns the value stored at the index. If the index is not present, * NULL is returned. */ Modified: head/sys/vm/vm_radix.h ============================================================================== --- head/sys/vm/vm_radix.h Fri Aug 23 17:03:43 2013 (r254718) +++ head/sys/vm/vm_radix.h Fri Aug 23 17:27:12 2013 (r254719) @@ -37,6 +37,7 @@ void vm_radix_init(void); int vm_radix_insert(struct vm_radix *rtree, vm_page_t page); +boolean_t vm_radix_is_singleton(struct vm_radix *rtree); vm_page_t vm_radix_lookup(struct vm_radix *rtree, vm_pindex_t index); vm_page_t vm_radix_lookup_ge(struct vm_radix *rtree, vm_pindex_t index); vm_page_t vm_radix_lookup_le(struct vm_radix *rtree, vm_pindex_t index);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201308231727.r7NHRDUI077451>