diff options
author | tegge <tegge@FreeBSD.org> | 2005-10-09 20:00:16 +0000 |
---|---|---|
committer | tegge <tegge@FreeBSD.org> | 2005-10-09 20:00:16 +0000 |
commit | 62d200d06fea630c4ba1af09988b2f6c025f229d (patch) | |
tree | 989adbb7a82f540fff60dff0c541743be16de93d /sys/ufs/ffs | |
parent | 1a45f40f4f2ed50cafc76140382fc71c309bec76 (diff) | |
download | FreeBSD-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/ufs/ffs')
-rw-r--r-- | sys/ufs/ffs/ffs_snapshot.c | 5 |
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); |