]>
Commit | Line | Data |
---|---|---|
24b2c7a7 TT |
1 | /* |
2 | * resize2fs.c --- ext2 main routine | |
3 | * | |
4 | * Copyright (C) 1997 Theodore Ts'o | |
5 | * | |
6 | * %Begin-Header% | |
7 | * All rights reserved. | |
8 | * %End-Header% | |
9 | */ | |
10 | ||
11 | #include "resize2fs.h" | |
12 | ||
13 | /* | |
14 | * This routine adjusts the superblock and other data structures... | |
15 | */ | |
16 | static errcode_t adjust_superblock(ext2_resize_t rfs, blk_t new_size) | |
17 | { | |
18 | ext2_filsys fs; | |
19 | int overhead = 0; | |
20 | int rem; | |
21 | errcode_t retval; | |
22 | ino_t real_end; | |
23 | blk_t blk, group_block; | |
1e1da29f | 24 | unsigned long i, j; |
24b2c7a7 | 25 | struct ext2_group_desc *new; |
1e1da29f TT |
26 | char *buf; |
27 | int old_numblocks, numblocks, adjblocks; | |
24b2c7a7 TT |
28 | |
29 | fs = rfs->new_fs; | |
30 | fs->super->s_blocks_count = new_size; | |
1e1da29f TT |
31 | ext2fs_mark_super_dirty(fs); |
32 | ext2fs_mark_bb_dirty(fs); | |
33 | ext2fs_mark_ib_dirty(fs); | |
24b2c7a7 TT |
34 | |
35 | retry: | |
36 | fs->group_desc_count = (fs->super->s_blocks_count - | |
37 | fs->super->s_first_data_block + | |
38 | EXT2_BLOCKS_PER_GROUP(fs->super) - 1) | |
39 | / EXT2_BLOCKS_PER_GROUP(fs->super); | |
40 | if (fs->group_desc_count == 0) | |
41 | return EXT2_ET_TOOSMALL; | |
42 | fs->desc_blocks = (fs->group_desc_count + | |
43 | EXT2_DESC_PER_BLOCK(fs->super) - 1) | |
44 | / EXT2_DESC_PER_BLOCK(fs->super); | |
45 | ||
46 | /* | |
47 | * Overhead is the number of bookkeeping blocks per group. It | |
48 | * includes the superblock backup, the group descriptor | |
49 | * backups, the inode bitmap, the block bitmap, and the inode | |
50 | * table. | |
51 | * | |
52 | * XXX Not all block groups need the descriptor blocks, but | |
53 | * being clever is tricky... | |
54 | */ | |
55 | overhead = 3 + fs->desc_blocks + fs->inode_blocks_per_group; | |
56 | ||
57 | /* | |
58 | * See if the last group is big enough to support the | |
59 | * necessary data structures. If not, we need to get rid of | |
60 | * it. | |
61 | */ | |
62 | rem = (fs->super->s_blocks_count - fs->super->s_first_data_block) % | |
63 | fs->super->s_blocks_per_group; | |
64 | if ((fs->group_desc_count == 1) && rem && (rem < overhead)) | |
65 | return EXT2_ET_TOOSMALL; | |
66 | if (rem && (rem < overhead+50)) { | |
67 | fs->super->s_blocks_count -= rem; | |
68 | goto retry; | |
69 | } | |
70 | /* | |
71 | * Adjust the number of inodes | |
72 | */ | |
73 | fs->super->s_inodes_count = fs->super->s_inodes_per_group * | |
74 | fs->group_desc_count; | |
75 | ||
76 | /* | |
77 | * Adjust the number of free blocks | |
78 | */ | |
79 | blk = rfs->old_fs->super->s_blocks_count; | |
80 | if (blk > fs->super->s_blocks_count) | |
81 | fs->super->s_free_blocks_count -= | |
82 | (blk - fs->super->s_blocks_count); | |
83 | else | |
84 | fs->super->s_free_blocks_count += | |
85 | (fs->super->s_blocks_count - blk); | |
86 | ||
87 | /* | |
88 | * Adjust the bitmaps for size | |
89 | */ | |
90 | retval = ext2fs_resize_inode_bitmap(fs->super->s_inodes_count, | |
91 | fs->super->s_inodes_count, | |
92 | fs->inode_map); | |
93 | if (retval) | |
94 | return retval; | |
95 | ||
96 | real_end = ((EXT2_BLOCKS_PER_GROUP(fs->super) | |
97 | * fs->group_desc_count)) - 1 + | |
98 | fs->super->s_first_data_block; | |
99 | retval = ext2fs_resize_block_bitmap(fs->super->s_blocks_count-1, | |
100 | real_end, fs->block_map); | |
101 | ||
102 | if (retval) | |
103 | return retval; | |
104 | ||
105 | /* | |
106 | * Reallocate the group descriptors as necessary. | |
107 | */ | |
108 | if (rfs->old_fs->desc_blocks != fs->desc_blocks) { | |
109 | new = realloc(fs->group_desc, | |
110 | fs->desc_blocks * fs->blocksize); | |
111 | if (!new) | |
112 | return ENOMEM; | |
113 | fs->group_desc = new; | |
114 | } | |
1e1da29f TT |
115 | |
116 | /* | |
117 | * Fix the count of the last (old) block group | |
118 | */ | |
119 | if (rfs->old_fs->group_desc_count > fs->group_desc_count) | |
120 | return 0; | |
121 | old_numblocks = (rfs->old_fs->super->s_blocks_count - | |
122 | rfs->old_fs->super->s_first_data_block) % | |
123 | rfs->old_fs->super->s_blocks_per_group; | |
124 | if (!old_numblocks) | |
125 | old_numblocks = rfs->old_fs->super->s_blocks_per_group; | |
126 | if (rfs->old_fs->group_desc_count == fs->group_desc_count) { | |
127 | numblocks = (rfs->new_fs->super->s_blocks_count - | |
128 | rfs->new_fs->super->s_first_data_block) % | |
129 | rfs->new_fs->super->s_blocks_per_group; | |
130 | if (!numblocks) | |
131 | numblocks = rfs->new_fs->super->s_blocks_per_group; | |
132 | } else | |
133 | numblocks = rfs->new_fs->super->s_blocks_per_group; | |
134 | i = rfs->old_fs->group_desc_count - 1; | |
135 | fs->group_desc[i].bg_free_blocks_count += (numblocks-old_numblocks); | |
136 | ||
137 | /* | |
138 | * Initialize the new block group descriptors | |
139 | */ | |
140 | if (rfs->old_fs->group_desc_count >= fs->group_desc_count) | |
141 | return 0; | |
142 | buf = malloc(fs->blocksize); | |
143 | if (!buf) | |
144 | return ENOMEM; | |
145 | memset(buf, 0, fs->blocksize); | |
146 | group_block = fs->super->s_first_data_block + | |
147 | rfs->old_fs->group_desc_count * fs->super->s_blocks_per_group; | |
148 | for (i = rfs->old_fs->group_desc_count; | |
149 | i < fs->group_desc_count; i++) { | |
150 | memset(&fs->group_desc[i], 0, | |
151 | sizeof(struct ext2_group_desc)); | |
152 | adjblocks = 0; | |
153 | ||
154 | if (i == fs->group_desc_count-1) { | |
155 | numblocks = (fs->super->s_blocks_count - | |
156 | fs->super->s_first_data_block) % | |
157 | fs->super->s_blocks_per_group; | |
158 | if (!numblocks) | |
159 | numblocks = fs->super->s_blocks_per_group; | |
160 | } else | |
161 | numblocks = fs->super->s_blocks_per_group; | |
162 | ||
163 | if (ext2fs_bg_has_super(fs, i)) { | |
164 | for (j=0; j < fs->desc_blocks+1; j++) | |
165 | ext2fs_mark_block_bitmap(fs->block_map, | |
166 | group_block + j); | |
167 | adjblocks = 1 + fs->desc_blocks; | |
24b2c7a7 | 168 | } |
1e1da29f TT |
169 | adjblocks += 2 + fs->inode_blocks_per_group; |
170 | ||
171 | numblocks -= adjblocks; | |
172 | fs->super->s_free_blocks_count -= adjblocks; | |
173 | fs->super->s_free_inodes_count += | |
174 | fs->super->s_inodes_per_group; | |
175 | fs->group_desc[i].bg_free_blocks_count = numblocks; | |
176 | fs->group_desc[i].bg_free_inodes_count = | |
177 | fs->super->s_inodes_per_group; | |
178 | fs->group_desc[i].bg_used_dirs_count = 0; | |
24b2c7a7 | 179 | |
1e1da29f TT |
180 | retval = ext2fs_allocate_group_table(fs, i, 0); |
181 | if (retval) | |
182 | return retval; | |
24b2c7a7 | 183 | |
1e1da29f TT |
184 | for (blk=fs->group_desc[i].bg_inode_table, j=0; |
185 | j < fs->inode_blocks_per_group; | |
186 | blk++, j++) { | |
187 | retval = io_channel_write_blk(fs->io, blk, 1, buf); | |
188 | if (retval) | |
189 | return retval; | |
24b2c7a7 | 190 | } |
1e1da29f | 191 | group_block += fs->super->s_blocks_per_group; |
24b2c7a7 | 192 | } |
1e1da29f | 193 | return 0; |
24b2c7a7 TT |
194 | } |
195 | ||
24b2c7a7 TT |
196 | /* |
197 | * This routine marks and unmarks reserved blocks in the new block | |
198 | * bitmap. It also determines which blocks need to be moved and | |
199 | * places this information into the move_blocks bitmap. | |
200 | */ | |
201 | static errcode_t determine_relocations(ext2_resize_t rfs) | |
202 | { | |
052db4b7 | 203 | int i, j, max, adj; |
24b2c7a7 TT |
204 | blk_t blk, group_blk; |
205 | unsigned long old_blocks, new_blocks; | |
206 | errcode_t retval; | |
1e1da29f | 207 | ext2_filsys fs = rfs->new_fs; |
24b2c7a7 TT |
208 | |
209 | retval = ext2fs_allocate_block_bitmap(rfs->old_fs, | |
210 | "blocks to be moved", | |
1e1da29f | 211 | &rfs->reserve_blocks); |
24b2c7a7 TT |
212 | if (retval) |
213 | return retval; | |
1e1da29f TT |
214 | |
215 | /* | |
216 | * If we're shrinking the filesystem, we need to move all of | |
217 | * the blocks that don't fit any more | |
218 | */ | |
219 | for (blk = fs->super->s_blocks_count; | |
220 | blk < rfs->old_fs->super->s_blocks_count; blk++) { | |
221 | if (ext2fs_test_block_bitmap(rfs->old_fs->block_map, blk)) | |
222 | rfs->needed_blocks++; | |
223 | ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk); | |
224 | } | |
24b2c7a7 TT |
225 | |
226 | old_blocks = rfs->old_fs->desc_blocks; | |
1e1da29f TT |
227 | new_blocks = fs->desc_blocks; |
228 | ||
229 | if (old_blocks == new_blocks) | |
230 | return 0; | |
24b2c7a7 | 231 | |
052db4b7 TT |
232 | max = fs->group_desc_count; |
233 | if (max > rfs->old_fs->group_desc_count) | |
234 | max = rfs->old_fs->group_desc_count; | |
24b2c7a7 TT |
235 | group_blk = rfs->old_fs->super->s_first_data_block; |
236 | /* | |
237 | * If we're reducing the number of descriptor blocks, this | |
238 | * makes life easy. :-) We just have to mark some extra | |
239 | * blocks as free. | |
240 | */ | |
241 | if (old_blocks > new_blocks) { | |
052db4b7 | 242 | for (i = 0; i < max; i++) { |
1e1da29f TT |
243 | if (!ext2fs_bg_has_super(fs, i)) { |
244 | group_blk += fs->super->s_blocks_per_group; | |
24b2c7a7 TT |
245 | continue; |
246 | } | |
247 | for (blk = group_blk+1+old_blocks; | |
052db4b7 | 248 | blk < group_blk+1+new_blocks; blk++) { |
1e1da29f | 249 | ext2fs_unmark_block_bitmap(fs->block_map, |
24b2c7a7 | 250 | blk); |
052db4b7 TT |
251 | rfs->needed_blocks--; |
252 | } | |
1e1da29f | 253 | group_blk += fs->super->s_blocks_per_group; |
24b2c7a7 | 254 | } |
1e1da29f | 255 | return 0; |
24b2c7a7 TT |
256 | } |
257 | /* | |
258 | * If we're increasing the number of descriptor blocks, life | |
1e1da29f | 259 | * gets interesting.... |
24b2c7a7 | 260 | */ |
052db4b7 | 261 | for (i = 0; i < max; i++) { |
1e1da29f TT |
262 | if (!ext2fs_bg_has_super(fs, i)) |
263 | goto next_group; | |
264 | ||
265 | for (blk = group_blk; | |
266 | blk < group_blk + 1 + new_blocks; blk++) { | |
267 | ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk); | |
268 | ext2fs_mark_block_bitmap(fs->block_map, blk); | |
269 | ||
270 | /* | |
271 | * Check to see if we overlap with the inode | |
272 | * or block bitmap | |
273 | */ | |
052db4b7 TT |
274 | if (blk == fs->group_desc[i].bg_block_bitmap) { |
275 | fs->group_desc[i].bg_block_bitmap = 0; | |
276 | rfs->needed_blocks++; | |
277 | } | |
278 | if (blk == fs->group_desc[i].bg_inode_bitmap) { | |
1e1da29f | 279 | fs->group_desc[i].bg_inode_bitmap = 0; |
052db4b7 TT |
280 | rfs->needed_blocks++; |
281 | } | |
1e1da29f TT |
282 | /* |
283 | * Check to see if we overlap with the inode | |
284 | * table | |
285 | */ | |
286 | if (blk < fs->group_desc[i].bg_inode_table) | |
24b2c7a7 | 287 | continue; |
1e1da29f TT |
288 | if (blk >= (fs->group_desc[i].bg_inode_table + |
289 | fs->inode_blocks_per_group)) | |
290 | continue; | |
291 | fs->group_desc[i].bg_inode_table = 0; | |
292 | blk = fs->group_desc[i].bg_inode_table + | |
293 | fs->inode_blocks_per_group - 1; | |
24b2c7a7 | 294 | } |
1e1da29f TT |
295 | if (fs->group_desc[i].bg_inode_table && |
296 | fs->group_desc[i].bg_inode_bitmap && | |
297 | fs->group_desc[i].bg_block_bitmap) | |
298 | goto next_group; | |
24b2c7a7 | 299 | |
1e1da29f TT |
300 | /* |
301 | * Allocate the missing bitmap and inode table | |
302 | * structures, passing in rfs->reserve_blocks to | |
303 | * prevent a conflict. | |
304 | */ | |
305 | if (fs->group_desc[i].bg_block_bitmap) | |
306 | ext2fs_mark_block_bitmap(rfs->reserve_blocks, | |
307 | fs->group_desc[i].bg_block_bitmap); | |
308 | if (fs->group_desc[i].bg_inode_bitmap) | |
309 | ext2fs_mark_block_bitmap(rfs->reserve_blocks, | |
310 | fs->group_desc[i].bg_inode_bitmap); | |
311 | if (fs->group_desc[i].bg_inode_table) | |
312 | for (blk = fs->group_desc[i].bg_inode_table, j=0; | |
313 | j < fs->inode_blocks_per_group ; j++, blk++) | |
314 | ext2fs_mark_block_bitmap(rfs->reserve_blocks, | |
315 | blk); | |
24b2c7a7 | 316 | |
1e1da29f TT |
317 | retval = ext2fs_allocate_group_table(fs, i, |
318 | rfs->reserve_blocks); | |
319 | if (retval) | |
320 | return retval; | |
24b2c7a7 | 321 | |
1e1da29f TT |
322 | /* |
323 | * Now make sure these blocks are reserved in the new | |
324 | * block bitmap | |
325 | */ | |
326 | ext2fs_mark_block_bitmap(fs->block_map, | |
327 | fs->group_desc[i].bg_block_bitmap); | |
328 | ext2fs_mark_block_bitmap(fs->block_map, | |
329 | fs->group_desc[i].bg_inode_bitmap); | |
24b2c7a7 | 330 | |
052db4b7 TT |
331 | /* |
332 | * The inode table, if we need to relocate it, is | |
333 | * handled specially. We have to reserve the blocks | |
334 | * for both the old and the new inode table, since we | |
335 | * can't have the inode table be destroyed during the | |
336 | * block relocation phase. | |
337 | */ | |
338 | adj = fs->group_desc[i].bg_inode_table - | |
339 | rfs->old_fs->group_desc[i].bg_inode_table; | |
340 | if (!adj) | |
341 | goto next_group; /* inode table not moved */ | |
342 | ||
343 | /* | |
344 | * Figure out how many blocks we need to have free. | |
345 | * This takes into account that we need to reserve | |
346 | * both inode tables, which may be overallping. | |
347 | */ | |
348 | if (adj < 0) | |
349 | adj = -adj; | |
350 | if (adj > fs->inode_blocks_per_group) | |
351 | adj = fs->inode_blocks_per_group; | |
352 | rfs->needed_blocks += fs->inode_blocks_per_group + adj; | |
353 | ||
354 | /* | |
355 | * Mark the new inode table as in use in the new block | |
356 | * allocation bitmap. | |
357 | */ | |
1e1da29f TT |
358 | for (blk = fs->group_desc[i].bg_inode_table, j=0; |
359 | j < fs->inode_blocks_per_group ; j++, blk++) | |
360 | ext2fs_mark_block_bitmap(fs->block_map, blk); | |
1e1da29f | 361 | /* |
052db4b7 TT |
362 | * Make sure the old inode table is reserved in the |
363 | * block reservation bitmap. | |
1e1da29f | 364 | */ |
052db4b7 TT |
365 | for (blk = rfs->old_fs->group_desc[i].bg_inode_table, j=0; |
366 | j < fs->inode_blocks_per_group ; j++, blk++) | |
367 | ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk); | |
1e1da29f TT |
368 | |
369 | next_group: | |
370 | group_blk += rfs->new_fs->super->s_blocks_per_group; | |
371 | } | |
052db4b7 | 372 | return 0; |
1e1da29f | 373 | } |
24b2c7a7 TT |
374 | |
375 | ||
052db4b7 TT |
376 | /* |
377 | * A very scary routine --- this one moves the inode table around!!! | |
378 | * | |
379 | * After this you have to use the rfs->new_fs file handle to read and | |
380 | * write inodes. | |
381 | */ | |
382 | errcode_t move_itables(ext2_resize_t rfs) | |
383 | { | |
384 | int i, max; | |
385 | ext2_filsys fs = rfs->new_fs; | |
386 | char *buf; | |
387 | blk_t old, new; | |
388 | errcode_t retval, err; | |
389 | ||
390 | printf("Hide the women and children --- " | |
391 | "commencing inode table moves!!\n"); | |
392 | ||
393 | max = fs->group_desc_count; | |
394 | if (max > rfs->old_fs->group_desc_count) | |
395 | max = rfs->old_fs->group_desc_count; | |
396 | ||
397 | buf = malloc(fs->blocksize * fs->inode_blocks_per_group); | |
398 | if (!buf) | |
399 | return ENOMEM; | |
400 | ||
401 | for (i=0; i < max; i++) { | |
402 | old = rfs->old_fs->group_desc[i].bg_inode_table; | |
403 | new = fs->group_desc[i].bg_inode_table; | |
404 | ||
405 | printf("Group %d block %ld->%ld\n", i, old, new); | |
406 | ||
407 | if (old == new) | |
408 | continue; | |
409 | ||
410 | retval = io_channel_read_blk(fs->io, old, | |
411 | fs->inode_blocks_per_group, buf); | |
412 | if (retval) | |
413 | goto backout; | |
414 | retval = io_channel_write_blk(fs->io, new, | |
415 | fs->inode_blocks_per_group, buf); | |
416 | if (retval) { | |
417 | io_channel_write_blk(fs->io, old, | |
418 | fs->inode_blocks_per_group, buf); | |
419 | goto backout; | |
420 | } | |
421 | } | |
422 | ext2fs_flush(rfs->new_fs); | |
423 | printf("Inode table move finished.\n"); | |
424 | return 0; | |
425 | ||
426 | backout: | |
427 | printf("Error: %s; now backing out!\n", error_message(retval)); | |
428 | while (--i >= 0) { | |
429 | printf("Group %d block %ld->%ld\n", i, new, old); | |
430 | old = rfs->old_fs->group_desc[i].bg_inode_table; | |
431 | new = fs->group_desc[i].bg_inode_table; | |
432 | ||
433 | err = io_channel_read_blk(fs->io, new, | |
434 | fs->inode_blocks_per_group, buf); | |
435 | if (err) | |
436 | continue; | |
437 | err = io_channel_write_blk(fs->io, old, | |
438 | fs->inode_blocks_per_group, buf); | |
439 | } | |
440 | return retval; | |
441 | } | |
442 | ||
443 | /* | |
444 | * Finally, recalculate the summary information | |
445 | */ | |
446 | static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs) | |
447 | { | |
448 | blk_t blk; | |
449 | ino_t ino; | |
450 | int group = 0; | |
451 | int count = 0; | |
452 | int total_free = 0; | |
453 | int group_free = 0; | |
454 | ||
455 | /* | |
456 | * First calculate the block statistics | |
457 | */ | |
458 | for (blk = fs->super->s_first_data_block; | |
459 | blk < fs->super->s_blocks_count; blk++) { | |
460 | if (!ext2fs_fast_test_block_bitmap(fs->block_map, blk)) { | |
461 | group_free++; | |
462 | total_free++; | |
463 | } | |
464 | count++; | |
465 | if ((count == fs->super->s_blocks_per_group) || | |
466 | (blk == fs->super->s_blocks_count-1)) { | |
467 | fs->group_desc[group++].bg_free_blocks_count = | |
468 | group_free; | |
469 | count = 0; | |
470 | group_free = 0; | |
471 | } | |
472 | } | |
473 | fs->super->s_free_blocks_count = total_free; | |
474 | ||
475 | /* | |
476 | * Next, calculate the inode statistics | |
477 | */ | |
478 | group_free = 0; | |
479 | total_free = 0; | |
480 | count = 0; | |
481 | group = 0; | |
482 | for (ino = 1; ino <= fs->super->s_inodes_count; ino++) { | |
483 | if (!ext2fs_fast_test_inode_bitmap(fs->inode_map, ino)) { | |
484 | group_free++; | |
485 | total_free++; | |
486 | } | |
487 | count++; | |
488 | if ((count == fs->super->s_inodes_per_group) || | |
489 | (ino == fs->super->s_inodes_count)) { | |
490 | fs->group_desc[group++].bg_free_inodes_count = | |
491 | group_free; | |
492 | count = 0; | |
493 | group_free = 0; | |
494 | } | |
495 | } | |
496 | fs->super->s_free_inodes_count = total_free; | |
497 | ext2fs_mark_super_dirty(fs); | |
498 | return 0; | |
499 | } | |
500 | ||
501 | ||
502 | ||
24b2c7a7 TT |
503 | /* |
504 | * This is the top-level routine which does the dirty deed.... | |
505 | */ | |
506 | errcode_t resize_fs(ext2_filsys fs, blk_t new_size) | |
507 | { | |
508 | ext2_resize_t rfs; | |
509 | errcode_t retval; | |
510 | ||
1e1da29f TT |
511 | retval = ext2fs_read_bitmaps(fs); |
512 | if (retval) | |
513 | return retval; | |
514 | ||
24b2c7a7 | 515 | /* |
1e1da29f | 516 | * Create the data structure |
24b2c7a7 TT |
517 | */ |
518 | rfs = malloc(sizeof(struct ext2_resize_struct)); | |
519 | if (!rfs) | |
520 | return ENOMEM; | |
521 | memset(rfs, 0, sizeof(struct ext2_resize_struct)); | |
522 | ||
523 | rfs->old_fs = fs; | |
524 | retval = ext2fs_dup_handle(fs, &rfs->new_fs); | |
1e1da29f TT |
525 | if (retval) |
526 | goto errout; | |
527 | ||
24b2c7a7 TT |
528 | retval = adjust_superblock(rfs, new_size); |
529 | if (retval) | |
530 | goto errout; | |
1e1da29f TT |
531 | |
532 | retval = determine_relocations(rfs); | |
533 | if (retval) | |
534 | goto errout; | |
535 | ||
052db4b7 TT |
536 | printf("Number of free blocks: %d, Needed: %d\n", |
537 | fs->super->s_free_blocks_count, rfs->needed_blocks); | |
538 | ||
539 | if (rfs->needed_blocks > fs->super->s_free_blocks_count) { | |
540 | retval = ENOSPC; | |
541 | goto errout; | |
542 | } | |
543 | ||
1e1da29f TT |
544 | printf("\nOld superblock:\n"); |
545 | list_super(rfs->old_fs->super); | |
546 | printf("\n\nNew superblock:\n"); | |
547 | list_super(rfs->new_fs->super); | |
548 | printf("\n"); | |
549 | ||
550 | retval = ext2fs_move_blocks(rfs->old_fs, rfs->reserve_blocks, | |
052db4b7 | 551 | rfs->new_fs->block_map, |
1e1da29f | 552 | EXT2_BMOVE_GET_DBLIST); |
052db4b7 TT |
553 | if (retval) |
554 | return retval; | |
1e1da29f | 555 | |
052db4b7 TT |
556 | retval = ext2fs_inode_move(rfs); |
557 | if (retval) | |
558 | return retval; | |
559 | ||
560 | retval = move_itables(rfs); | |
561 | if (retval) | |
562 | return retval; | |
563 | ||
564 | retval = ext2fs_calculate_summary_stats(rfs->new_fs); | |
565 | if (retval) | |
566 | return retval; | |
567 | ||
1e1da29f TT |
568 | retval = ext2fs_close(rfs->new_fs); |
569 | if (retval) | |
570 | return retval; | |
571 | ||
572 | ext2fs_free(rfs->old_fs); | |
24b2c7a7 TT |
573 | |
574 | return 0; | |
575 | ||
576 | errout: | |
1e1da29f TT |
577 | if (rfs->new_fs) |
578 | ext2fs_free(rfs->new_fs); | |
24b2c7a7 TT |
579 | free(rfs); |
580 | return retval; | |
581 | } |