diff options
author | kib <kib@FreeBSD.org> | 2006-10-10 09:20:54 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2006-10-10 09:20:54 +0000 |
commit | dc1147adb06ee01012984702aebef6c27b92c7e0 (patch) | |
tree | b21ac1bbb7acef29dace7ac99cf8f176bcc4b0fc /sys/ufs/ffs/ffs_snapshot.c | |
parent | c23de2fec88f3af5873cf8856e1e480b353f63cd (diff) | |
download | FreeBSD-src-dc1147adb06ee01012984702aebef6c27b92c7e0.zip FreeBSD-src-dc1147adb06ee01012984702aebef6c27b92c7e0.tar.gz |
Do not translate the IN_ACCESS inode flag into the IN_MODIFIED while filesystem
is suspending/suspended. Doing so may result in deadlock. Instead, set the
(new) IN_LAZYACCESS flag, that becomes IN_MODIFIED when suspend is lifted.
Change the locking protocol in order to set the IN_ACCESS and timestamps
without upgrading shared vnode lock to exclusive (see comments in the
inode.h). Before that, inode was modified while holding only shared
lock.
Tested by: Peter Holm
Reviewed by: tegge, bde
Approved by: pjd (mentor)
MFC after: 3 weeks
Diffstat (limited to 'sys/ufs/ffs/ffs_snapshot.c')
-rw-r--r-- | sys/ufs/ffs/ffs_snapshot.c | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index 473dbfd..6ab9af2 100644 --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -2309,15 +2309,16 @@ readblock(vp, bp, lbn) return (bp->b_error); } - /* * Process file deletes that were deferred by ufs_inactive() due to - * the file system being suspended. + * the file system being suspended. Transfer IN_LAZYACCESS into + * IN_MODIFIED for vnodes that were accessed during suspension. */ static void process_deferred_inactive(struct mount *mp) { struct vnode *vp, *mvp; + struct inode *ip; struct thread *td; int error; @@ -2327,9 +2328,15 @@ process_deferred_inactive(struct mount *mp) loop: MNT_VNODE_FOREACH(vp, mp, mvp) { VI_LOCK(vp); - if ((vp->v_iflag & (VI_DOOMED | VI_OWEINACT)) != VI_OWEINACT || - vp->v_usecount > 0 || - vp->v_type == VNON) { + /* + * IN_LAZYACCESS is checked here without holding any + * vnode lock, but this flag is set only while holding + * vnode interlock. + */ + if (vp->v_type == VNON || (vp->v_iflag & VI_DOOMED) != 0 || + ((VTOI(vp)->i_flag & IN_LAZYACCESS) == 0 && + ((vp->v_iflag & VI_OWEINACT) == 0 || + vp->v_usecount > 0))) { VI_UNLOCK(vp); continue; } @@ -2344,8 +2351,13 @@ process_deferred_inactive(struct mount *mp) MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); goto loop; } + ip = VTOI(vp); + if ((ip->i_flag & IN_LAZYACCESS) != 0) { + ip->i_flag &= ~IN_LAZYACCESS; + ip->i_flag |= IN_MODIFIED; + } VI_LOCK(vp); - if ((vp->v_iflag & VI_OWEINACT) == 0) { + if ((vp->v_iflag & VI_OWEINACT) == 0 || vp->v_usecount > 0) { VI_UNLOCK(vp); VOP_UNLOCK(vp, 0, td); vdrop(vp); |