1 /* $NetBSD: vm_vfs.c,v 1.14 2009/11/10 16:55:12 pooka Exp $ */
4 * Copyright (c) 2008 Antti Kantee. All Rights Reserved.
6 * Development of this software was supported by the
7 * Finnish Cultural Foundation.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: vm_vfs.c,v 1.14 2009/11/10 16:55:12 pooka Exp $");
34 #include <sys/param.h>
37 #include <sys/vnode.h>
40 #include <uvm/uvm_readahead.h>
43 * release resources held during async io. this is almost the
44 * same as uvm_aio_aiodone() from uvm_pager.c and only lacks the
45 * call to uvm_aio_aiodone_pages(): unbusies pages directly here.
48 uvm_aio_aiodone(struct buf
*bp
)
50 int i
, npages
= bp
->b_bufsize
>> PAGE_SHIFT
;
54 pgs
= kmem_alloc(npages
* sizeof(*pgs
), KM_SLEEP
);
55 for (i
= 0; i
< npages
; i
++) {
56 va
= (vaddr_t
)bp
->b_data
+ (i
<< PAGE_SHIFT
);
57 pgs
[i
] = uvm_pageratop(va
);
58 pgs
[i
]->flags
&= ~PG_PAGEOUT
;
61 uvm_pagermapout((vaddr_t
)bp
->b_data
, npages
);
62 uvm_page_unbusy(pgs
, npages
);
64 if (BUF_ISWRITE(bp
) && (bp
->b_cflags
& BC_AGE
) != 0) {
65 mutex_enter(bp
->b_objlock
);
67 mutex_exit(bp
->b_objlock
);
72 kmem_free(pgs
, npages
* sizeof(*pgs
));
76 uvm_aio_biodone(struct buf
*bp
)
87 uvm_vnp_zerorange(struct vnode
*vp
, off_t off
, size_t len
)
89 struct uvm_object
*uobj
= &vp
->v_uobj
;
91 int maxpages
= MIN(32, round_page(len
) >> PAGE_SHIFT
);
97 pgs
= kmem_zalloc(maxpages
* sizeof(pgs
), KM_SLEEP
);
99 npages
= MIN(maxpages
, round_page(len
) >> PAGE_SHIFT
);
100 memset(pgs
, 0, npages
* sizeof(struct vm_page
*));
101 mutex_enter(&uobj
->vmobjlock
);
102 rv
= uobj
->pgops
->pgo_get(uobj
, off
, pgs
, &npages
, 0,
103 VM_PROT_READ
| VM_PROT_WRITE
, 0, PGO_SYNCIO
);
106 for (i
= 0; i
< npages
; i
++) {
108 size_t chunkoff
, chunklen
;
110 chunkoff
= off
& PAGE_MASK
;
111 chunklen
= MIN(PAGE_SIZE
- chunkoff
, len
);
112 start
= (uint8_t *)pgs
[i
]->uanon
+ chunkoff
;
114 memset(start
, 0, chunklen
);
115 pgs
[i
]->flags
&= ~PG_CLEAN
;
120 uvm_page_unbusy(pgs
, npages
);
122 kmem_free(pgs
, maxpages
* sizeof(pgs
));
128 #define len2npages(off, len) \
129 (((((len) + PAGE_MASK) & ~(PAGE_MASK)) >> PAGE_SHIFT) \
130 + (((off & PAGE_MASK) + (len & PAGE_MASK)) > PAGE_SIZE))
133 ubc_uiomove(struct uvm_object
*uobj
, struct uio
*uio
, vsize_t todo
,
134 int advice
, int flags
)
136 struct vm_page
**pgs
;
137 int npages
= len2npages(uio
->uio_offset
, todo
);
139 int i
, rv
, pagerflags
;
141 pgalloc
= npages
* sizeof(pgs
);
142 pgs
= kmem_zalloc(pgalloc
, KM_SLEEP
);
144 pagerflags
= PGO_SYNCIO
| PGO_NOBLOCKALLOC
| PGO_NOTIMESTAMP
;
145 if (flags
& UBC_WRITE
)
146 pagerflags
|= PGO_PASTEOF
;
147 if (flags
& UBC_FAULTBUSY
)
148 pagerflags
|= PGO_OVERWRITE
;
151 mutex_enter(&uobj
->vmobjlock
);
152 rv
= uobj
->pgops
->pgo_get(uobj
, uio
->uio_offset
& ~PAGE_MASK
,
153 pgs
, &npages
, 0, VM_PROT_READ
| VM_PROT_WRITE
, 0,
158 for (i
= 0; i
< npages
; i
++) {
162 pageoff
= uio
->uio_offset
& PAGE_MASK
;
163 xfersize
= MIN(MIN(todo
, PAGE_SIZE
), PAGE_SIZE
-pageoff
);
164 KASSERT(xfersize
> 0);
165 uiomove((uint8_t *)pgs
[i
]->uanon
+ pageoff
,
167 if (uio
->uio_rw
== UIO_WRITE
)
168 pgs
[i
]->flags
&= ~(PG_CLEAN
| PG_FAKE
);
171 uvm_page_unbusy(pgs
, npages
);
175 kmem_free(pgs
, pgalloc
);