xref: /onnv-gate/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_meta.c (revision 9663:ace9a2ac3683)
1*9663SMark.Logan@Sun.COM /*
2*9663SMark.Logan@Sun.COM     ext2_meta.c -- ext2 metadata mover
3*9663SMark.Logan@Sun.COM     Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc.
4*9663SMark.Logan@Sun.COM 
5*9663SMark.Logan@Sun.COM     This program is free software; you can redistribute it and/or modify
6*9663SMark.Logan@Sun.COM     it under the terms of the GNU General Public License as published by
7*9663SMark.Logan@Sun.COM     the Free Software Foundation; either version 3 of the License, or
8*9663SMark.Logan@Sun.COM     (at your option) any later version.
9*9663SMark.Logan@Sun.COM 
10*9663SMark.Logan@Sun.COM     This program is distributed in the hope that it will be useful,
11*9663SMark.Logan@Sun.COM     but WITHOUT ANY WARRANTY; without even the implied warranty of
12*9663SMark.Logan@Sun.COM     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*9663SMark.Logan@Sun.COM     GNU General Public License for more details.
14*9663SMark.Logan@Sun.COM 
15*9663SMark.Logan@Sun.COM     You should have received a copy of the GNU General Public License
16*9663SMark.Logan@Sun.COM     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17*9663SMark.Logan@Sun.COM */
18*9663SMark.Logan@Sun.COM 
19*9663SMark.Logan@Sun.COM #include <config.h>
20*9663SMark.Logan@Sun.COM 
21*9663SMark.Logan@Sun.COM #ifndef DISCOVER_ONLY
22*9663SMark.Logan@Sun.COM 
23*9663SMark.Logan@Sun.COM #include <stdio.h>
24*9663SMark.Logan@Sun.COM #include <stdlib.h>
25*9663SMark.Logan@Sun.COM #include "ext2.h"
26*9663SMark.Logan@Sun.COM 
ext2_metadata_push(struct ext2_fs * fs,blk_t newsize)27*9663SMark.Logan@Sun.COM int ext2_metadata_push(struct ext2_fs *fs, blk_t newsize)
28*9663SMark.Logan@Sun.COM {
29*9663SMark.Logan@Sun.COM 	int   i;
30*9663SMark.Logan@Sun.COM 	int   newgdblocks;
31*9663SMark.Logan@Sun.COM 	blk_t newitoffset;
32*9663SMark.Logan@Sun.COM 
33*9663SMark.Logan@Sun.COM 	newgdblocks = ped_div_round_up (newsize
34*9663SMark.Logan@Sun.COM                         - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb),
35*9663SMark.Logan@Sun.COM 			      EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb));
36*9663SMark.Logan@Sun.COM 	newgdblocks = ped_div_round_up (newgdblocks
37*9663SMark.Logan@Sun.COM                         * sizeof(struct ext2_group_desc),
38*9663SMark.Logan@Sun.COM 			      fs->blocksize);
39*9663SMark.Logan@Sun.COM 	newitoffset = newgdblocks + 3;
40*9663SMark.Logan@Sun.COM 
41*9663SMark.Logan@Sun.COM 	if (newitoffset <= fs->itoffset)
42*9663SMark.Logan@Sun.COM 		return 1;
43*9663SMark.Logan@Sun.COM 
44*9663SMark.Logan@Sun.COM 	for (i=0;i<fs->numgroups;i++)
45*9663SMark.Logan@Sun.COM 	{
46*9663SMark.Logan@Sun.COM 		blk_t diff;
47*9663SMark.Logan@Sun.COM 		blk_t j;
48*9663SMark.Logan@Sun.COM 		blk_t fromblock;
49*9663SMark.Logan@Sun.COM 		blk_t start;
50*9663SMark.Logan@Sun.COM 
51*9663SMark.Logan@Sun.COM 		start = (i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb))
52*9663SMark.Logan@Sun.COM 			+ EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb);
53*9663SMark.Logan@Sun.COM 
54*9663SMark.Logan@Sun.COM 		if (EXT2_GROUP_INODE_TABLE(fs->gd[i]) >= start + newitoffset
55*9663SMark.Logan@Sun.COM 		    && EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]) >= start + newitoffset - 2
56*9663SMark.Logan@Sun.COM 		    && EXT2_GROUP_INODE_BITMAP(fs->gd[i]) >= start + newitoffset - 1)
57*9663SMark.Logan@Sun.COM 			continue;
58*9663SMark.Logan@Sun.COM 
59*9663SMark.Logan@Sun.COM 		diff = newitoffset - (EXT2_GROUP_INODE_TABLE(fs->gd[i]) - start);
60*9663SMark.Logan@Sun.COM 
61*9663SMark.Logan@Sun.COM 		/* inode table */
62*9663SMark.Logan@Sun.COM 		fromblock = EXT2_GROUP_INODE_TABLE(fs->gd[i]) + fs->inodeblocks;
63*9663SMark.Logan@Sun.COM 
64*9663SMark.Logan@Sun.COM 		if (fs->opt_debug)
65*9663SMark.Logan@Sun.COM 		{
66*9663SMark.Logan@Sun.COM 			for (j=0;j<diff;j++)
67*9663SMark.Logan@Sun.COM 				if (!ext2_get_block_state(fs, fromblock+j))
68*9663SMark.Logan@Sun.COM 				{
69*9663SMark.Logan@Sun.COM 					fprintf(stderr,
70*9663SMark.Logan@Sun.COM 						"error: block relocator "
71*9663SMark.Logan@Sun.COM 						"should have relocated "
72*9663SMark.Logan@Sun.COM 						"%i\n",
73*9663SMark.Logan@Sun.COM 						fromblock);
74*9663SMark.Logan@Sun.COM 
75*9663SMark.Logan@Sun.COM 					return 0;
76*9663SMark.Logan@Sun.COM 				}
77*9663SMark.Logan@Sun.COM 		}
78*9663SMark.Logan@Sun.COM 
79*9663SMark.Logan@Sun.COM 		for (j=0;j<diff;j++)
80*9663SMark.Logan@Sun.COM 			if (!ext2_set_block_state(fs, fromblock+j, 1, 0))
81*9663SMark.Logan@Sun.COM 				return 0;
82*9663SMark.Logan@Sun.COM 
83*9663SMark.Logan@Sun.COM 		if (!ext2_move_blocks(fs,
84*9663SMark.Logan@Sun.COM 				      EXT2_GROUP_INODE_TABLE(fs->gd[i]),
85*9663SMark.Logan@Sun.COM 				      fs->inodeblocks,
86*9663SMark.Logan@Sun.COM 				      EXT2_GROUP_INODE_TABLE(fs->gd[i]) + diff))
87*9663SMark.Logan@Sun.COM 			return 0;
88*9663SMark.Logan@Sun.COM 		fs->gd[i].bg_inode_table = PED_CPU_TO_LE32 (
89*9663SMark.Logan@Sun.COM 			EXT2_GROUP_INODE_TABLE(fs->gd[i]) + diff);
90*9663SMark.Logan@Sun.COM 		fs->metadirty |= EXT2_META_GD;
91*9663SMark.Logan@Sun.COM 
92*9663SMark.Logan@Sun.COM 		if (fs->opt_safe)
93*9663SMark.Logan@Sun.COM 			if (!ext2_sync(fs))
94*9663SMark.Logan@Sun.COM 				return 0;
95*9663SMark.Logan@Sun.COM 
96*9663SMark.Logan@Sun.COM 		/* block bitmap and inode bitmap */
97*9663SMark.Logan@Sun.COM 		fromblock = EXT2_GROUP_INODE_TABLE(fs->gd[i]);
98*9663SMark.Logan@Sun.COM 		if (ext2_is_group_sparse(fs, i))
99*9663SMark.Logan@Sun.COM 		{
100*9663SMark.Logan@Sun.COM 			if (!ext2_copy_block(fs,
101*9663SMark.Logan@Sun.COM 				EXT2_GROUP_INODE_BITMAP(fs->gd[i]),
102*9663SMark.Logan@Sun.COM 				EXT2_GROUP_INODE_BITMAP(fs->gd[i]) + diff))
103*9663SMark.Logan@Sun.COM 				return 0;
104*9663SMark.Logan@Sun.COM 			fs->gd[i].bg_inode_bitmap = PED_CPU_TO_LE32 (
105*9663SMark.Logan@Sun.COM 				EXT2_GROUP_INODE_BITMAP(fs->gd[i]) + diff);
106*9663SMark.Logan@Sun.COM                         fs->metadirty |= EXT2_META_GD;
107*9663SMark.Logan@Sun.COM 
108*9663SMark.Logan@Sun.COM 			if (fs->opt_safe)
109*9663SMark.Logan@Sun.COM 				if (!ext2_sync(fs))
110*9663SMark.Logan@Sun.COM 					return 0;
111*9663SMark.Logan@Sun.COM 
112*9663SMark.Logan@Sun.COM 			if (!ext2_copy_block(fs,
113*9663SMark.Logan@Sun.COM 				EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]),
114*9663SMark.Logan@Sun.COM 				EXT2_GROUP_BLOCK_BITMAP(fs->gd[i])+diff))
115*9663SMark.Logan@Sun.COM 				return 0;
116*9663SMark.Logan@Sun.COM 			fs->gd[i].bg_block_bitmap = PED_CPU_TO_LE32 (
117*9663SMark.Logan@Sun.COM 				EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]) + diff);
118*9663SMark.Logan@Sun.COM 			fs->metadirty |= EXT2_META_GD;
119*9663SMark.Logan@Sun.COM 
120*9663SMark.Logan@Sun.COM 			if (fs->opt_safe)
121*9663SMark.Logan@Sun.COM 				if (!ext2_sync(fs))
122*9663SMark.Logan@Sun.COM 					return 0;
123*9663SMark.Logan@Sun.COM 
124*9663SMark.Logan@Sun.COM 			fromblock = EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]);
125*9663SMark.Logan@Sun.COM 		}
126*9663SMark.Logan@Sun.COM 
127*9663SMark.Logan@Sun.COM 		ext2_zero_blocks(fs, fromblock-diff, diff);
128*9663SMark.Logan@Sun.COM 		for (j=0;j<diff;j++)
129*9663SMark.Logan@Sun.COM 			if (!ext2_set_block_state(fs, fromblock+j-diff, 0, 0))
130*9663SMark.Logan@Sun.COM 				return 0;
131*9663SMark.Logan@Sun.COM 
132*9663SMark.Logan@Sun.COM 		if (fs->opt_verbose)
133*9663SMark.Logan@Sun.COM 			fprintf(stderr,
134*9663SMark.Logan@Sun.COM 				"ext2_metadata_push: group %i/%i\r",
135*9663SMark.Logan@Sun.COM 				i+1, fs->numgroups);
136*9663SMark.Logan@Sun.COM 	}
137*9663SMark.Logan@Sun.COM 
138*9663SMark.Logan@Sun.COM 	fs->itoffset = newitoffset;
139*9663SMark.Logan@Sun.COM 
140*9663SMark.Logan@Sun.COM 	if (fs->opt_verbose)
141*9663SMark.Logan@Sun.COM                 fputc ('\n', stderr);
142*9663SMark.Logan@Sun.COM 
143*9663SMark.Logan@Sun.COM 	return 1;
144*9663SMark.Logan@Sun.COM }
145*9663SMark.Logan@Sun.COM #endif /* !DISCOVER_ONLY */
146