From cfba50c070a2fb93a60c35b7952c0778c0d6f8b5 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 30 Jun 2009 10:07:33 +0000 Subject: [PATCH] For SU mounts, softdep_fsync() might drop vnode lock, allowing other threads to put dirty buffers on the vnode bufobj list. For regular files and synchronous fsync requests, check for the condition and restart the fsync vop if a new dirty buffer arrived. Tested by: pho Approved by: re (kensmith) MFC after: 1 month --- sys/ufs/ffs/ffs_vnops.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 1abb994422b..a6a4c05d3ec 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -180,15 +180,36 @@ struct vop_vector ffs_fifoops2 = { static int ffs_fsync(struct vop_fsync_args *ap) { + struct vnode *vp; + struct bufobj *bo; int error; - error = ffs_syncvnode(ap->a_vp, ap->a_waitfor); + vp = ap->a_vp; + bo = &vp->v_bufobj; +retry: + error = ffs_syncvnode(vp, ap->a_waitfor); if (error) return (error); if (ap->a_waitfor == MNT_WAIT && - (ap->a_vp->v_mount->mnt_flag & MNT_SOFTDEP)) - error = softdep_fsync(ap->a_vp); - return (error); + (vp->v_mount->mnt_flag & MNT_SOFTDEP)) { + error = softdep_fsync(vp); + if (error) + return (error); + + /* + * The softdep_fsync() function may drop vp lock, + * allowing for dirty buffers to reappear on the + * bo_dirty list. Recheck and resync as needed. + */ + BO_LOCK(bo); + if (vp->v_type == VREG && (bo->bo_numoutput > 0 || + bo->bo_dirty.bv_cnt > 0)) { + BO_UNLOCK(bo); + goto retry; + } + BO_UNLOCK(bo); + } + return (0); } int