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