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_subr.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_subr.c')
-rw-r--r-- | sys/kern/kern_subr.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c index 190706c..13faec6 100644 --- a/sys/kern/kern_subr.c +++ b/sys/kern/kern_subr.c @@ -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 |