13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * closefs.c --- close an ext2 filesystem
3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o *
621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %Begin-Header%
7543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library
8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2.
921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %End-Header%
103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h>
134cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_UNISTD_H
143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h>
154cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif
163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <time.h>
1750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <string.h>
183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
19b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h"
2021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include "ext2fsP.h"
213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
22e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int test_root(unsigned int a, unsigned int b)
231b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o{
241b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o	while (1) {
25e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (a < b)
26e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			return 0;
27e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (a == b)
281b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o			return 1;
291b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o		if (a % b)
301b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o			return 0;
311b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o		a = a / b;
321b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o	}
331b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o}
341b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o
35e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallint ext2fs_bg_has_super(ext2_filsys fs, dgrp_t group)
361b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o{
371b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o	if (!(fs->super->s_feature_ro_compat &
38e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	      EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) || group <= 1)
391b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o		return 1;
40e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (!(group & 1))
41e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		return 0;
42e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (test_root(group, 3) || (test_root(group, 5)) ||
43e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	    test_root(group, 7))
441b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o		return 1;
451b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o
461b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o	return 0;
471b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o}
481b4cd9c7464d5bd0f5b416c7303bcc827e312473Theodore Ts'o
494a568505ab904d39d9553e9c1d1c565615a5c6caTheodore Ts'o/*
50e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * ext2fs_super_and_bgd_loc2()
51e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @fs:			ext2 fs pointer
52e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @group		given block group
53e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ret_super_blk:	if !NULL, returns super block location
54e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ret_old_desc_blk:	if !NULL, returns location of the old block
55e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *			group descriptor
56e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ret_new_desc_blk:	if !NULL, returns location of meta_bg block
57e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *			group descriptor
58e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ret_used_blks:	if !NULL, returns number of blocks used by
59e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *			super block and group_descriptors.
604a568505ab904d39d9553e9c1d1c565615a5c6caTheodore Ts'o *
61e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Returns errcode_t of 0
624a568505ab904d39d9553e9c1d1c565615a5c6caTheodore Ts'o */
63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_super_and_bgd_loc2(ext2_filsys fs,
64e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					   dgrp_t group,
65e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					   blk64_t *ret_super_blk,
66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					   blk64_t *ret_old_desc_blk,
67e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					   blk64_t *ret_new_desc_blk,
68e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					   blk_t *ret_used_blks)
69ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o{
70e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t	group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0;
71544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	unsigned int meta_bg, meta_bg_size;
72e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk_t	numblocks = 0;
73e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t old_desc_blocks;
745d38ef1d049bf56d1c1e88b8b4d287c0f9470e61Valerie Clement	int	has_super;
75ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o
76e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	group_block = ext2fs_group_first_block2(fs, group);
77e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (group_block == 0 && fs->blocksize == 1024)
78e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		group_block = 1; /* Deal with 1024 blocksize && bigalloc */
79ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o
80ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
81ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		old_desc_blocks = fs->super->s_first_meta_bg;
82ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	else
83efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		old_desc_blocks =
84d323f8fb369089b97d6f3bf0f8d64ceeab0b10f5Theodore Ts'o			fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
85ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o
86ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	has_super = ext2fs_bg_has_super(fs, group);
87ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o
88ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	if (has_super) {
89ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		super_blk = group_block;
90e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		numblocks++;
91ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	}
92f2de1d38d0819b17895977fabc52d81d0ea6ec00Valerie Clement	meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
93ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	meta_bg = group / meta_bg_size;
94ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o
95ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
96ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	    (meta_bg < fs->super->s_first_meta_bg)) {
97ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		if (has_super) {
98ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o			old_desc_blk = group_block + 1;
99e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			numblocks += old_desc_blocks;
100ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		}
101ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	} else {
102ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		if (((group % meta_bg_size) == 0) ||
103ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		    ((group % meta_bg_size) == 1) ||
104ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		    ((group % meta_bg_size) == (meta_bg_size-1))) {
105ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o			if (has_super)
106ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o				has_super = 1;
107ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o			new_desc_blk = group_block + has_super;
108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			numblocks++;
109ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		}
110ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	}
111efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
112ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	if (ret_super_blk)
113ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		*ret_super_blk = super_blk;
114ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	if (ret_old_desc_blk)
115ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		*ret_old_desc_blk = old_desc_blk;
116ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	if (ret_new_desc_blk)
117ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		*ret_new_desc_blk = new_desc_blk;
118e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (ret_used_blks)
119e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		*ret_used_blks = numblocks;
120e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
121e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return 0;
122ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o}
123ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o
124e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/*
125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * This function returns the location of the superblock, block group
126e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * descriptors for a given block group.  It currently returns the
127e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * number of free blocks assuming that inode table and allocation
128e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * bitmaps will be in the group.  This is not necessarily the case
129e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * when the flex_bg feature is enabled, so callers should take care!
130e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * It was only really intended for use by mke2fs, and even there it's
131e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * not that useful.
132e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *
133e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * The ext2fs_super_and_bgd_loc2() function is 64-bit block number
134e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * capable and returns the number of blocks used by super block and
135e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * group descriptors.
136e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */
137e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallint ext2fs_super_and_bgd_loc(ext2_filsys fs,
138e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			     dgrp_t group,
139e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			     blk_t *ret_super_blk,
140e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			     blk_t *ret_old_desc_blk,
141e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			     blk_t *ret_new_desc_blk,
142e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			     int *ret_meta_bg)
143e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
144e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t ret_super_blk2;
145e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t ret_old_desc_blk2;
146e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t ret_new_desc_blk2;
147e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk_t ret_used_blks;
148e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk_t numblocks;
149e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	unsigned int meta_bg_size;
150e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
151e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_super_and_bgd_loc2(fs, group, &ret_super_blk2,
152e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					&ret_old_desc_blk2,
153e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					&ret_new_desc_blk2,
154e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					&ret_used_blks);
155e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
156e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	numblocks = ext2fs_group_blocks_count(fs, group);
157e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
158e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (ret_super_blk)
159e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		*ret_super_blk = (blk_t)ret_super_blk2;
160e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (ret_old_desc_blk)
161e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		*ret_old_desc_blk = (blk_t)ret_old_desc_blk2;
162e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (ret_new_desc_blk)
163e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		*ret_new_desc_blk = (blk_t)ret_new_desc_blk2;
164e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (ret_meta_bg) {
165e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
166e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		*ret_meta_bg = group / meta_bg_size;
167e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
168e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
169e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	numblocks -= 2 + fs->inode_blocks_per_group + ret_used_blks;
170e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
171e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return numblocks;
172e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
173ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o
174c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o/*
175c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o * This function forces out the primary superblock.  We need to only
176c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o * write out those fields which we have changed, since if the
177c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o * filesystem is mounted, it may have changed some of the other
178c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o * fields.
179c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o *
180c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o * It takes as input a superblock which has already been byte swapped
181c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o * (if necessary).
182c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o *
183c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o */
184c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'ostatic errcode_t write_primary_superblock(ext2_filsys fs,
185c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o					  struct ext2_super_block *super)
186c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o{
187c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o	__u16		*old_super, *new_super;
188c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o	int		check_idx, write_idx, size;
189c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o	errcode_t	retval;
190c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o
191c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o	if (!fs->io->manager->write_byte || !fs->orig_super) {
1927f1a1fbf850f6b73b5c9c82365f01029fb250a1cTheodore Ts'o	fallback:
193c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o		io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
194e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		retval = io_channel_write_blk64(fs->io, 1, -SUPERBLOCK_SIZE,
195c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o					      super);
196c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o		io_channel_set_blksize(fs->io, fs->blocksize);
197c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o		return retval;
198c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o	}
199c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o
200c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o	old_super = (__u16 *) fs->orig_super;
201c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o	new_super = (__u16 *) super;
202c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o
203c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o	for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) {
204c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o		if (old_super[check_idx] == new_super[check_idx])
205c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o			continue;
206c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o		write_idx = check_idx;
207c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o		for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++)
208c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o			if (old_super[check_idx] == new_super[check_idx])
209c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o				break;
210c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o		size = 2 * (check_idx - write_idx);
211c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o#if 0
212c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o		printf("Writing %d bytes starting at %d\n",
213c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o		       size, write_idx*2);
214c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o#endif
215c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o		retval = io_channel_write_byte(fs->io,
216c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o			       SUPERBLOCK_OFFSET + (2 * write_idx), size,
217c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o					       new_super + write_idx);
2187f1a1fbf850f6b73b5c9c82365f01029fb250a1cTheodore Ts'o		if (retval == EXT2_ET_UNIMPLEMENTED)
2197f1a1fbf850f6b73b5c9c82365f01029fb250a1cTheodore Ts'o			goto fallback;
220c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o		if (retval)
221c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o			return retval;
222c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o	}
2233c6b8977d44c66f0a50dd77c18a78b57b1022f8cTheodore Ts'o	memcpy(fs->orig_super, super, SUPERBLOCK_SIZE);
224c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o	return 0;
225c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o}
226c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o
227c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o
2283fe973b3068f68bb9d3ea6ba309dc7d2df30301fTheodore Ts'o/*
2293fe973b3068f68bb9d3ea6ba309dc7d2df30301fTheodore Ts'o * Updates the revision to EXT2_DYNAMIC_REV
2303fe973b3068f68bb9d3ea6ba309dc7d2df30301fTheodore Ts'o */
231a917d1ccf49605b3009f4e7225f00b81fc16100bTheodore Ts'ovoid ext2fs_update_dynamic_rev(ext2_filsys fs)
2323fe973b3068f68bb9d3ea6ba309dc7d2df30301fTheodore Ts'o{
2333fe973b3068f68bb9d3ea6ba309dc7d2df30301fTheodore Ts'o	struct ext2_super_block *sb = fs->super;
2343fe973b3068f68bb9d3ea6ba309dc7d2df30301fTheodore Ts'o
2353fe973b3068f68bb9d3ea6ba309dc7d2df30301fTheodore Ts'o	if (sb->s_rev_level > EXT2_GOOD_OLD_REV)
2363fe973b3068f68bb9d3ea6ba309dc7d2df30301fTheodore Ts'o		return;
2373fe973b3068f68bb9d3ea6ba309dc7d2df30301fTheodore Ts'o
2383fe973b3068f68bb9d3ea6ba309dc7d2df30301fTheodore Ts'o	sb->s_rev_level = EXT2_DYNAMIC_REV;
2393fe973b3068f68bb9d3ea6ba309dc7d2df30301fTheodore Ts'o	sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
2403fe973b3068f68bb9d3ea6ba309dc7d2df30301fTheodore Ts'o	sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
2413fe973b3068f68bb9d3ea6ba309dc7d2df30301fTheodore Ts'o	/* s_uuid is handled by e2fsck already */
2423fe973b3068f68bb9d3ea6ba309dc7d2df30301fTheodore Ts'o	/* other fields should be left alone */
2433fe973b3068f68bb9d3ea6ba309dc7d2df30301fTheodore Ts'o}
2443fe973b3068f68bb9d3ea6ba309dc7d2df30301fTheodore Ts'o
245c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'ostatic errcode_t write_backup_super(ext2_filsys fs, dgrp_t group,
246e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				    blk64_t group_block,
247c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o				    struct ext2_super_block *super_shadow)
248c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o{
249c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o	dgrp_t	sgrp = group;
250efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
251c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o	if (sgrp > ((1 << 16) - 1))
252c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o		sgrp = (1 << 16) - 1;
253126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#ifdef WORDS_BIGENDIAN
254126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o	super_shadow->s_block_group_nr = ext2fs_swab16(sgrp);
255126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#else
256126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o	fs->super->s_block_group_nr = sgrp;
257c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o#endif
258c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o
259e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return io_channel_write_blk64(fs->io, group_block, -SUPERBLOCK_SIZE,
260c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o				    super_shadow);
261c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o}
262c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o
26365f0aab98b20b5994a726ab90d355248bcddfffdJP Abgrallerrcode_t ext2fs_flush(ext2_filsys fs)
2649d9a53e651fa877eb4f9df0bfd97fbcc5f514293Richard W.M. Jones{
265e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return ext2fs_flush2(fs, 0);
266e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
267e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
268e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_flush2(ext2_filsys fs, int flags)
269e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
2702d328bb76d2d63bdfdba923b54c28bd686bd8fecTheodore Ts'o	dgrp_t		i;
2713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	errcode_t	retval;
272f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	unsigned long	fs_state;
2739a083af71a2388ae47252f8af2b796f9055f4af7Theodore Ts'o	__u32		feature_incompat;
27450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	struct ext2_super_block *super_shadow = 0;
27550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	struct ext2_group_desc *group_shadow = 0;
2762d328bb76d2d63bdfdba923b54c28bd686bd8fecTheodore Ts'o#ifdef WORDS_BIGENDIAN
277e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	struct ext2_group_desc *gdp;
2782d328bb76d2d63bdfdba923b54c28bd686bd8fecTheodore Ts'o	dgrp_t		j;
2792d328bb76d2d63bdfdba923b54c28bd686bd8fecTheodore Ts'o#endif
280ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	char	*group_ptr;
281ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	int	old_desc_blocks;
282e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	struct ext2fs_numeric_progress_struct progress;
283efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
284f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
285f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
28650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	fs_state = fs->super->s_state;
2879a083af71a2388ae47252f8af2b796f9055f4af7Theodore Ts'o	feature_incompat = fs->super->s_feature_incompat;
28850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
28932138187f08d1f1dc03feb269f987982db76f3dbTheodore Ts'o	fs->super->s_wtime = fs->now ? fs->now : time(NULL);
290e5b38a5fafe4807b54d90a2e70bddf4b41b1695bTheodore Ts'o	fs->super->s_block_group_nr = 0;
291126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#ifdef WORDS_BIGENDIAN
292126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o	retval = EXT2_ET_NO_MEMORY;
293126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o	retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow);
294126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o	if (retval)
295126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o		goto errout;
296efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
297e6a4571eec5ce0e75fb8a5a41c30bf0e68d90efeTheodore Ts'o				  &group_shadow);
298126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o	if (retval)
299126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o		goto errout;
300e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	memcpy(group_shadow, fs->group_desc, (size_t) fs->blocksize *
301126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o	       fs->desc_blocks);
302efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
303126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o	/* swap the group descriptors */
304e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	for (j = 0; j < fs->group_desc_count; j++) {
305e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		gdp = ext2fs_group_desc(fs, group_shadow, j);
306e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_swap_group_desc2(fs, gdp);
30750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
3085df55d7f847e29d23227592a0bb23daad1a61500Theodore Ts'o#else
3095df55d7f847e29d23227592a0bb23daad1a61500Theodore Ts'o	super_shadow = fs->super;
310e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	group_shadow = ext2fs_group_desc(fs, fs->group_desc, 0);
3115df55d7f847e29d23227592a0bb23daad1a61500Theodore Ts'o#endif
312efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
3133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	/*
31450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * Set the state of the FS to be non-valid.  (The state has
315a63d12678369f4ab0edf8fc5741825c035e78bf9Theodore Ts'o	 * already been backed up earlier, and will be restored after
316a63d12678369f4ab0edf8fc5741825c035e78bf9Theodore Ts'o	 * we write out the backup superblocks.)
317f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	 */
318f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	fs->super->s_state &= ~EXT2_VALID_FS;
3199a083af71a2388ae47252f8af2b796f9055f4af7Theodore Ts'o	fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
320126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#ifdef WORDS_BIGENDIAN
321126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o	*super_shadow = *fs->super;
322126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o	ext2fs_swap_super(super_shadow);
3235df55d7f847e29d23227592a0bb23daad1a61500Theodore Ts'o#endif
324f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
325f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	/*
3260d961040fe9ad927254b5a0e1a4de7bedadd8579Theodore Ts'o	 * If this is an external journal device, don't write out the
3270d961040fe9ad927254b5a0e1a4de7bedadd8579Theodore Ts'o	 * block group descriptors or any of the backup superblocks
3280d961040fe9ad927254b5a0e1a4de7bedadd8579Theodore Ts'o	 */
3290d961040fe9ad927254b5a0e1a4de7bedadd8579Theodore Ts'o	if (fs->super->s_feature_incompat &
3300d961040fe9ad927254b5a0e1a4de7bedadd8579Theodore Ts'o	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
3310d961040fe9ad927254b5a0e1a4de7bedadd8579Theodore Ts'o		goto write_primary_superblock_only;
3320d961040fe9ad927254b5a0e1a4de7bedadd8579Theodore Ts'o
3330d961040fe9ad927254b5a0e1a4de7bedadd8579Theodore Ts'o	/*
3343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	 * Write out the master group descriptors, and the backup
3353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	 * superblocks and group descriptors.
3363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	 */
337ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	group_ptr = (char *) group_shadow;
338ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
339ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		old_desc_blocks = fs->super->s_first_meta_bg;
340ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o	else
341ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		old_desc_blocks = fs->desc_blocks;
342ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o
343e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_numeric_progress_init(fs, &progress, NULL,
344e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				     fs->group_desc_count);
345e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
346e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
347bfd418832d46da1767517b40a7857de449ea03feTheodore Ts'o	for (i = 0; i < fs->group_desc_count; i++) {
348e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		blk64_t	super_blk, old_desc_blk, new_desc_blk;
349ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o
350e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_numeric_progress_update(fs, &progress, i);
351e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_super_and_bgd_loc2(fs, i, &super_blk, &old_desc_blk,
352e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					 &new_desc_blk, 0);
353ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o
354ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) {
355ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o			retval = write_backup_super(fs, i, super_blk,
356c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o						    super_shadow);
35750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			if (retval)
35850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o				goto errout;
3593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
360ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		if (fs->flags & EXT2_FLAG_SUPER_ONLY)
361ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o			continue;
362efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		if ((old_desc_blk) &&
363ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		    (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) {
364e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			retval = io_channel_write_blk64(fs->io,
365ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o			      old_desc_blk, old_desc_blocks, group_ptr);
366ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o			if (retval)
367ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o				goto errout;
368ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		}
369ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o		if (new_desc_blk) {
370e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			int meta_bg = i / EXT2_DESC_PER_BLOCK(fs->super);
371e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
372e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			retval = io_channel_write_blk64(fs->io, new_desc_blk,
373ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o				1, group_ptr + (meta_bg*fs->blocksize));
374ef344e13d2125e9dae3764b98f9fe3a170cd79e2Theodore Ts'o			if (retval)
37550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o				goto errout;
3763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
3773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
3783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
379e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_numeric_progress_close(fs, &progress, NULL);
380e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
3813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	/*
3823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	 * If the write_bitmaps() function is present, call it to
3833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	 * flush the bitmaps.  This is done this way so that a simple
3843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	 * program that doesn't mess with the bitmaps doesn't need to
3853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	 * drag in the bitmaps.c code.
3863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	 */
3873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (fs->write_bitmaps) {
3883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		retval = fs->write_bitmaps(fs);
3893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (retval)
39050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			goto errout;
3913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
392b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o
393a63d12678369f4ab0edf8fc5741825c035e78bf9Theodore Ts'owrite_primary_superblock_only:
394b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o	/*
395a63d12678369f4ab0edf8fc5741825c035e78bf9Theodore Ts'o	 * Write out master superblock.  This has to be done
396a63d12678369f4ab0edf8fc5741825c035e78bf9Theodore Ts'o	 * separately, since it is located at a fixed location
397a63d12678369f4ab0edf8fc5741825c035e78bf9Theodore Ts'o	 * (SUPERBLOCK_OFFSET).  We flush all other pending changes
398a63d12678369f4ab0edf8fc5741825c035e78bf9Theodore Ts'o	 * out to disk first, just to avoid a race condition with an
399a63d12678369f4ab0edf8fc5741825c035e78bf9Theodore Ts'o	 * insy-tinsy window....
400b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o	 */
4010d961040fe9ad927254b5a0e1a4de7bedadd8579Theodore Ts'o
4020d961040fe9ad927254b5a0e1a4de7bedadd8579Theodore Ts'o	fs->super->s_block_group_nr = 0;
4030d961040fe9ad927254b5a0e1a4de7bedadd8579Theodore Ts'o	fs->super->s_state = fs_state;
4049a083af71a2388ae47252f8af2b796f9055f4af7Theodore Ts'o	fs->super->s_feature_incompat = feature_incompat;
405126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#ifdef WORDS_BIGENDIAN
406126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o	*super_shadow = *fs->super;
407126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o	ext2fs_swap_super(super_shadow);
4080d961040fe9ad927254b5a0e1a4de7bedadd8579Theodore Ts'o#endif
4090d961040fe9ad927254b5a0e1a4de7bedadd8579Theodore Ts'o
410e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC))
411e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		retval = io_channel_flush(fs->io);
412a63d12678369f4ab0edf8fc5741825c035e78bf9Theodore Ts'o	retval = write_primary_superblock(fs, super_shadow);
413a63d12678369f4ab0edf8fc5741825c035e78bf9Theodore Ts'o	if (retval)
414a63d12678369f4ab0edf8fc5741825c035e78bf9Theodore Ts'o		goto errout;
415a63d12678369f4ab0edf8fc5741825c035e78bf9Theodore Ts'o
416a63d12678369f4ab0edf8fc5741825c035e78bf9Theodore Ts'o	fs->flags &= ~EXT2_FLAG_DIRTY;
417a63d12678369f4ab0edf8fc5741825c035e78bf9Theodore Ts'o
418e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC))
419e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		retval = io_channel_flush(fs->io);
42050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'oerrout:
42150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	fs->super->s_state = fs_state;
422126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#ifdef WORDS_BIGENDIAN
423126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o	if (super_shadow)
424126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o		ext2fs_free_mem(&super_shadow);
425126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o	if (group_shadow)
426126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o		ext2fs_free_mem(&group_shadow);
427126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#endif
42850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	return retval;
4293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
4303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
4313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oerrcode_t ext2fs_close(ext2_filsys fs)
4323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
433e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return ext2fs_close2(fs, 0);
434e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
435e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
436e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_close2(ext2_filsys fs, int flags)
437e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
4383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	errcode_t	retval;
439b7c5b4030870b31d73019d9d9ec55d550772590bTheodore Ts'o	int		meta_blks;
440b7c5b4030870b31d73019d9d9ec55d550772590bTheodore Ts'o	io_stats stats = 0;
441efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
442f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
443f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
444b7c5b4030870b31d73019d9d9ec55d550772590bTheodore Ts'o	if (fs->write_bitmaps) {
445b7c5b4030870b31d73019d9d9ec55d550772590bTheodore Ts'o		retval = fs->write_bitmaps(fs);
4463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (retval)
4473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			return retval;
4483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
449b7c5b4030870b31d73019d9d9ec55d550772590bTheodore Ts'o	if (fs->super->s_kbytes_written &&
450b7c5b4030870b31d73019d9d9ec55d550772590bTheodore Ts'o	    fs->io->manager->get_stats)
451b7c5b4030870b31d73019d9d9ec55d550772590bTheodore Ts'o		fs->io->manager->get_stats(fs->io, &stats);
452b7c5b4030870b31d73019d9d9ec55d550772590bTheodore Ts'o	if (stats && stats->bytes_written && (fs->flags & EXT2_FLAG_RW)) {
453b7c5b4030870b31d73019d9d9ec55d550772590bTheodore Ts'o		fs->super->s_kbytes_written += stats->bytes_written >> 10;
454b7c5b4030870b31d73019d9d9ec55d550772590bTheodore Ts'o		meta_blks = fs->desc_blocks + 1;
455b7c5b4030870b31d73019d9d9ec55d550772590bTheodore Ts'o		if (!(fs->flags & EXT2_FLAG_SUPER_ONLY))
456b7c5b4030870b31d73019d9d9ec55d550772590bTheodore Ts'o			fs->super->s_kbytes_written += meta_blks /
457b7c5b4030870b31d73019d9d9ec55d550772590bTheodore Ts'o				(fs->blocksize / 1024);
4586d67ee305cdfff7131a4105551409d1603dba81dTheodore Ts'o		if ((fs->flags & EXT2_FLAG_DIRTY) == 0)
4596d67ee305cdfff7131a4105551409d1603dba81dTheodore Ts'o			fs->flags |= EXT2_FLAG_SUPER_ONLY | EXT2_FLAG_DIRTY;
460b7c5b4030870b31d73019d9d9ec55d550772590bTheodore Ts'o	}
461b7c5b4030870b31d73019d9d9ec55d550772590bTheodore Ts'o	if (fs->flags & EXT2_FLAG_DIRTY) {
462e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		retval = ext2fs_flush2(fs, flags);
46321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o		if (retval)
46421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o			return retval;
46521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o	}
466e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
467e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	retval = ext2fs_mmp_stop(fs);
468e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (retval)
469e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		return retval;
470e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
4713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	ext2fs_free(fs);
4723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 0;
4733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
47421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
475