diff options
author | mckusick <mckusick@FreeBSD.org> | 2002-11-30 07:27:12 +0000 |
---|---|---|
committer | mckusick <mckusick@FreeBSD.org> | 2002-11-30 07:27:12 +0000 |
commit | d4a32db4aeca128cddc225630f42930c901c8cf5 (patch) | |
tree | 0841cd020a90f81787c8ef4ac67b2bee71d5a0d3 /sys/ufs | |
parent | 70f58b67569498f46105eb01cd36ac3ad3142eea (diff) | |
download | FreeBSD-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.c | 9 |
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); /* |