Deleted Added
sdiff udiff text old ( 12662 ) new ( 12767 )
full compact
1/*
2 * Copyright (c) 1990 University of Utah.
3 * Copyright (c) 1991 The Regents of the University of California.
4 * All rights reserved.
5 * Copyright (c) 1993, 1994 John S. Dyson
6 * Copyright (c) 1995, David Greenman
7 *
8 * This code is derived from software contributed to Berkeley by

--- 24 unchanged lines hidden (view full) ---

33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * from: @(#)vnode_pager.c 7.5 (Berkeley) 4/20/91
41 * $Id: vnode_pager.c,v 1.53 1995/11/20 12:19:11 phk Exp $
42 */
43
44/*
45 * Page to/from files (vnodes).
46 */
47
48/*
49 * TODO:

--- 16 unchanged lines hidden (view full) ---

66#include <vm/vm_param.h>
67#include <vm/vm_prot.h>
68#include <vm/vm_object.h>
69#include <vm/vm_page.h>
70#include <vm/vm_pager.h>
71#include <vm/vnode_pager.h>
72#include <vm/vm_extern.h>
73
74extern vm_offset_t vnode_pager_addr __P((struct vnode *vp, vm_offset_t address,
75 int *run));
76extern void vnode_pager_iodone __P((struct buf *bp));
77extern int vnode_pager_input_smlfs __P((vm_object_t object, vm_page_t m));
78extern int vnode_pager_input_old __P((vm_object_t object, vm_page_t m));
79
80struct pagerops vnodepagerops = {
81 NULL,
82 vnode_pager_alloc,

--- 14 unchanged lines hidden (view full) ---

97 * Allocate (or lookup) pager for a vnode.
98 * Handle is a vnode pointer.
99 */
100vm_object_t
101vnode_pager_alloc(handle, size, prot, offset)
102 void *handle;
103 vm_size_t size;
104 vm_prot_t prot;
105 vm_offset_t offset;
106{
107 vm_object_t object;
108 struct vnode *vp;
109
110 /*
111 * Pageout to vnode, no can do yet.
112 */
113 if (handle == NULL)

--- 18 unchanged lines hidden (view full) ---

132 while (((object = vp->v_object) != NULL) && (object->flags & OBJ_DEAD)) {
133 tsleep(object, PVM, "vadead", 0);
134 }
135
136 if (object == NULL) {
137 /*
138 * And an object of the appropriate size
139 */
140 object = vm_object_allocate(OBJT_VNODE, round_page(size));
141 object->flags = OBJ_CANPERSIST;
142
143 /*
144 * Hold a reference to the vnode and initialize object data.
145 */
146 VREF(vp);
147 object->un_pager.vnp.vnp_size = size;
148
149 object->handle = handle;
150 vp->v_object = object;
151 } else {
152 /*
153 * vm_object_reference() will remove the object from the cache if
154 * found and gain a reference to the object.
155 */

--- 33 unchanged lines hidden (view full) ---

189
190 vp->v_object = NULL;
191 vp->v_flag &= ~(VTEXT | VVMIO);
192 vp->v_flag |= VAGE;
193 vrele(vp);
194}
195
196boolean_t
197vnode_pager_haspage(object, offset, before, after)
198 vm_object_t object;
199 vm_offset_t offset;
200 int *before;
201 int *after;
202{
203 struct vnode *vp = object->handle;
204 daddr_t bn;
205 int err;
206 daddr_t reqblock;
207 int poff;
208 int bsize;
209 int pagesperblock;
210
211 /*
212 * If filesystem no longer mounted or offset beyond end of file we do
213 * not have the page.
214 */
215 if ((vp->v_mount == NULL) || (offset >= object->un_pager.vnp.vnp_size))
216 return FALSE;
217
218 bsize = vp->v_mount->mnt_stat.f_iosize;
219 pagesperblock = bsize / PAGE_SIZE;
220 reqblock = offset / bsize;
221 err = VOP_BMAP(vp, reqblock, (struct vnode **) 0, &bn,
222 after, before);
223 if (err)
224 return TRUE;
225 if ( bn == -1)
226 return FALSE;
227 poff = (offset - (reqblock * bsize)) / PAGE_SIZE;
228 if (before) {
229 *before *= pagesperblock;
230 *before += poff;
231 }
232 if (after) {
233 int numafter;
234 *after *= pagesperblock;
235 numafter = pagesperblock - (poff + 1);
236 if (offset + numafter * PAGE_SIZE > object->un_pager.vnp.vnp_size) {
237 numafter = (object->un_pager.vnp.vnp_size - offset)/PAGE_SIZE;
238 }
239 *after += numafter;
240 }
241 return TRUE;
242}
243
244/*
245 * Lets the VM system know about a change in size for a file.
246 * We adjust our own internal size and flush any cached pages in
247 * the associated object that are affected by the size change.
248 *
249 * Note: this routine may be invoked as a result of a pager put
250 * operation (possibly at object termination time), so we must be careful.
251 */
252void
253vnode_pager_setsize(vp, nsize)
254 struct vnode *vp;
255 u_long nsize;
256{
257 vm_object_t object = vp->v_object;
258
259 if (object == NULL)
260 return;
261
262 /*
263 * Hasn't changed size
264 */
265 if (nsize == object->un_pager.vnp.vnp_size)
266 return;
267
268 /*
269 * File has shrunk. Toss any cached pages beyond the new EOF.
270 */
271 if (nsize < object->un_pager.vnp.vnp_size) {
272 if (round_page((vm_offset_t) nsize) < object->un_pager.vnp.vnp_size) {
273 vm_object_page_remove(object,
274 round_page((vm_offset_t) nsize), object->un_pager.vnp.vnp_size, FALSE);
275 }
276 /*
277 * this gets rid of garbage at the end of a page that is now
278 * only partially backed by the vnode...
279 */
280 if (nsize & PAGE_MASK) {
281 vm_offset_t kva;
282 vm_page_t m;
283
284 m = vm_page_lookup(object, trunc_page((vm_offset_t) nsize));
285 if (m) {
286 kva = vm_pager_map_page(m);
287 bzero((caddr_t) kva + (nsize & PAGE_MASK),
288 round_page(nsize) - nsize);
289 vm_pager_unmap_page(kva);
290 }
291 }
292 }
293 object->un_pager.vnp.vnp_size = (vm_offset_t) nsize;
294 object->size = round_page(nsize);
295}
296
297void
298vnode_pager_umount(mp)
299 register struct mount *mp;
300{
301 struct vnode *vp, *nvp;
302

--- 60 unchanged lines hidden (view full) ---

363
364/*
365 * calculate the linear (byte) disk address of specified virtual
366 * file address
367 */
368vm_offset_t
369vnode_pager_addr(vp, address, run)
370 struct vnode *vp;
371 vm_offset_t address;
372 int *run;
373{
374 int rtaddress;
375 int bsize;
376 vm_offset_t block;
377 struct vnode *rtvp;
378 int err;
379 int vblock, voffset;
380
381 if ((int) address < 0)
382 return -1;
383
384 if (vp->v_mount == NULL)
385 return -1;
386
387 bsize = vp->v_mount->mnt_stat.f_iosize;

--- 52 unchanged lines hidden (view full) ---

440
441
442 VOP_BMAP(vp, 0, &dp, 0, NULL, NULL);
443
444 kva = vm_pager_map_page(m);
445
446 for (i = 0; i < PAGE_SIZE / bsize; i++) {
447
448 if ((vm_page_bits(m->offset + i * bsize, bsize) & m->valid))
449 continue;
450
451 fileaddr = vnode_pager_addr(vp, m->offset + i * bsize, (int *)0);
452 if (fileaddr != -1) {
453 bp = getpbuf();
454
455 /* build a minimal buffer header */
456 bp->b_flags = B_BUSY | B_READ | B_CALL;
457 bp->b_iodone = vnode_pager_iodone;
458 bp->b_proc = curproc;
459 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred;

--- 58 unchanged lines hidden (view full) ---

518 int size;
519 vm_offset_t kva;
520
521 error = 0;
522
523 /*
524 * Return failure if beyond current EOF
525 */
526 if (m->offset >= object->un_pager.vnp.vnp_size) {
527 return VM_PAGER_BAD;
528 } else {
529 size = PAGE_SIZE;
530 if (m->offset + size > object->un_pager.vnp.vnp_size)
531 size = object->un_pager.vnp.vnp_size - m->offset;
532
533 /*
534 * Allocate a kernel virtual address and initialize so that
535 * we can use VOP_READ/WRITE routines.
536 */
537 kva = vm_pager_map_page(m);
538
539 aiov.iov_base = (caddr_t) kva;
540 aiov.iov_len = size;
541 auio.uio_iov = &aiov;
542 auio.uio_iovcnt = 1;
543 auio.uio_offset = m->offset;
544 auio.uio_segflg = UIO_SYSSPACE;
545 auio.uio_rw = UIO_READ;
546 auio.uio_resid = size;
547 auio.uio_procp = (struct proc *) 0;
548
549 error = VOP_READ(object->handle, &auio, 0, curproc->p_ucred);
550 if (!error) {
551 register int count = size - auio.uio_resid;

--- 34 unchanged lines hidden (view full) ---

586
587static int
588vnode_pager_leaf_getpages(object, m, count, reqpage)
589 vm_object_t object;
590 vm_page_t *m;
591 int count;
592 int reqpage;
593{
594 vm_offset_t kva, foff;
595 int i, size, bsize, first, firstaddr;
596 struct vnode *dp, *vp;
597 int runpg;
598 int runend;
599 struct buf *bp;
600 int s;
601 int error = 0;
602

--- 4 unchanged lines hidden (view full) ---

607 bsize = vp->v_mount->mnt_stat.f_iosize;
608
609 /* get the UNDERLYING device for the file with VOP_BMAP() */
610
611 /*
612 * originally, we did not check for an error return value -- assuming
613 * an fs always has a bmap entry point -- that assumption is wrong!!!
614 */
615 foff = m[reqpage]->offset;
616
617 /*
618 * if we can't bmap, use old VOP code
619 */
620 if (VOP_BMAP(vp, 0, &dp, 0, NULL, NULL)) {
621 for (i = 0; i < count; i++) {
622 if (i != reqpage) {
623 vnode_pager_freepage(m[i]);

--- 37 unchanged lines hidden (view full) ---

661 * here on direct device I/O
662 */
663
664 firstaddr = -1;
665 /*
666 * calculate the run that includes the required page
667 */
668 for(first = 0, i = 0; i < count; i = runend) {
669 firstaddr = vnode_pager_addr(vp, m[i]->offset, &runpg);
670 if (firstaddr == -1) {
671 if (i == reqpage && foff < object->un_pager.vnp.vnp_size) {
672 panic("vnode_pager_putpages: unexpected missing page: firstaddr: %d, foff: %ld, vnp_size: %d",
673 firstaddr, foff, object->un_pager.vnp.vnp_size);
674 }
675 vnode_pager_freepage(m[i]);
676 runend = i + 1;
677 first = runend;

--- 26 unchanged lines hidden (view full) ---

704 }
705 count -= first;
706 reqpage -= first;
707 }
708
709 /*
710 * calculate the file virtual address for the transfer
711 */
712 foff = m[0]->offset;
713
714 /*
715 * calculate the size of the transfer
716 */
717 size = count * PAGE_SIZE;
718 if ((foff + size) > object->un_pager.vnp.vnp_size)
719 size = object->un_pager.vnp.vnp_size - foff;
720

--- 114 unchanged lines hidden (view full) ---

835 int count;
836 boolean_t sync;
837 int *rtvals;
838{
839 int i;
840
841 struct vnode *vp;
842 int maxsize, ncount;
843 struct uio auio;
844 struct iovec aiov;
845 int error;
846
847 vp = object->handle;;
848 for (i = 0; i < count; i++)
849 rtvals[i] = VM_PAGER_AGAIN;
850
851 if ((int) m[0]->offset < 0) {
852 printf("vnode_pager_putpages: attempt to write meta-data!!! -- 0x%x(%x)\n", m[0]->offset, m[0]->dirty);
853 rtvals[0] = VM_PAGER_BAD;
854 return VM_PAGER_BAD;
855 }
856
857 maxsize = count * PAGE_SIZE;
858 ncount = count;
859
860 if (maxsize + m[0]->offset > object->un_pager.vnp.vnp_size) {
861 if (object->un_pager.vnp.vnp_size > m[0]->offset)
862 maxsize = object->un_pager.vnp.vnp_size - m[0]->offset;
863 else
864 maxsize = 0;
865 ncount = (maxsize + PAGE_SIZE - 1) / PAGE_SIZE;
866 if (ncount < count) {
867 for (i = ncount; i < count; i++) {
868 rtvals[i] = VM_PAGER_BAD;
869 }
870 if (ncount == 0) {
871 printf("vnode_pager_putpages: write past end of file: %ld, %ld\n",
872 m[0]->offset,
873 object->un_pager.vnp.vnp_size);
874 return rtvals[0];
875 }
876 }
877 }
878
879 for (i = 0; i < count; i++) {
880 m[i]->busy++;
881 m[i]->flags &= ~PG_BUSY;
882 }
883
884 aiov.iov_base = (caddr_t) 0;
885 aiov.iov_len = maxsize;
886 auio.uio_iov = &aiov;
887 auio.uio_iovcnt = 1;
888 auio.uio_offset = m[0]->offset;
889 auio.uio_segflg = UIO_NOCOPY;
890 auio.uio_rw = UIO_WRITE;
891 auio.uio_resid = maxsize;
892 auio.uio_procp = (struct proc *) 0;
893 error = VOP_WRITE(vp, &auio, IO_VMIO, curproc->p_ucred);
894 cnt.v_vnodeout++;
895 cnt.v_vnodepgsout += ncount;
896
897 if (error) {
898 printf("vnode_pager_putpages: I/O error %d\n", error);
899 }
900 if (auio.uio_resid) {
901 printf("vnode_pager_putpages: residual I/O %d at %ld\n",
902 auio.uio_resid, m[0]->offset);
903 }
904 for (i = 0; i < count; i++) {
905 m[i]->busy--;
906 if (i < ncount) {
907 rtvals[i] = VM_PAGER_OK;
908 }
909 if ((m[i]->busy == 0) && (m[i]->flags & PG_WANTED))
910 wakeup(m[i]);

--- 17 unchanged lines hidden ---