Konstantin Belousov wrote: > > Please try the following patch. It is against HEAD, might need some > adjustments for 8. I do the resume and write accounting atomically, > not allowing other suspension to intervent between. > > diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c > index 3f65b05..cf49ecb 100644 > --- a/sys/kern/vfs_vnops.c > +++ b/sys/kern/vfs_vnops.c > @@ -1434,6 +1434,40 @@ vn_closefile(fp, td) > * proceed. If a suspend request is in progress, we wait until the > * suspension is over, and then proceed. > */ > +static int > +vn_start_write_locked(struct mount *mp, int flags) > +{ > + int error; > + > + mtx_assert(MNT_MTX(mp), MA_OWNED); > + error = 0; > + > + /* > + * Check on status of suspension. > + */ > + if ((curthread->td_pflags & TDP_IGNSUSP) == 0 || > + mp->mnt_susp_owner != curthread) { > + while ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0) { > + if (flags & V_NOWAIT) { > + error = EWOULDBLOCK; > + goto unlock; > + } > + error = msleep(&mp->mnt_flag, MNT_MTX(mp), > + (PUSER - 1) | (flags & PCATCH), "suspfs", 0); > + if (error) > + goto unlock; > + } > + } > + if (flags & V_XSLEEP) > + goto unlock; > + mp->mnt_writeopcount++; > +unlock: > + if (error != 0 || (flags & V_XSLEEP) != 0) > + MNT_REL(mp); > + MNT_IUNLOCK(mp); > + return (error); > +} > + > int > vn_start_write(vp, mpp, flags) > struct vnode *vp; > @@ -1470,30 +1504,7 @@ vn_start_write(vp, mpp, flags) > if (vp == NULL) > MNT_REF(mp); > > - /* > - * Check on status of suspension. > - */ > - if ((curthread->td_pflags & TDP_IGNSUSP) == 0 || > - mp->mnt_susp_owner != curthread) { > - while ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0) { > - if (flags & V_NOWAIT) { > - error = EWOULDBLOCK; > - goto unlock; > - } > - error = msleep(&mp->mnt_flag, MNT_MTX(mp), > - (PUSER - 1) | (flags & PCATCH), "suspfs", 0); > - if (error) > - goto unlock; > - } > - } > - if (flags & V_XSLEEP) > - goto unlock; > - mp->mnt_writeopcount++; > -unlock: > - if (error != 0 || (flags & V_XSLEEP) != 0) > - MNT_REL(mp); > - MNT_IUNLOCK(mp); > - return (error); > + return (vn_start_write_locked(mp, flags)); > } > > /* > @@ -1639,8 +1650,7 @@ vfs_write_suspend(mp) > * Request a filesystem to resume write operations. > */ > void > -vfs_write_resume(mp) > - struct mount *mp; > +vfs_write_resume_flags(struct mount *mp, int flags) > { > > MNT_ILOCK(mp); > @@ -1652,10 +1662,25 @@ vfs_write_resume(mp) > wakeup(&mp->mnt_writeopcount); > wakeup(&mp->mnt_flag); > curthread->td_pflags &= ~TDP_IGNSUSP; > + if ((flags & VR_START_WRITE) != 0) { > + MNT_REF(mp); > + mp->mnt_writeopcount++; > + } > MNT_IUNLOCK(mp); > VFS_SUSP_CLEAN(mp); > - } else > + } else if ((flags & VR_START_WRITE) != 0) { > + MNT_REF(mp); > + vn_start_write_locked(mp, 0); > + } else { > MNT_IUNLOCK(mp); > + } > +} > + > +void > +vfs_write_resume(struct mount *mp) > +{ > + > + vfs_write_resume_flags(mp, 0); > } > > /* > diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h > index 42f9e5f..4371b40 100644 > --- a/sys/sys/vnode.h > +++ b/sys/sys/vnode.h > @@ -392,6 +392,8 @@ extern int vttoif_tab[]; > #define V_NOWAIT 0x0002 /* vn_start_write: don't sleep for > suspend */ > #define V_XSLEEP 0x0004 /* vn_start_write: just return after > sleep */ > > +#define VR_START_WRITE 0x0001 /* vfs_write_resume: start write > atomically */ > + > #define VREF(vp) vref(vp) > > #ifdef DIAGNOSTIC > @@ -701,6 +703,7 @@ int vn_io_fault_uiomove(char *data, int xfersize, > struct uio *uio); > int vfs_cache_lookup(struct vop_lookup_args *ap); > void vfs_timestamp(struct timespec *); > void vfs_write_resume(struct mount *mp); > +void vfs_write_resume_flags(struct mount *mp, int flags); > int vfs_write_suspend(struct mount *mp); > int vop_stdbmap(struct vop_bmap_args *); > int vop_stdfsync(struct vop_fsync_args *); > diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c > index e528509..25ad79c 100644 > --- a/sys/ufs/ffs/ffs_snapshot.c > +++ b/sys/ufs/ffs/ffs_snapshot.c > @@ -687,8 +687,7 @@ out1: > /* > * Resume operation on filesystem. > */ > - vfs_write_resume(vp->v_mount); > - vn_start_write(NULL, &wrtmp, V_WAIT); > + vfs_write_resume_flags(vp->v_mount, VR_START_WRITE); > if (collectsnapstats && starttime.tv_sec > 0) { > nanotime(&endtime); > timespecsub(&endtime, &starttime);
Your patch adjusted to FreeBSD Stable 8 works fine. Creating a snapshot every minute runs without errors for more than 6 hours now, without the patch my test machine hangs not later than one hour. -- Andreas Longwitz _______________________________________________ freebsd-stable@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-stable To unsubscribe, send any mail to "freebsd-stable-unsubscr...@freebsd.org"