ext4: avoid declaring fs inconsistent due to invalid file handles
[platform/kernel/linux-rpi.git] / fs / ext4 / ialloc.c
index fb83750..091a18a 100644 (file)
@@ -90,6 +90,8 @@ static int ext4_validate_inode_bitmap(struct super_block *sb,
                return -EFSCORRUPTED;
 
        ext4_lock_group(sb, block_group);
+       if (buffer_verified(bh))
+               goto verified;
        blk = ext4_inode_bitmap(sb, desc);
        if (!ext4_inode_bitmap_csum_verify(sb, block_group, desc, bh,
                                           EXT4_INODES_PER_GROUP(sb) / 8)) {
@@ -101,6 +103,7 @@ static int ext4_validate_inode_bitmap(struct super_block *sb,
                return -EFSBADCRC;
        }
        set_buffer_verified(bh);
+verified:
        ext4_unlock_group(sb, block_group);
        return 0;
 }
@@ -135,9 +138,9 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
        }
        bh = sb_getblk(sb, bitmap_blk);
        if (unlikely(!bh)) {
-               ext4_error(sb, "Cannot read inode bitmap - "
-                           "block_group = %u, inode_bitmap = %llu",
-                           block_group, bitmap_blk);
+               ext4_warning(sb, "Cannot read inode bitmap - "
+                            "block_group = %u, inode_bitmap = %llu",
+                            block_group, bitmap_blk);
                return ERR_PTR(-ENOMEM);
        }
        if (bitmap_uptodate(bh))
@@ -1083,7 +1086,7 @@ got:
        /* This is the optimal IO size (for stat), not the fs block size */
        inode->i_blocks = 0;
        inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
-       ei->i_crtime = timespec64_to_timespec(inode->i_mtime);
+       ei->i_crtime = inode->i_mtime;
 
        memset(ei->i_data, 0, sizeof(ei->i_data));
        ei->i_dir_start_lookup = 0;
@@ -1222,7 +1225,7 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
        if (!ext4_test_bit(bit, bitmap_bh->b_data))
                goto bad_orphan;
 
-       inode = ext4_iget(sb, ino);
+       inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                ext4_error(sb, "couldn't read orphan inode %lu (err %d)",
@@ -1385,7 +1388,10 @@ int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,
                            ext4_itable_unused_count(sb, gdp)),
                            sbi->s_inodes_per_block);
 
-       if ((used_blks < 0) || (used_blks > sbi->s_itb_per_group)) {
+       if ((used_blks < 0) || (used_blks > sbi->s_itb_per_group) ||
+           ((group == 0) && ((EXT4_INODES_PER_GROUP(sb) -
+                              ext4_itable_unused_count(sb, gdp)) <
+                             EXT4_FIRST_INO(sb)))) {
                ext4_error(sb, "Something is wrong with group %u: "
                           "used itable blocks: %d; "
                           "itable unused count: %u",