int ext2fs_bg_has_super(ext2_filsys fs, dgrp_t group)
{
- if (!(fs->super->s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) || group <= 1)
+ if (group == 0)
+ return 1;
+ if (ext2fs_has_feature_sparse_super2(fs->super)) {
+ if (group == fs->super->s_backup_bgs[0] ||
+ group == fs->super->s_backup_bgs[1])
+ return 1;
+ return 0;
+ }
+ if ((group <= 1) || !ext2fs_has_feature_sparse_super(fs->super))
return 1;
if (!(group & 1))
return 0;
if (group_block == 0 && fs->blocksize == 1024)
group_block = 1; /* Deal with 1024 blocksize && bigalloc */
- if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
+ if (ext2fs_has_feature_meta_bg(fs->super))
old_desc_blocks = fs->super->s_first_meta_bg;
else
old_desc_blocks =
meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
meta_bg = group / meta_bg_size;
- if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
+ if (!ext2fs_has_feature_meta_bg(fs->super) ||
(meta_bg < fs->super->s_first_meta_bg)) {
if (has_super) {
old_desc_blk = group_block + 1;
if (sgrp > ((1 << 16) - 1))
sgrp = (1 << 16) - 1;
- super_shadow->s_block_group_nr = sgrp;
-#ifdef WORDS_BIGENDIAN
- ext2fs_swap_super(super_shadow);
-#endif
+ super_shadow->s_block_group_nr = ext2fs_cpu_to_le16(sgrp);
+
retval = ext2fs_superblock_csum_set(fs, super_shadow);
if (retval)
return retval;
unsigned long fs_state;
__u32 feature_incompat;
struct ext2_super_block *super_shadow = 0;
- struct ext2_group_desc *group_shadow = 0;
+ struct opaque_ext2_group_desc *group_shadow = 0;
#ifdef WORDS_BIGENDIAN
struct ext2_group_desc *gdp;
dgrp_t j;
#endif
char *group_ptr;
- int old_desc_blocks;
+ blk64_t old_desc_blocks;
struct ext2fs_numeric_progress_struct progress;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+ if ((fs->flags & EXT2_FLAG_SUPER_ONLY) == 0 &&
+ !ext2fs_has_feature_journal_dev(fs->super) &&
+ fs->group_desc == NULL)
+ return EXT2_ET_NO_GDESC;
+
fs_state = fs->super->s_state;
feature_incompat = fs->super->s_feature_incompat;
goto errout;
}
- /* Prepare the group descriptors for writing */
+ /*
+ * Set the state of the FS to be non-valid. (The state has
+ * already been backed up earlier, and will be restored after
+ * we write out the backup superblocks.)
+ */
+ fs->super->s_state &= ~EXT2_VALID_FS;
+ ext2fs_clear_feature_journal_needs_recovery(fs->super);
+
+ /* Byte swap the superblock and the group descriptors if necessary */
#ifdef WORDS_BIGENDIAN
retval = EXT2_ET_NO_MEMORY;
retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow);
if (retval)
goto errout;
- retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
- &group_shadow);
- if (retval)
- goto errout;
memcpy(super_shadow, fs->super, sizeof(struct ext2_super_block));
- memcpy(group_shadow, fs->group_desc, (size_t) fs->blocksize *
- fs->desc_blocks);
+ ext2fs_swap_super(super_shadow);
+
+ if (((fs->flags & EXT2_FLAG_SUPER_ONLY) == 0) &&
+ !ext2fs_has_feature_journal_dev(fs->super)) {
+ retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
+ &group_shadow);
+ if (retval)
+ goto errout;
+ memcpy(group_shadow, fs->group_desc, (size_t) fs->blocksize *
+ fs->desc_blocks);
- /* swap the group descriptors */
- for (j = 0; j < fs->group_desc_count; j++) {
- gdp = ext2fs_group_desc(fs, group_shadow, j);
- ext2fs_swap_group_desc2(fs, gdp);
+ for (j = 0; j < fs->group_desc_count; j++) {
+ gdp = ext2fs_group_desc(fs, group_shadow, j);
+ ext2fs_swap_group_desc2(fs, gdp);
+ }
}
#else
super_shadow = fs->super;
- group_shadow = ext2fs_group_desc(fs, fs->group_desc, 0);
+ group_shadow = fs->group_desc;
#endif
/*
- * Set the state of the FS to be non-valid. (The state has
- * already been backed up earlier, and will be restored after
- * we write out the backup superblocks.)
- */
- fs->super->s_state &= ~EXT2_VALID_FS;
- fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
-
- /*
* If this is an external journal device, don't write out the
* block group descriptors or any of the backup superblocks
*/
- if (fs->super->s_feature_incompat &
- EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
+ if (ext2fs_has_feature_journal_dev(fs->super))
goto write_primary_superblock_only;
/*
* superblocks and group descriptors.
*/
group_ptr = (char *) group_shadow;
- if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
+ if (ext2fs_has_feature_meta_bg(fs->super)) {
old_desc_blocks = fs->super->s_first_meta_bg;
- else
+ if (old_desc_blocks > fs->desc_blocks)
+ old_desc_blocks = fs->desc_blocks;
+ } else
old_desc_blocks = fs->desc_blocks;
if (fs->progress_ops && fs->progress_ops->init)
if (retval)
return retval;
- if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC))
+ if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC)) {
retval = io_channel_flush(fs->io);
+ if (retval)
+ goto errout;
+ }
retval = write_primary_superblock(fs, super_shadow);
if (retval)
goto errout;
fs->flags &= ~EXT2_FLAG_DIRTY;
- if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC))
+ if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC)) {
retval = io_channel_flush(fs->io);
+ if (retval)
+ goto errout;
+ }
errout:
fs->super->s_state = fs_state;
#ifdef WORDS_BIGENDIAN
return retval;
}
+errcode_t ext2fs_close_free(ext2_filsys *fs_ptr)
+{
+ errcode_t ret;
+ ext2_filsys fs = *fs_ptr;
+
+ ret = ext2fs_close2(fs, 0);
+ if (ret)
+ ext2fs_free(fs);
+ *fs_ptr = NULL;
+ return ret;
+}
+
errcode_t ext2fs_close(ext2_filsys fs)
{
return ext2fs_close2(fs, 0);