diff options
author | jeff <jeff@FreeBSD.org> | 2002-07-06 22:14:38 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2002-07-06 22:14:38 +0000 |
commit | 8d0c32ea13b07fa32c171057bd3dccec349c0cc3 (patch) | |
tree | 8b1c24cd648021c58cf54cf184631f37666144c6 /sys/vm | |
parent | f1b0400267ed5a6ad5d01b82e0b2c2d50adc97e4 (diff) | |
download | FreeBSD-src-8d0c32ea13b07fa32c171057bd3dccec349c0cc3.zip FreeBSD-src-8d0c32ea13b07fa32c171057bd3dccec349c0cc3.tar.gz |
- Hold a lock on the vnode acquired from the file table across the call to
vm_mmap() as well as the GETATTR etc.
- If the handle is a vnode in vm_mmap() assert that it is locked.
- Wiggle Giant around a little to account for the extra vnode operation.
Diffstat (limited to 'sys/vm')
-rw-r--r-- | sys/vm/vm_mmap.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 698179a..b9894a4 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -217,6 +217,7 @@ mmap(td, uap) flags = uap->flags; pos = uap->pos; + vp = NULL; fp = NULL; /* make sure mapping fits into numeric range etc */ if ((ssize_t) uap->len < 0 || @@ -310,6 +311,9 @@ mmap(td, uap) if (fp->f_flag & FPOSIXSHM) flags |= MAP_NOSYNC; vp = (struct vnode *) fp->f_data; + error = vget(vp, LK_EXCLUSIVE, td); + if (error) + goto done; if (vp->v_type != VREG && vp->v_type != VCHR) { error = EINVAL; goto done; @@ -322,7 +326,11 @@ mmap(td, uap) error = EINVAL; goto done; } - vp = (struct vnode*)obj->handle; + if (obj->handle != vp) { + vput(vp); + vp = (struct vnode*)obj->handle; + vget(vp, LK_EXCLUSIVE, td); + } } /* * XXX hack to handle use of /dev/zero to map anon memory (ala @@ -423,14 +431,16 @@ mmap(td, uap) mtx_unlock(&Giant); error = vm_mmap(&vms->vm_map, &addr, size, prot, maxprot, flags, handle, pos); + mtx_lock(&Giant); if (error == 0) td->td_retval[0] = (register_t) (addr + pageoff); - goto done2; done: + if (vp) + vput(vp); mtx_unlock(&Giant); -done2: if (fp) fdrop(fp, td); + return (error); } @@ -1165,6 +1175,7 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot, } else { vp = (struct vnode *) handle; mtx_lock(&Giant); + ASSERT_VOP_LOCKED(vp, "vm_mmap"); if (vp->v_type == VCHR) { type = OBJT_DEVICE; handle = (void *)(intptr_t)vp->v_rdev; |