diff options
Diffstat (limited to 'sys/ufs/ffs')
-rw-r--r-- | sys/ufs/ffs/ffs_inode.c | 12 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_snapshot.c | 24 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_vnops.c | 10 |
3 files changed, 33 insertions, 13 deletions
diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c index 33b65bf..ad6bff9 100644 --- a/sys/ufs/ffs/ffs_inode.c +++ b/sys/ufs/ffs/ffs_inode.c @@ -66,9 +66,11 @@ static int ffs_indirtrunc(struct inode *, ufs2_daddr_t, ufs2_daddr_t, * IN_ACCESS, IN_UPDATE, and IN_CHANGE flags respectively. Write the inode * to disk if the IN_MODIFIED flag is set (it may be set initially, or by * the timestamp update). The IN_LAZYMOD flag is set to force a write - * later if not now. If we write now, then clear both IN_MODIFIED and - * IN_LAZYMOD to reflect the presumably successful write, and if waitfor is - * set, then wait for the write to complete. + * later if not now. The IN_LAZYACCESS is set instead of IN_MODIFIED if the fs + * is currently being suspended (or is suspended) and vnode has been accessed. + * If we write now, then clear IN_MODIFIED, IN_LAZYACCESS and IN_LAZYMOD to + * reflect the presumably successful write, and if waitfor is set, then wait + * for the write to complete. */ int ffs_update(vp, waitfor) @@ -80,12 +82,12 @@ ffs_update(vp, waitfor) struct inode *ip; int error; - ASSERT_VOP_LOCKED(vp, "ffs_update"); + ASSERT_VOP_ELOCKED(vp, "ffs_update"); ufs_itimes(vp); ip = VTOI(vp); if ((ip->i_flag & IN_MODIFIED) == 0 && waitfor == 0) return (0); - ip->i_flag &= ~(IN_LAZYMOD | IN_MODIFIED); + ip->i_flag &= ~(IN_LAZYACCESS | IN_LAZYMOD | IN_MODIFIED); fs = ip->i_fs; if (fs->fs_ronly) return (0); 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); diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 91d2c01..4d8d9ef 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -593,8 +593,11 @@ ffs_read(ap) } if ((error == 0 || uio->uio_resid != orig_resid) && - (vp->v_mount->mnt_flag & MNT_NOATIME) == 0) + (vp->v_mount->mnt_flag & MNT_NOATIME) == 0) { + VI_LOCK(vp); ip->i_flag |= IN_ACCESS; + VI_UNLOCK(vp); + } return (error); } @@ -989,8 +992,11 @@ ffs_extread(struct vnode *vp, struct uio *uio, int ioflag) } if ((error == 0 || uio->uio_resid != orig_resid) && - (vp->v_mount->mnt_flag & MNT_NOATIME) == 0) + (vp->v_mount->mnt_flag & MNT_NOATIME) == 0) { + VI_LOCK(vp); ip->i_flag |= IN_ACCESS; + VI_UNLOCK(vp); + } return (error); } |