diff options
-rw-r--r-- | sys/kern/sys_pipe.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 289bc37..135d5eb 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -616,18 +616,27 @@ pipe_build_write_buffer(wpipe, uio) for (i = 0; addr < endaddr; addr += PAGE_SIZE, i++) { vm_page_t m; + /* + * vm_fault_quick() can sleep. Consequently, + * vm_page_lock_queue() and vm_page_unlock_queue() + * should not be performed outside of this loop. + */ if (vm_fault_quick((caddr_t)addr, VM_PROT_READ) < 0 || (paddr = pmap_extract(vmspace_pmap(curproc->p_vmspace), addr)) == 0) { int j; + vm_page_lock_queues(); for (j = 0; j < i; j++) vm_page_unwire(wpipe->pipe_map.ms[j], 1); + vm_page_unlock_queues(); return (EFAULT); } m = PHYS_TO_VM_PAGE(paddr); + vm_page_lock_queues(); vm_page_wire(m); + vm_page_unlock_queues(); wpipe->pipe_map.ms[i] = m; } @@ -690,8 +699,10 @@ pipe_destroy_write_buffer(wpipe) amountpipekva -= wpipe->pipe_buffer.size + PAGE_SIZE; } } + vm_page_lock_queues(); for (i = 0; i < wpipe->pipe_map.npages; i++) vm_page_unwire(wpipe->pipe_map.ms[i], 1); + vm_page_unlock_queues(); wpipe->pipe_map.npages = 0; } |