summaryrefslogtreecommitdiffstats
path: root/sys/ufs/ffs
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2001-05-14 17:16:49 +0000
committermckusick <mckusick@FreeBSD.org>2001-05-14 17:16:49 +0000
commitdca0cbadc364dfad338512a273178976abbfe1dc (patch)
tree9c642f2ff4d4b1063e879967c24aa0bf5b9bb380 /sys/ufs/ffs
parentbcc6e22c2f11fa2f58e4bf99df106d84736a5a8a (diff)
downloadFreeBSD-src-dca0cbadc364dfad338512a273178976abbfe1dc.zip
FreeBSD-src-dca0cbadc364dfad338512a273178976abbfe1dc.tar.gz
Further fixes for deadlock in the presence of multiple snapshots.
There are still more to find, but this fix should cover the common cases that folks are hitting.
Diffstat (limited to 'sys/ufs/ffs')
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index b16c62a..1cbfe28 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -73,8 +73,18 @@ static int mapacct __P((struct vnode *, ufs_daddr_t *, ufs_daddr_t *,
static int ffs_copyonwrite __P((struct vnode *, struct buf *));
static int readblock __P((struct buf *, daddr_t));
+/*
+ * To ensure the consistency of snapshots across crashes, we must
+ * synchronously write out copied blocks before allowing the
+ * originals to be modified. Because of the rather severe speed
+ * penalty that this imposes, the following flag allows this
+ * crash persistence to be disabled.
+ */
+int dopersistence = 0;
+
#ifdef DEBUG
#include <sys/sysctl.h>
+SYSCTL_INT(_debug, OID_AUTO, dopersistence, CTLFLAG_RW, &dopersistence, 0, "");
int snapdebug = 0;
SYSCTL_INT(_debug, OID_AUTO, snapdebug, CTLFLAG_RW, &snapdebug, 0, "");
#endif /* DEBUG */
@@ -955,7 +965,7 @@ ffs_snapblkfree(freeip, bno, size)
if (savedcbp != 0) {
bcopy(savedcbp->b_data, cbp->b_data, fs->fs_bsize);
bawrite(cbp);
- if (ip->i_effnlink > 0)
+ if (dopersistence && ip->i_effnlink > 0)
(void) VOP_FSYNC(vp, KERNCRED, MNT_WAIT, p);
VOP_UNLOCK(vp, 0, p);
continue;
@@ -966,7 +976,7 @@ ffs_snapblkfree(freeip, bno, size)
if ((error = readblock(cbp, lbn)) != 0) {
bzero(cbp->b_data, fs->fs_bsize);
bawrite(cbp);
- if (ip->i_effnlink > 0)
+ if (dopersistence && ip->i_effnlink > 0)
(void) VOP_FSYNC(vp, KERNCRED, MNT_WAIT, p);
VOP_UNLOCK(vp, 0, p);
break;
@@ -982,7 +992,7 @@ ffs_snapblkfree(freeip, bno, size)
if (savedcbp) {
vp = savedcbp->b_vp;
bawrite(savedcbp);
- if (VTOI(vp)->i_effnlink > 0) {
+ if (dopersistence && VTOI(vp)->i_effnlink > 0) {
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
(void) VOP_FSYNC(vp, KERNCRED, MNT_WAIT, p);
VOP_UNLOCK(vp, 0, p);
@@ -1172,7 +1182,7 @@ retry:
if (savedcbp != 0) {
bcopy(savedcbp->b_data, cbp->b_data, fs->fs_bsize);
bawrite(cbp);
- if (ip->i_effnlink > 0)
+ if (dopersistence && ip->i_effnlink > 0)
(void) VOP_FSYNC(vp, KERNCRED, MNT_WAIT, p);
VOP_UNLOCK(vp, 0, p);
continue;
@@ -1183,12 +1193,13 @@ retry:
if ((error = readblock(cbp, lbn)) != 0) {
bzero(cbp->b_data, fs->fs_bsize);
bawrite(cbp);
- if (ip->i_effnlink > 0)
+ if (dopersistence && ip->i_effnlink > 0)
(void) VOP_FSYNC(vp, KERNCRED, MNT_WAIT, p);
VOP_UNLOCK(vp, 0, p);
break;
}
savedcbp = cbp;
+ VOP_UNLOCK(vp, 0, p);
}
/*
* Note that we need to synchronously write snapshots that
@@ -1198,9 +1209,11 @@ retry:
if (savedcbp) {
vp = savedcbp->b_vp;
bawrite(savedcbp);
- if (VTOI(vp)->i_effnlink > 0)
+ if (dopersistence && VTOI(vp)->i_effnlink > 0) {
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
(void) VOP_FSYNC(vp, KERNCRED, MNT_WAIT, p);
- VOP_UNLOCK(vp, 0, p);
+ VOP_UNLOCK(vp, 0, p);
+ }
}
return (error);
}
OpenPOWER on IntegriCloud