summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2002-11-30 07:27:12 +0000
committermckusick <mckusick@FreeBSD.org>2002-11-30 07:27:12 +0000
commitd4a32db4aeca128cddc225630f42930c901c8cf5 (patch)
tree0841cd020a90f81787c8ef4ac67b2bee71d5a0d3 /sys/ufs
parent70f58b67569498f46105eb01cd36ac3ad3142eea (diff)
downloadFreeBSD-src-d4a32db4aeca128cddc225630f42930c901c8cf5.zip
FreeBSD-src-d4a32db4aeca128cddc225630f42930c901c8cf5.tar.gz
Fix two deadlocks in snapshots:
1) Release the snapshot file lock while suspending the system. Otherwise a process trying to read the lock may block on its containing directory preventing the suspension from completing. Thanks to Sean Kelly <smkelly@zombie.org> for finding this deadlock. 2) Replace some bdwrite's with bawrite's so as not to fill all the buffers with dirty data. The buffers could not be cleaned as the snapshot vnode was locked hence the system could deadlock when making snapshots of really massive filesystems. Thanks to Hidetoshi Shimokawa <simokawa@sat.t.u-tokyo.ac.jp> for figuring this out. Sponsored by: DARPA & NAI Labs.
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index 667b937..efa01df 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -230,7 +230,7 @@ restart:
fs->fs_bsize, td->td_ucred, BA_METAONLY, &ibp);
if (error)
goto out;
- bdwrite(ibp);
+ bawrite(ibp);
}
/*
* Allocate copies for the superblock and its summary information.
@@ -257,7 +257,7 @@ restart:
fs->fs_bsize, KERNCRED, 0, &nbp);
if (error)
goto out;
- bdwrite(nbp);
+ bawrite(nbp);
}
/*
* Copy all the cylinder group maps. Although the
@@ -290,9 +290,12 @@ restart:
ip->i_flag |= IN_CHANGE | IN_UPDATE;
/*
* Ensure that the snapshot is completely on disk.
+ * Since we have marked it as a snapshot it is safe to
+ * unlock it as no process will be allowed to write to it.
*/
if ((error = VOP_FSYNC(vp, KERNCRED, MNT_WAIT, td)) != 0)
goto out;
+ VOP_UNLOCK(vp, 0, td);
/*
* All allocations are done, so we can now snapshot the system.
*
@@ -309,12 +312,14 @@ restart:
vn_finished_write(wrtmp);
if ((error = vfs_write_suspend(vp->v_mount)) != 0) {
vn_start_write(NULL, &wrtmp, V_WAIT);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
goto out;
}
if (mp->mnt_kern_flag & MNTK_SUSPENDED)
break;
vn_start_write(NULL, &wrtmp, V_WAIT);
}
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (collectsnapstats)
nanotime(&starttime);
/*
OpenPOWER on IntegriCloud