diff options
author | John Baldwin <jhb@FreeBSD.org> | 2011-02-08 13:02:25 +0000 |
---|---|---|
committer | John Baldwin <jhb@FreeBSD.org> | 2011-02-08 13:02:25 +0000 |
commit | 73dd6d1f8fddfdd8949e89dfa698ce7287bc54df (patch) | |
tree | a5cb521f45c81cd75b73fe46dfe8c049efc8f47d /sys/fs/ext2fs | |
parent | e0e5b8b471f914d7045b5a700c488c7268928cf1 (diff) | |
download | src-73dd6d1f8fddfdd8949e89dfa698ce7287bc54df.tar.gz src-73dd6d1f8fddfdd8949e89dfa698ce7287bc54df.zip |
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
Notes
Notes:
svn path=/head/; revision=218438
Diffstat (limited to 'sys/fs/ext2fs')
-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 baab4a5677d1..7abfe2b2bf09 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; |