Subject: Re: ubc and nfs file truncation
To: None <chuq@chuq.com>
From: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
List: tech-kern
Date: 12/11/2004 12:35:27
--NextPart-20041211123418-0088500
Content-Type: Text/Plain; charset=us-ascii

hi,

> > the diff I've been working with is at
> > 	ftp://ftp.netbsd.org/pub/NetBSD/misc/chs/diff.ubc-novp
> > 
> > the gist of the change is that instead of limiting the getpages request
> > to the vnode's size, we ask for however many pages are left in the
> > mapping window.  however, genfs_getpages() trims the request to the
> > vnode's size (rounded to the fs block size) anyway, so the result
> > should be the same.  testing hasn't revealed any problems so far.
> 
> i don't think that the result is the exactly same.
> genfs_getpages doesn't trim the request with PGO_PASTEOF,
> which is set by ubc_fault, and will allocate a few extra pages.
> is it intended?

how about the attached diff?  (after diff.ubc-novp)

YAMAMOTO Takashi

--NextPart-20041211123418-0088500
Content-Type: Text/Plain; charset=us-ascii
Content-Disposition: attachment; filename="a.diff"

Index: uvm_bio.c
===================================================================
--- uvm_bio.c	(revision 980)
+++ uvm_bio.c	(working copy)
@@ -80,8 +80,8 @@ struct ubc_map
 {
 	struct uvm_object *	uobj;		/* mapped object */
 	voff_t			offset;		/* offset into uobj */
-	voff_t			writeoff;	/* overwrite offset */
-	vsize_t			writelen;	/* overwrite len */
+	voff_t			writeoff;	/* write offset */
+	vsize_t			writelen;	/* write len */
 	int			refcount;	/* refcount on mapping */
 	int			flags;		/* extra state */
 
@@ -249,10 +249,26 @@ ubc_fault(ufi, ign1, ign2, ign3, ign4, f
 	KASSERT(umap->refcount != 0);
 	slot_offset = ubc_offset & (ubc_winsize - 1);
 
+#ifdef DIAGNOSTIC
+	if ((access_type & VM_PROT_WRITE) != 0) {
+		if (slot_offset < trunc_page(umap->writeoff) ||
+		    umap->writeoff + umap->writelen <= slot_offset) {
+			panic("ubc_fault: out of range write");
+		}
+	}
+#endif
+
 	/* no umap locking needed since we have a ref on the umap */
 	uobj = umap->uobj;
 
-	npages = (ubc_winsize - slot_offset) >> PAGE_SHIFT;
+	if ((access_type & VM_PROT_WRITE) == 0) {
+		npages = (ubc_winsize - slot_offset) >> PAGE_SHIFT;
+	} else {
+		npages = (round_page(umap->offset + umap->writeoff +
+		    umap->writelen) - (umap->offset + slot_offset))
+		    >> PAGE_SHIFT;
+		flags |= PGO_PASTEOF;
+	}
 
 again:
 	memset(pgs, 0, sizeof (pgs));
@@ -263,7 +279,6 @@ again:
 	UVMHIST_LOG(ubchist, "getpages uobj %p offset 0x%x npages %d",
 	    uobj, umap->offset + slot_offset, npages, 0);
 
-	flags |= PGO_PASTEOF;
 	error = (*uobj->pgops->pgo_get)(uobj, umap->offset + slot_offset, pgs,
 	    &npages, 0, access_type, 0, flags);
 	UVMHIST_LOG(ubchist, "getpages error %d npages %d", error, npages, 0,
@@ -431,7 +446,7 @@ again:
 
 #ifdef DIAGNOSTIC
 	if ((flags & UBC_WRITE) && (umap->writeoff || umap->writelen)) {
-		panic("ubc_fault: concurrent writes uobj %p", uobj);
+		panic("ubc_alloc: concurrent writes uobj %p", uobj);
 	}
 #endif
 	if (flags & UBC_WRITE) {

--NextPart-20041211123418-0088500--