This solves a deadlock that can occur when read()ing into a file-mmap()
space. When doing this, it is possible to for another process to attempt to get an exclusive lock on the vnode and deadlock the mmap/read combination when the uiomove() call tries to obtain a second shared lock on the vnode. There is still a potential deadlock situation with write()/mmap(). Submitted by: Matt Dillon <dillon@freebsd.org> Reviewed by: Luoqi Chen <luoqi@freebsd.org> Delimmitted by tag PRE_MATT_MMAP_LOCK and POST_MATT_MMAP_LOCK in kern/kern_lock.c kern/kern_subr.c
This commit is contained in:
parent
4ef2094e45
commit
beef8a367c
@ -38,7 +38,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)kern_lock.c 8.18 (Berkeley) 5/21/95
|
||||
* $Id: kern_lock.c,v 1.22 1999/01/10 01:58:24 eivind Exp $
|
||||
* $Id: kern_lock.c,v 1.23 1999/01/20 14:49:11 eivind Exp $
|
||||
*/
|
||||
|
||||
#include "opt_lint.h"
|
||||
@ -205,9 +205,30 @@ debuglockmgr(lkp, flags, interlkp, p, name, file, line)
|
||||
switch (flags & LK_TYPE_MASK) {
|
||||
|
||||
case LK_SHARED:
|
||||
/*
|
||||
* If we are not the exclusive lock holder, we have to block
|
||||
* while there is an exclusive lock holder or while an
|
||||
* exclusive lock request or upgrade request is in progress.
|
||||
*
|
||||
* However, if P_DEADLKTREAT is set, we override exclusive
|
||||
* lock requests or upgrade requests ( but not the exclusive
|
||||
* lock itself ).
|
||||
*/
|
||||
if (lkp->lk_lockholder != pid) {
|
||||
error = acquire(lkp, extflags,
|
||||
LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE);
|
||||
if (p->p_flag & P_DEADLKTREAT) {
|
||||
error = acquire(
|
||||
lkp,
|
||||
extflags,
|
||||
LK_HAVE_EXCL
|
||||
);
|
||||
} else {
|
||||
error = acquire(
|
||||
lkp,
|
||||
extflags,
|
||||
LK_HAVE_EXCL | LK_WANT_EXCL |
|
||||
LK_WANT_UPGRADE
|
||||
);
|
||||
}
|
||||
if (error)
|
||||
break;
|
||||
sharelock(lkp, 1);
|
||||
|
@ -36,7 +36,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
|
||||
* $Id: kern_subr.c,v 1.26 1999/02/22 16:57:47 bde Exp $
|
||||
* $Id: kern_subr.c,v 1.27 1999/02/22 18:39:49 bde Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -63,13 +63,19 @@ uiomove(cp, n, uio)
|
||||
{
|
||||
register struct iovec *iov;
|
||||
u_int cnt;
|
||||
int error;
|
||||
int error = 0;
|
||||
int save = 0;
|
||||
|
||||
KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
|
||||
("uiomove: mode"));
|
||||
KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_procp == curproc,
|
||||
("uiomove proc"));
|
||||
|
||||
if (curproc) {
|
||||
save = curproc->p_flag & P_DEADLKTREAT;
|
||||
curproc->p_flag |= P_DEADLKTREAT;
|
||||
}
|
||||
|
||||
while (n > 0 && uio->uio_resid) {
|
||||
iov = uio->uio_iov;
|
||||
cnt = iov->iov_len;
|
||||
@ -92,7 +98,7 @@ uiomove(cp, n, uio)
|
||||
else
|
||||
error = copyin(iov->iov_base, cp, cnt);
|
||||
if (error)
|
||||
return (error);
|
||||
break;
|
||||
break;
|
||||
|
||||
case UIO_SYSSPACE:
|
||||
@ -111,7 +117,9 @@ uiomove(cp, n, uio)
|
||||
cp += cnt;
|
||||
n -= cnt;
|
||||
}
|
||||
return (0);
|
||||
if (curproc)
|
||||
curproc->p_flag = (curproc->p_flag & ~P_DEADLKTREAT) | save;
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
|
Loading…
x
Reference in New Issue
Block a user