Subject: Re: kern/10231: panic in soft dependence code
To: Matthias Scheler <tron@lyssa.zhadum.de>
From: Charles M. Hannum <root@ihack.net>
List: current-users
Date: 05/30/2000 12:27:19
I believe this bug is now fixed.  Let me know whether or not you get
more panics with the following patch.


Index: gnu/sys/ufs/ffs/ffs_softdep.c
===================================================================
RCS file: /cvsroot/gnusrc/gnu/sys/ufs/ffs/ffs_softdep.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -c -2 -r1.10 -r1.11
*** ffs_softdep.c	2000/05/27 06:51:30	1.10
--- ffs_softdep.c	2000/05/30 17:26:08	1.11
***************
*** 1,3 ****
! /*	$NetBSD: ffs_softdep.c,v 1.10 2000/05/27 06:51:30 thorpej Exp $	*/
  
  /*
--- 1,3 ----
! /*	$NetBSD: ffs_softdep.c,v 1.11 2000/05/30 17:26:08 mycroft Exp $	*/
  
  /*
***************
*** 3897,3900 ****
--- 3897,3901 ----
  	} */ *ap = v;
  	struct vnode *vp = ap->a_vp;
+ 	struct inodedep *inodedep;
  	struct pagedep *pagedep;
  	struct allocdirect *adp;
***************
*** 3943,3950 ****
  	waitfor = MNT_NOWAIT;
  top:
! 	if (getdirtybuf(&vp->v_dirtyblkhd.lh_first, MNT_WAIT) == 0) {
! 		FREE_LOCK(&lk);
! 		return (0);
! 	}
  	bp = vp->v_dirtyblkhd.lh_first;
  loop:
--- 3944,3949 ----
  	waitfor = MNT_NOWAIT;
  top:
! 	if (getdirtybuf(&vp->v_dirtyblkhd.lh_first, MNT_WAIT) == 0)
! 		goto clean;
  	bp = vp->v_dirtyblkhd.lh_first;
  loop:
***************
*** 4121,4141 ****
  	 * devices, we may need to do further work.
  	 */
! 	if (vp->v_dirtyblkhd.lh_first == NULL) {
  		FREE_LOCK(&lk);
! 		return (0);
  	}
  
! 	FREE_LOCK(&lk);
  	/*
! 	 * If we are trying to sync a block device, some of its buffers may
! 	 * contain metadata that cannot be written until the contents of some
! 	 * partially written files have been written to disk. The only easy
! 	 * way to accomplish this is to sync the entire filesystem (luckily
! 	 * this happens rarely).
! 	 */
! 	if (vp->v_type == VBLK && vp->v_specmountpoint && !VOP_ISLOCKED(vp) &&
! 	    (error = VFS_SYNC(vp->v_specmountpoint, MNT_WAIT, ap->a_cred,
! 	     ap->a_p)) != 0)
! 		return (error);
  	return (0);
  }
--- 4120,4150 ----
  	 * devices, we may need to do further work.
  	 */
! 	if (vp->v_dirtyblkhd.lh_first != NULL) {
  		FREE_LOCK(&lk);
! 		/*
! 		 * If we are trying to sync a block device, some of its buffers
! 		 * may contain metadata that cannot be written until the
! 		 * contents of some partially written files have been written
! 		 * to disk. The only easy way to accomplish this is to sync the
! 		 * entire filesystem (luckily this happens rarely).
! 		 */
! 		if (vp->v_type == VBLK && vp->v_specmountpoint &&
! 		    !VOP_ISLOCKED(vp) &&
! 		    (error = VFS_SYNC(vp->v_specmountpoint, MNT_WAIT,
! 		     ap->a_cred, ap->a_p)) != 0)
! 			return (error);
! 		ACQUIRE_LOCK(&lk);
  	}
  
! clean:
  	/*
! 	 * If there is still an inodedep, we know that the inode has pending
! 	 * modifications, and we must force it to be flushed to disk.  We do
! 	 * this by explicitly setting IN_MODIFIED so that ffs_update() will
! 	 * see it.
! 	 */
! 	if (inodedep_lookup(VTOI(vp)->i_fs, VTOI(vp)->i_number, 0, &inodedep))
! 		VTOI(vp)->i_flag |= IN_MODIFIED;
! 	FREE_LOCK(&lk);
  	return (0);
  }
Index: sys/ufs/ffs/ffs_inode.c
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ffs/ffs_inode.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -c -2 -r1.34 -r1.35
*** ffs_inode.c	2000/05/29 18:04:30	1.34
--- ffs_inode.c	2000/05/30 17:23:52	1.35
***************
*** 1,3 ****
! /*	$NetBSD: ffs_inode.c,v 1.34 2000/05/29 18:04:30 mycroft Exp $	*/
  
  /*
--- 1,3 ----
! /*	$NetBSD: ffs_inode.c,v 1.35 2000/05/30 17:23:52 mycroft Exp $	*/
  
  /*
***************
*** 108,117 ****
  	if (flags == 0)
  		return (0);
- 	ip->i_flag &= ~flags;
  	fs = ip->i_fs;
  
! 	waitfor = ap->a_flags & UPDATE_WAIT;
! 	if ((ap->a_flags & UPDATE_DIROP) && !DOINGSOFTDEP(ap->a_vp))
! 		waitfor |= UPDATE_WAIT;
  
  	/*
--- 108,120 ----
  	if (flags == 0)
  		return (0);
  	fs = ip->i_fs;
  
! 	if ((flags & IN_MODIFIED) != 0 &&
! 	    (ap->a_vp->v_mount->mnt_flag & MNT_ASYNC) == 0) {
! 		waitfor = ap->a_flags & UPDATE_WAIT;
! 		if ((ap->a_flags & UPDATE_DIROP) && !DOINGSOFTDEP(ap->a_vp))
! 			waitfor |= UPDATE_WAIT;
! 	} else
! 		waitfor = 0;
  
  	/*
***************
*** 130,133 ****
--- 133,137 ----
  		return (error);
  	}
+ 	ip->i_flag &= ~(IN_MODIFIED | IN_ACCESSED);
  	if (DOINGSOFTDEP(ap->a_vp))
  		softdep_update_inodeblock(ip, bp, waitfor);
***************
*** 142,147 ****
  #endif
  		memcpy(cp, &ip->i_din.ffs_din, DINODE_SIZE);
! 	if (waitfor && (flags & IN_MODIFIED) != 0 &&
! 	    (ap->a_vp->v_mount->mnt_flag & MNT_ASYNC) == 0) {
  		return (bwrite(bp));
  	} else {
--- 146,150 ----
  #endif
  		memcpy(cp, &ip->i_din.ffs_din, DINODE_SIZE);
! 	if (waitfor) {
  		return (bwrite(bp));
  	} else {