diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2001-12-10 04:45:33 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2001-12-10 04:45:33 +0000 |
commit | 1eef7286fcf85dd357190316b332838378170946 (patch) | |
tree | 5d07152a5670a8b50e09c86d0ca76970e76c6fc0 /sys | |
parent | c7c6e636a8bfbf2c68e2ed3e6d20fa1c5237bfb0 (diff) |
Big cleanup inspired by NetBSD with some parts of the code from NetBSD.
- get rid of VOP_BALLOCN and VOP_SIZE
- move the generic getpages and putpages into miscfs/genfs
- create a genfs_node which must be added to the top of the private portion
of each vnode for filsystems that want to use genfs_{get,put}pages
- rename genfs_mmap to vop_generic_mmap
Diffstat (limited to 'sys')
31 files changed, 908 insertions, 908 deletions
diff --git a/sys/adosfs/adosfs.h b/sys/adosfs/adosfs.h index d890747b09b..c608fba701b 100644 --- a/sys/adosfs/adosfs.h +++ b/sys/adosfs/adosfs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: adosfs.h,v 1.8 1998/08/21 23:03:13 csapuntz Exp $ */ +/* $OpenBSD: adosfs.h,v 1.9 2001/12/10 04:45:31 art Exp $ */ /* $NetBSD: adosfs.h,v 1.12 1996/10/08 22:18:02 thorpej Exp $ */ /* @@ -32,6 +32,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <miscfs/genfs/genfs.h> + /* * Amigados datestamp. (from 1/1/1978 00:00:00 local) */ @@ -51,6 +53,7 @@ enum anode_type { AROOT, ADIR, AFILE, ALDIR, ALFILE, ASLINK }; * table for f/e. it is always ANODETABSZ(ap) bytes in size. */ struct anode { + struct genfs_node gnode; LIST_ENTRY(anode) link; enum anode_type type; char name[31]; /* (r/d/f) name for object */ diff --git a/sys/adosfs/advfsops.c b/sys/adosfs/advfsops.c index 93c61772029..5cd599c4f8e 100644 --- a/sys/adosfs/advfsops.c +++ b/sys/adosfs/advfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: advfsops.c,v 1.19 2001/05/16 12:48:31 ho Exp $ */ +/* $OpenBSD: advfsops.c,v 1.20 2001/12/10 04:45:31 art Exp $ */ /* $NetBSD: advfsops.c,v 1.24 1996/12/22 10:10:12 cgd Exp $ */ /* @@ -557,6 +557,7 @@ adosfs_vget(mp, an, vpp) *vpp = vp; /* return vp */ brelse(bp); /* release buffer */ + vp->v_size = ap->fsize; return (0); } diff --git a/sys/adosfs/advnops.c b/sys/adosfs/advnops.c index 08b2dd3b7ac..4928e2b1b93 100644 --- a/sys/adosfs/advnops.c +++ b/sys/adosfs/advnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: advnops.c,v 1.20 2001/12/10 02:19:34 art Exp $ */ +/* $OpenBSD: advnops.c,v 1.21 2001/12/10 04:45:31 art Exp $ */ /* $NetBSD: advnops.c,v 1.32 1996/10/13 02:52:09 christos Exp $ */ /* @@ -132,8 +132,7 @@ struct vnodeopv_entry_desc adosfs_vnodeop_entries[] = { { &vop_advlock_desc, adosfs_advlock }, /* advlock */ { &vop_bwrite_desc, adosfs_bwrite }, /* bwrite */ { &vop_getpages_desc, genfs_getpages }, - { &vop_size_desc, genfs_size }, - { &vop_mmap_desc, genfs_mmap }, + { &vop_mmap_desc, vop_generic_mmap }, { NULL, NULL } }; diff --git a/sys/conf/files b/sys/conf/files index a8eb0af4854..b7331c270ea 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.232 2001/11/29 08:40:09 itojun Exp $ +# $OpenBSD: files,v 1.233 2001/12/10 04:45:31 art Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -533,6 +533,7 @@ file kern/vfs_syscalls.c file kern/vfs_vnops.c file kern/vnode_if.c file miscfs/deadfs/dead_vnops.c +file miscfs/genfs/genfs_vnops.c file miscfs/fdesc/fdesc_vfsops.c fdesc file miscfs/fdesc/fdesc_vnops.c fdesc file miscfs/fifofs/fifo_vnops.c fifo diff --git a/sys/isofs/cd9660/cd9660_node.h b/sys/isofs/cd9660/cd9660_node.h index d319e0bf8a1..15d02647f3a 100644 --- a/sys/isofs/cd9660/cd9660_node.h +++ b/sys/isofs/cd9660/cd9660_node.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cd9660_node.h,v 1.10 2001/06/23 02:14:22 csapuntz Exp $ */ +/* $OpenBSD: cd9660_node.h,v 1.11 2001/12/10 04:45:31 art Exp $ */ /* $NetBSD: cd9660_node.h,v 1.15 1997/04/11 21:52:01 kleink Exp $ */ /*- @@ -42,6 +42,7 @@ */ #include <sys/buf.h> +#include <miscfs/genfs/genfs.h> /* * Theoretically, directories can be more than 2Gb in length, @@ -76,6 +77,7 @@ struct iso_dnode { #endif struct iso_node { + struct genfs_node i_gnode; struct iso_node *i_next, **i_prev; /* hash chain */ struct vnode *i_vnode; /* vnode associated with this inode */ struct vnode *i_devvp; /* vnode for block I/O */ diff --git a/sys/isofs/cd9660/cd9660_vfsops.c b/sys/isofs/cd9660/cd9660_vfsops.c index b2b1455e6eb..75eb9be50a5 100644 --- a/sys/isofs/cd9660/cd9660_vfsops.c +++ b/sys/isofs/cd9660/cd9660_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cd9660_vfsops.c,v 1.25 2001/11/27 05:27:11 art Exp $ */ +/* $OpenBSD: cd9660_vfsops.c,v 1.26 2001/12/10 04:45:31 art Exp $ */ /* $NetBSD: cd9660_vfsops.c,v 1.26 1997/06/13 15:38:58 pk Exp $ */ /*- @@ -80,6 +80,10 @@ struct vfsops cd9660_vfsops = { cd9660_check_export }; +struct genfs_ops cd9660_genfsops = { + genfs_size, +}; + /* * Called by vfs_mountroot when iso is going to be mounted as root. */ @@ -939,7 +943,8 @@ retry: /* * XXX need generation number? */ - + + genfs_node_init(vp, &cd9660_genfsops); *vpp = vp; return (0); } diff --git a/sys/isofs/cd9660/cd9660_vnops.c b/sys/isofs/cd9660/cd9660_vnops.c index 28e6dfaecef..d137c5bd85f 100644 --- a/sys/isofs/cd9660/cd9660_vnops.c +++ b/sys/isofs/cd9660/cd9660_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cd9660_vnops.c,v 1.17 2001/12/10 02:19:34 art Exp $ */ +/* $OpenBSD: cd9660_vnops.c,v 1.18 2001/12/10 04:45:31 art Exp $ */ /* $NetBSD: cd9660_vnops.c,v 1.42 1997/10/16 23:56:57 christos Exp $ */ /*- @@ -1068,7 +1068,6 @@ struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { { &vop_advlock_desc, cd9660_advlock }, /* advlock */ { &vop_bwrite_desc, vop_generic_bwrite }, { &vop_getpages_desc, genfs_getpages }, - { &vop_size_desc, genfs_size }, { &vop_mmap_desc, cd9660_mmap }, { NULL, NULL } }; diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index df32acf1323..73414b79b42 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_default.c,v 1.14 2001/12/10 02:19:34 art Exp $ */ +/* $OpenBSD: vfs_default.c,v 1.15 2001/12/10 04:45:31 art Exp $ */ /* * Portions of this code are: @@ -312,690 +312,8 @@ lease_check(void *v) return (0); } -/* - * generic VM getpages routine. - * Return PG_BUSY pages for the given range, - * reading from backing store if necessary. - */ - -int -genfs_getpages(v) - void *v; -{ - struct vop_getpages_args /* { - struct vnode *a_vp; - voff_t a_offset; - vm_page_t *a_m; - int *a_count; - int a_centeridx; - vm_prot_t a_access_type; - int a_advice; - int a_flags; - } */ *ap = v; - - off_t newsize, diskeof, memeof; - off_t offset, origoffset, startoffset, endoffset, raoffset; - daddr_t lbn, blkno; - int s, i, error, npages, orignpages, npgs, run, ridx, pidx, pcount; - int fs_bshift, fs_bsize, dev_bshift, dev_bsize; - int flags = ap->a_flags; - size_t bytes, iobytes, tailbytes, totalbytes, skipbytes; - vaddr_t kva; - struct buf *bp, *mbp; - struct vnode *vp = ap->a_vp; - struct uvm_object *uobj = &vp->v_uobj; - struct vm_page *pgs[16]; /* XXXUBC 16 */ - struct ucred *cred = curproc->p_ucred; /* XXXUBC curproc */ - boolean_t async = (flags & PGO_SYNCIO) == 0; - boolean_t write = (ap->a_access_type & VM_PROT_WRITE) != 0; - boolean_t sawhole = FALSE; - struct proc *p = curproc; - UVMHIST_FUNC("genfs_getpages"); UVMHIST_CALLED(ubchist); - - UVMHIST_LOG(ubchist, "vp %p off 0x%x/%x count %d", - vp, ap->a_offset >> 32, ap->a_offset, *ap->a_count); - - /* XXXUBC temp limit */ - if (*ap->a_count > 16) { - return EINVAL; - } - - error = 0; - origoffset = ap->a_offset; - orignpages = *ap->a_count; - error = VOP_SIZE(vp, vp->v_size, &diskeof); - if (error) { - return error; - } - if (flags & PGO_PASTEOF) { - newsize = MAX(vp->v_size, - origoffset + (orignpages << PAGE_SHIFT)); - error = VOP_SIZE(vp, newsize, &memeof); - if (error) { - return error; - } - } else { - memeof = diskeof; - } - KASSERT(ap->a_centeridx >= 0 || ap->a_centeridx <= orignpages); - KASSERT((origoffset & (PAGE_SIZE - 1)) == 0 && origoffset >= 0); - KASSERT(orignpages > 0); - - /* - * Bounds-check the request. - */ - - if (origoffset + (ap->a_centeridx << PAGE_SHIFT) >= memeof) { - if ((flags & PGO_LOCKED) == 0) { - simple_unlock(&uobj->vmobjlock); - } - UVMHIST_LOG(ubchist, "off 0x%x count %d goes past EOF 0x%x", - origoffset, *ap->a_count, memeof,0); - return EINVAL; - } - - /* - * For PGO_LOCKED requests, just return whatever's in memory. - */ - - if (flags & PGO_LOCKED) { - uvn_findpages(uobj, origoffset, ap->a_count, ap->a_m, - UFP_NOWAIT|UFP_NOALLOC|UFP_NORDONLY); - - return ap->a_m[ap->a_centeridx] == NULL ? EBUSY : 0; - } - - /* vnode is VOP_LOCKed, uobj is locked */ - - if (write && (vp->v_bioflag & VBIOONSYNCLIST) == 0) { - vn_syncer_add_to_worklist(vp, syncdelay); - } - - /* - * find the requested pages and make some simple checks. - * leave space in the page array for a whole block. - */ - - fs_bshift = vp->v_mount->mnt_fs_bshift; - fs_bsize = 1 << fs_bshift; - dev_bshift = vp->v_mount->mnt_dev_bshift; - dev_bsize = 1 << dev_bshift; - KASSERT((diskeof & (dev_bsize - 1)) == 0); - KASSERT((memeof & (dev_bsize - 1)) == 0); - - orignpages = MIN(orignpages, - round_page(memeof - origoffset) >> PAGE_SHIFT); - npages = orignpages; - startoffset = origoffset & ~(fs_bsize - 1); - endoffset = round_page((origoffset + (npages << PAGE_SHIFT) - + fs_bsize - 1) & ~(fs_bsize - 1)); - endoffset = MIN(endoffset, round_page(memeof)); - ridx = (origoffset - startoffset) >> PAGE_SHIFT; - - memset(pgs, 0, sizeof(pgs)); - uvn_findpages(uobj, origoffset, &npages, &pgs[ridx], UFP_ALL); - - /* - * if PGO_OVERWRITE is set, don't bother reading the pages. - * PGO_OVERWRITE also means that the caller guarantees - * that the pages already have backing store allocated. - */ - - if (flags & PGO_OVERWRITE) { - UVMHIST_LOG(ubchist, "PGO_OVERWRITE",0,0,0,0); - - for (i = 0; i < npages; i++) { - struct vm_page *pg = pgs[ridx + i]; - - if (pg->flags & PG_FAKE) { - uvm_pagezero(pg); - pg->flags &= ~(PG_FAKE); - } - pg->flags &= ~(PG_RDONLY); - } - npages += ridx; - goto out; - } - - /* - * if the pages are already resident, just return them. - */ - - for (i = 0; i < npages; i++) { - struct vm_page *pg = pgs[ridx + i]; - - if ((pg->flags & PG_FAKE) || - (write && (pg->flags & PG_RDONLY))) { - break; - } - } - if (i == npages) { - UVMHIST_LOG(ubchist, "returning cached pages", 0,0,0,0); - raoffset = origoffset + (orignpages << PAGE_SHIFT); - npages += ridx; - goto raout; - } - - /* - * the page wasn't resident and we're not overwriting, - * so we're going to have to do some i/o. - * find any additional pages needed to cover the expanded range. - */ - - npages = (endoffset - startoffset) >> PAGE_SHIFT; - if (startoffset != origoffset || npages != orignpages) { - - /* - * XXXUBC we need to avoid deadlocks caused by locking - * additional pages at lower offsets than pages we - * already have locked. for now, unlock them all and - * start over. - */ - - for (i = 0; i < orignpages; i++) { - struct vm_page *pg = pgs[ridx + i]; - - if (pg->flags & PG_FAKE) { - pg->flags |= PG_RELEASED; - } - } - uvm_page_unbusy(&pgs[ridx], orignpages); - memset(pgs, 0, sizeof(pgs)); - - UVMHIST_LOG(ubchist, "reset npages start 0x%x end 0x%x", - startoffset, endoffset, 0,0); - npgs = npages; - uvn_findpages(uobj, startoffset, &npgs, pgs, UFP_ALL); - } - simple_unlock(&uobj->vmobjlock); - - /* - * read the desired page(s). - */ - - totalbytes = npages << PAGE_SHIFT; - bytes = MIN(totalbytes, MAX(diskeof - startoffset, 0)); - tailbytes = totalbytes - bytes; - skipbytes = 0; - - kva = uvm_pagermapin(pgs, npages, UVMPAGER_MAPIN_WAITOK | - UVMPAGER_MAPIN_READ); - - s = splbio(); - mbp = pool_get(&bufpool, PR_WAITOK); - splx(s); - mbp->b_bufsize = totalbytes; - mbp->b_data = (void *)kva; - mbp->b_resid = mbp->b_bcount = bytes; - mbp->b_flags = B_BUSY|B_READ| (async ? B_CALL : 0); - mbp->b_iodone = uvm_aio_biodone; - mbp->b_vp = NULL; - LIST_INIT(&mbp->b_dep); - bgetvp(vp, mbp); - - /* - * if EOF is in the middle of the range, zero the part past EOF. - */ - - if (tailbytes > 0) { - memset((void *)(kva + bytes), 0, tailbytes); - } - - /* - * now loop over the pages, reading as needed. - */ - - if (write) { - lockmgr(&vp->v_glock, LK_EXCLUSIVE, NULL, p); - } else { - lockmgr(&vp->v_glock, LK_SHARED, NULL, p); - } - - bp = NULL; - for (offset = startoffset; - bytes > 0; - offset += iobytes, bytes -= iobytes) { - - /* - * skip pages which don't need to be read. - */ - - pidx = (offset - startoffset) >> PAGE_SHIFT; - while ((pgs[pidx]->flags & (PG_FAKE|PG_RDONLY)) == 0) { - size_t b; - - KASSERT((offset & (PAGE_SIZE - 1)) == 0); - b = MIN(PAGE_SIZE, bytes); - offset += b; - bytes -= b; - skipbytes += b; - pidx++; - UVMHIST_LOG(ubchist, "skipping, new offset 0x%x", - offset, 0,0,0); - if (bytes == 0) { - goto loopdone; - } - } - - /* - * bmap the file to find out the blkno to read from and - * how much we can read in one i/o. if bmap returns an error, - * skip the rest of the top-level i/o. - */ - - lbn = offset >> fs_bshift; - error = VOP_BMAP(vp, lbn, NULL, &blkno, &run); - if (error) { - UVMHIST_LOG(ubchist, "VOP_BMAP lbn 0x%x -> %d\n", - lbn, error,0,0); - skipbytes += bytes; - goto loopdone; - } - - /* - * see how many pages can be read with this i/o. - * reduce the i/o size if necessary to avoid - * overwriting pages with valid data. - */ - - iobytes = MIN((((off_t)lbn + 1 + run) << fs_bshift) - offset, - bytes); - if (offset + iobytes > round_page(offset)) { - pcount = 1; - while (pidx + pcount < npages && - pgs[pidx + pcount]->flags & PG_FAKE) { - pcount++; - } - iobytes = MIN(iobytes, (pcount << PAGE_SHIFT) - - (offset - trunc_page(offset))); - } - - /* - * if this block isn't allocated, zero it instead of reading it. - * if this is a read access, mark the pages we zeroed PG_RDONLY. - */ - - if (blkno < 0) { - int holepages = (round_page(offset + iobytes) - - trunc_page(offset)) >> PAGE_SHIFT; - UVMHIST_LOG(ubchist, "lbn 0x%x -> HOLE", lbn,0,0,0); - - sawhole = TRUE; - memset((char *)kva + (offset - startoffset), 0, - iobytes); - skipbytes += iobytes; - - for (i = 0; i < holepages; i++) { - if (write) { - pgs[pidx + i]->flags &= ~PG_CLEAN; - } else { - pgs[pidx + i]->flags |= PG_RDONLY; - } - } - continue; - } - - /* - * allocate a sub-buf for this piece of the i/o - * (or just use mbp if there's only 1 piece), - * and start it going. - */ - - if (offset == startoffset && iobytes == bytes) { - bp = mbp; - } else { - s = splbio(); - bp = pool_get(&bufpool, PR_WAITOK); - splx(s); - bp->b_data = (char *)kva + offset - startoffset; - bp->b_resid = bp->b_bcount = iobytes; - bp->b_flags = B_BUSY|B_READ|B_CALL; - bp->b_iodone = uvm_aio_biodone1; - bp->b_vp = vp; - LIST_INIT(&bp->b_dep); - } - bp->b_lblkno = 0; - bp->b_private = mbp; - - /* adjust physical blkno for partial blocks */ - bp->b_blkno = blkno + ((offset - ((off_t)lbn << fs_bshift)) >> - dev_bshift); - - UVMHIST_LOG(ubchist, "bp %p offset 0x%x bcount 0x%x blkno 0x%x", - bp, offset, iobytes, bp->b_blkno); - - VOP_STRATEGY(bp); - } - -loopdone: - if (skipbytes) { - s = splbio(); - if (error) { - mbp->b_flags |= B_ERROR; - mbp->b_error = error; - } - mbp->b_resid -= skipbytes; - if (mbp->b_resid == 0) { - biodone(mbp); - } - splx(s); - } - - if (async) { - UVMHIST_LOG(ubchist, "returning 0 (async)",0,0,0,0); - lockmgr(&vp->v_glock, LK_RELEASE, NULL, p); - return 0; - } - if (bp != NULL) { - error = biowait(mbp); - } - s = splbio(); - (void) buf_cleanout(mbp); - pool_put(&bufpool, mbp); - splx(s); - uvm_pagermapout(kva, npages); - raoffset = startoffset + totalbytes; - - /* - * if this we encountered a hole then we have to do a little more work. - * for read faults, we marked the page PG_RDONLY so that future - * write accesses to the page will fault again. - * for write faults, we must make sure that the backing store for - * the page is completely allocated while the pages are locked. - */ - - if (error == 0 && sawhole && write) { - error = VOP_BALLOCN(vp, startoffset, npages << PAGE_SHIFT, - cred, 0); - if (error) { - UVMHIST_LOG(ubchist, "balloc lbn 0x%x -> %d", - lbn, error,0,0); - lockmgr(&vp->v_glock, LK_RELEASE, NULL, p); - simple_lock(&uobj->vmobjlock); - goto out; - } - } - lockmgr(&vp->v_glock, LK_RELEASE, NULL, p); - simple_lock(&uobj->vmobjlock); - - /* - * see if we want to start any readahead. - * XXXUBC for now, just read the next 128k on 64k boundaries. - * this is pretty nonsensical, but it is 50% faster than reading - * just the next 64k. - */ - -raout: - if (!error && !async && !write && ((int)raoffset & 0xffff) == 0 && - PAGE_SHIFT <= 16) { - int racount; - - racount = 1 << (16 - PAGE_SHIFT); - (void) VOP_GETPAGES(vp, raoffset, NULL, &racount, 0, - VM_PROT_READ, 0, 0); - simple_lock(&uobj->vmobjlock); - - racount = 1 << (16 - PAGE_SHIFT); - (void) VOP_GETPAGES(vp, raoffset + 0x10000, NULL, &racount, 0, - VM_PROT_READ, 0, 0); - simple_lock(&uobj->vmobjlock); - } - - /* - * we're almost done! release the pages... - * for errors, we free the pages. - * otherwise we activate them and mark them as valid and clean. - * also, unbusy pages that were not actually requested. - */ - -out: - if (error) { - uvm_lock_pageq(); - for (i = 0; i < npages; i++) { - if (pgs[i] == NULL) { - continue; - } - UVMHIST_LOG(ubchist, "examining pg %p flags 0x%x", - pgs[i], pgs[i]->flags, 0,0); - if (pgs[i]->flags & PG_WANTED) { - wakeup(pgs[i]); - } - if (pgs[i]->flags & PG_RELEASED) { - uvm_unlock_pageq(); - (uobj->pgops->pgo_releasepg)(pgs[i], NULL); - uvm_lock_pageq(); - continue; - } - if (pgs[i]->flags & PG_FAKE) { - uvm_pagefree(pgs[i]); - continue; - } - uvm_pageactivate(pgs[i]); - pgs[i]->flags &= ~(PG_WANTED|PG_BUSY); - UVM_PAGE_OWN(pgs[i], NULL); - } - uvm_unlock_pageq(); - simple_unlock(&uobj->vmobjlock); - UVMHIST_LOG(ubchist, "returning error %d", error,0,0,0); - return error; - } - - UVMHIST_LOG(ubchist, "succeeding, npages %d", npages,0,0,0); - uvm_lock_pageq(); - for (i = 0; i < npages; i++) { - if (pgs[i] == NULL) { - continue; - } - UVMHIST_LOG(ubchist, "examining pg %p flags 0x%x", - pgs[i], pgs[i]->flags, 0,0); - if (pgs[i]->flags & PG_FAKE) { - UVMHIST_LOG(ubchist, "unfaking pg %p offset 0x%x", - pgs[i], pgs[i]->offset,0,0); - pgs[i]->flags &= ~(PG_FAKE); - pmap_clear_modify(pgs[i]); - pmap_clear_reference(pgs[i]); - } - if (write) { - pgs[i]->flags &= ~(PG_RDONLY); - } - if (i < ridx || i >= ridx + orignpages || async) { - UVMHIST_LOG(ubchist, "unbusy pg %p offset 0x%x", - pgs[i], pgs[i]->offset,0,0); - if (pgs[i]->flags & PG_WANTED) { - wakeup(pgs[i]); - } - if (pgs[i]->flags & PG_RELEASED) { - uvm_unlock_pageq(); - (uobj->pgops->pgo_releasepg)(pgs[i], NULL); - uvm_lock_pageq(); - continue; - } - uvm_pageactivate(pgs[i]); - pgs[i]->flags &= ~(PG_WANTED|PG_BUSY); - UVM_PAGE_OWN(pgs[i], NULL); - } - } - uvm_unlock_pageq(); - simple_unlock(&uobj->vmobjlock); - if (ap->a_m != NULL) { - memcpy(ap->a_m, &pgs[ridx], - orignpages * sizeof(struct vm_page *)); - } - return 0; -} - -/* - * generic VM putpages routine. - * Write the given range of pages to backing store. - */ - -int -genfs_putpages(v) - void *v; -{ - struct vop_putpages_args /* { - struct vnode *a_vp; - struct vm_page **a_m; - int a_count; - int a_flags; - int *a_rtvals; - } */ *ap = v; - - int s, error, npages, run; - int fs_bshift, dev_bshift, dev_bsize; - vaddr_t kva; - off_t eof, offset, startoffset; - size_t bytes, iobytes, skipbytes; - daddr_t lbn, blkno; - struct vm_page *pg; - struct buf *mbp, *bp; - struct vnode *vp = ap->a_vp; - boolean_t async = (ap->a_flags & PGO_SYNCIO) == 0; - UVMHIST_FUNC("genfs_putpages"); UVMHIST_CALLED(ubchist); - UVMHIST_LOG(ubchist, "vp %p offset 0x%x count %d", - vp, ap->a_m[0]->offset, ap->a_count, 0); - - simple_unlock(&vp->v_uobj.vmobjlock); - - error = VOP_SIZE(vp, vp->v_size, &eof); - if (error) { - return error; - } - - error = 0; - npages = ap->a_count; - fs_bshift = vp->v_mount->mnt_fs_bshift; - dev_bshift = vp->v_mount->mnt_dev_bshift; - dev_bsize = 1 << dev_bshift; - KASSERT((eof & (dev_bsize - 1)) == 0); - - pg = ap->a_m[0]; - startoffset = pg->offset; - bytes = MIN(npages << PAGE_SHIFT, eof - startoffset); - skipbytes = 0; - KASSERT(bytes != 0); - - kva = uvm_pagermapin(ap->a_m, npages, UVMPAGER_MAPIN_WAITOK); - - s = splbio(); - vp->v_numoutput += 2; - mbp = pool_get(&bufpool, PR_WAITOK); - UVMHIST_LOG(ubchist, "vp %p mbp %p num now %d bytes 0x%x", - vp, mbp, vp->v_numoutput, bytes); - splx(s); - mbp->b_bufsize = npages << PAGE_SHIFT; - mbp->b_data = (void *)kva; - mbp->b_resid = mbp->b_bcount = bytes; - mbp->b_flags = B_BUSY|B_WRITE|B_AGE | - (async ? B_CALL : 0) | - (curproc == uvm.pagedaemon_proc ? B_PDAEMON : 0); - mbp->b_iodone = uvm_aio_biodone; - mbp->b_vp = NULL; - LIST_INIT(&mbp->b_dep); - bgetvp(vp, mbp); - - bp = NULL; - for (offset = startoffset; - bytes > 0; - offset += iobytes, bytes -= iobytes) { - lbn = offset >> fs_bshift; - error = VOP_BMAP(vp, lbn, NULL, &blkno, &run); - if (error) { - UVMHIST_LOG(ubchist, "VOP_BMAP() -> %d", error,0,0,0); - skipbytes += bytes; - bytes = 0; - break; - } - - iobytes = MIN((((off_t)lbn + 1 + run) << fs_bshift) - offset, - bytes); - if (blkno == (daddr_t)-1) { - skipbytes += iobytes; - continue; - } - - /* if it's really one i/o, don't make a second buf */ - if (offset == startoffset && iobytes == bytes) { - bp = mbp; - } else { - s = splbio(); - vp->v_numoutput++; - bp = pool_get(&bufpool, PR_WAITOK); - UVMHIST_LOG(ubchist, "vp %p bp %p num now %d", - vp, bp, vp->v_numoutput, 0); - splx(s); - bp->b_data = (char *)kva + - (vaddr_t)(offset - pg->offset); - bp->b_resid = bp->b_bcount = iobytes; - bp->b_flags = B_BUSY|B_WRITE|B_CALL|B_ASYNC; - bp->b_iodone = uvm_aio_biodone1; - bp->b_vp = vp; - LIST_INIT(&bp->b_dep); - } - bp->b_lblkno = 0; - bp->b_private = mbp; - - /* adjust physical blkno for partial blocks */ - bp->b_blkno = blkno + ((offset - ((off_t)lbn << fs_bshift)) >> - dev_bshift); - UVMHIST_LOG(ubchist, "vp %p offset 0x%x bcount 0x%x blkno 0x%x", - vp, offset, bp->b_bcount, bp->b_blkno); - VOP_STRATEGY(bp); - } - if (skipbytes) { - UVMHIST_LOG(ubchist, "skipbytes %d", skipbytes, 0,0,0); - s = splbio(); - mbp->b_resid -= skipbytes; - if (error) { - mbp->b_flags |= B_ERROR; - mbp->b_error = error; - } - if (mbp->b_resid == 0) { - biodone(mbp); - } - splx(s); - } - if (async) { - UVMHIST_LOG(ubchist, "returning 0 (async)", 0,0,0,0); - return 0; - } - if (bp != NULL) { - UVMHIST_LOG(ubchist, "waiting for mbp %p", mbp,0,0,0); - error = biowait(mbp); - } - if (bioops.io_pageiodone) { - (*bioops.io_pageiodone)(mbp); - } - s = splbio(); - if (mbp->b_vp) { - vwakeup(mbp->b_vp); - } - buf_cleanout(mbp); - pool_put(&bufpool, mbp); - splx(s); - uvm_pagermapout(kva, npages); - UVMHIST_LOG(ubchist, "returning, error %d", error,0,0,0); - return error; -} - -int -genfs_size(v) - void *v; -{ - struct vop_size_args /* { - struct vnode *a_vp; - off_t a_size; - off_t *a_eobp; - } */ *ap = v; - int bsize; - - bsize = 1 << ap->a_vp->v_mount->mnt_fs_bshift; - *ap->a_eobp = (ap->a_size + bsize - 1) & ~(bsize - 1); - return 0; -} - int -genfs_mmap(v) +vop_generic_mmap(v) void *v; { return 0; diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 723d837c606..6fbb27dbecb 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_subr.c,v 1.77 2001/12/10 02:19:34 art Exp $ */ +/* $OpenBSD: vfs_subr.c,v 1.78 2001/12/10 04:45:31 art Exp $ */ /* $NetBSD: vfs_subr.c,v 1.53 1996/04/22 01:39:13 christos Exp $ */ /* @@ -460,7 +460,6 @@ getnewvnode(tag, mp, vops, vpp) vp->v_socket = 0; } vp->v_type = VNON; - lockinit(&vp->v_glock, PVFS, "glock", 0, 0); cache_purge(vp); vp->v_tag = tag; vp->v_op = vops; diff --git a/sys/kern/vnode_if.c b/sys/kern/vnode_if.c index 8459a5486a7..9819bea72e4 100644 --- a/sys/kern/vnode_if.c +++ b/sys/kern/vnode_if.c @@ -1230,39 +1230,6 @@ int VOP_WHITEOUT(dvp, cnp, flags) return (VCALL(dvp, VOFFSET(vop_whiteout), &a)); } -int vop_ballocn_vp_offsets[] = { - VOPARG_OFFSETOF(struct vop_ballocn_args,a_vp), - VDESC_NO_OFFSET -}; -struct vnodeop_desc vop_ballocn_desc = { - 0, - "vop_ballocn", - 0, - vop_ballocn_vp_offsets, - VDESC_NO_OFFSET, - VOPARG_OFFSETOF(struct vop_ballocn_args, a_cred), - VDESC_NO_OFFSET, - VDESC_NO_OFFSET, - NULL, -}; - -int VOP_BALLOCN(vp, offset, length, cred, flags) - struct vnode *vp; - off_t offset; - off_t length; - struct ucred *cred; - int flags; -{ - struct vop_ballocn_args a; - a.a_desc = VDESC(vop_ballocn); - a.a_vp = vp; - a.a_offset = offset; - a.a_length = length; - a.a_cred = cred; - a.a_flags = flags; - return (VCALL(vp, VOFFSET(vop_ballocn), &a)); -} - int vop_getpages_vp_offsets[] = { VOPARG_OFFSETOF(struct vop_getpages_args,a_vp), VDESC_NO_OFFSET @@ -1335,35 +1302,6 @@ int VOP_PUTPAGES(vp, m, count, flags, rtvals) return (VCALL(vp, VOFFSET(vop_putpages), &a)); } -int vop_size_vp_offsets[] = { - VOPARG_OFFSETOF(struct vop_size_args,a_vp), - VDESC_NO_OFFSET -}; -struct vnodeop_desc vop_size_desc = { - 0, - "vop_size", - 0, - vop_size_vp_offsets, - VDESC_NO_OFFSET, - VDESC_NO_OFFSET, - VDESC_NO_OFFSET, - VDESC_NO_OFFSET, - NULL, -}; - -int VOP_SIZE(vp, size, eobp) - struct vnode *vp; - off_t size; - off_t *eobp; -{ - struct vop_size_args a; - a.a_desc = VDESC(vop_size); - a.a_vp = vp; - a.a_size = size; - a.a_eobp = eobp; - return (VCALL(vp, VOFFSET(vop_size), &a)); -} - int vop_mmap_vp_offsets[] = { VOPARG_OFFSETOF(struct vop_mmap_args,a_vp), VDESC_NO_OFFSET @@ -1488,10 +1426,8 @@ struct vnodeop_desc *vfs_op_descs[] = { &vop_advlock_desc, &vop_reallocblks_desc, &vop_whiteout_desc, - &vop_ballocn_desc, &vop_getpages_desc, &vop_putpages_desc, - &vop_size_desc, &vop_mmap_desc, NULL }; diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index fc1a45351cd..0efb5afdd4f 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -1,4 +1,4 @@ -# $OpenBSD: vnode_if.src,v 1.16 2001/12/04 22:44:31 art Exp $ +# $OpenBSD: vnode_if.src,v 1.17 2001/12/10 04:45:31 art Exp $ # $NetBSD: vnode_if.src,v 1.10 1996/05/11 18:26:27 mycroft Exp $ # # Copyright (c) 1992, 1993 @@ -469,17 +469,6 @@ vop_whiteout { #}; # -#% ballocn vp L L L -# -vop_ballocn { - IN struct vnode *vp; - IN off_t offset; - IN off_t length; - IN struct ucred *cred; - IN int flags; -}; - -# #% getpages vp L L L # vop_getpages { @@ -505,15 +494,6 @@ vop_putpages { }; # -#% size vp = = = -# -vop_size { - IN struct vnode *vp; - IN off_t size; - OUT off_t *eobp; -}; - -# #% mmap vp = = = # vop_mmap { diff --git a/sys/miscfs/genfs/genfs.h b/sys/miscfs/genfs/genfs.h new file mode 100644 index 00000000000..8cb886b5074 --- /dev/null +++ b/sys/miscfs/genfs/genfs.h @@ -0,0 +1,71 @@ +/* $OpenBSD: genfs.h,v 1.1 2001/12/10 04:45:31 art Exp $ */ +/* $NetBSD: genfs_node.h,v 1.2 2001/09/15 22:38:40 chs Exp $ */ + +/* + * Copyright (c) 2001 Chuck Silvers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Chuck Silvers. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MISCFS_GENFS_GENFS_NODE_H_ +#define _MISCFS_GENFS_GENFS_NODE_H_ + +struct vm_page; + +struct genfs_ops { + void (*gop_size)(struct vnode *, off_t, off_t *); + int (*gop_alloc)(struct vnode *, off_t, off_t, int, struct ucred *); +#ifdef notyet + int (*gop_write)(struct vnode *, struct vm_page **, int, int); +#endif +}; + +#define GOP_SIZE(vp, size, eobp) \ + (*VTOG(vp)->g_op->gop_size)((vp), (size), (eobp)) +#define GOP_ALLOC(vp, off, len, flags, cred) \ + (*VTOG(vp)->g_op->gop_alloc)((vp), (off), (len), (flags), (cred)) +#ifdef notyet +#define GOP_WRITE(vp, pgs, npages, flags) \ + (*VTOG(vp)->g_op->gop_write)((vp), (pgs), (npages), (flags)) +#endif +struct genfs_node { + struct genfs_ops *g_op; /* ops vector */ + struct lock g_glock; /* getpages lock */ +}; + +#define VTOG(vp) ((struct genfs_node *)(vp)->v_data) + +void genfs_size(struct vnode *, off_t, off_t *); +void genfs_node_init(struct vnode *, struct genfs_ops *); +#ifdef notyet +int genfs_gop_write(struct vnode *, struct vm_page **, int, int); +#endif + +int genfs_getpages __P((void *)); +int genfs_putpages __P((void *)); + +#endif /* _MISCFS_GENFS_GENFS_NODE_H_ */ diff --git a/sys/miscfs/genfs/genfs_vnops.c b/sys/miscfs/genfs/genfs_vnops.c new file mode 100644 index 00000000000..7630caa60e7 --- /dev/null +++ b/sys/miscfs/genfs/genfs_vnops.c @@ -0,0 +1,723 @@ +/* $OpenBSD: genfs_vnops.c,v 1.1 2001/12/10 04:45:31 art Exp $ */ +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/kernel.h> +#include <sys/mount.h> +#include <sys/namei.h> +#include <sys/vnode.h> +#include <sys/fcntl.h> +#include <sys/malloc.h> +#include <sys/poll.h> +#include <sys/mman.h> +#include <sys/pool.h> + +#include <miscfs/genfs/genfs.h> +#include <miscfs/specfs/specdev.h> + +#include <uvm/uvm.h> +#include <uvm/uvm_pager.h> + +/* + * generic VM getpages routine. + * Return PG_BUSY pages for the given range, + * reading from backing store if necessary. + */ + +int +genfs_getpages(v) + void *v; +{ + struct vop_getpages_args /* { + struct vnode *a_vp; + voff_t a_offset; + vm_page_t *a_m; + int *a_count; + int a_centeridx; + vm_prot_t a_access_type; + int a_advice; + int a_flags; + } */ *ap = v; + + off_t newsize, diskeof, memeof; + off_t offset, origoffset, startoffset, endoffset, raoffset; + daddr_t lbn, blkno; + int s, i, error, npages, orignpages, npgs, run, ridx, pidx, pcount; + int fs_bshift, fs_bsize, dev_bshift; + int flags = ap->a_flags; + size_t bytes, iobytes, tailbytes, totalbytes, skipbytes; + vaddr_t kva; + struct buf *bp, *mbp; + struct vnode *vp = ap->a_vp; + struct uvm_object *uobj = &vp->v_uobj; + struct vm_page *pgs[16]; /* XXXUBC 16 */ + struct genfs_node *gp = VTOG(vp); + struct ucred *cred = curproc->p_ucred; /* XXXUBC curproc */ + boolean_t async = (flags & PGO_SYNCIO) == 0; + boolean_t write = (ap->a_access_type & VM_PROT_WRITE) != 0; + boolean_t sawhole = FALSE; + struct proc *p = curproc; + UVMHIST_FUNC("genfs_getpages"); UVMHIST_CALLED(ubchist); + + UVMHIST_LOG(ubchist, "vp %p off 0x%x/%x count %d", + vp, ap->a_offset >> 32, ap->a_offset, *ap->a_count); + + /* XXXUBC temp limit */ + if (*ap->a_count > 16) { + return EINVAL; + } + + error = 0; + origoffset = ap->a_offset; + orignpages = *ap->a_count; + GOP_SIZE(vp, vp->v_size, &diskeof); + if (flags & PGO_PASTEOF) { + newsize = MAX(vp->v_size, + origoffset + (orignpages << PAGE_SHIFT)); + GOP_SIZE(vp, newsize, &memeof); + } else { + memeof = diskeof; + } + KASSERT(ap->a_centeridx >= 0 || ap->a_centeridx <= orignpages); + KASSERT((origoffset & (PAGE_SIZE - 1)) == 0 && origoffset >= 0); + KASSERT(orignpages > 0); + + /* + * Bounds-check the request. + */ + + if (origoffset + (ap->a_centeridx << PAGE_SHIFT) >= memeof) { + if ((flags & PGO_LOCKED) == 0) { + simple_unlock(&uobj->vmobjlock); + } + UVMHIST_LOG(ubchist, "off 0x%x count %d goes past EOF 0x%x", + origoffset, *ap->a_count, memeof,0); + return EINVAL; + } + + /* + * For PGO_LOCKED requests, just return whatever's in memory. + */ + + if (flags & PGO_LOCKED) { + uvn_findpages(uobj, origoffset, ap->a_count, ap->a_m, + UFP_NOWAIT|UFP_NOALLOC|UFP_NORDONLY); + + return ap->a_m[ap->a_centeridx] == NULL ? EBUSY : 0; + } + + /* vnode is VOP_LOCKed, uobj is locked */ + + if (write && (vp->v_bioflag & VBIOONSYNCLIST) == 0) { + vn_syncer_add_to_worklist(vp, syncdelay); + } + + /* + * find the requested pages and make some simple checks. + * leave space in the page array for a whole block. + */ + + fs_bshift = vp->v_mount->mnt_fs_bshift; + fs_bsize = 1 << fs_bshift; + dev_bshift = vp->v_mount->mnt_dev_bshift; + + orignpages = MIN(orignpages, + round_page(memeof - origoffset) >> PAGE_SHIFT); + npages = orignpages; + startoffset = origoffset & ~(fs_bsize - 1); + endoffset = round_page((origoffset + (npages << PAGE_SHIFT) + + fs_bsize - 1) & ~(fs_bsize - 1)); + endoffset = MIN(endoffset, round_page(memeof)); + ridx = (origoffset - startoffset) >> PAGE_SHIFT; + + memset(pgs, 0, sizeof(pgs)); + uvn_findpages(uobj, origoffset, &npages, &pgs[ridx], UFP_ALL); + + /* + * if PGO_OVERWRITE is set, don't bother reading the pages. + * PGO_OVERWRITE also means that the caller guarantees + * that the pages already have backing store allocated. + */ + + if (flags & PGO_OVERWRITE) { + UVMHIST_LOG(ubchist, "PGO_OVERWRITE",0,0,0,0); + + for (i = 0; i < npages; i++) { + struct vm_page *pg = pgs[ridx + i]; + + if (pg->flags & PG_FAKE) { + uvm_pagezero(pg); + pg->flags &= ~(PG_FAKE); + } + pg->flags &= ~(PG_RDONLY); + } + npages += ridx; + goto out; + } + + /* + * if the pages are already resident, just return them. + */ + + for (i = 0; i < npages; i++) { + struct vm_page *pg = pgs[ridx + i]; + + if ((pg->flags & PG_FAKE) || + (write && (pg->flags & PG_RDONLY))) { + break; + } + } + if (i == npages) { + UVMHIST_LOG(ubchist, "returning cached pages", 0,0,0,0); + raoffset = origoffset + (orignpages << PAGE_SHIFT); + npages += ridx; + goto raout; + } + + /* + * the page wasn't resident and we're not overwriting, + * so we're going to have to do some i/o. + * find any additional pages needed to cover the expanded range. + */ + + npages = (endoffset - startoffset) >> PAGE_SHIFT; + if (startoffset != origoffset || npages != orignpages) { + + /* + * XXXUBC we need to avoid deadlocks caused by locking + * additional pages at lower offsets than pages we + * already have locked. for now, unlock them all and + * start over. + */ + + for (i = 0; i < orignpages; i++) { + struct vm_page *pg = pgs[ridx + i]; + + if (pg->flags & PG_FAKE) { + pg->flags |= PG_RELEASED; + } + } + uvm_page_unbusy(&pgs[ridx], orignpages); + memset(pgs, 0, sizeof(pgs)); + + UVMHIST_LOG(ubchist, "reset npages start 0x%x end 0x%x", + startoffset, endoffset, 0,0); + npgs = npages; + uvn_findpages(uobj, startoffset, &npgs, pgs, UFP_ALL); + } + simple_unlock(&uobj->vmobjlock); + + /* + * read the desired page(s). + */ + + totalbytes = npages << PAGE_SHIFT; + bytes = MIN(totalbytes, MAX(diskeof - startoffset, 0)); + tailbytes = totalbytes - bytes; + skipbytes = 0; + + kva = uvm_pagermapin(pgs, npages, UVMPAGER_MAPIN_WAITOK | + UVMPAGER_MAPIN_READ); + + s = splbio(); + mbp = pool_get(&bufpool, PR_WAITOK); + splx(s); + mbp->b_bufsize = totalbytes; + mbp->b_data = (void *)kva; + mbp->b_resid = mbp->b_bcount = bytes; + mbp->b_flags = B_BUSY|B_READ| (async ? B_CALL : 0); + mbp->b_iodone = uvm_aio_biodone; + mbp->b_vp = NULL; + LIST_INIT(&mbp->b_dep); + bgetvp(vp, mbp); + + /* + * if EOF is in the middle of the range, zero the part past EOF. + */ + + if (tailbytes > 0) { + memset((void *)(kva + bytes), 0, tailbytes); + } + + /* + * now loop over the pages, reading as needed. + */ + + if (write) { + lockmgr(&gp->g_glock, LK_EXCLUSIVE, NULL, p); + } else { + lockmgr(&gp->g_glock, LK_SHARED, NULL, p); + } + + bp = NULL; + for (offset = startoffset; + bytes > 0; + offset += iobytes, bytes -= iobytes) { + + /* + * skip pages which don't need to be read. + */ + + pidx = (offset - startoffset) >> PAGE_SHIFT; + while ((pgs[pidx]->flags & (PG_FAKE|PG_RDONLY)) == 0) { + size_t b; + + KASSERT((offset & (PAGE_SIZE - 1)) == 0); + b = MIN(PAGE_SIZE, bytes); + offset += b; + bytes -= b; + skipbytes += b; + pidx++; + UVMHIST_LOG(ubchist, "skipping, new offset 0x%x", + offset, 0,0,0); + if (bytes == 0) { + goto loopdone; + } + } + + /* + * bmap the file to find out the blkno to read from and + * how much we can read in one i/o. if bmap returns an error, + * skip the rest of the top-level i/o. + */ + + lbn = offset >> fs_bshift; + error = VOP_BMAP(vp, lbn, NULL, &blkno, &run); + if (error) { + UVMHIST_LOG(ubchist, "VOP_BMAP lbn 0x%x -> %d\n", + lbn, error,0,0); + skipbytes += bytes; + goto loopdone; + } + + /* + * see how many pages can be read with this i/o. + * reduce the i/o size if necessary to avoid + * overwriting pages with valid data. + */ + + iobytes = MIN((((off_t)lbn + 1 + run) << fs_bshift) - offset, + bytes); + if (offset + iobytes > round_page(offset)) { + pcount = 1; + while (pidx + pcount < npages && + pgs[pidx + pcount]->flags & PG_FAKE) { + pcount++; + } + iobytes = MIN(iobytes, (pcount << PAGE_SHIFT) - + (offset - trunc_page(offset))); + } + + /* + * if this block isn't allocated, zero it instead of reading it. + * if this is a read access, mark the pages we zeroed PG_RDONLY. + */ + + if (blkno < 0) { + int holepages = (round_page(offset + iobytes) - + trunc_page(offset)) >> PAGE_SHIFT; + UVMHIST_LOG(ubchist, "lbn 0x%x -> HOLE", lbn,0,0,0); + + sawhole = TRUE; + memset((char *)kva + (offset - startoffset), 0, + iobytes); + skipbytes += iobytes; + + for (i = 0; i < holepages; i++) { + if (write) { + pgs[pidx + i]->flags &= ~PG_CLEAN; + } else { + pgs[pidx + i]->flags |= PG_RDONLY; + } + } + continue; + } + + /* + * allocate a sub-buf for this piece of the i/o + * (or just use mbp if there's only 1 piece), + * and start it going. + */ + + if (offset == startoffset && iobytes == bytes) { + bp = mbp; + } else { + s = splbio(); + bp = pool_get(&bufpool, PR_WAITOK); + splx(s); + bp->b_data = (char *)kva + offset - startoffset; + bp->b_resid = bp->b_bcount = iobytes; + bp->b_flags = B_BUSY|B_READ|B_CALL; + bp->b_iodone = uvm_aio_biodone1; + bp->b_vp = vp; + LIST_INIT(&bp->b_dep); + } + bp->b_lblkno = 0; + bp->b_private = mbp; + + /* adjust physical blkno for partial blocks */ + bp->b_blkno = blkno + ((offset - ((off_t)lbn << fs_bshift)) >> + dev_bshift); + + UVMHIST_LOG(ubchist, "bp %p offset 0x%x bcount 0x%x blkno 0x%x", + bp, offset, iobytes, bp->b_blkno); + + VOP_STRATEGY(bp); + } + +loopdone: + if (skipbytes) { + s = splbio(); + if (error) { + mbp->b_flags |= B_ERROR; + mbp->b_error = error; + } + mbp->b_resid -= skipbytes; + if (mbp->b_resid == 0) { + biodone(mbp); + } + splx(s); + } + + if (async) { + UVMHIST_LOG(ubchist, "returning 0 (async)",0,0,0,0); + lockmgr(&gp->g_glock, LK_RELEASE, NULL, p); + return 0; + } + if (bp != NULL) { + error = biowait(mbp); + } + s = splbio(); + (void) buf_cleanout(mbp); + pool_put(&bufpool, mbp); + splx(s); + uvm_pagermapout(kva, npages); + raoffset = startoffset + totalbytes; + + /* + * if this we encountered a hole then we have to do a little more work. + * for read faults, we marked the page PG_RDONLY so that future + * write accesses to the page will fault again. + * for write faults, we must make sure that the backing store for + * the page is completely allocated while the pages are locked. + */ + + if (error == 0 && sawhole && write) { + error = GOP_ALLOC(vp, startoffset, npages << PAGE_SHIFT, 0, + cred); + if (error) { + UVMHIST_LOG(ubchist, "balloc lbn 0x%x -> %d", + lbn, error,0,0); + lockmgr(&gp->g_glock, LK_RELEASE, NULL, p); + simple_lock(&uobj->vmobjlock); + goto out; + } + } + lockmgr(&gp->g_glock, LK_RELEASE, NULL, p); + simple_lock(&uobj->vmobjlock); + + /* + * see if we want to start any readahead. + * XXXUBC for now, just read the next 128k on 64k boundaries. + * this is pretty nonsensical, but it is 50% faster than reading + * just the next 64k. + */ + +raout: + if (!error && !async && !write && ((int)raoffset & 0xffff) == 0 && + PAGE_SHIFT <= 16) { + int racount; + + racount = 1 << (16 - PAGE_SHIFT); + (void) VOP_GETPAGES(vp, raoffset, NULL, &racount, 0, + VM_PROT_READ, 0, 0); + simple_lock(&uobj->vmobjlock); + + racount = 1 << (16 - PAGE_SHIFT); + (void) VOP_GETPAGES(vp, raoffset + 0x10000, NULL, &racount, 0, + VM_PROT_READ, 0, 0); + simple_lock(&uobj->vmobjlock); + } + + /* + * we're almost done! release the pages... + * for errors, we free the pages. + * otherwise we activate them and mark them as valid and clean. + * also, unbusy pages that were not actually requested. + */ + +out: + if (error) { + uvm_lock_pageq(); + for (i = 0; i < npages; i++) { + if (pgs[i] == NULL) { + continue; + } + UVMHIST_LOG(ubchist, "examining pg %p flags 0x%x", + pgs[i], pgs[i]->flags, 0,0); + if (pgs[i]->flags & PG_WANTED) { + wakeup(pgs[i]); + } + if (pgs[i]->flags & PG_RELEASED) { + uvm_unlock_pageq(); + (uobj->pgops->pgo_releasepg)(pgs[i], NULL); + uvm_lock_pageq(); + continue; + } + if (pgs[i]->flags & PG_FAKE) { + uvm_pagefree(pgs[i]); + continue; + } + uvm_pageactivate(pgs[i]); + pgs[i]->flags &= ~(PG_WANTED|PG_BUSY); + UVM_PAGE_OWN(pgs[i], NULL); + } + uvm_unlock_pageq(); + simple_unlock(&uobj->vmobjlock); + UVMHIST_LOG(ubchist, "returning error %d", error,0,0,0); + return error; + } + + UVMHIST_LOG(ubchist, "succeeding, npages %d", npages,0,0,0); + uvm_lock_pageq(); + for (i = 0; i < npages; i++) { + if (pgs[i] == NULL) { + continue; + } + UVMHIST_LOG(ubchist, "examining pg %p flags 0x%x", + pgs[i], pgs[i]->flags, 0,0); + if (pgs[i]->flags & PG_FAKE) { + UVMHIST_LOG(ubchist, "unfaking pg %p offset 0x%x", + pgs[i], pgs[i]->offset,0,0); + pgs[i]->flags &= ~(PG_FAKE); + pmap_clear_modify(pgs[i]); + pmap_clear_reference(pgs[i]); + } + if (write) { + pgs[i]->flags &= ~(PG_RDONLY); + } + if (i < ridx || i >= ridx + orignpages || async) { + UVMHIST_LOG(ubchist, "unbusy pg %p offset 0x%x", + pgs[i], pgs[i]->offset,0,0); + if (pgs[i]->flags & PG_WANTED) { + wakeup(pgs[i]); + } + if (pgs[i]->flags & PG_RELEASED) { + uvm_unlock_pageq(); + (uobj->pgops->pgo_releasepg)(pgs[i], NULL); + uvm_lock_pageq(); + continue; + } + uvm_pageactivate(pgs[i]); + pgs[i]->flags &= ~(PG_WANTED|PG_BUSY); + UVM_PAGE_OWN(pgs[i], NULL); + } + } + uvm_unlock_pageq(); + simple_unlock(&uobj->vmobjlock); + if (ap->a_m != NULL) { + memcpy(ap->a_m, &pgs[ridx], + orignpages * sizeof(struct vm_page *)); + } + return 0; +} + +/* + * generic VM putpages routine. + * Write the given range of pages to backing store. + */ + +int +genfs_putpages(v) + void *v; +{ + struct vop_putpages_args /* { + struct vnode *a_vp; + struct vm_page **a_m; + int a_count; + int a_flags; + int *a_rtvals; + } */ *ap = v; + + int s, error, npages, run; + int fs_bshift, dev_bshift; + vaddr_t kva; + off_t eof, offset, startoffset; + size_t bytes, iobytes, skipbytes; + daddr_t lbn, blkno; + struct vm_page *pg; + struct buf *mbp, *bp; + struct vnode *vp = ap->a_vp; + boolean_t async = (ap->a_flags & PGO_SYNCIO) == 0; + UVMHIST_FUNC("genfs_putpages"); UVMHIST_CALLED(ubchist); + UVMHIST_LOG(ubchist, "vp %p offset 0x%x count %d", + vp, ap->a_m[0]->offset, ap->a_count, 0); + + simple_unlock(&vp->v_uobj.vmobjlock); + + GOP_SIZE(vp, vp->v_size, &eof); + + error = 0; + npages = ap->a_count; + fs_bshift = vp->v_mount->mnt_fs_bshift; + dev_bshift = vp->v_mount->mnt_dev_bshift; + + pg = ap->a_m[0]; + startoffset = pg->offset; + bytes = MIN(npages << PAGE_SHIFT, eof - startoffset); + skipbytes = 0; + KASSERT(bytes != 0); + + kva = uvm_pagermapin(ap->a_m, npages, UVMPAGER_MAPIN_WAITOK); + + s = splbio(); + vp->v_numoutput += 2; + mbp = pool_get(&bufpool, PR_WAITOK); + UVMHIST_LOG(ubchist, "vp %p mbp %p num now %d bytes 0x%x", + vp, mbp, vp->v_numoutput, bytes); + splx(s); + mbp->b_bufsize = npages << PAGE_SHIFT; + mbp->b_data = (void *)kva; + mbp->b_resid = mbp->b_bcount = bytes; + mbp->b_flags = B_BUSY|B_WRITE|B_AGE | + (async ? B_CALL : 0) | + (curproc == uvm.pagedaemon_proc ? B_PDAEMON : 0); + mbp->b_iodone = uvm_aio_biodone; + mbp->b_vp = NULL; + LIST_INIT(&mbp->b_dep); + bgetvp(vp, mbp); + + bp = NULL; + for (offset = startoffset; + bytes > 0; + offset += iobytes, bytes -= iobytes) { + lbn = offset >> fs_bshift; + error = VOP_BMAP(vp, lbn, NULL, &blkno, &run); + if (error) { + UVMHIST_LOG(ubchist, "VOP_BMAP() -> %d", error,0,0,0); + skipbytes += bytes; + bytes = 0; + break; + } + + iobytes = MIN((((off_t)lbn + 1 + run) << fs_bshift) - offset, + bytes); + if (blkno == (daddr_t)-1) { + skipbytes += iobytes; + continue; + } + + /* if it's really one i/o, don't make a second buf */ + if (offset == startoffset && iobytes == bytes) { + bp = mbp; + } else { + s = splbio(); + vp->v_numoutput++; + bp = pool_get(&bufpool, PR_WAITOK); + UVMHIST_LOG(ubchist, "vp %p bp %p num now %d", + vp, bp, vp->v_numoutput, 0); + splx(s); + bp->b_data = (char *)kva + + (vaddr_t)(offset - pg->offset); + bp->b_resid = bp->b_bcount = iobytes; + bp->b_flags = B_BUSY|B_WRITE|B_CALL|B_ASYNC; + bp->b_iodone = uvm_aio_biodone1; + bp->b_vp = vp; + LIST_INIT(&bp->b_dep); + } + bp->b_lblkno = 0; + bp->b_private = mbp; + + /* adjust physical blkno for partial blocks */ + bp->b_blkno = blkno + ((offset - ((off_t)lbn << fs_bshift)) >> + dev_bshift); + UVMHIST_LOG(ubchist, "vp %p offset 0x%x bcount 0x%x blkno 0x%x", + vp, offset, bp->b_bcount, bp->b_blkno); + VOP_STRATEGY(bp); + } + if (skipbytes) { + UVMHIST_LOG(ubchist, "skipbytes %d", skipbytes, 0,0,0); + s = splbio(); + mbp->b_resid -= skipbytes; + if (error) { + mbp->b_flags |= B_ERROR; + mbp->b_error = error; + } + if (mbp->b_resid == 0) { + biodone(mbp); + } + splx(s); + } + if (async) { + UVMHIST_LOG(ubchist, "returning 0 (async)", 0,0,0,0); + return 0; + } + if (bp != NULL) { + UVMHIST_LOG(ubchist, "waiting for mbp %p", mbp,0,0,0); + error = biowait(mbp); + } + if (bioops.io_pageiodone) { + (*bioops.io_pageiodone)(mbp); + } + s = splbio(); + if (mbp->b_vp) { + vwakeup(mbp->b_vp); + } + buf_cleanout(mbp); + pool_put(&bufpool, mbp); + splx(s); + uvm_pagermapout(kva, npages); + UVMHIST_LOG(ubchist, "returning, error %d", error,0,0,0); + return error; +} + +void +genfs_size(struct vnode *vp, off_t size, off_t *eobp) +{ + int bsize; + + bsize = 1 << vp->v_mount->mnt_fs_bshift; + *eobp = (size + bsize - 1) & ~(bsize - 1); +} + +void +genfs_node_init(struct vnode *vp, struct genfs_ops *ops) +{ + struct genfs_node *gp = VTOG(vp); + + lockinit(&gp->g_glock, PINOD, "glock", 0, 0); + gp->g_op = ops; +} diff --git a/sys/msdosfs/denode.h b/sys/msdosfs/denode.h index 665c74d2fd3..db945e35bcd 100644 --- a/sys/msdosfs/denode.h +++ b/sys/msdosfs/denode.h @@ -1,4 +1,4 @@ -/* $OpenBSD: denode.h,v 1.10 2001/06/23 02:15:24 csapuntz Exp $ */ +/* $OpenBSD: denode.h,v 1.11 2001/12/10 04:45:31 art Exp $ */ /* $NetBSD: denode.h,v 1.24 1997/10/17 11:23:39 ws Exp $ */ /*- @@ -91,6 +91,8 @@ * things. */ +#include <miscfs/genfs/genfs.h> + /* * Internal pseudo-offset for (nonexistent) directory entry for the root * dir in the root dir @@ -135,6 +137,7 @@ struct fatcache { * contained within a vnode. */ struct denode { + struct genfs_node de_gnode; struct denode *de_next; /* Hash chain forward */ struct denode **de_prev; /* Hash chain back */ struct vnode *de_vnode; /* addr of vnode we are part of */ @@ -311,4 +314,5 @@ void reinsert __P((struct denode *)); int removede __P((struct denode *, struct denode *)); int uniqdosname __P((struct denode *, struct componentname *, u_char *)); int findwin95 __P((struct denode *)); +int msdosfs_gop_alloc __P((struct vnode *, off_t, off_t, int, struct ucred *)); #endif /* _KERNEL */ diff --git a/sys/msdosfs/msdosfs_denode.c b/sys/msdosfs/msdosfs_denode.c index 601ac17df6b..e01491efc85 100644 --- a/sys/msdosfs/msdosfs_denode.c +++ b/sys/msdosfs/msdosfs_denode.c @@ -1,4 +1,4 @@ -/* $OpenBSD: msdosfs_denode.c,v 1.21 2001/12/10 02:19:34 art Exp $ */ +/* $OpenBSD: msdosfs_denode.c,v 1.22 2001/12/10 04:45:31 art Exp $ */ /* $NetBSD: msdosfs_denode.c,v 1.23 1997/10/17 11:23:58 ws Exp $ */ /*- @@ -74,6 +74,11 @@ u_long dehash; /* size of hash table - 1 */ extern int prtactive; +struct genfs_ops msdosfs_genfsops = { + genfs_size, + msdosfs_gop_alloc, +}; + static struct denode *msdosfs_hashget __P((dev_t, u_long, u_long)); static int msdosfs_hashins __P((struct denode *)); static void msdosfs_hashrem __P((struct denode *)); @@ -332,6 +337,7 @@ retry: } } else nvp->v_type = VREG; + genfs_node_init(nvp, &msdosfs_genfsops); VREF(ldep->de_devvp); *depp = ldep; nvp->v_size = ldep->de_FileSize; @@ -687,3 +693,10 @@ out: vrecycle(vp, (struct simplelock *)0, p); return (error); } + +int +msdosfs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags, + struct ucred *cred) +{ + return 0; +} diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c index 91b3196ced1..8d08da9e229 100644 --- a/sys/msdosfs/msdosfs_vnops.c +++ b/sys/msdosfs/msdosfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: msdosfs_vnops.c,v 1.33 2001/12/10 02:19:34 art Exp $ */ +/* $OpenBSD: msdosfs_vnops.c,v 1.34 2001/12/10 04:45:31 art Exp $ */ /* $NetBSD: msdosfs_vnops.c,v 1.63 1997/10/17 11:24:19 ws Exp $ */ /*- @@ -1878,8 +1878,7 @@ struct vnodeopv_entry_desc msdosfs_vnodeop_entries[] = { { &vop_bwrite_desc, vop_generic_bwrite }, /* bwrite */ { &vop_getpages_desc, genfs_getpages }, { &vop_putpages_desc, genfs_putpages }, - { &vop_size_desc, genfs_size }, - { &vop_mmap_desc, genfs_mmap }, + { &vop_mmap_desc, vop_generic_mmap }, { NULL, NULL } }; struct vnodeopv_desc msdosfs_vnodeop_opv_desc = diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c index 34831240777..ee9fc5bc4be 100644 --- a/sys/nfs/nfs_vnops.c +++ b/sys/nfs/nfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_vnops.c,v 1.42 2001/12/10 02:19:34 art Exp $ */ +/* $OpenBSD: nfs_vnops.c,v 1.43 2001/12/10 04:45:31 art Exp $ */ /* $NetBSD: nfs_vnops.c,v 1.62.4.1 1996/07/08 20:26:52 jtc Exp $ */ /* @@ -128,7 +128,7 @@ struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = { { &vop_bwrite_desc, nfs_bwrite }, { &vop_getpages_desc, nfs_getpages }, /* getpages */ { &vop_putpages_desc, nfs_putpages }, /* putpages */ - { &vop_mmap_desc, genfs_mmap }, + { &vop_mmap_desc, vop_generic_mmap }, { NULL, NULL } }; struct vnodeopv_desc nfsv2_vnodeop_opv_desc = diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 77d773afe17..e97fa77b696 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vnode.h,v 1.45 2001/12/10 02:19:34 art Exp $ */ +/* $OpenBSD: vnode.h,v 1.46 2001/12/10 04:45:31 art Exp $ */ /* $NetBSD: vnode.h,v 1.38 1996/02/29 20:59:05 cgd Exp $ */ /* @@ -114,7 +114,6 @@ struct vnode { } v_un; struct lock *v_vnlock; /* used for non-locking fs's */ - struct lock v_glock; /* getpages lock */ enum vtagtype v_tag; /* type of underlying data */ void *v_data; /* private data for fs */ struct { @@ -452,12 +451,7 @@ int vop_generic_lock __P((void *)); int vop_generic_unlock __P((void *)); int vop_generic_revoke __P((void *)); int vop_generic_kqfilter __P((void *)); - -/* XXXUBC - doesn't really belong here. */ -int genfs_getpages __P((void *)); -int genfs_putpages __P((void *)); -int genfs_size __P((void *)); -int genfs_mmap __P((void *)); +int vop_generic_mmap __P((void *)); int vn_stat __P((struct vnode *vp, struct stat *sb, struct proc *p)); int vn_statfile __P((struct file *fp, struct stat *sb, struct proc *p)); diff --git a/sys/sys/vnode_if.h b/sys/sys/vnode_if.h index 7a332ae5fd8..0abec5aabad 100644 --- a/sys/sys/vnode_if.h +++ b/sys/sys/vnode_if.h @@ -397,17 +397,6 @@ struct vop_whiteout_args { extern struct vnodeop_desc vop_whiteout_desc; int VOP_WHITEOUT __P((struct vnode *, struct componentname *, int)); -struct vop_ballocn_args { - struct vnodeop_desc *a_desc; - struct vnode *a_vp; - off_t a_offset; - off_t a_length; - struct ucred *a_cred; - int a_flags; -}; -extern struct vnodeop_desc vop_ballocn_desc; -int VOP_BALLOCN __P((struct vnode *, off_t, off_t, struct ucred *, int)); - struct vop_getpages_args { struct vnodeop_desc *a_desc; struct vnode *a_vp; @@ -434,15 +423,6 @@ struct vop_putpages_args { extern struct vnodeop_desc vop_putpages_desc; int VOP_PUTPAGES __P((struct vnode *, struct vm_page **, int, int, int *)); -struct vop_size_args { - struct vnodeop_desc *a_desc; - struct vnode *a_vp; - off_t a_size; - off_t *a_eobp; -}; -extern struct vnodeop_desc vop_size_desc; -int VOP_SIZE __P((struct vnode *, off_t, off_t *)); - struct vop_mmap_args { struct vnodeop_desc *a_desc; struct vnode *a_vp; diff --git a/sys/ufs/ext2fs/ext2fs_balloc.c b/sys/ufs/ext2fs/ext2fs_balloc.c index a6daf74d8c6..390f02dc13f 100644 --- a/sys/ufs/ext2fs/ext2fs_balloc.c +++ b/sys/ufs/ext2fs/ext2fs_balloc.c @@ -314,29 +314,17 @@ fail: } int -ext2fs_ballocn(v) - void *v; +ext2fs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags, + struct ucred *cred) { - struct vop_ballocn_args /* { - struct vnode *a_vp; - off_t a_offset; - off_t a_length; - struct ucred *a_cred; - int a_flags; - } */ *ap = v; - off_t off, len; - struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); struct m_ext2fs *fs = ip->i_e2fs; int error, delta, bshift, bsize; - UVMHIST_FUNC("ext2fs_ballocn"); UVMHIST_CALLED(ubchist); + UVMHIST_FUNC("ext2fs_gop_alloc"); UVMHIST_CALLED(ubchist); bshift = fs->e2fs_bshift; bsize = 1 << bshift; - off = ap->a_offset; - len = ap->a_length; - delta = off & (bsize - 1); off -= delta; len += delta; @@ -346,8 +334,8 @@ ext2fs_ballocn(v) UVMHIST_LOG(ubchist, "off 0x%x len 0x%x bsize 0x%x", off, len, bsize, 0); - error = ext2fs_buf_alloc(ip, lblkno(fs, off), bsize, ap->a_cred, - NULL, ap->a_flags); + error = ext2fs_buf_alloc(ip, lblkno(fs, off), bsize, cred, + NULL, flags); if (error) { UVMHIST_LOG(ubchist, "error %d", error, 0,0,0); return error; @@ -389,6 +377,7 @@ ext2fs_balloc_range(vp, off, len, cred, flags) { off_t oldeof, eof, pagestart; struct uvm_object *uobj; + struct genfs_node *gp = VTOG(vp); int i, delta, error, npages; int bshift = vp->v_mount->mnt_fs_bshift; int bsize = 1 << bshift; @@ -441,10 +430,10 @@ ext2fs_balloc_range(vp, off, len, cred, flags) * now allocate the range. */ - lockmgr(&vp->v_glock, LK_EXCLUSIVE, NULL, curproc); - error = VOP_BALLOCN(vp, off, len, cred, flags); - UVMHIST_LOG(ubchist, "ballocn %d", error,0,0,0); - lockmgr(&vp->v_glock, LK_RELEASE, NULL, curproc); + lockmgr(&gp->g_glock, LK_EXCLUSIVE, NULL, curproc); + error = GOP_ALLOC(vp, off, len, flags, cred); + UVMHIST_LOG(ubchist, "alloc %d", error,0,0,0); + lockmgr(&gp->g_glock, LK_RELEASE, NULL, curproc); /* * unbusy any pages we are holding. diff --git a/sys/ufs/ext2fs/ext2fs_extern.h b/sys/ufs/ext2fs/ext2fs_extern.h index af23fb6ef2d..5f5b2c3a47b 100644 --- a/sys/ufs/ext2fs/ext2fs_extern.h +++ b/sys/ufs/ext2fs/ext2fs_extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ext2fs_extern.h,v 1.11 2001/11/27 05:27:12 art Exp $ */ +/* $OpenBSD: ext2fs_extern.h,v 1.12 2001/12/10 04:45:31 art Exp $ */ /* $NetBSD: ext2fs_extern.h,v 1.9 2000/11/27 08:39:53 chs Exp $ */ /*- @@ -74,7 +74,7 @@ int ext2fs_inode_free(struct inode *pip, ino_t ino, int mode); /* ext2fs_balloc.c */ int ext2fs_buf_alloc(struct inode *, daddr_t, int, struct ucred *, struct buf **, int); -int ext2fs_ballocn __P((void *)); +int ext2fs_gop_alloc __P((struct vnode *, off_t, off_t, int, struct ucred *)); int ext2fs_balloc_range __P((struct vnode *, off_t, off_t, struct ucred *, int)); diff --git a/sys/ufs/ext2fs/ext2fs_vfsops.c b/sys/ufs/ext2fs/ext2fs_vfsops.c index 87eab5f5c2b..b77f4edec62 100644 --- a/sys/ufs/ext2fs/ext2fs_vfsops.c +++ b/sys/ufs/ext2fs/ext2fs_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ext2fs_vfsops.c,v 1.18 2001/12/10 02:19:34 art Exp $ */ +/* $OpenBSD: ext2fs_vfsops.c,v 1.19 2001/12/10 04:45:31 art Exp $ */ /* $NetBSD: ext2fs_vfsops.c,v 1.40 2000/11/27 08:39:53 chs Exp $ */ /* @@ -100,6 +100,11 @@ struct vfsops ext2fs_vfsops = { ufs_check_export }; +struct genfs_ops ext2fs_genfsops = { + genfs_size, + ext2fs_gop_alloc, +}; + struct pool ext2fs_inode_pool; extern u_long ext2gennumber; @@ -916,6 +921,7 @@ ext2fs_vget(mp, ino, vpp) /* * Finish inode initialization now that aliasing has been resolved. */ + genfs_node_init(vp, &ext2fs_genfsops); ip->i_devvp = ump->um_devvp; VREF(ip->i_devvp); /* diff --git a/sys/ufs/ext2fs/ext2fs_vnops.c b/sys/ufs/ext2fs/ext2fs_vnops.c index defbaedf0cb..6e82f66279a 100644 --- a/sys/ufs/ext2fs/ext2fs_vnops.c +++ b/sys/ufs/ext2fs/ext2fs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ext2fs_vnops.c,v 1.19 2001/12/04 22:44:32 art Exp $ */ +/* $OpenBSD: ext2fs_vnops.c,v 1.20 2001/12/10 04:45:31 art Exp $ */ /* $NetBSD: ext2fs_vnops.c,v 1.30 2000/11/27 08:39:53 chs Exp $ */ /* @@ -1467,10 +1467,8 @@ struct vnodeopv_entry_desc ext2fs_vnodeop_entries[] = { { &vop_pathconf_desc, ufs_pathconf }, /* pathconf */ { &vop_advlock_desc, ext2fs_advlock }, /* advlock */ { &vop_bwrite_desc, vop_generic_bwrite }, /* bwrite */ - { &vop_ballocn_desc, ext2fs_ballocn }, { &vop_getpages_desc, genfs_getpages }, { &vop_putpages_desc, genfs_putpages }, - { &vop_size_desc, genfs_size }, { &vop_mmap_desc, ufs_mmap }, { NULL, NULL } }; diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index dfbf97c232c..aa452edeabb 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ffs_balloc.c,v 1.20 2001/12/10 02:19:34 art Exp $ */ +/* $OpenBSD: ffs_balloc.c,v 1.21 2001/12/10 04:45:32 art Exp $ */ /* $NetBSD: ffs_balloc.c,v 1.3 1996/02/09 22:22:21 christos Exp $ */ /* @@ -404,19 +404,9 @@ fail: } int -ffs_ballocn(v) - void *v; +ffs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags, + struct ucred *cred) { - struct vop_ballocn_args /* { - struct vnode *a_vp; - off_t a_offset; - off_t a_length; - struct ucred *a_cred; - int a_flags; - } */ *ap = v; - - off_t off, len; - struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); struct fs *fs = ip->i_fs; int error, delta, bshift, bsize; @@ -425,18 +415,14 @@ ffs_ballocn(v) bshift = fs->fs_bshift; bsize = 1 << bshift; - off = ap->a_offset; - len = ap->a_length; - delta = off & (bsize - 1); off -= delta; len += delta; while (len > 0) { - bsize = min(bsize, len); + bsize = MIN(bsize, len); - error = ffs_balloc(ip, off, bsize, ap->a_cred, ap->a_flags, - NULL); + error = ffs_balloc(ip, off, bsize, cred, flags, NULL); if (error) { goto out; } diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h index 2875a332a57..7aac0f33de9 100644 --- a/sys/ufs/ffs/ffs_extern.h +++ b/sys/ufs/ffs/ffs_extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ffs_extern.h,v 1.15 2001/11/27 05:27:12 art Exp $ */ +/* $OpenBSD: ffs_extern.h,v 1.16 2001/12/10 04:45:32 art Exp $ */ /* $NetBSD: ffs_extern.h,v 1.4 1996/02/09 22:22:22 christos Exp $ */ /*- @@ -87,7 +87,7 @@ void ffs_clusteracct __P((struct fs *, struct cg *, daddr_t, int)); /* ffs_balloc.c */ int ffs_balloc(struct inode *, off_t, int, struct ucred *, int, struct buf **); -int ffs_ballocn(void *); +int ffs_gop_alloc(struct vnode *, off_t, off_t, int, struct ucred *); /* ffs_inode.c */ int ffs_init __P((struct vfsconf *)); @@ -129,7 +129,7 @@ int ffs_read __P((void *)); int ffs_write __P((void *)); int ffs_fsync __P((void *)); int ffs_reclaim __P((void *)); -int ffs_size __P((void *)); +void ffs_gop_size __P((struct vnode *, off_t, off_t *)); /* * Soft dependency function prototypes. diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c index 64f0aef27a3..3bec117a700 100644 --- a/sys/ufs/ffs/ffs_inode.c +++ b/sys/ufs/ffs/ffs_inode.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ffs_inode.c,v 1.27 2001/12/10 02:19:34 art Exp $ */ +/* $OpenBSD: ffs_inode.c,v 1.28 2001/12/10 04:45:32 art Exp $ */ /* $NetBSD: ffs_inode.c,v 1.10 1996/05/11 18:27:19 mycroft Exp $ */ /* @@ -148,7 +148,8 @@ ffs_update(struct inode *ip, struct timespec *atime, int ffs_truncate(struct inode *oip, off_t length, int flags, struct ucred *cred) { - struct vnode *ovp; + struct vnode *ovp = ITOV(oip); + struct genfs_node *gp = VTOG(ovp); daddr_t lastblock; daddr_t bn, lastiblock[NIADDR], indir_lbn[NIADDR]; daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR]; @@ -162,7 +163,6 @@ ffs_truncate(struct inode *oip, off_t length, int flags, struct ucred *cred) if (length < 0) return (EINVAL); - ovp = ITOV(oip); if (ovp->v_type != VREG && ovp->v_type != VDIR && @@ -235,7 +235,7 @@ ffs_truncate(struct inode *oip, off_t length, int flags, struct ucred *cred) simple_unlock(&uobj->vmobjlock); } - lockmgr(&ovp->v_glock, LK_EXCLUSIVE, NULL, p); + lockmgr(&gp->g_glock, LK_EXCLUSIVE, NULL, p); if (DOINGSOFTDEP(ovp)) { if (length > 0 || softdep_slowdown(ovp)) { @@ -250,7 +250,7 @@ ffs_truncate(struct inode *oip, off_t length, int flags, struct ucred *cred) */ if ((error = VOP_FSYNC(ovp, cred, MNT_WAIT, curproc)) != 0) { - lockmgr(&ovp->v_glock, LK_RELEASE, NULL, p); + lockmgr(&gp->g_glock, LK_RELEASE, NULL, p); return (error); } } else { @@ -259,7 +259,7 @@ ffs_truncate(struct inode *oip, off_t length, int flags, struct ucred *cred) NOCRED); softdep_setup_freeblocks(oip, length); (void) vinvalbuf(ovp, 0, cred, curproc, 0, 0); - lockmgr(&ovp->v_glock, LK_RELEASE, NULL, p); + lockmgr(&gp->g_glock, LK_RELEASE, NULL, p); oip->i_flag |= IN_CHANGE | IN_UPDATE; return (UFS_UPDATE(oip, 0)); } @@ -396,7 +396,7 @@ done: oip->i_ffs_blocks -= blocksreleased; if (oip->i_ffs_blocks < 0) /* sanity */ oip->i_ffs_blocks = 0; - lockmgr(&ovp->v_glock, LK_RELEASE, NULL, p); + lockmgr(&gp->g_glock, LK_RELEASE, NULL, p); oip->i_flag |= IN_CHANGE; (void)ufs_quota_free_blocks(oip, blocksreleased, NOCRED); return (allerror); diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 19c77726fa8..4aac12f8752 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ffs_vfsops.c,v 1.46 2001/11/27 05:27:12 art Exp $ */ +/* $OpenBSD: ffs_vfsops.c,v 1.47 2001/12/10 04:45:32 art Exp $ */ /* $NetBSD: ffs_vfsops.c,v 1.19 1996/02/09 22:22:26 christos Exp $ */ /* @@ -96,6 +96,11 @@ struct inode_vtbl ffs_vtbl = { ffs_bufatoff }; +struct genfs_ops ffs_genfsops = { + ffs_gop_size, + ffs_gop_alloc, +}; + extern u_long nextgennumber; /* @@ -1182,6 +1187,8 @@ retry: /* * Finish inode initialization now that aliasing has been resolved. */ + + genfs_node_init(vp, &ffs_genfsops); ip->i_devvp = ump->um_devvp; VREF(ip->i_devvp); /* diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 6bf1ddc5642..3794d5e8049 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ffs_vnops.c,v 1.23 2001/12/10 02:19:34 art Exp $ */ +/* $OpenBSD: ffs_vnops.c,v 1.24 2001/12/10 04:45:32 art Exp $ */ /* $NetBSD: ffs_vnops.c,v 1.7 1996/05/11 18:27:24 mycroft Exp $ */ /* @@ -107,10 +107,8 @@ struct vnodeopv_entry_desc ffs_vnodeop_entries[] = { { &vop_advlock_desc, ufs_advlock }, /* advlock */ { &vop_reallocblks_desc, ffs_reallocblks }, /* reallocblks */ { &vop_bwrite_desc, vop_generic_bwrite }, - { &vop_ballocn_desc, ffs_ballocn }, { &vop_getpages_desc, genfs_getpages }, { &vop_putpages_desc, genfs_putpages }, - { &vop_size_desc, ffs_size }, { &vop_mmap_desc, ufs_mmap }, { NULL, NULL } }; @@ -158,7 +156,7 @@ struct vnodeopv_entry_desc ffs_specop_entries[] = { { &vop_advlock_desc, spec_advlock }, /* advlock */ { &vop_reallocblks_desc, spec_reallocblks }, /* reallocblks */ { &vop_bwrite_desc, vop_generic_bwrite }, - { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL } + { NULL, NULL } }; struct vnodeopv_desc ffs_specop_opv_desc = { &ffs_specop_p, ffs_specop_entries }; @@ -204,7 +202,7 @@ struct vnodeopv_entry_desc ffs_fifoop_entries[] = { { &vop_advlock_desc, fifo_advlock }, /* advlock */ { &vop_reallocblks_desc, fifo_reallocblks }, /* reallocblks */ { &vop_bwrite_desc, vop_generic_bwrite }, - { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL } + { NULL, NULL } }; struct vnodeopv_desc ffs_fifoop_opv_desc = { &ffs_fifoop_p, ffs_fifoop_entries }; @@ -376,26 +374,18 @@ ffs_reclaim(v) * Return the last logical file offset that should be written for this file * if we're doing a write that ends at "size". */ -int -ffs_size(v) - void *v; +void +ffs_gop_size(struct vnode *vp, off_t size, off_t *eobp) { - struct vop_size_args /* { - struct vnode *a_vp; - off_t a_size; - off_t *a_eobp; - } */ *ap = v; - struct inode *ip = VTOI(ap->a_vp); + struct inode *ip = VTOI(vp); struct fs *fs = ip->i_fs; ufs_lbn_t olbn, nlbn; olbn = lblkno(fs, ip->i_ffs_size); - nlbn = lblkno(fs, ap->a_size); - + nlbn = lblkno(fs, size); if (nlbn < NDADDR && olbn <= nlbn) { - *ap->a_eobp = fragroundup(fs, ap->a_size); + *eobp = fragroundup(fs, size); } else { - *ap->a_eobp = blkroundup(fs, ap->a_size); + *eobp = blkroundup(fs, size); } - return 0; } diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h index 98c73de5579..eb3f0069790 100644 --- a/sys/ufs/ufs/inode.h +++ b/sys/ufs/ufs/inode.h @@ -1,4 +1,4 @@ -/* $OpenBSD: inode.h,v 1.17 2001/11/27 05:27:12 art Exp $ */ +/* $OpenBSD: inode.h,v 1.18 2001/12/10 04:45:32 art Exp $ */ /* $NetBSD: inode.h,v 1.8 1995/06/15 23:22:50 cgd Exp $ */ /* @@ -45,6 +45,7 @@ #include <ufs/ufs/dinode.h> #include <ufs/ufs/dir.h> #include <ufs/ext2fs/ext2fs_dinode.h> +#include <miscfs/genfs/genfs.h> typedef long ufs_lbn_t; @@ -66,6 +67,7 @@ struct ext2fs_inode_ext { * active, and is put back when the file is no longer being used. */ struct inode { + struct genfs_node i_gnode; LIST_ENTRY(inode) i_hash; /* Hash chain */ struct vnode *i_vnode;/* Vnode associated with this inode. */ struct vnode *i_devvp;/* Vnode for block I/O. */ diff --git a/sys/ufs/ufs/ufs_extern.h b/sys/ufs/ufs/ufs_extern.h index a89656344c0..85df8cf99ec 100644 --- a/sys/ufs/ufs/ufs_extern.h +++ b/sys/ufs/ufs/ufs_extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_extern.h,v 1.14 2001/12/04 22:44:32 art Exp $ */ +/* $OpenBSD: ufs_extern.h,v 1.15 2001/12/10 04:45:32 art Exp $ */ /* $NetBSD: ufs_extern.h,v 1.5 1996/02/09 22:36:03 christos Exp $ */ /*- @@ -98,7 +98,7 @@ int ufs_whiteout __P((void *)); int ufsspec_close __P((void *)); int ufsspec_read __P((void *)); int ufsspec_write __P((void *)); -#define ufs_mmap genfs_mmap +#define ufs_mmap vop_generic_mmap #ifdef FIFO int ufsfifo_read __P((void *)); diff --git a/sys/ufs/ufs/ufs_inode.c b/sys/ufs/ufs/ufs_inode.c index 8c328b83f39..61ec4eeede9 100644 --- a/sys/ufs/ufs/ufs_inode.c +++ b/sys/ufs/ufs/ufs_inode.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_inode.c,v 1.14 2001/12/10 02:19:34 art Exp $ */ +/* $OpenBSD: ufs_inode.c,v 1.15 2001/12/10 04:45:32 art Exp $ */ /* $NetBSD: ufs_inode.c,v 1.7 1996/05/11 18:27:52 mycroft Exp $ */ /* @@ -170,6 +170,7 @@ ufs_balloc_range(vp, off, len, cred, flags) { off_t oldeof, neweof, oldeob, neweob, oldpagestart, pagestart; struct uvm_object *uobj; + struct genfs_node *gp = VTOG(vp); int i, delta, error, npages1, npages2; int bshift = vp->v_mount->mnt_fs_bshift; int bsize = 1 << bshift; @@ -180,16 +181,10 @@ ufs_balloc_range(vp, off, len, cred, flags) vp, off, len, vp->v_size); oldeof = vp->v_size; - error = VOP_SIZE(vp, oldeof, &oldeob); - if (error) { - return error; - } + GOP_SIZE(vp, oldeof, &oldeob); neweof = MAX(vp->v_size, off + len); - error = VOP_SIZE(vp, neweof, &neweob); - if (error) { - return error; - } + GOP_SIZE(vp, neweof, &neweob); error = 0; uobj = &vp->v_uobj; @@ -267,9 +262,9 @@ ufs_balloc_range(vp, off, len, cred, flags) * now allocate the range. */ - lockmgr(&vp->v_glock, LK_EXCLUSIVE, NULL, curproc); - error = VOP_BALLOCN(vp, off, len, cred, flags); - lockmgr(&vp->v_glock, LK_RELEASE, NULL, curproc); + lockmgr(&gp->g_glock, LK_EXCLUSIVE, NULL, curproc); + error = GOP_ALLOC(vp, off, len, flags, cred); + lockmgr(&gp->g_glock, LK_RELEASE, NULL, curproc); /* * clear PG_RDONLY on any pages we are holding |