Add vm locking to sendfile(2) and sf_buf_free().
Reported by: Tamiji Homma <thomma@BayNetworks.com> Tested by: Tamiji Homma <thomma@BayNetworks.com>
This commit is contained in:
parent
f19ccd9f40
commit
e1ee9e1e41
@ -1487,12 +1487,11 @@ sf_buf_free(caddr_t addr, void *args)
|
||||
{
|
||||
struct sf_buf *sf;
|
||||
struct vm_page *m;
|
||||
int s;
|
||||
|
||||
sf = dtosf(addr);
|
||||
mtx_lock(&vm_mtx);
|
||||
pmap_qremove((vm_offset_t)addr, 1);
|
||||
m = sf->m;
|
||||
s = splvm();
|
||||
vm_page_unwire(m, 0);
|
||||
/*
|
||||
* Check for the object going away on us. This can
|
||||
@ -1501,7 +1500,7 @@ sf_buf_free(caddr_t addr, void *args)
|
||||
*/
|
||||
if (m->wire_count == 0 && m->object == NULL)
|
||||
vm_page_free(m);
|
||||
splx(s);
|
||||
mtx_unlock(&vm_mtx);
|
||||
sf->m = NULL;
|
||||
mtx_lock(&sf_freelist.sf_lock);
|
||||
SLIST_INSERT_HEAD(&sf_freelist.sf_head, sf, free_list);
|
||||
@ -1646,16 +1645,19 @@ sendfile(struct proc *p, struct sendfile_args *uap)
|
||||
*
|
||||
* Wait and loop if busy.
|
||||
*/
|
||||
mtx_lock(&vm_mtx);
|
||||
pg = vm_page_lookup(obj, pindex);
|
||||
|
||||
if (pg == NULL) {
|
||||
pg = vm_page_alloc(obj, pindex, VM_ALLOC_NORMAL);
|
||||
if (pg == NULL) {
|
||||
VM_WAIT;
|
||||
mtx_unlock(&vm_mtx);
|
||||
goto retry_lookup;
|
||||
}
|
||||
vm_page_wakeup(pg);
|
||||
} else if (vm_page_sleep_busy(pg, TRUE, "sfpbsy")) {
|
||||
mtx_unlock(&vm_mtx);
|
||||
goto retry_lookup;
|
||||
}
|
||||
|
||||
@ -1680,6 +1682,7 @@ sendfile(struct proc *p, struct sendfile_args *uap)
|
||||
* completes.
|
||||
*/
|
||||
vm_page_io_start(pg);
|
||||
mtx_unlock(&vm_mtx);
|
||||
|
||||
/*
|
||||
* Get the page from backing store.
|
||||
@ -1698,6 +1701,7 @@ sendfile(struct proc *p, struct sendfile_args *uap)
|
||||
error = VOP_READ(vp, &auio, IO_VMIO | ((MAXBSIZE / bsize) << 16),
|
||||
p->p_ucred);
|
||||
VOP_UNLOCK(vp, 0, p);
|
||||
mtx_lock(&vm_mtx);
|
||||
vm_page_flag_clear(pg, PG_ZERO);
|
||||
vm_page_io_finish(pg);
|
||||
if (error) {
|
||||
@ -1712,6 +1716,7 @@ sendfile(struct proc *p, struct sendfile_args *uap)
|
||||
vm_page_busy(pg);
|
||||
vm_page_free(pg);
|
||||
}
|
||||
mtx_unlock(&vm_mtx);
|
||||
sbunlock(&so->so_snd);
|
||||
goto done;
|
||||
}
|
||||
@ -1722,12 +1727,13 @@ sendfile(struct proc *p, struct sendfile_args *uap)
|
||||
* Get a sendfile buf. We usually wait as long as necessary,
|
||||
* but this wait can be interrupted.
|
||||
*/
|
||||
mtx_unlock(&vm_mtx);
|
||||
if ((sf = sf_buf_alloc()) == NULL) {
|
||||
s = splvm();
|
||||
mtx_lock(&vm_mtx);
|
||||
vm_page_unwire(pg, 0);
|
||||
if (pg->wire_count == 0 && pg->object == NULL)
|
||||
vm_page_free(pg);
|
||||
splx(s);
|
||||
mtx_unlock(&vm_mtx);
|
||||
sbunlock(&so->so_snd);
|
||||
error = EINTR;
|
||||
goto done;
|
||||
@ -1737,8 +1743,10 @@ sendfile(struct proc *p, struct sendfile_args *uap)
|
||||
* Allocate a kernel virtual page and insert the physical page
|
||||
* into it.
|
||||
*/
|
||||
mtx_lock(&vm_mtx);
|
||||
sf->m = pg;
|
||||
pmap_qenter(sf->kva, &pg, 1);
|
||||
mtx_unlock(&vm_mtx);
|
||||
/*
|
||||
* Get an mbuf header and set it up as having external storage.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user