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)
{