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