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