diff options
author | jhb <jhb@FreeBSD.org> | 2011-02-08 13:02:25 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2011-02-08 13:02:25 +0000 |
commit | 4cecfec664c9451137c592bb8d43ed0ea071b329 (patch) | |
tree | a5cb521f45c81cd75b73fe46dfe8c049efc8f47d | |
parent | 44dfaf952a7967d189f26651e2b6a5b528202378 (diff) | |
download | FreeBSD-src-4cecfec664c9451137c592bb8d43ed0ea071b329.zip FreeBSD-src-4cecfec664c9451137c592bb8d43ed0ea071b329.tar.gz |
After reading a bitmap block for i-nodes or blocks, recheck the count of
free i-nodes or blocks to handle a race where another thread might have
allocated the last i-node or block while we were waiting for the buffer.
Tested by: dougb
-rw-r--r-- | sys/fs/ext2fs/ext2_alloc.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/sys/fs/ext2fs/ext2_alloc.c b/sys/fs/ext2fs/ext2_alloc.c index baab4a5..7abfe2b 100644 --- a/sys/fs/ext2fs/ext2_alloc.c +++ b/sys/fs/ext2fs/ext2_alloc.c @@ -650,6 +650,15 @@ ext2_alloccg(struct inode *ip, int cg, daddr_t bpref, int size) EXT2_LOCK(ump); return (0); } + if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0) { + /* + * Another thread allocated the last block in this + * group while we were waiting for the buffer. + */ + brelse(bp); + EXT2_LOCK(ump); + return (0); + } bbp = (char *)bp->b_data; if (dtog(fs, bpref) != cg) @@ -776,6 +785,15 @@ ext2_nodealloccg(struct inode *ip, int cg, daddr_t ipref, int mode) EXT2_LOCK(ump); return (0); } + if (fs->e2fs_gd[cg].ext2bgd_nifree == 0) { + /* + * Another thread allocated the last i-node in this + * group while we were waiting for the buffer. + */ + brelse(bp); + EXT2_LOCK(ump); + return (0); + } ibp = (char *)bp->b_data; if (ipref) { ipref %= fs->e2fs->e2fs_ipg; |