2 * Copyright (c) 1997, Duke University
6 * Andrew Gallatin <gallatin@cs.duke.edu>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgements:
18 * This product includes software developed by Duke University
19 * 4. The name of Duke University may not be used to endorse or promote
20 * products derived from this software without specific prior written
23 * THIS SOFTWARE IS PROVIDED BY DUKE UNIVERSITY ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DUKE UNIVERSITY BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITSOR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
31 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 * This is a set of routines for enabling and disabling copy on write
39 * protection for data written into sockets.
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
47 #include <sys/mutex.h>
49 #include <sys/socketvar.h>
53 #include <vm/vm_param.h>
55 #include <vm/vm_map.h>
56 #include <vm/vm_page.h>
57 #include <vm/vm_object.h>
59 #include <vm/vm_pager.h>
60 #include <vm/vm_kern.h>
61 #include <vm/vm_extern.h>
62 #include <vm/vm_zone.h>
63 #include <vm/swap_pager.h>
67 struct netsend_cow_stats {
81 static struct netsend_cow_stats socow_stats = {0,0,0,0,0,0,0,0,0,0,0};
83 extern struct sf_buf *sf_bufs;
84 extern vm_offset_t sf_base;
85 #define dtosf(x) (&sf_bufs[((uintptr_t)(x) - (uintptr_t)sf_base) >> PAGE_SHIFT])
86 void sf_buf_free(caddr_t addr, void *args);
87 struct sf_buf *sf_buf_alloc(void);
88 static void socow_iodone(void *addr, void *args);
91 socow_iodone(void *addr, void *args)
100 paddr = vtophys((vm_offset_t)addr);
101 pp = PHYS_TO_VM_PAGE(paddr);
103 /* remove COW mapping */
104 vm_page_cowclear(pp);
105 vm_object_deallocate(pp->object);
107 /* note that sf_buf_free() unwires the page for us*/
108 sf_buf_free(addr, NULL);
109 socow_stats.iodone++;
113 socow_setup(struct mbuf *m0, struct uio *uio)
119 struct vmspace *vmspace;
124 vmspace = curproc->p_vmspace;;
125 map = &vmspace->vm_map;
126 uva = (vm_offset_t) uio->uio_iov->iov_base;
131 * verify page is mapped & not already wired for i/o
133 socow_stats.attempted++;
134 pa=pmap_extract(map->pmap, uva);
136 socow_stats.fail_not_mapped++;
140 pp = PHYS_TO_VM_PAGE(pa);
144 pmap_qenter(sf->kva, &pp, 1);
149 vm_page_cowsetup(pp);
152 * wire the page for I/O
157 * prevent the process from exiting on us.
159 vm_object_reference(pp->object);
164 m0->m_data = (caddr_t)sf->kva;
165 m0->m_len = PAGE_SIZE;
166 MEXTADD(m0, sf->kva, PAGE_SIZE, socow_iodone, NULL, 0, EXT_SFBUF);
167 socow_stats.success++;
170 iov->iov_base += PAGE_SIZE;
171 iov->iov_len -= PAGE_SIZE;
172 uio->uio_resid -= PAGE_SIZE;
173 uio->uio_offset += PAGE_SIZE;
174 if (iov->iov_len == 0) {