Subject: Re: kern/15364
To: None <chs@netbsd.org, gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: Chuck Silvers <chuq@chuq.com>
List: netbsd-bugs
Date: 08/28/2005 15:01:03
The following reply was made to PR kern/15364; it has been noted by GNATS.
From: Chuck Silvers <chuq@chuq.com>
To: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
Cc: gnats-bugs@NetBSD.org
Subject: Re: kern/15364
Date: Sun, 28 Aug 2005 08:00:27 -0700
--ew6BAiZeqk4r7MaW
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
ah, it's the write clustering that's causing the problem.
the attached patch forces the putpages write clustering to obey
the same block-alignment rule that the getpages path uses, so that
pages involved in a softdep dependency will always be written together.
do you see any problem with this?
-Chuck
--ew6BAiZeqk4r7MaW
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="diff.softdep"
Index: src/sys/sys/mount.h
===================================================================
RCS file: /cvsroot/src/sys/sys/mount.h,v
retrieving revision 1.129
diff -u -p -r1.129 mount.h
--- src/sys/sys/mount.h 29 May 2005 21:19:41 -0000 1.129
+++ src/sys/sys/mount.h 28 Aug 2005 14:55:26 -0000
@@ -126,6 +126,7 @@ struct mount {
int mnt_iflag; /* internal flags */
int mnt_fs_bshift; /* offset shift for lblkno */
int mnt_dev_bshift; /* shift for device sectors */
+ int mnt_clusteralign; /* cluster alignment needed */
struct statvfs mnt_stat; /* cache of filesystem stats */
void *mnt_data; /* private data */
int mnt_wcnt; /* count of vfs_busy waiters */
Index: src/sys/kern/vfs_syscalls.c
===================================================================
RCS file: /cvsroot/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.229
diff -u -p -r1.229 vfs_syscalls.c
--- src/sys/kern/vfs_syscalls.c 19 Aug 2005 12:30:02 -0000 1.229
+++ src/sys/kern/vfs_syscalls.c 28 Aug 2005 14:55:28 -0000
@@ -314,6 +314,7 @@ sys_mount(struct lwp *l, void *v, regist
mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
mp->mnt_unmounter = NULL;
mp->mnt_leaf = mp;
+ mp->mnt_clusteralign = PAGE_SIZE;
/*
* The underlying file system may refuse the mount for
Index: src/sys/ufs/ffs/ffs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.169
diff -u -p -r1.169 ffs_vfsops.c
--- src/sys/ufs/ffs/ffs_vfsops.c 23 Aug 2005 08:05:13 -0000 1.169
+++ src/sys/ufs/ffs/ffs_vfsops.c 28 Aug 2005 14:55:29 -0000
@@ -450,6 +450,9 @@ ffs_mount(struct mount *mp, const char *
}
(void) ffs_cgupdate(ump, MNT_WAIT);
}
+ if (mp->mnt_flag & MNT_SOFTDEP) {
+ mp->mnt_clusteralign = MAX(PAGE_SIZE, fs->fs_bsize);
+ }
return (error);
fail:
Index: src/sys/miscfs/genfs/genfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/genfs/genfs_vnops.c,v
retrieving revision 1.104
diff -u -p -r1.104 genfs_vnops.c
--- src/sys/miscfs/genfs/genfs_vnops.c 26 Jul 2005 08:06:29 -0000 1.104
+++ src/sys/miscfs/genfs/genfs_vnops.c 28 Aug 2005 14:55:30 -0000
@@ -1095,24 +1095,21 @@ genfs_putpages(void *v)
voff_t a_offhi;
int a_flags;
} */ *ap = v;
+ const int maxpages = MAXPHYS >> PAGE_SHIFT;
struct vnode *vp = ap->a_vp;
struct uvm_object *uobj = &vp->v_uobj;
struct simplelock *slock = &uobj->vmobjlock;
+ struct lwp *l = curlwp ? curlwp : &lwp0;
+ struct genfs_node *gp = VTOG(vp);
+ struct vm_page *pgs[maxpages], *pg, *nextpg, *tpg, curmp, endmp;
off_t startoff = ap->a_offlo;
off_t endoff = ap->a_offhi;
- off_t off;
+ off_t off, aofflo, aoffhi;
int flags = ap->a_flags;
- /* Even for strange MAXPHYS, the shift rounds down to a page */
- const int maxpages = MAXPHYS >> PAGE_SHIFT;
- int i, s, error, npages, nback;
- int freeflag;
- struct vm_page *pgs[maxpages], *pg, *nextpg, *tpg, curmp, endmp;
+ int i, s, error, npages, nbytes, nback, freeflag, dirtygen, amask;
boolean_t wasclean, by_list, needs_clean, yld;
boolean_t async = (flags & PGO_SYNCIO) == 0;
boolean_t pagedaemon = curproc == uvm.pagedaemon_proc;
- struct lwp *l = curlwp ? curlwp : &lwp0;
- struct genfs_node *gp = VTOG(vp);
- int dirtygen;
boolean_t modified = FALSE;
boolean_t cleanall;
@@ -1183,6 +1180,11 @@ genfs_putpages(void *v)
startoff == 0 && endoff == trunc_page(LLONG_MAX) &&
(vp->v_flag & VONWORKLST) != 0;
dirtygen = gp->g_dirtygen;
+ if (vp->v_type == VREG) {
+ amask = vp->v_mount->mnt_clusteralign - 1;
+ } else {
+ amask = PAGE_MASK;
+ }
freeflag = pagedaemon ? PG_PAGEOUT : PG_RELEASED;
curmp.uobject = uobj;
curmp.offset = (voff_t)-1;
@@ -1326,11 +1328,16 @@ genfs_putpages(void *v)
UVM_PAGE_OWN(pg, "genfs_putpages");
/*
- * first look backward.
+ * first look backward, making sure the range
+ * is aligned as needed.
*/
- npages = MIN(maxpages >> 1, off >> PAGE_SHIFT);
+ nbytes = MIN(maxpages << (PAGE_SHIFT - 1), off);
+ aofflo = (off - PAGE_SIZE - nbytes + amask) & ~amask;
+ aoffhi = MAX(off - PAGE_SIZE, 0);
+ npages = MIN(aoffhi - aofflo, off) >> PAGE_SHIFT;
nback = npages;
+
uvn_findpages(uobj, off - PAGE_SIZE, &nback, &pgs[0],
UFP_NOWAIT|UFP_NOALLOC|UFP_DIRTYONLY|UFP_BACKWARD);
if (nback) {
@@ -1352,10 +1359,14 @@ genfs_putpages(void *v)
/*
* then look forward to fill in the remaining space in
- * the array of pages.
+ * the array of pages, again aligning the range.
*/
- npages = maxpages - nback - 1;
+ nbytes = (maxpages - nback - 1) << PAGE_SHIFT;
+ aofflo = off + PAGE_SIZE;
+ aoffhi = (aofflo + nbytes) & ~amask;
+ npages = (aoffhi - aofflo) >> PAGE_SHIFT;
+
uvn_findpages(uobj, off + PAGE_SIZE, &npages,
&pgs[nback + 1],
UFP_NOWAIT|UFP_NOALLOC|UFP_DIRTYONLY);
--ew6BAiZeqk4r7MaW--