There was a situation where sendfile() might attempt to initiate I/O

on a PG_BUSY page, due to a bug in its sequencing of a conditional.
This commit is contained in:
Matthew Dillon 1999-01-24 01:15:58 +00:00
parent aaba53da90
commit 89600e8663

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94
* $Id: uipc_syscalls.c,v 1.50 1999/01/21 08:29:04 dillon Exp $
* $Id: uipc_syscalls.c,v 1.51 1999/01/21 09:00:26 dillon Exp $
*/
#include "opt_compat.h"
@ -1525,17 +1525,13 @@ sendfile(struct proc *p, struct sendfile_args *uap)
goto done;
}
/*
* Attempt to look up the page. If the page doesn't exist or the
* part we're interested in isn't valid, then read it from disk.
* If some other part of the kernel has this page (i.e. it's busy),
* then disk I/O may be occuring on it, so wait and retry.
* Attempt to look up the page.
*
* Allocate if not found
*
* Wait and loop if busy.
*/
pg = vm_page_lookup(obj, pindex);
if (pg == NULL || (!(pg->flags & PG_BUSY) && !pg->busy &&
!vm_page_is_valid(pg, pgoff, xfsize))) {
struct uio auio;
struct iovec aiov;
int bsize;
if (pg == NULL) {
pg = vm_page_alloc(obj, pindex, VM_ALLOC_NORMAL);
@ -1543,19 +1539,33 @@ sendfile(struct proc *p, struct sendfile_args *uap)
VM_WAIT;
goto retry_lookup;
}
/*
* don't just clear PG_BUSY manually -
* vm_page_alloc() should be considered opaque,
* use the VM routine provided to clear
* PG_BUSY.
*/
vm_page_wakeup(pg);
} else if (vm_page_sleep_busy(pg, TRUE, "sfpbsy")) {
goto retry_lookup;
}
/*
* Ensure that our page is still around when the I/O completes.
* Wire the page so it does not get ripped out from under
* us.
*/
vm_page_wire(pg);
/*
* If page is not valid for what we need, initiate I/O
*/
if (!pg->valid || !vm_page_is_valid(pg, pgoff, xfsize)) {
struct uio auio;
struct iovec aiov;
int bsize;
/*
* Ensure that our page is still around when the I/O
* completes.
*/
vm_page_io_start(pg);
vm_page_wire(pg);
/*
* Get the page from backing store.
*/
@ -1588,20 +1598,13 @@ sendfile(struct proc *p, struct sendfile_args *uap)
sbunlock(&so->so_snd);
goto done;
}
} else {
if (vm_page_sleep_busy(pg, TRUE, "sfpbsy"))
goto retry_lookup;
/*
* Protect from having the page ripped out from
* beneath us.
*/
vm_page_wire(pg);
}
/*
* Allocate a kernel virtual page and insert the physical page
* into it.
*/
sf = sf_buf_alloc();
sf->m = pg;
pmap_qenter(sf->kva, &pg, 1);