diff options
author | julian <julian@FreeBSD.org> | 1999-03-12 03:09:29 +0000 |
---|---|---|
committer | julian <julian@FreeBSD.org> | 1999-03-12 03:09:29 +0000 |
commit | 35ed86543837074d1d29e42be3c5833e7d86259a (patch) | |
tree | fd711020444efce3db2a73b8041ad8a741f93dfe /sys/kern/kern_lock.c | |
parent | f27c95753fda68261265d744a5d8a9e59144d460 (diff) | |
download | FreeBSD-src-35ed86543837074d1d29e42be3c5833e7d86259a.zip FreeBSD-src-35ed86543837074d1d29e42be3c5833e7d86259a.tar.gz |
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
Diffstat (limited to 'sys/kern/kern_lock.c')
-rw-r--r-- | sys/kern/kern_lock.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c index e832acf..1685b4c 100644 --- a/sys/kern/kern_lock.c +++ b/sys/kern/kern_lock.c @@ -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); |