|
@@ -730,6 +730,27 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int find_inode_bit(struct super_block *sb, ext4_group_t group,
|
|
|
+ struct buffer_head *bitmap, unsigned long *ino)
|
|
|
+{
|
|
|
+next:
|
|
|
+ *ino = ext4_find_next_zero_bit((unsigned long *)
|
|
|
+ bitmap->b_data,
|
|
|
+ EXT4_INODES_PER_GROUP(sb), *ino);
|
|
|
+ if (*ino >= EXT4_INODES_PER_GROUP(sb))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if ((EXT4_SB(sb)->s_journal == NULL) &&
|
|
|
+ recently_deleted(sb, group, *ino)) {
|
|
|
+ *ino = *ino + 1;
|
|
|
+ if (*ino < EXT4_INODES_PER_GROUP(sb))
|
|
|
+ goto next;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* There are two policies for allocating an inode. If the new inode is
|
|
|
* a directory, then a forward search is made for a block group with both
|
|
@@ -910,21 +931,16 @@ got_group:
|
|
|
}
|
|
|
|
|
|
repeat_in_this_group:
|
|
|
- ino = ext4_find_next_zero_bit((unsigned long *)
|
|
|
- inode_bitmap_bh->b_data,
|
|
|
- EXT4_INODES_PER_GROUP(sb), ino);
|
|
|
- if (ino >= EXT4_INODES_PER_GROUP(sb))
|
|
|
+ ret2 = find_inode_bit(sb, group, inode_bitmap_bh, &ino);
|
|
|
+ if (!ret2)
|
|
|
goto next_group;
|
|
|
- if (group == 0 && (ino+1) < EXT4_FIRST_INO(sb)) {
|
|
|
+
|
|
|
+ if (group == 0 && (ino + 1) < EXT4_FIRST_INO(sb)) {
|
|
|
ext4_error(sb, "reserved inode found cleared - "
|
|
|
"inode=%lu", ino + 1);
|
|
|
goto next_group;
|
|
|
}
|
|
|
- if ((EXT4_SB(sb)->s_journal == NULL) &&
|
|
|
- recently_deleted(sb, group, ino)) {
|
|
|
- ino++;
|
|
|
- goto next_inode;
|
|
|
- }
|
|
|
+
|
|
|
if (!handle) {
|
|
|
BUG_ON(nblocks <= 0);
|
|
|
handle = __ext4_journal_start_sb(dir->i_sb, line_no,
|
|
@@ -944,11 +960,23 @@ repeat_in_this_group:
|
|
|
}
|
|
|
ext4_lock_group(sb, group);
|
|
|
ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data);
|
|
|
+ if (ret2) {
|
|
|
+ /* Someone already took the bit. Repeat the search
|
|
|
+ * with lock held.
|
|
|
+ */
|
|
|
+ ret2 = find_inode_bit(sb, group, inode_bitmap_bh, &ino);
|
|
|
+ if (ret2) {
|
|
|
+ ext4_set_bit(ino, inode_bitmap_bh->b_data);
|
|
|
+ ret2 = 0;
|
|
|
+ } else {
|
|
|
+ ret2 = 1; /* we didn't grab the inode */
|
|
|
+ }
|
|
|
+ }
|
|
|
ext4_unlock_group(sb, group);
|
|
|
ino++; /* the inode bitmap is zero-based */
|
|
|
if (!ret2)
|
|
|
goto got; /* we grabbed the inode! */
|
|
|
-next_inode:
|
|
|
+
|
|
|
if (ino < EXT4_INODES_PER_GROUP(sb))
|
|
|
goto repeat_in_this_group;
|
|
|
next_group:
|