aboutsummaryrefslogtreecommitdiff
path: root/sys/fs
diff options
context:
space:
mode:
authorJohn Dyson <dyson@FreeBSD.org>1995-10-23 02:23:29 +0000
committerJohn Dyson <dyson@FreeBSD.org>1995-10-23 02:23:29 +0000
commit2c4488fce37090fbfb35b31f1a0390f4fa6da3fb (patch)
tree5523ea9a03a0c87c10ad76292dec8feb90cea8fc /sys/fs
parent9d45c3af90b96b38d4f6407c2c9b6c2a08215abb (diff)
downloadsrc-2c4488fce37090fbfb35b31f1a0390f4fa6da3fb.tar.gz
src-2c4488fce37090fbfb35b31f1a0390f4fa6da3fb.zip
Finalize GETPAGES layering scheme. Move the device GETPAGES
interface into specfs code. No need at this point to modify the PUTPAGES stuff except in the layered-type (NULL/UNION) filesystems.
Notes
Notes: svn path=/head/; revision=11701
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/cd9660/cd9660_vnops.c3
-rw-r--r--sys/fs/specfs/spec_vnops.c126
2 files changed, 127 insertions, 2 deletions
diff --git a/sys/fs/cd9660/cd9660_vnops.c b/sys/fs/cd9660/cd9660_vnops.c
index a187a664909f..32fe2c173c49 100644
--- a/sys/fs/cd9660/cd9660_vnops.c
+++ b/sys/fs/cd9660/cd9660_vnops.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)cd9660_vnops.c 8.3 (Berkeley) 1/23/94
- * $Id: cd9660_vnops.c,v 1.15 1995/08/02 13:00:40 dfr Exp $
+ * $Id: cd9660_vnops.c,v 1.16 1995/09/04 00:20:05 dyson Exp $
*/
#include <sys/param.h>
@@ -1007,6 +1007,7 @@ struct vnodeopv_entry_desc cd9660_specop_entries[] = {
{ &vop_vfree_desc, spec_vfree }, /* vfree */
{ &vop_truncate_desc, spec_truncate }, /* truncate */
{ &vop_update_desc, cd9660_update }, /* update */
+ { &vop_getpages_desc, spec_getpages},
{ &vop_bwrite_desc, vn_bwrite },
{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
};
diff --git a/sys/fs/specfs/spec_vnops.c b/sys/fs/specfs/spec_vnops.c
index 8705c7b9d72e..c7430b562470 100644
--- a/sys/fs/specfs/spec_vnops.c
+++ b/sys/fs/specfs/spec_vnops.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)spec_vnops.c 8.6 (Berkeley) 4/9/94
- * $Id: spec_vnops.c,v 1.14 1995/09/04 00:20:37 dyson Exp $
+ * $Id: spec_vnops.c,v 1.15 1995/10/06 09:47:58 phk Exp $
*/
#include <sys/param.h>
@@ -94,6 +94,7 @@ struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
{ &vop_truncate_desc, spec_truncate }, /* truncate */
{ &vop_update_desc, spec_update }, /* update */
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */
+ { &vop_getpages_desc, spec_getpages}, /* getpages */
{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
};
struct vnodeopv_desc spec_vnodeop_opv_desc =
@@ -101,6 +102,10 @@ struct vnodeopv_desc spec_vnodeop_opv_desc =
VNODEOP_SET(spec_vnodeop_opv_desc);
+#include <vm/vm.h>
+#include <vm/vm_pager.h>
+#include <vm/vnode_pager.h>
+
/*
* Trivial lookup routine that always fails.
*/
@@ -706,3 +711,122 @@ spec_badop()
panic("spec_badop called");
/* NOTREACHED */
}
+
+static void spec_getpages_iodone(struct buf *bp) {
+ bp->b_flags |= B_DONE;
+ wakeup(bp);
+}
+
+/*
+ * get page routine
+ */
+int
+spec_getpages(ap)
+ struct vop_getpages_args *ap;
+{
+ vm_offset_t kva;
+ int i, size;
+ daddr_t blkno;
+ struct buf *bp;
+ int s;
+ int error = 0;
+ int pcount;
+
+ pcount = round_page(ap->a_count) / PAGE_SIZE;
+ /*
+ * calculate the size of the transfer
+ */
+ blkno = (ap->a_m[0]->offset + ap->a_offset) / DEV_BSIZE;
+
+ /*
+ * round up physical size for real devices
+ */
+ size = (ap->a_count + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
+
+ bp = getpbuf();
+ kva = (vm_offset_t) bp->b_data;
+
+ /*
+ * and map the pages to be read into the kva
+ */
+ pmap_qenter(kva, ap->a_m, pcount);
+
+ /* build a minimal buffer header */
+ bp->b_flags = B_BUSY | B_READ | B_CALL;
+ bp->b_iodone = spec_getpages_iodone;
+ /* B_PHYS is not set, but it is nice to fill this in */
+ bp->b_proc = curproc;
+ bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred;
+ if (bp->b_rcred != NOCRED)
+ crhold(bp->b_rcred);
+ if (bp->b_wcred != NOCRED)
+ crhold(bp->b_wcred);
+ bp->b_blkno = blkno;
+ bp->b_lblkno = blkno;
+ pbgetvp(ap->a_vp, bp);
+ bp->b_bcount = size;
+ bp->b_bufsize = size;
+
+ cnt.v_vnodein++;
+ cnt.v_vnodepgsin += pcount;
+
+ /* do the input */
+ VOP_STRATEGY(bp);
+ if (bp->b_flags & B_ASYNC) {
+ return VM_PAGER_PEND;
+ }
+
+ s = splbio();
+ /* we definitely need to be at splbio here */
+
+ while ((bp->b_flags & B_DONE) == 0) {
+ tsleep(bp, PVM, "vnread", 0);
+ }
+ splx(s);
+ if ((bp->b_flags & B_ERROR) != 0)
+ error = EIO;
+
+ if (!error) {
+ if (ap->a_count != pcount * PAGE_SIZE) {
+ bzero((caddr_t) kva + ap->a_count,
+ PAGE_SIZE * pcount - ap->a_count);
+ }
+ }
+ pmap_qremove(kva, pcount);
+
+ /*
+ * free the buffer header back to the swap buffer pool
+ */
+ relpbuf(bp);
+
+ for (i = 0; i < pcount; i++) {
+ pmap_clear_modify(VM_PAGE_TO_PHYS(ap->a_m[i]));
+ ap->a_m[i]->dirty = 0;
+ ap->a_m[i]->valid = VM_PAGE_BITS_ALL;
+ if (i != ap->a_reqpage) {
+
+ /*
+ * whether or not to leave the page activated is up in
+ * the air, but we should put the page on a page queue
+ * somewhere. (it already is in the object). Result:
+ * It appears that emperical results show that
+ * deactivating pages is best.
+ */
+
+ /*
+ * just in case someone was asking for this page we
+ * now tell them that it is ok to use
+ */
+ if (!error) {
+ vm_page_deactivate(ap->a_m[i]);
+ PAGE_WAKEUP(ap->a_m[i]);
+ } else {
+ vnode_pager_freepage(ap->a_m[i]);
+ }
+ }
+ }
+ if (error) {
+ printf("spec_getpages: I/O read error\n");
+ }
+ return (error ? VM_PAGER_ERROR : VM_PAGER_OK);
+}