diff options
Diffstat (limited to 'fs/ext4/ialloc.c')
-rw-r--r-- | fs/ext4/ialloc.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 4637af036d9c..25d8c9781ad9 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -252,7 +252,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode) | |||
252 | fatal = ext4_journal_get_write_access(handle, bh2); | 252 | fatal = ext4_journal_get_write_access(handle, bh2); |
253 | } | 253 | } |
254 | ext4_lock_group(sb, block_group); | 254 | ext4_lock_group(sb, block_group); |
255 | cleared = ext4_clear_bit(bit, bitmap_bh->b_data); | 255 | cleared = ext4_test_and_clear_bit(bit, bitmap_bh->b_data); |
256 | if (fatal || !cleared) { | 256 | if (fatal || !cleared) { |
257 | ext4_unlock_group(sb, block_group); | 257 | ext4_unlock_group(sb, block_group); |
258 | goto out; | 258 | goto out; |
@@ -358,7 +358,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, | |||
358 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 358 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
359 | ext4_group_t real_ngroups = ext4_get_groups_count(sb); | 359 | ext4_group_t real_ngroups = ext4_get_groups_count(sb); |
360 | int inodes_per_group = EXT4_INODES_PER_GROUP(sb); | 360 | int inodes_per_group = EXT4_INODES_PER_GROUP(sb); |
361 | unsigned int freei, avefreei; | 361 | unsigned int freei, avefreei, grp_free; |
362 | ext4_fsblk_t freeb, avefreec; | 362 | ext4_fsblk_t freeb, avefreec; |
363 | unsigned int ndirs; | 363 | unsigned int ndirs; |
364 | int max_dirs, min_inodes; | 364 | int max_dirs, min_inodes; |
@@ -477,8 +477,8 @@ fallback_retry: | |||
477 | for (i = 0; i < ngroups; i++) { | 477 | for (i = 0; i < ngroups; i++) { |
478 | grp = (parent_group + i) % ngroups; | 478 | grp = (parent_group + i) % ngroups; |
479 | desc = ext4_get_group_desc(sb, grp, NULL); | 479 | desc = ext4_get_group_desc(sb, grp, NULL); |
480 | if (desc && ext4_free_inodes_count(sb, desc) && | 480 | grp_free = ext4_free_inodes_count(sb, desc); |
481 | ext4_free_inodes_count(sb, desc) >= avefreei) { | 481 | if (desc && grp_free && grp_free >= avefreei) { |
482 | *group = grp; | 482 | *group = grp; |
483 | return 0; | 483 | return 0; |
484 | } | 484 | } |
@@ -618,7 +618,7 @@ static int ext4_claim_inode(struct super_block *sb, | |||
618 | */ | 618 | */ |
619 | down_read(&grp->alloc_sem); | 619 | down_read(&grp->alloc_sem); |
620 | ext4_lock_group(sb, group); | 620 | ext4_lock_group(sb, group); |
621 | if (ext4_set_bit(ino, inode_bitmap_bh->b_data)) { | 621 | if (ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data)) { |
622 | /* not a free inode */ | 622 | /* not a free inode */ |
623 | retval = 1; | 623 | retval = 1; |
624 | goto err_ret; | 624 | goto err_ret; |
@@ -885,8 +885,12 @@ got: | |||
885 | if (IS_DIRSYNC(inode)) | 885 | if (IS_DIRSYNC(inode)) |
886 | ext4_handle_sync(handle); | 886 | ext4_handle_sync(handle); |
887 | if (insert_inode_locked(inode) < 0) { | 887 | if (insert_inode_locked(inode) < 0) { |
888 | err = -EINVAL; | 888 | /* |
889 | goto fail_drop; | 889 | * Likely a bitmap corruption causing inode to be allocated |
890 | * twice. | ||
891 | */ | ||
892 | err = -EIO; | ||
893 | goto fail; | ||
890 | } | 894 | } |
891 | spin_lock(&sbi->s_next_gen_lock); | 895 | spin_lock(&sbi->s_next_gen_lock); |
892 | inode->i_generation = sbi->s_next_generation++; | 896 | inode->i_generation = sbi->s_next_generation++; |