summaryrefslogtreecommitdiffstats
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
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.
-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