summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2011-02-08 13:02:25 +0000
committerjhb <jhb@FreeBSD.org>2011-02-08 13:02:25 +0000
commit4cecfec664c9451137c592bb8d43ed0ea071b329 (patch)
treea5cb521f45c81cd75b73fe46dfe8c049efc8f47d
parent44dfaf952a7967d189f26651e2b6a5b528202378 (diff)
downloadFreeBSD-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.c18
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;
OpenPOWER on IntegriCloud