Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 2 Mar 1999 01:56:19 +1100
From:      Bruce Evans <bde@zeta.org.au>
To:        bde@zeta.org.au, dick@tar.com
Cc:        current@FreeBSD.ORG, julian@whistle.com, pangolin@home.com
Subject:   Re: lockmgr panic with mmap()
Message-ID:  <199903011456.BAA18860@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>> mincore() locks the vmspace map, and initialises vec[] a byte at a time
>> using subyte().  When vec[] is sufficiently large, it is not all in core
>> initially and a page fault occurs in subyte().  The new stack growing
>> code locks the vmspace map early and panics.
>
>It appears to me the potential for deadlock exists in the old grow code
>too, but is less likely.  
>
>I've attached a patch that addresses the issue, though there is a
>question if this is the best solution.
>
>With the old grow code, if the map lock is already held, one of the
>following will be true
>a) the grow code doesn't get executed because the va is not
>   in the stack region, which is equivalent to grow returning
>   success
>b) the grow code returns success because there's no need to
>   grow the region because the va is aready in the mapped region.
>c) the grow code returns false if the va is within the stack
>   region and there's no room left, which normally will result
>   in a SIGSEGV
>d) the grow code attempts to grow the stack via vm_map_find and
>   will then deadlock at the vm_map_lock call
>
>With this patch, if the map lock is already held, by always returning
>success, cases a) and b) will be the same as before.  For case c)
>the code will attempt to continue to execute, generally calling
>vm_fault, which should, I think, generate a SIGSEGV, essentially
>the same result as the old code, but via a different path.  Case d)
>will now continue executing in a manner equivalent to the new case c).
>
>The question is whether there is a way to do the autogrow function if
>the map lock is already held.

I think it shouldn't work.  Copying to and from user space must not
generate SIGSEGV if the application could access its memory directly.
The easiest way to implement this is to never lock maps before
accessing user memory.  Atomic copies won't get any easier to do
after you've backed out of a deadlock.

I think mincore() should just unlock the map while calling subyte() and
restart if the map changes significantly underneath it.  Some critical
examples:

1. mincore(addr, 0xfffffff0, vec) at rtprio 0 (in only process with this
   priority).  vec[] only needs to have size 1MB (for 4K pages).
   It's barely reasonable for the application to expect vec[] to be all
   mapped and to perfectly represent the current state.  To implement
   this, mincore() would have to prefault vec[] (or backtrack to give
   the equivalent) so that it doesn't block.

2. mincore(vec, len, vec).  This is quite likely to change the incore'ness
   of vec[].

Bruce


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




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