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.54 1995/12/07 12:48:31 davidg 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_ooffset_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_ooffset_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, 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 = (vm_ooffset_t) size * PAGE_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, pindex, before, after)
198 vm_object_t object;
199 vm_pindex_t pindex;
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) ||
216 (IDX_TO_OFF(pindex) >= object->un_pager.vnp.vnp_size))
217 return FALSE;
218
219 bsize = vp->v_mount->mnt_stat.f_iosize;
220 pagesperblock = bsize / PAGE_SIZE;
221 reqblock = pindex / pagesperblock;
222 err = VOP_BMAP(vp, reqblock, (struct vnode **) 0, &bn,
223 after, before);
224 if (err)
225 return TRUE;
226 if ( bn == -1)
227 return FALSE;
228 poff = pindex - (reqblock * pagesperblock);
229 if (before) {
230 *before *= pagesperblock;
231 *before += poff;
232 }
233 if (after) {
234 int numafter;
235 *after *= pagesperblock;
236 numafter = pagesperblock - (poff + 1);
237 if (IDX_TO_OFF(pindex + numafter) > object->un_pager.vnp.vnp_size) {
238 numafter = OFF_TO_IDX((object->un_pager.vnp.vnp_size - IDX_TO_OFF(pindex)));
239 }
240 *after += numafter;
241 }
242 return TRUE;
243}
244
245/*
246 * Lets the VM system know about a change in size for a file.
247 * We adjust our own internal size and flush any cached pages in
248 * the associated object that are affected by the size change.
249 *
250 * Note: this routine may be invoked as a result of a pager put
251 * operation (possibly at object termination time), so we must be careful.
252 */
253void
254vnode_pager_setsize(vp, nsize)
255 struct vnode *vp;
256 vm_ooffset_t nsize;
257{
258 vm_object_t object = vp->v_object;
259
260 if (object == NULL)
261 return;
262
263 /*
264 * Hasn't changed size
265 */
266 if (nsize == object->un_pager.vnp.vnp_size)
267 return;
268
269 /*
270 * File has shrunk. Toss any cached pages beyond the new EOF.
271 */
272 if (nsize < object->un_pager.vnp.vnp_size) {
273 vm_ooffset_t nsizerounded;
274 nsizerounded = IDX_TO_OFF(OFF_TO_IDX(nsize + PAGE_SIZE - 1));
275 if (nsizerounded < object->un_pager.vnp.vnp_size) {
276 vm_object_page_remove(object,
277 OFF_TO_IDX(nsize + PAGE_SIZE - 1),
278 OFF_TO_IDX(object->un_pager.vnp.vnp_size),
279 FALSE);
280 }
281 /*
282 * this gets rid of garbage at the end of a page that is now
283 * only partially backed by the vnode...
284 */
285 if (nsize & PAGE_MASK) {
286 vm_offset_t kva;
287 vm_page_t m;
288
289 m = vm_page_lookup(object, OFF_TO_IDX(nsize));
290 if (m) {
291 kva = vm_pager_map_page(m);
292 bzero((caddr_t) kva + (nsize & PAGE_MASK),
293 (int) (round_page(nsize) - nsize));
294 vm_pager_unmap_page(kva);
295 }
296 }
297 }
298 object->un_pager.vnp.vnp_size = nsize;
299 object->size = OFF_TO_IDX(nsize + PAGE_SIZE - 1);
300}
301
302void
303vnode_pager_umount(mp)
304 register struct mount *mp;
305{
306 struct vnode *vp, *nvp;
307

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

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

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

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

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

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

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

593
594static int
595vnode_pager_leaf_getpages(object, m, count, reqpage)
596 vm_object_t object;
597 vm_page_t *m;
598 int count;
599 int reqpage;
600{
601 vm_offset_t kva;
602 off_t foff;
603 int i, size, bsize, first, firstaddr;
604 struct vnode *dp, *vp;
605 int runpg;
606 int runend;
607 struct buf *bp;
608 int s;
609 int error = 0;
610

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

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

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

669 * here on direct device I/O
670 */
671
672 firstaddr = -1;
673 /*
674 * calculate the run that includes the required page
675 */
676 for(first = 0, i = 0; i < count; i = runend) {
677 firstaddr = vnode_pager_addr(vp,
678 IDX_TO_OFF(m[i]->pindex), &runpg);
679 if (firstaddr == -1) {
680 if (i == reqpage && foff < object->un_pager.vnp.vnp_size) {
681 panic("vnode_pager_putpages: unexpected missing page: firstaddr: %d, foff: %ld, vnp_size: %d",
682 firstaddr, foff, object->un_pager.vnp.vnp_size);
683 }
684 vnode_pager_freepage(m[i]);
685 runend = i + 1;
686 first = runend;

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

713 }
714 count -= first;
715 reqpage -= first;
716 }
717
718 /*
719 * calculate the file virtual address for the transfer
720 */
721 foff = IDX_TO_OFF(m[0]->pindex);
722
723 /*
724 * calculate the size of the transfer
725 */
726 size = count * PAGE_SIZE;
727 if ((foff + size) > object->un_pager.vnp.vnp_size)
728 size = object->un_pager.vnp.vnp_size - foff;
729

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

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

--- 17 unchanged lines hidden ---