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