119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * closefs.c --- close an ext2 filesystem 33984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. 519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %Begin-Header% 78558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * This file may be redistributed under the terms of the GNU Library 88558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * General Public License, version 2. 919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %End-Header% 1019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdio.h> 1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_UNISTD_H 1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <unistd.h> 1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <time.h> 1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <string.h> 1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2_fs.h" 2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2fsP.h" 2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int test_root(int a, int b) 2319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 2419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (a == 0) 2519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 1; 2619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project while (1) { 2719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (a == 1) 2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 1; 2919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (a % b) 3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project a = a / b; 3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 3419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 3519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectint ext2fs_bg_has_super(ext2_filsys fs, int group_block) 3619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 3719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!(fs->super->s_feature_ro_compat & 3819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) 3919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 1; 4019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 4119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (test_root(group_block, 3) || (test_root(group_block, 5)) || 4219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project test_root(group_block, 7)) 4319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 1; 4419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 4519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 4619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 4719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/* 493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * This function returns the location of the superblock, block group 503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * descriptors for a given block group. It currently returns the 513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * number of free blocks assuming that inode table and allocation 523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * bitmaps will be in the group. This is not necessarily the case 533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * when the flex_bg feature is enabled, so callers should take care! 543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * It was only really intended for use by mke2fs, and even there it's 553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * not that useful. In the future, when we redo this function for 563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 64-bit block numbers, we should probably return the number of 573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * blocks used by the super block and group descriptors instead. 583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * See also the comment for ext2fs_reserve_super_and_bgd() 603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtint ext2fs_super_and_bgd_loc(ext2_filsys fs, 6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project dgrp_t group, 6319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t *ret_super_blk, 6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t *ret_old_desc_blk, 6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t *ret_new_desc_blk, 6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int *ret_meta_bg) 6719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 6819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0; 6919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project unsigned int meta_bg, meta_bg_size; 703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt blk_t numblocks, old_desc_blocks; 713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int has_super; 7219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt group_block = ext2fs_group_first_block(fs, group); 7419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 7519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) 7619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project old_desc_blocks = fs->super->s_first_meta_bg; 7719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project else 783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt old_desc_blocks = 7919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->desc_blocks + fs->super->s_reserved_gdt_blocks; 8019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 8119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (group == fs->group_desc_count-1) { 8219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project numblocks = (fs->super->s_blocks_count - 8319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_first_data_block) % 8419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_blocks_per_group; 8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!numblocks) 8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project numblocks = fs->super->s_blocks_per_group; 8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } else 8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project numblocks = fs->super->s_blocks_per_group; 8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 9019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project has_super = ext2fs_bg_has_super(fs, group); 9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (has_super) { 9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project super_blk = group_block; 9419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project numblocks--; 9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super); 9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project meta_bg = group / meta_bg_size; 9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) || 10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (meta_bg < fs->super->s_first_meta_bg)) { 10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (has_super) { 10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project old_desc_blk = group_block + 1; 10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project numblocks -= old_desc_blocks; 10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 10519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } else { 10619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (((group % meta_bg_size) == 0) || 10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ((group % meta_bg_size) == 1) || 10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ((group % meta_bg_size) == (meta_bg_size-1))) { 10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (has_super) 11019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project has_super = 1; 11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project new_desc_blk = group_block + has_super; 11219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project numblocks--; 11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 1153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 11619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project numblocks -= 2 + fs->inode_blocks_per_group; 11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 11819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ret_super_blk) 11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *ret_super_blk = super_blk; 12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ret_old_desc_blk) 12119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *ret_old_desc_blk = old_desc_blk; 12219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ret_new_desc_blk) 12319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *ret_new_desc_blk = new_desc_blk; 12419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ret_meta_bg) 12519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *ret_meta_bg = meta_bg; 12619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return (numblocks); 12719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 12819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 12919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 13019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 13119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function forces out the primary superblock. We need to only 13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * write out those fields which we have changed, since if the 13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * filesystem is mounted, it may have changed some of the other 13419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * fields. 13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 13619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * It takes as input a superblock which has already been byte swapped 13719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * (if necessary). 13819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 13919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 14019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic errcode_t write_primary_superblock(ext2_filsys fs, 14119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_super_block *super) 14219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 14319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project __u16 *old_super, *new_super; 14419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int check_idx, write_idx, size; 14519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 14619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 14719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!fs->io->manager->write_byte || !fs->orig_super) { 1488558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall fallback: 14919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET); 15019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = io_channel_write_blk(fs->io, 1, -SUPERBLOCK_SIZE, 15119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project super); 15219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project io_channel_set_blksize(fs->io, fs->blocksize); 15319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 15419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 15519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 15619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project old_super = (__u16 *) fs->orig_super; 15719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project new_super = (__u16 *) super; 15819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 15919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) { 16019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (old_super[check_idx] == new_super[check_idx]) 16119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project continue; 16219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project write_idx = check_idx; 16319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++) 16419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (old_super[check_idx] == new_super[check_idx]) 16519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project break; 16619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project size = 2 * (check_idx - write_idx); 16719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if 0 16819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project printf("Writing %d bytes starting at %d\n", 16919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project size, write_idx*2); 17019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 17119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = io_channel_write_byte(fs->io, 17219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project SUPERBLOCK_OFFSET + (2 * write_idx), size, 17319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project new_super + write_idx); 1748558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall if (retval == EXT2_ET_UNIMPLEMENTED) 1758558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall goto fallback; 17619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 17719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 17819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 17919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memcpy(fs->orig_super, super, SUPERBLOCK_SIZE); 18019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 18119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 18219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 18319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 18419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 18519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Updates the revision to EXT2_DYNAMIC_REV 18619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 18719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectvoid ext2fs_update_dynamic_rev(ext2_filsys fs) 18819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 18919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_super_block *sb = fs->super; 19019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 19119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (sb->s_rev_level > EXT2_GOOD_OLD_REV) 19219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 19319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 19419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project sb->s_rev_level = EXT2_DYNAMIC_REV; 19519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO; 19619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE; 19719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* s_uuid is handled by e2fsck already */ 19819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* other fields should be left alone */ 19919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 20019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 20119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic errcode_t write_backup_super(ext2_filsys fs, dgrp_t group, 20219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t group_block, 20319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_super_block *super_shadow) 20419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 20519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project dgrp_t sgrp = group; 2063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 20719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (sgrp > ((1 << 16) - 1)) 20819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project sgrp = (1 << 16) - 1; 2093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef WORDS_BIGENDIAN 2103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt super_shadow->s_block_group_nr = ext2fs_swab16(sgrp); 2113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#else 2123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fs->super->s_block_group_nr = sgrp; 21319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 21419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 2153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return io_channel_write_blk(fs->io, group_block, -SUPERBLOCK_SIZE, 21619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project super_shadow); 21719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 21819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 21919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 22019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_flush(ext2_filsys fs) 22119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 2223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt dgrp_t i; 22319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 22419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project unsigned long fs_state; 22519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project __u32 feature_incompat; 22619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_super_block *super_shadow = 0; 22719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_group_desc *group_shadow = 0; 2283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef WORDS_BIGENDIAN 22919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_group_desc *s, *t; 2303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt dgrp_t j; 2313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif 23219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *group_ptr; 23319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int old_desc_blocks; 2343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 23519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 23619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 23719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs_state = fs->super->s_state; 23819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project feature_incompat = fs->super->s_feature_incompat; 23919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 24019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_wtime = fs->now ? fs->now : time(NULL); 24119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_block_group_nr = 0; 2423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef WORDS_BIGENDIAN 2433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = EXT2_ET_NO_MEMORY; 2443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow); 2453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval) 2463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt goto errout; 2473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize, 2483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt &group_shadow); 2493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval) 2503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt goto errout; 2513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt memset(group_shadow, 0, (size_t) fs->blocksize * 2523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fs->desc_blocks); 2533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* swap the group descriptors */ 2553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt for (j=0, s=fs->group_desc, t=group_shadow; 2563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt j < fs->group_desc_count; j++, t++, s++) { 2573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *t = *s; 2583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_swap_group_desc(t); 25919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 26019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#else 26119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project super_shadow = fs->super; 26219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project group_shadow = fs->group_desc; 26319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 2643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 26519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 26619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Set the state of the FS to be non-valid. (The state has 26719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * already been backed up earlier, and will be restored after 26819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * we write out the backup superblocks.) 26919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 27019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_state &= ~EXT2_VALID_FS; 27119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER; 2723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef WORDS_BIGENDIAN 2733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *super_shadow = *fs->super; 2743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_swap_super(super_shadow); 27519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 27619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 27719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 27819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * If this is an external journal device, don't write out the 27919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * block group descriptors or any of the backup superblocks 28019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 28119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->super->s_feature_incompat & 28219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) 28319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto write_primary_superblock_only; 28419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 28519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 28619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Write out the master group descriptors, and the backup 28719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * superblocks and group descriptors. 28819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 28919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project group_ptr = (char *) group_shadow; 29019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) 29119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project old_desc_blocks = fs->super->s_first_meta_bg; 29219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project else 29319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project old_desc_blocks = fs->desc_blocks; 29419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 29519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project for (i = 0; i < fs->group_desc_count; i++) { 29619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t super_blk, old_desc_blk, new_desc_blk; 29719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int meta_bg; 29819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 2993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_super_and_bgd_loc(fs, i, &super_blk, &old_desc_blk, 30019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project &new_desc_blk, &meta_bg); 30119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 30219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) { 30319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = write_backup_super(fs, i, super_blk, 30419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project super_shadow); 30519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 30619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 30719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 30819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->flags & EXT2_FLAG_SUPER_ONLY) 30919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project continue; 3103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if ((old_desc_blk) && 31119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) { 31219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = io_channel_write_blk(fs->io, 31319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project old_desc_blk, old_desc_blocks, group_ptr); 31419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 31519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 31619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 31719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (new_desc_blk) { 31819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = io_channel_write_blk(fs->io, new_desc_blk, 31919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 1, group_ptr + (meta_bg*fs->blocksize)); 32019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 32119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 32219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 32319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 32419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 32519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 32619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * If the write_bitmaps() function is present, call it to 32719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * flush the bitmaps. This is done this way so that a simple 32819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * program that doesn't mess with the bitmaps doesn't need to 32919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * drag in the bitmaps.c code. 33019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 33119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->write_bitmaps) { 33219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = fs->write_bitmaps(fs); 33319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 33419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 33519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 33619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 33719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectwrite_primary_superblock_only: 33819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 33919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Write out master superblock. This has to be done 34019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * separately, since it is located at a fixed location 34119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * (SUPERBLOCK_OFFSET). We flush all other pending changes 34219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * out to disk first, just to avoid a race condition with an 34319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * insy-tinsy window.... 34419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 34519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 34619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_block_group_nr = 0; 34719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_state = fs_state; 34819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_feature_incompat = feature_incompat; 3493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef WORDS_BIGENDIAN 3503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *super_shadow = *fs->super; 3513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_swap_super(super_shadow); 35219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 35319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 35419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = io_channel_flush(fs->io); 35519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = write_primary_superblock(fs, super_shadow); 35619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 35719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 35819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 35919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->flags &= ~EXT2_FLAG_DIRTY; 36019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 36119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = io_channel_flush(fs->io); 36219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrout: 36319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_state = fs_state; 3643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef WORDS_BIGENDIAN 3653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (super_shadow) 3663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_free_mem(&super_shadow); 3673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (group_shadow) 3683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_free_mem(&group_shadow); 3693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif 37019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 37119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 37219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 37319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_close(ext2_filsys fs) 37419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 37519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 3763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int meta_blks; 3773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt io_stats stats = 0; 3783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 37919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 38019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 3813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fs->write_bitmaps) { 3823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = fs->write_bitmaps(fs); 38319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 38419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 38519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 3863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fs->super->s_kbytes_written && 3873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fs->io->manager->get_stats) 3883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fs->io->manager->get_stats(fs->io, &stats); 3893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (stats && stats->bytes_written && (fs->flags & EXT2_FLAG_RW)) { 3903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fs->super->s_kbytes_written += stats->bytes_written >> 10; 3913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt meta_blks = fs->desc_blocks + 1; 3923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!(fs->flags & EXT2_FLAG_SUPER_ONLY)) 3933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fs->super->s_kbytes_written += meta_blks / 3943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (fs->blocksize / 1024); 3953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if ((fs->flags & EXT2_FLAG_DIRTY) == 0) 3963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fs->flags |= EXT2_FLAG_SUPER_ONLY | EXT2_FLAG_DIRTY; 3973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 3983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fs->flags & EXT2_FLAG_DIRTY) { 3993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = ext2fs_flush(fs); 40019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 40119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 40219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 40319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free(fs); 40419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 40519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 40619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 407