errcode_t ext2fs_close2(ext2_filsys fs, int flags) { errcode_t retval; int meta_blks; io_stats stats = 0; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); if (fs->write_bitmaps) { retval = fs->write_bitmaps(fs); if (retval) return retval; } if (fs->super->s_kbytes_written && fs->io->manager->get_stats) fs->io->manager->get_stats(fs->io, &stats); if (stats && stats->bytes_written && (fs->flags & EXT2_FLAG_RW)) { fs->super->s_kbytes_written += stats->bytes_written >> 10; meta_blks = fs->desc_blocks + 1; if (!(fs->flags & EXT2_FLAG_SUPER_ONLY)) fs->super->s_kbytes_written += meta_blks / (fs->blocksize / 1024); if ((fs->flags & EXT2_FLAG_DIRTY) == 0) fs->flags |= EXT2_FLAG_SUPER_ONLY | EXT2_FLAG_DIRTY; }
errcode_t ext2fs_close(ext2_filsys fs) { errcode_t retval; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); if (fs->flags & EXT2_FLAG_DIRTY) { retval = ext2fs_flush(fs); if (retval) return retval; } if (fs->write_bitmaps) { retval = fs->write_bitmaps(fs); if (retval) return retval; } ext2fs_free(fs); return 0; }
errcode_t ext2fs_flush2(ext2_filsys fs, int flags) { dgrp_t i; errcode_t retval; unsigned long fs_state; __u32 feature_incompat; struct ext2_super_block *super_shadow = 0; struct ext2_group_desc *group_shadow = 0; #ifdef WORDS_BIGENDIAN struct ext2_group_desc *gdp; dgrp_t j; #endif char *group_ptr; blk64_t old_desc_blocks; struct ext2fs_numeric_progress_struct progress; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); fs_state = fs->super->s_state; feature_incompat = fs->super->s_feature_incompat; fs->super->s_wtime = fs->now ? fs->now : time(NULL); fs->super->s_block_group_nr = 0; /* * If the write_bitmaps() function is present, call it to * flush the bitmaps. This is done this way so that a simple * program that doesn't mess with the bitmaps doesn't need to * drag in the bitmaps.c code. * * Bitmap checksums live in the group descriptor, so the * bitmaps need to be written before the descriptors. */ if (fs->write_bitmaps) { retval = fs->write_bitmaps(fs); if (retval) goto errout; } /* Prepare the group descriptors for writing */ #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); /* 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); } #else super_shadow = fs->super; group_shadow = ext2fs_group_desc(fs, fs->group_desc, 0); #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; ext2fs_clear_feature_journal_needs_recovery(fs->super); /* * If this is an external journal device, don't write out the * block group descriptors or any of the backup superblocks */ if (ext2fs_has_feature_journal_dev(fs->super)) goto write_primary_superblock_only; /* * Write out the master group descriptors, and the backup * superblocks and group descriptors. */ group_ptr = (char *) group_shadow; if (ext2fs_has_feature_meta_bg(fs->super)) { old_desc_blocks = fs->super->s_first_meta_bg; 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) (fs->progress_ops->init)(fs, &progress, NULL, fs->group_desc_count); for (i = 0; i < fs->group_desc_count; i++) { blk64_t super_blk, old_desc_blk, new_desc_blk; if (fs->progress_ops && fs->progress_ops->update) (fs->progress_ops->update)(fs, &progress, i); ext2fs_super_and_bgd_loc2(fs, i, &super_blk, &old_desc_blk, &new_desc_blk, 0); if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) { retval = write_backup_super(fs, i, super_blk, super_shadow); if (retval) goto errout; } if (fs->flags & EXT2_FLAG_SUPER_ONLY) continue; if ((old_desc_blk) && (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) { retval = io_channel_write_blk64(fs->io, old_desc_blk, old_desc_blocks, group_ptr); if (retval) goto errout; } if (new_desc_blk) { int meta_bg = i / EXT2_DESC_PER_BLOCK(fs->super); retval = io_channel_write_blk64(fs->io, new_desc_blk, 1, group_ptr + (meta_bg*fs->blocksize)); if (retval) goto errout; } } if (fs->progress_ops && fs->progress_ops->close) (fs->progress_ops->close)(fs, &progress, NULL); write_primary_superblock_only: /* * Write out master superblock. This has to be done * separately, since it is located at a fixed location * (SUPERBLOCK_OFFSET). We flush all other pending changes * out to disk first, just to avoid a race condition with an * insy-tinsy window.... */ fs->super->s_block_group_nr = 0; fs->super->s_state = fs_state; fs->super->s_feature_incompat = feature_incompat; #ifdef WORDS_BIGENDIAN *super_shadow = *fs->super; ext2fs_swap_super(super_shadow); #endif retval = ext2fs_superblock_csum_set(fs, super_shadow); if (retval) return retval; if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC)) retval = io_channel_flush(fs->io); retval = write_primary_superblock(fs, super_shadow); if (retval) goto errout; fs->flags &= ~EXT2_FLAG_DIRTY; if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC)) retval = io_channel_flush(fs->io); errout: fs->super->s_state = fs_state; #ifdef WORDS_BIGENDIAN if (super_shadow) ext2fs_free_mem(&super_shadow); if (group_shadow) ext2fs_free_mem(&group_shadow); #endif return retval; }
errcode_t ext2fs_flush(ext2_filsys fs) { dgrp_t i; errcode_t retval; unsigned long fs_state; __u32 feature_incompat; struct ext2_super_block *super_shadow = 0; struct ext2_group_desc *group_shadow = 0; #if defined(WORDS_BIGENDIAN) || (BYTE_ORDER == BIG_ENDIAN) struct ext2_group_desc *s, *t; dgrp_t j; #endif char *group_ptr; int old_desc_blocks; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); fs_state = fs->super->s_state; feature_incompat = fs->super->s_feature_incompat; fs->super->s_wtime = fs->now ? fs->now : time(NULL); fs->super->s_block_group_nr = 0; #if defined(WORDS_BIGENDIAN) || (BYTE_ORDER == BIG_ENDIAN) 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; memset(group_shadow, 0, (size_t) fs->blocksize * fs->desc_blocks); /* swap the group descriptors */ for (j=0, s=fs->group_desc, t=group_shadow; j < fs->group_desc_count; j++, t++, s++) { *t = *s; ext2fs_swap_group_desc(t); } #else super_shadow = fs->super; 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 defined(WORDS_BIGENDIAN) || (BYTE_ORDER == BIG_ENDIAN) *super_shadow = *fs->super; ext2fs_swap_super(super_shadow); #endif /* * 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) goto write_primary_superblock_only; /* * Write out the master group descriptors, and the backup * superblocks and group descriptors. */ group_ptr = (char *) group_shadow; if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) old_desc_blocks = fs->super->s_first_meta_bg; else old_desc_blocks = fs->desc_blocks; for (i = 0; i < fs->group_desc_count; i++) { blk_t super_blk, old_desc_blk, new_desc_blk; int meta_bg; ext2fs_super_and_bgd_loc(fs, i, &super_blk, &old_desc_blk, &new_desc_blk, &meta_bg); if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) { retval = write_backup_super(fs, i, super_blk, super_shadow); if (retval) goto errout; } if (fs->flags & EXT2_FLAG_SUPER_ONLY) continue; if ((old_desc_blk) && (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) { retval = io_channel_write_blk(fs->io, old_desc_blk, old_desc_blocks, group_ptr); if (retval) goto errout; } if (new_desc_blk) { retval = io_channel_write_blk(fs->io, new_desc_blk, 1, group_ptr + (meta_bg*fs->blocksize)); if (retval) goto errout; } } /* * If the write_bitmaps() function is present, call it to * flush the bitmaps. This is done this way so that a simple * program that doesn't mess with the bitmaps doesn't need to * drag in the bitmaps.c code. */ if (fs->write_bitmaps) { retval = fs->write_bitmaps(fs); if (retval) goto errout; } write_primary_superblock_only: /* * Write out master superblock. This has to be done * separately, since it is located at a fixed location * (SUPERBLOCK_OFFSET). We flush all other pending changes * out to disk first, just to avoid a race condition with an * insy-tinsy window.... */ fs->super->s_block_group_nr = 0; fs->super->s_state = fs_state; fs->super->s_feature_incompat = feature_incompat; #if defined(WORDS_BIGENDIAN) || (BYTE_ORDER == BIG_ENDIAN) *super_shadow = *fs->super; ext2fs_swap_super(super_shadow); #endif retval = io_channel_flush(fs->io); retval = write_primary_superblock(fs, super_shadow); if (retval) goto errout; fs->flags &= ~EXT2_FLAG_DIRTY; retval = io_channel_flush(fs->io); errout: fs->super->s_state = fs_state; #if defined(WORDS_BIGENDIAN) || (BYTE_ORDER == BIG_ENDIAN) if (super_shadow) ext2fs_free_mem(&super_shadow); if (group_shadow) ext2fs_free_mem(&group_shadow); #endif return retval; }
errcode_t ext2fs_flush(ext2_filsys fs) { dgrp_t i; errcode_t retval; unsigned long fs_state; __u32 feature_incompat; struct ext2_super_block *super_shadow = 0; struct ext2_group_desc *group_shadow = 0; #ifdef WORDS_BIGENDIAN struct ext2_group_desc *s, *t; dgrp_t j; #endif char *group_ptr; int old_desc_blocks; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); fs_state = fs->super->s_state; feature_incompat = fs->super->s_feature_incompat; fs->super->s_wtime = fs->now ? fs->now : time(NULL); fs->super->s_block_group_nr = 0; #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; memset(group_shadow, 0, (size_t) fs->blocksize * fs->desc_blocks); for (j=0, s=fs->group_desc, t=group_shadow; j < fs->group_desc_count; j++, t++, s++) { *t = *s; ext2fs_swap_group_desc(t); } #else super_shadow = fs->super; group_shadow = fs->group_desc; #endif fs->super->s_state &= ~EXT2_VALID_FS; fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER; #ifdef WORDS_BIGENDIAN *super_shadow = *fs->super; ext2fs_swap_super(super_shadow); #endif if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) goto write_primary_superblock_only; group_ptr = (char *) group_shadow; if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) old_desc_blocks = fs->super->s_first_meta_bg; else old_desc_blocks = fs->desc_blocks; for (i = 0; i < fs->group_desc_count; i++) { blk_t super_blk, old_desc_blk, new_desc_blk; int meta_bg; ext2fs_super_and_bgd_loc(fs, i, &super_blk, &old_desc_blk, &new_desc_blk, &meta_bg); if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) { retval = write_backup_super(fs, i, super_blk, super_shadow); if (retval) goto errout; } if (fs->flags & EXT2_FLAG_SUPER_ONLY) continue; if ((old_desc_blk) && (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) { retval = io_channel_write_blk(fs->io, old_desc_blk, old_desc_blocks, group_ptr); if (retval) goto errout; } if (new_desc_blk) { retval = io_channel_write_blk(fs->io, new_desc_blk, 1, group_ptr + (meta_bg*fs->blocksize)); if (retval) goto errout; } } if (fs->write_bitmaps) { retval = fs->write_bitmaps(fs); if (retval) goto errout; } write_primary_superblock_only: fs->super->s_block_group_nr = 0; fs->super->s_state = fs_state; fs->super->s_feature_incompat = feature_incompat; #ifdef WORDS_BIGENDIAN *super_shadow = *fs->super; ext2fs_swap_super(super_shadow); #endif retval = io_channel_flush(fs->io); retval = write_primary_superblock(fs, super_shadow); if (retval) goto errout; fs->flags &= ~EXT2_FLAG_DIRTY; retval = io_channel_flush(fs->io); errout: fs->super->s_state = fs_state; #ifdef WORDS_BIGENDIAN if (super_shadow) ext2fs_free_mem(&super_shadow); if (group_shadow) ext2fs_free_mem(&group_shadow); #endif return retval; }