summaryrefslogtreecommitdiffstats
path: root/sys/ufs/ffs
diff options
context:
space:
mode:
authortegge <tegge@FreeBSD.org>2006-03-02 22:13:28 +0000
committertegge <tegge@FreeBSD.org>2006-03-02 22:13:28 +0000
commit774f51ad2c9890088551e2fef8c7c2ec8bc1e446 (patch)
treea136dfc347b9ef7b044439ec33fe997d02fb4061 /sys/ufs/ffs
parent29fc266dddf27264a642495e94c044465289b437 (diff)
downloadFreeBSD-src-774f51ad2c9890088551e2fef8c7c2ec8bc1e446.zip
FreeBSD-src-774f51ad2c9890088551e2fef8c7c2ec8bc1e446.tar.gz
Eliminate a deadlock when creating snapshots. Blocking vn_start_write() must
be called without any vnode locks held. Remove calls to vn_start_write() and vn_finished_write() in vnode_pager_putpages() and add these calls before the vnode lock is obtained to most of the callers that don't already have them.
Diffstat (limited to 'sys/ufs/ffs')
-rw-r--r--sys/ufs/ffs/ffs_rawread.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/sys/ufs/ffs/ffs_rawread.c b/sys/ufs/ffs/ffs_rawread.c
index 3afa6c3..ec0d4fe 100644
--- a/sys/ufs/ffs/ffs_rawread.c
+++ b/sys/ufs/ffs/ffs_rawread.c
@@ -101,6 +101,7 @@ ffs_rawread_sync(struct vnode *vp, struct thread *td)
int error;
int upgraded;
struct bufobj *bo;
+ struct mount *mp;
/* Check for dirty mmap, pending writes and dirty buffers */
spl = splbio();
@@ -112,7 +113,15 @@ ffs_rawread_sync(struct vnode *vp, struct thread *td)
splx(spl);
VI_UNLOCK(vp);
- if (VOP_ISLOCKED(vp, td) != LK_EXCLUSIVE) {
+ if (vn_start_write(vp, &mp, V_NOWAIT) != 0) {
+ if (VOP_ISLOCKED(vp, td) != LK_EXCLUSIVE)
+ upgraded = 1;
+ else
+ upgraded = 0;
+ VOP_UNLOCK(vp, 0, td);
+ (void) vn_start_write(vp, &mp, V_WAIT);
+ VOP_LOCK(vp, LK_EXCLUSIVE, td);
+ } else if (VOP_ISLOCKED(vp, td) != LK_EXCLUSIVE) {
upgraded = 1;
/* Upgrade to exclusive lock, this might block */
VOP_LOCK(vp, LK_UPGRADE, td);
@@ -161,6 +170,7 @@ ffs_rawread_sync(struct vnode *vp, struct thread *td)
VI_UNLOCK(vp);
if (upgraded != 0)
VOP_LOCK(vp, LK_DOWNGRADE, td);
+ vn_finished_write(mp);
} else {
splx(spl);
VI_UNLOCK(vp);
OpenPOWER on IntegriCloud