Module Name: src Committed By: uebayasi Date: Sun Nov 21 17:07:38 UTC 2010
Modified Files: src/sys/miscfs/genfs [uebayasi-xip]: genfs_io.c Log Message: Put back XIP putpages, but slightly modifed to be called from the generic putpages, and to call pgo_get() than a specific function. Without this, UVM went mad after unmount (vinval, etc.). To generate a diff of this commit: cvs rdiff -u -r1.36.2.62 -r1.36.2.63 src/sys/miscfs/genfs/genfs_io.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/miscfs/genfs/genfs_io.c diff -u src/sys/miscfs/genfs/genfs_io.c:1.36.2.62 src/sys/miscfs/genfs/genfs_io.c:1.36.2.63 --- src/sys/miscfs/genfs/genfs_io.c:1.36.2.62 Sun Nov 21 15:00:12 2010 +++ src/sys/miscfs/genfs/genfs_io.c Sun Nov 21 17:07:38 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: genfs_io.c,v 1.36.2.62 2010/11/21 15:00:12 uebayasi Exp $ */ +/* $NetBSD: genfs_io.c,v 1.36.2.63 2010/11/21 17:07:38 uebayasi Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.36.2.62 2010/11/21 15:00:12 uebayasi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.36.2.63 2010/11/21 17:07:38 uebayasi Exp $"); #include "opt_xip.h" @@ -993,6 +993,12 @@ * range by an estimate of the relatively higher cost of the hash lookup. */ +#ifdef XIP +static int +genfs_do_putpages_xip_free(struct vnode *vp, off_t startoff, off_t endoff, + int origflags); +#endif + int genfs_putpages(void *v) { @@ -1062,6 +1068,15 @@ WAPBL_END(vp->v_mount); fstrans_done(vp->v_mount); } +#ifdef XIP + if ((vp->v_vflag & VV_XIP) != 0) { + if (flags & PGO_FREE) { + error = genfs_do_putpages_xip_free(vp, + startoff, endoff, origflags); + KASSERT(error == 0); + } + } +#endif mutex_exit(slock); return (0); } @@ -1469,6 +1484,83 @@ return (error); } +#ifdef XIP +static int +genfs_do_putpages_xip_free(struct vnode *vp, off_t startoff, off_t endoff, + int origflags) +{ + struct uvm_object * const uobj = &vp->v_uobj; + + KASSERT(uobj->uo_npages == 0); + + /* + * For PGO_FREE (or (PGO_CLEANIT | PGO_FREE)), we invalidate MMU + * mappings of both XIP pages and XIP zero pages. + * + * Hole page is freed when one of its mapped offset is freed, even if + * one file (vnode) has many holes and mapping its zero page to all + * of those hole pages. + * + * We don't know which pages are currently mapped in the given vnode, + * because XIP pages are not added to vnode. What we can do is to + * locate pages by querying the filesystem as done in getpages. Call + * genfs_do_getpages_xip_io(). + */ + + off_t off, eof; + + off = trunc_page(startoff); + if (endoff == 0 || (origflags & PGO_ALLPAGES)) + GOP_SIZE(vp, vp->v_size, &eof, GOP_SIZE_MEM); + else + eof = endoff; + + while (off < eof) { + int npages, orignpages, error, i; + struct vm_page *pgs[maxpages], *pg; + + npages = round_page(eof - off) >> PAGE_SHIFT; + if (npages > maxpages) + npages = maxpages; + + orignpages = npages; + KASSERT(mutex_owned(&uobj->vmobjlock)); + error = (*uobj->pgops->pgo_get)(uobj, off, pgs, &npages, 0, + VM_PROT_ALL, 0, PGO_SYNCIO); + KASSERT(error == 0); + KASSERT(npages == orignpages); + mutex_enter(&uobj->vmobjlock); + for (i = 0; i < npages; i++) { + pg = pgs[i]; + if (pg == NULL || pg == PGO_DONTCARE) + continue; + if (pg == PGO_HOLE) { + pg = uvm_page_holepage; + KASSERT(pg != NULL); + /* + * XXXUEBS + * Invalidating hole pages may be unnecessary, + * but just for safety. + */ + } else { + /* + * Freeing normal XIP pages; nothing to do. + */ + KASSERT((pg->flags & PG_RDONLY) != 0); + KASSERT((pg->flags & PG_CLEAN) != 0); + KASSERT((pg->flags & PG_FAKE) == 0); + KASSERT((pg->flags & PG_DEVICE) != 0); + pg->flags &= ~PG_BUSY; + } + pmap_page_protect(pg, VM_PROT_NONE); + } + off += npages << PAGE_SHIFT; + } + + return 0; +} +#endif + int genfs_gop_write(struct vnode *vp, struct vm_page **pgs, int npages, int flags) {