Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 25 Feb 1999 10:46:19 -0800 (PST)
From:      Matthew Dillon <dillon@apollo.backplane.com>
To:        Luoqi Chen <luoqi@watermarkgroup.com>
Cc:        dfr@nlsystems.com, freebsd-hackers@FreeBSD.ORG, luoqi@watermarkgroup.com, mjacob@feral.com
Subject:   Re: Panic in FFS/4.0 as of yesterday - update
Message-ID:  <199902251846.KAA07913@apollo.backplane.com>
References:   <199902251343.IAA26707@lor.watermarkgroup.com>

next in thread | previous in thread | raw e-mail | index | archive | help
:There seems to be a problem with buffer kva space accounting: buffer_map
:is allocated with nbuf*BKVASIZE amount of kva space, but maxbufspace is
:only initialized to (nbuf+8)*DFLTBSIZE, that means half of the kva space
:will not be utilized (DFLTBSIZE=4096 BKVASIZE=8192)??? Maybe this is why
:getblk() didn't block on numfreebuffers and instead thought kva space was
:out and started to flush the B_DELWRI buffers.

    I noticed that too, but it wasn't the cause of my lockup.   If I understand
    the buffer cache, other entities use the buffer KVA space too, not just
    the primary buffer cache.  There is also the getpbuf() pool.

:>     At the moment, getnewbuf() attempts to convert B_DELWRI buffers into
:>     async writes in order to push them out.  This is what leads to the
:>     recursion problem.  I don't think we can afford to recurse even once,
:>     therefore we cannot push out B_DELWRI buffers in getnewbuf().  At all.
:> 
:The recurse doesn't seem to be avoidable though, if we have any kind of
:layered fs. We recurse either with getnewbuf() caller's stack or with
:syncer's stack.

    Not exactly.  The getnewbuf() recursion occurs because getnewbuf() calls
    an asynch-write which then, due to the VFS layering, calls getnewbuf()
    again.  getnewbuf() then calls a asynch-write for a totally unrelated
    buffer that also has VFS layering an the whole thing repeats.

    If getnewbuf() lets the syncer start the async I/O, getnewbuf() simply
    blocks in the calling process.  There is no recursion.

    Of course, the syncer may indirectly call getnewbuf() as well, which is
    why getnewbuf() needs to be able to allocate out of an emergency reserve 
    ( < lonumfreebuffers ) - in order to guarentee that if it *does* block,
    there are enough writes in progress to clear out some more free buffers.

    The same emergency reserve must be implemented for KVA space, for the same
    reason.  These 'emergecy reserves' are really just comparisons against
    summary counters, aka 'numfreebuffers' and 'kvafreespace'.

:>     as 'lofreebuffers' and blocks if numfreebuffers < lofreebuffers.  I
:>     believe we must relax that rule if curproc == updateproc ( i.e. the
:>     syncer ), thus guarenteeing sufficient buffers for the syncer to be
:>     able to operate in extreme conditions.
:> 
:Yes, if syncer has to recurse.

    That's what the emergency reserve is for.  The syncer can, in fact, block,
    because if the emergency reserve is exhausted then there is known to be
    I/O in progress by the syncer that will soon be freed up in brelse().
    So the syncer shouldn't have to recurse in that case.

    We may have to play a little with brelse/bqrelse.  I don't know yet.  I'm
    fixing the problems one at a time.

					-Matt
:
:-lq

					Matthew Dillon 
					<dillon@backplane.com>


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




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