]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/kern/uipc_cow.c
catch up with mextadd callback taking a void argument instead of a caddr_t.
[FreeBSD/FreeBSD.git] / sys / kern / uipc_cow.c
1 /*-
2  * Copyright (c) 1997, Duke University
3  * All rights reserved.
4  *
5  * Author:
6  *         Andrew Gallatin <gallatin@cs.duke.edu>  
7  *            
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
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 
21  *    permission.
22  * 
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.  
34  *
35  * $FreeBSD$
36  */
37 /*
38  * This is a set of routines for enabling and disabling copy on write
39  * protection for data written into sockets.
40  */
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/proc.h>
46 #include <sys/lock.h>
47 #include <sys/mutex.h>
48 #include <sys/mbuf.h>
49 #include <sys/socketvar.h>
50 #include <sys/uio.h>
51
52 #include <vm/vm.h>
53 #include <vm/vm_param.h>
54 #include <vm/pmap.h>
55 #include <vm/vm_map.h>
56 #include <vm/vm_page.h>
57 #include <vm/vm_object.h>
58 #if 0
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>
64 #endif
65
66
67 struct netsend_cow_stats {
68         int attempted;
69         int fail_not_mapped;
70         int fail_wired;
71         int fail_not_anon;
72         int fail_pmap_cow;
73         int fail_pg_error;
74         int fail_kva;
75         int free_post_exit;
76         int success;
77         int iodone;
78         int freed;
79 };
80
81 static struct netsend_cow_stats socow_stats = {0,0,0,0,0,0,0,0,0,0,0};
82
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);
89
90 static void
91 socow_iodone(void *addr, void *args)
92 {       
93         int s;
94         struct sf_buf *sf;
95
96         vm_offset_t paddr; 
97         vm_page_t pp;
98
99         sf = dtosf(addr);
100         paddr = vtophys((vm_offset_t)addr);
101         pp = PHYS_TO_VM_PAGE(paddr);
102         s = splvm();
103         /* remove COW mapping  */
104         vm_page_cowclear(pp);
105         vm_object_deallocate(pp->object);
106         splx(s);
107         /* note that sf_buf_free() unwires the page for us*/
108         sf_buf_free(addr, NULL);
109         socow_stats.iodone++;
110 }
111
112 int
113 socow_setup(struct mbuf *m0, struct uio *uio)
114 {
115         struct sf_buf *sf;
116         vm_page_t pp;
117         vm_offset_t pa;
118         struct iovec *iov;
119         struct vmspace *vmspace;
120         struct vm_map *map;
121         vm_offset_t uva;
122         int s;
123
124         vmspace = curproc->p_vmspace;;
125         map = &vmspace->vm_map;
126         uva = (vm_offset_t) uio->uio_iov->iov_base;
127
128         s = splvm();
129
130        /* 
131         * verify page is mapped & not already wired for i/o
132         */
133         socow_stats.attempted++;
134         pa=pmap_extract(map->pmap, uva);
135         if(!pa) {
136                 socow_stats.fail_not_mapped++;
137                 splx(s);
138                 return(0);
139         }
140         pp = PHYS_TO_VM_PAGE(pa);
141
142         sf = sf_buf_alloc();
143         sf->m = pp;
144         pmap_qenter(sf->kva, &pp, 1);
145
146         /* 
147          * set up COW
148          */
149         vm_page_cowsetup(pp);
150
151         /*
152          * wire the page for I/O
153          */
154         vm_page_wire(pp);
155
156         /*
157          * prevent the process from exiting on us.
158          */
159         vm_object_reference(pp->object);
160
161         /* 
162          * attach to mbuf
163          */
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++;
168
169         iov = uio->uio_iov;
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) {
175                 uio->uio_iov++;
176                 uio->uio_iovcnt--;
177         }
178
179         splx(s);
180         return(1);
181 }