summaryrefslogtreecommitdiffstats
path: root/sys/ufs/ffs/ffs_vfsops.c
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2001-04-25 08:11:18 +0000
committermckusick <mckusick@FreeBSD.org>2001-04-25 08:11:18 +0000
commitf863141979de490194a5cb124d97ed1e3a000632 (patch)
tree0ea574f62c45c0ac1caa946e11d97f05e3fd2b80 /sys/ufs/ffs/ffs_vfsops.c
parentfa10273007fa4451f879e6b720eb020c082d4453 (diff)
downloadFreeBSD-src-f863141979de490194a5cb124d97ed1e3a000632.zip
FreeBSD-src-f863141979de490194a5cb124d97ed1e3a000632.tar.gz
When closing the last reference to an unlinked file, it is freed
by the inactive routine. Because the freeing causes the filesystem to be modified, the close must be held up during periods when the filesystem is suspended. For snapshots to be consistent across crashes, they must write blocks that they copy and claim those written blocks in their on-disk block pointers before the old blocks that they referenced can be allowed to be written. Close a loophole that allowed unwritten blocks to be skipped when doing ffs_sync with a request to wait for all I/O activity to be completed.
Diffstat (limited to 'sys/ufs/ffs/ffs_vfsops.c')
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 7d48fdb..02c3eaf 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -952,7 +952,7 @@ ffs_sync(mp, waitfor, cred, p)
struct ucred *cred;
struct proc *p;
{
- struct vnode *nvp, *vp;
+ struct vnode *nvp, *vp, *devvp;
struct inode *ip;
struct ufsmount *ump = VFSTOUFS(mp);
struct fs *fs;
@@ -1026,12 +1026,21 @@ loop:
#ifdef QUOTA
qsync(mp);
#endif
- if (waitfor != MNT_LAZY) {
- vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
- if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
+ devvp = ump->um_devvp;
+ mtx_lock(&devvp->v_interlock);
+ if (waitfor != MNT_LAZY &&
+ (devvp->v_numoutput > 0 || TAILQ_FIRST(&devvp->v_dirtyblkhd))) {
+ mtx_unlock(&devvp->v_interlock);
+ vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
+ if ((error = VOP_FSYNC(devvp, cred, waitfor, p)) != 0)
allerror = error;
- VOP_UNLOCK(ump->um_devvp, 0, p);
- }
+ VOP_UNLOCK(devvp, 0, p);
+ if (waitfor == MNT_WAIT) {
+ mtx_lock(&mntvnode_mtx);
+ goto loop;
+ }
+ } else
+ mtx_unlock(&devvp->v_interlock);
/*
* Write back modified superblock.
*/
OpenPOWER on IntegriCloud