@cd $(top_builddir); CONFIG_FILES=lib/ext2fs/ext2fs.pc ./config.status
tst_badblocks: tst_badblocks.o freefs.o bitmaps.o rw_bitmaps.o \
- read_bb_file.o write_bb_file.o badblocks.o
+ read_bb_file.o write_bb_file.o badblocks.o csum.o crc16.o \
+ closefs.o io_manager.o
@echo " LD $@"
- @$(CC) -o tst_badblocks tst_badblocks.o freefs.o \
- read_bb_file.o write_bb_file.o badblocks.o rw_bitmaps.o \
- inline.o bitops.o gen_bitmap.o bitmaps.o $(LIBCOM_ERR)
+ @$(CC) -o tst_badblocks tst_badblocks.o freefs.o read_bb_file.o \
+ write_bb_file.o badblocks.o rw_bitmaps.o inline.o bitops.o \
+ gen_bitmap.o bitmaps.o csum.o crc16.o closefs.o io_manager.o \
+ $(LIBCOM_ERR)
tst_icount: icount.c initialize.o $(STATIC_LIBEXT2FS)
@echo " LD $@"
fs->group_desc[group].bg_free_inodes_count -= inuse;
if (isdir)
fs->group_desc[group].bg_used_dirs_count += inuse;
+
+ /* We don't strictly need to be clearing these if inuse < 0
+ * (i.e. freeing inodes) but it also means something is bad. */
+ fs->group_desc[group].bg_flags &= ~(EXT2_BG_INODE_UNINIT |
+ EXT2_BG_BLOCK_UNINIT);
+ if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+ ext2_ino_t first_unused_inode = fs->super->s_inodes_per_group -
+ fs->group_desc[group].bg_itable_unused +
+ group * fs->super->s_inodes_per_group + 1;
+
+ if (ino >= first_unused_inode)
+ fs->group_desc[group].bg_itable_unused =
+ group * fs->super->s_inodes_per_group +
+ fs->super->s_inodes_per_group - ino;
+
+ ext2fs_group_desc_csum_set(fs, group);
+ }
+
fs->super->s_free_inodes_count -= inuse;
ext2fs_mark_super_dirty(fs);
ext2fs_mark_ib_dirty(fs);
else
ext2fs_unmark_block_bitmap(fs->block_map, blk);
fs->group_desc[group].bg_free_blocks_count -= inuse;
+ fs->group_desc[group].bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
+ ext2fs_group_desc_csum_set(fs, group);
+
fs->super->s_free_blocks_count -= inuse;
ext2fs_mark_super_dirty(fs);
ext2fs_mark_bb_dirty(fs);
ext2fs_mark_block_bitmap(bmap, blk);
fs->group_desc[group].bg_inode_table = new_blk;
}
+ ext2fs_group_desc_csum_set(fs, group);
-
return 0;
}
-
-
errcode_t ext2fs_allocate_tables(ext2_filsys fs)
{
errcode_t retval;
#endif
#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
EXT2_FEATURE_RO_COMPAT_LARGE_FILE|\
- EXT4_FEATURE_RO_COMPAT_DIR_NLINK)
+ EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
/*
* These features are only allowed if EXT2_FLAG_SOFTSUPP_FEATURES is passed
fs->group_desc[i].bg_free_inodes_count =
fs->super->s_inodes_per_group;
fs->group_desc[i].bg_used_dirs_count = 0;
+ ext2fs_group_desc_csum_set(fs, i);
}
c = (char) 255;
if (EXT2_HAS_COMPAT_FEATURE(fs->super,
EXT2_FEATURE_COMPAT_LAZY_BG))
scan->scan_flags |= EXT2_SF_DO_LAZY;
+ if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
+ scan->scan_flags |= EXT2_SF_DO_LAZY;
*ret_scan = scan;
return 0;
}
*/
static errcode_t get_next_blockgroup(ext2_inode_scan scan)
{
+ ext2_filsys fs = scan->fs;
+
scan->current_group++;
scan->groups_left--;
-
- scan->current_block = scan->fs->
- group_desc[scan->current_group].bg_inode_table;
+
+ scan->current_block =fs->group_desc[scan->current_group].bg_inode_table;
scan->current_inode = scan->current_group *
- EXT2_INODES_PER_GROUP(scan->fs->super);
+ EXT2_INODES_PER_GROUP(fs->super);
scan->bytes_left = 0;
- scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
- scan->blocks_left = scan->fs->inode_blocks_per_group;
+ scan->inodes_left = EXT2_INODES_PER_GROUP(fs->super);
+ scan->blocks_left = fs->inode_blocks_per_group;
+ if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+ scan->inodes_left -=
+ fs->group_desc[scan->current_group].bg_itable_unused;
+ scan->blocks_left =
+ (EXT2_INODES_PER_GROUP(fs->super) -
+ fs->group_desc[scan->current_group].bg_itable_unused +
+ fs->blocksize / scan->inode_size - 1) *
+ scan->inode_size / fs->blocksize;
+ }
+
return 0;
}
(scan->fs->group_desc[scan->current_group].bg_flags &
EXT2_BG_INODE_UNINIT))
goto force_new_group;
+ if (scan->inodes_left == 0)
+ goto force_new_group;
if (scan->current_block == 0) {
if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) {
goto force_new_group;
fs->stride = fs->super->s_raid_stride;
+ /*
+ * If recovery is from backup superblock, Clear _UNININT flags &
+ * reset bg_itable_unused to zero
+ */
+ if (superblock > 1 && EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+ struct ext2_group_desc *gd;
+ for (i = 0, gd = fs->group_desc; i < fs->group_desc_count;
+ i++, gd++) {
+ gd->bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
+ gd->bg_flags &= ~EXT2_BG_INODE_UNINIT;
+ gd->bg_itable_unused = 0;
+ }
+ ext2fs_mark_super_dirty(fs);
+ }
+
fs->flags &= ~EXT2_FLAG_NOFREE_ON_ERROR;
*ret_fs = fs;
return 0;
fs->write_bitmaps = ext2fs_write_bitmaps;
- if (EXT2_HAS_COMPAT_FEATURE(fs->super,
- EXT2_FEATURE_COMPAT_LAZY_BG))
+ if (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_LAZY_BG) ||
+ EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
lazy_flag = 1;
retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
if (block_bitmap) {
blk = fs->group_desc[i].bg_block_bitmap;
if (lazy_flag && fs->group_desc[i].bg_flags &
- EXT2_BG_BLOCK_UNINIT)
+ EXT2_BG_BLOCK_UNINIT &&
+ ext2fs_group_desc_csum_verify(fs, i))
blk = 0;
if (blk) {
retval = io_channel_read_blk(fs->io, blk,
if (inode_bitmap) {
blk = fs->group_desc[i].bg_inode_bitmap;
if (lazy_flag && fs->group_desc[i].bg_flags &
- EXT2_BG_INODE_UNINIT)
+ EXT2_BG_INODE_UNINIT &&
+ ext2fs_group_desc_csum_verify(fs, i))
blk = 0;
if (blk) {
retval = io_channel_read_blk(fs->io, blk,