Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Nov 2004 10:01:28 -0800 (PST)
From:      Matthew Dillon <dillon@apollo.backplane.com>
To:        freebsd-hackers@freebsd.org
Subject:   bugs in contigmalloc*() related to "page not found in hash" panics
Message-ID:  <200411101801.iAAI1SkK061883@apollo.backplane.com>

next in thread | raw e-mail | index | archive | help
    I've tracked down several bugs in contigmalloc*() in DragonFly based on
    kernel cores provided by David Rhodus.  These bugs have just been addressed
    in DFly but also need to be addressed in FreeBSD-4, and at least some
    work must also be done in FreeBSD-5/6.  So someone needs to take up 
    the ball and deal with this in FreeBSD.

    Here is the DragonFly commit.

    http://www.dragonflybsd.org/cvsweb/src/sys/vm/vm_contig.c.diff?r1=1.10&r2=1.11&f=u

    FreeBSD-4:

	FreeBSD-4 is in the same situation that DFly was in and requires the
	same fixes as the above patch, though note that in FreeBSD-4 the
	contigmalloc() code is in vm_page.c, not vm_contig.c.

    FreeBSD-5/6:

	FreeBSD-5/6 may also has issues, though it is likely that they are
	masked by later checks done in FreeBSD-5/6's contigmalloc code.

	The main issue is the attempt to reuse a PQ_CACHE page by 
	unconditionally vm_page_free()ing it without checking to see if 
	it is held, busied, or anything else.   This sounds a bit dangerous
	to me since vm_page_select_cache() does NOT do this.

	I recommend that FreeBSD-5/6's contigmalloc code be adjusted similar
	to vm_page_select_cache() and not try to free cache pages which
	are held or busied or otherwise in a weird state.

	FreeBSD-5/6 *DOES* recheck that the pages are PQ_FREE before it 
	actually reallocates them, and this may be its saving grace (since
	vm_page_free() might have moved the page to PQ_HOLD this recheck
	should catch the incorrect cache->free cases).  But it is unclear
	whether the PQ_CACHE  -> vm_page_free() code above was itself safe
	so it may be better to be safe then sorry.

	You also need to replace the unconditional 'm->object = NULL' with
	an assertion that m->object is already NULL, because if m->object
	isn't NULL it means that the page is in the VM page bucket hash table
	and NULLing out the object is guarenteed to corrupt the hash table.

    Note in particular the symptoms of the contigmalloc() problem:

    * "page not found in hash" panics (due to VM bucket hash table corruption).

    * Memory corruption, particularly filesystem corruption since those are
      the most likely pages to be in a held state while on the free list.
      Due to a page being reused before it is reusable.

    If you have either of these two symptoms in FreeBSD-5/6 then you need
    to take a very close look at your contigmalloc() code, even if you think
    it is correct.

					-Matt
					Matthew Dillon 
					<dillon@backplane.com>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200411101801.iAAI1SkK061883>