summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authortegge <tegge@FreeBSD.org>2005-10-09 20:00:16 +0000
committertegge <tegge@FreeBSD.org>2005-10-09 20:00:16 +0000
commit62d200d06fea630c4ba1af09988b2f6c025f229d (patch)
tree989adbb7a82f540fff60dff0c541743be16de93d /sys
parent1a45f40f4f2ed50cafc76140382fc71c309bec76 (diff)
downloadFreeBSD-src-62d200d06fea630c4ba1af09988b2f6c025f229d.zip
FreeBSD-src-62d200d06fea630c4ba1af09988b2f6c025f229d.tar.gz
Eliminate a deadlock that can occur during the cgaccount() processing due to
the cg map buffer being held when writing indirect blocks. The process ends up in ffs_copyonwrite(), attempting to get snaplk while holding the cg map buffer lock. Another process might be in ffs_copyonwrite(), trying to allocate a new block for a copy. It would hold snaplk while trying to get the cg map buffer lock. Release the cg map buffer early and use the copy for most of the cgaccount processing to avoid this deadlock.
Diffstat (limited to 'sys')
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c5
1 files changed, 2 insertions, 3 deletions
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index 39cfcf7..92746be 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -752,6 +752,8 @@ cgaccount(cg, vp, nbp, passno)
if (fs->fs_cgsize < fs->fs_bsize)
bzero(&nbp->b_data[fs->fs_cgsize],
fs->fs_bsize - fs->fs_cgsize);
+ cgp = (struct cg *)nbp->b_data;
+ bqrelse(bp);
if (passno == 2)
nbp->b_flags |= B_VALIDSUSPWRT;
numblks = howmany(fs->fs_size, fs->fs_frag);
@@ -773,7 +775,6 @@ cgaccount(cg, vp, nbp, passno)
error = UFS_BALLOC(vp, lblktosize(fs, (off_t)(base + loc)),
fs->fs_bsize, KERNCRED, BA_METAONLY, &ibp);
if (error) {
- brelse(bp);
return (error);
}
indiroff = (base + loc - NDADDR) % NINDIR(fs);
@@ -786,7 +787,6 @@ cgaccount(cg, vp, nbp, passno)
lblktosize(fs, (off_t)(base + loc)),
fs->fs_bsize, KERNCRED, BA_METAONLY, &ibp);
if (error) {
- brelse(bp);
return (error);
}
indiroff = 0;
@@ -812,7 +812,6 @@ cgaccount(cg, vp, nbp, passno)
((ufs2_daddr_t *)(ibp->b_data)) [indiroff] == BLK_NOCOPY)
panic("ffs_snapshot: lost indirect block");
}
- bqrelse(bp);
if (passno == 2)
ibp->b_flags |= B_VALIDSUSPWRT;
bdwrite(ibp);
OpenPOWER on IntegriCloud