2 * resize2fs.c --- ext2 main routine
4 * Copyright (C) 1997 Theodore Ts'o
12 * Resizing a filesystem consists of the following phases:
14 * 1. Adjust superblock and (*) write out new parts of the inode
16 * 2. Determine blocks which need to be relocated.
17 * 3. (*) Relocate blocks which must be moved, adjusting entries
18 * in the filesystem in the process.
19 * 4. (*) Move inodes which must be moved (only when shrinking a
21 * 5. (*) Move the inode tables, if necessary.
23 #include "resize2fs.h"
26 * This routine adjusts the superblock and other data structures...
28 static errcode_t adjust_superblock(ext2_resize_t rfs, blk_t new_size)
35 blk_t blk, group_block;
37 struct ext2_group_desc *new;
38 int old_numblocks, numblocks, adjblocks;
41 fs->super->s_blocks_count = new_size;
42 ext2fs_mark_super_dirty(fs);
43 ext2fs_mark_bb_dirty(fs);
44 ext2fs_mark_ib_dirty(fs);
47 fs->group_desc_count = (fs->super->s_blocks_count -
48 fs->super->s_first_data_block +
49 EXT2_BLOCKS_PER_GROUP(fs->super) - 1)
50 / EXT2_BLOCKS_PER_GROUP(fs->super);
51 if (fs->group_desc_count == 0)
52 return EXT2_ET_TOOSMALL;
53 fs->desc_blocks = (fs->group_desc_count +
54 EXT2_DESC_PER_BLOCK(fs->super) - 1)
55 / EXT2_DESC_PER_BLOCK(fs->super);
58 * Overhead is the number of bookkeeping blocks per group. It
59 * includes the superblock backup, the group descriptor
60 * backups, the inode bitmap, the block bitmap, and the inode
63 * XXX Not all block groups need the descriptor blocks, but
64 * being clever is tricky...
66 overhead = 3 + fs->desc_blocks + fs->inode_blocks_per_group;
69 * See if the last group is big enough to support the
70 * necessary data structures. If not, we need to get rid of
73 rem = (fs->super->s_blocks_count - fs->super->s_first_data_block) %
74 fs->super->s_blocks_per_group;
75 if ((fs->group_desc_count == 1) && rem && (rem < overhead))
76 return EXT2_ET_TOOSMALL;
77 if (rem && (rem < overhead+50)) {
78 fs->super->s_blocks_count -= rem;
82 * Adjust the number of inodes
84 fs->super->s_inodes_count = fs->super->s_inodes_per_group *
88 * Adjust the number of free blocks
90 blk = rfs->old_fs->super->s_blocks_count;
91 if (blk > fs->super->s_blocks_count)
92 fs->super->s_free_blocks_count -=
93 (blk - fs->super->s_blocks_count);
95 fs->super->s_free_blocks_count +=
96 (fs->super->s_blocks_count - blk);
99 * Adjust the bitmaps for size
101 retval = ext2fs_resize_inode_bitmap(fs->super->s_inodes_count,
102 fs->super->s_inodes_count,
107 real_end = ((EXT2_BLOCKS_PER_GROUP(fs->super)
108 * fs->group_desc_count)) - 1 +
109 fs->super->s_first_data_block;
110 retval = ext2fs_resize_block_bitmap(fs->super->s_blocks_count-1,
111 real_end, fs->block_map);
117 * Reallocate the group descriptors as necessary.
119 if (rfs->old_fs->desc_blocks != fs->desc_blocks) {
120 new = realloc(fs->group_desc,
121 fs->desc_blocks * fs->blocksize);
124 fs->group_desc = new;
128 * Fix the count of the last (old) block group
130 if (rfs->old_fs->group_desc_count > fs->group_desc_count)
132 old_numblocks = (rfs->old_fs->super->s_blocks_count -
133 rfs->old_fs->super->s_first_data_block) %
134 rfs->old_fs->super->s_blocks_per_group;
136 old_numblocks = rfs->old_fs->super->s_blocks_per_group;
137 if (rfs->old_fs->group_desc_count == fs->group_desc_count) {
138 numblocks = (rfs->new_fs->super->s_blocks_count -
139 rfs->new_fs->super->s_first_data_block) %
140 rfs->new_fs->super->s_blocks_per_group;
142 numblocks = rfs->new_fs->super->s_blocks_per_group;
144 numblocks = rfs->new_fs->super->s_blocks_per_group;
145 i = rfs->old_fs->group_desc_count - 1;
146 fs->group_desc[i].bg_free_blocks_count += (numblocks-old_numblocks);
149 * Initialize the new block group descriptors
151 if (rfs->old_fs->group_desc_count >= fs->group_desc_count)
153 rfs->itable_buf = malloc(fs->blocksize * fs->inode_blocks_per_group);
154 if (!rfs->itable_buf)
156 memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group);
157 group_block = fs->super->s_first_data_block +
158 rfs->old_fs->group_desc_count * fs->super->s_blocks_per_group;
159 for (i = rfs->old_fs->group_desc_count;
160 i < fs->group_desc_count; i++) {
161 memset(&fs->group_desc[i], 0,
162 sizeof(struct ext2_group_desc));
165 if (i == fs->group_desc_count-1) {
166 numblocks = (fs->super->s_blocks_count -
167 fs->super->s_first_data_block) %
168 fs->super->s_blocks_per_group;
170 numblocks = fs->super->s_blocks_per_group;
172 numblocks = fs->super->s_blocks_per_group;
174 if (ext2fs_bg_has_super(fs, i)) {
175 for (j=0; j < fs->desc_blocks+1; j++)
176 ext2fs_mark_block_bitmap(fs->block_map,
178 adjblocks = 1 + fs->desc_blocks;
180 adjblocks += 2 + fs->inode_blocks_per_group;
182 numblocks -= adjblocks;
183 fs->super->s_free_blocks_count -= adjblocks;
184 fs->super->s_free_inodes_count +=
185 fs->super->s_inodes_per_group;
186 fs->group_desc[i].bg_free_blocks_count = numblocks;
187 fs->group_desc[i].bg_free_inodes_count =
188 fs->super->s_inodes_per_group;
189 fs->group_desc[i].bg_used_dirs_count = 0;
191 retval = ext2fs_allocate_group_table(fs, i, 0);
196 * Write out the new inode table
198 retval = io_channel_write_blk(fs->io,
199 fs->group_desc[i].bg_inode_table,
200 fs->inode_blocks_per_group,
205 group_block += fs->super->s_blocks_per_group;
211 * This routine marks and unmarks reserved blocks in the new block
212 * bitmap. It also determines which blocks need to be moved and
213 * places this information into the move_blocks bitmap.
215 static errcode_t determine_relocations(ext2_resize_t rfs)
218 blk_t blk, group_blk;
219 unsigned long old_blocks, new_blocks;
221 ext2_filsys fs = rfs->new_fs;
223 retval = ext2fs_allocate_block_bitmap(rfs->old_fs,
224 "blocks to be moved",
225 &rfs->reserve_blocks);
230 * If we're shrinking the filesystem, we need to move all of
231 * the blocks that don't fit any more
233 for (blk = fs->super->s_blocks_count;
234 blk < rfs->old_fs->super->s_blocks_count; blk++) {
235 if (ext2fs_test_block_bitmap(rfs->old_fs->block_map, blk))
236 rfs->needed_blocks++;
237 ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk);
240 old_blocks = rfs->old_fs->desc_blocks;
241 new_blocks = fs->desc_blocks;
243 if (old_blocks == new_blocks)
246 max = fs->group_desc_count;
247 if (max > rfs->old_fs->group_desc_count)
248 max = rfs->old_fs->group_desc_count;
249 group_blk = rfs->old_fs->super->s_first_data_block;
251 * If we're reducing the number of descriptor blocks, this
252 * makes life easy. :-) We just have to mark some extra
255 if (old_blocks > new_blocks) {
256 for (i = 0; i < max; i++) {
257 if (!ext2fs_bg_has_super(fs, i)) {
258 group_blk += fs->super->s_blocks_per_group;
261 for (blk = group_blk+1+old_blocks;
262 blk < group_blk+1+new_blocks; blk++) {
263 ext2fs_unmark_block_bitmap(fs->block_map,
265 rfs->needed_blocks--;
267 group_blk += fs->super->s_blocks_per_group;
272 * If we're increasing the number of descriptor blocks, life
273 * gets interesting....
275 for (i = 0; i < max; i++) {
276 if (!ext2fs_bg_has_super(fs, i))
279 for (blk = group_blk;
280 blk < group_blk + 1 + new_blocks; blk++) {
281 ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk);
282 ext2fs_mark_block_bitmap(fs->block_map, blk);
285 * Check to see if we overlap with the inode
288 if (blk == fs->group_desc[i].bg_block_bitmap) {
289 fs->group_desc[i].bg_block_bitmap = 0;
290 rfs->needed_blocks++;
292 if (blk == fs->group_desc[i].bg_inode_bitmap) {
293 fs->group_desc[i].bg_inode_bitmap = 0;
294 rfs->needed_blocks++;
297 * Check to see if we overlap with the inode
300 if (blk < fs->group_desc[i].bg_inode_table)
302 if (blk >= (fs->group_desc[i].bg_inode_table +
303 fs->inode_blocks_per_group))
305 blk = fs->group_desc[i].bg_inode_table +
306 fs->inode_blocks_per_group - 1;
307 fs->group_desc[i].bg_inode_table = 0;
309 if (fs->group_desc[i].bg_inode_table &&
310 fs->group_desc[i].bg_inode_bitmap &&
311 fs->group_desc[i].bg_block_bitmap)
315 * Allocate the missing bitmap and inode table
316 * structures, passing in rfs->reserve_blocks to
317 * prevent a conflict.
319 if (fs->group_desc[i].bg_block_bitmap)
320 ext2fs_mark_block_bitmap(rfs->reserve_blocks,
321 fs->group_desc[i].bg_block_bitmap);
322 if (fs->group_desc[i].bg_inode_bitmap)
323 ext2fs_mark_block_bitmap(rfs->reserve_blocks,
324 fs->group_desc[i].bg_inode_bitmap);
325 if (fs->group_desc[i].bg_inode_table)
326 for (blk = fs->group_desc[i].bg_inode_table, j=0;
327 j < fs->inode_blocks_per_group ; j++, blk++)
328 ext2fs_mark_block_bitmap(rfs->reserve_blocks,
331 retval = ext2fs_allocate_group_table(fs, i,
332 rfs->reserve_blocks);
337 * Now make sure these blocks are reserved in the new
340 ext2fs_mark_block_bitmap(fs->block_map,
341 fs->group_desc[i].bg_block_bitmap);
342 ext2fs_mark_block_bitmap(fs->block_map,
343 fs->group_desc[i].bg_inode_bitmap);
346 * The inode table, if we need to relocate it, is
347 * handled specially. We have to reserve the blocks
348 * for both the old and the new inode table, since we
349 * can't have the inode table be destroyed during the
350 * block relocation phase.
352 adj = fs->group_desc[i].bg_inode_table -
353 rfs->old_fs->group_desc[i].bg_inode_table;
355 goto next_group; /* inode table not moved */
358 * Figure out how many blocks we need to have free.
359 * This takes into account that we need to reserve
360 * both inode tables, which may be overallping.
364 if (adj > fs->inode_blocks_per_group)
365 adj = fs->inode_blocks_per_group;
366 rfs->needed_blocks += fs->inode_blocks_per_group + adj;
369 * Mark the new inode table as in use in the new block
372 for (blk = fs->group_desc[i].bg_inode_table, j=0;
373 j < fs->inode_blocks_per_group ; j++, blk++)
374 ext2fs_mark_block_bitmap(fs->block_map, blk);
376 * Make sure the old inode table is reserved in the
377 * block reservation bitmap.
379 for (blk = rfs->old_fs->group_desc[i].bg_inode_table, j=0;
380 j < fs->inode_blocks_per_group ; j++, blk++)
381 ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk);
384 group_blk += rfs->new_fs->super->s_blocks_per_group;
391 * A very scary routine --- this one moves the inode table around!!!
393 * After this you have to use the rfs->new_fs file handle to read and
396 errcode_t move_itables(ext2_resize_t rfs)
398 int i, n, num, max, size, diff;
399 ext2_filsys fs = rfs->new_fs;
402 errcode_t retval, err;
404 max = fs->group_desc_count;
405 if (max > rfs->old_fs->group_desc_count)
406 max = rfs->old_fs->group_desc_count;
408 size = fs->blocksize * fs->inode_blocks_per_group;
409 if (!rfs->itable_buf) {
410 rfs->itable_buf = malloc(size);
411 if (!rfs->itable_buf)
415 for (i=0; i < max; i++) {
416 old = rfs->old_fs->group_desc[i].bg_inode_table;
417 new = fs->group_desc[i].bg_inode_table;
420 if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
421 printf("Itable move group %d block "
422 "%ld->%ld (diff %d)\n",
428 retval = io_channel_read_blk(fs->io, old,
429 fs->inode_blocks_per_group,
434 * The end of the inode table segment often contains
435 * all zeros. Find out if we have several blocks of
436 * zeros so we can optimize the write.
438 for (cp = rfs->itable_buf+size, n=0; n < size; n++, cp--)
441 n = n >> EXT2_BLOCK_SIZE_BITS(fs->super);
442 if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
443 printf("%d blocks of zeros...\n", n);
444 num = fs->inode_blocks_per_group;
448 retval = io_channel_write_blk(fs->io, new,
449 num, rfs->itable_buf);
451 io_channel_write_blk(fs->io, old,
452 num, rfs->itable_buf);
456 retval = io_channel_write_blk(fs->io,
457 old + fs->inode_blocks_per_group,
458 diff, rfs->itable_buf - fs->blocksize * diff);
462 io_channel_flush(fs->io);
464 ext2fs_flush(rfs->new_fs);
465 if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
466 printf("Inode table move finished.\n");
470 if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
471 printf("Error: %s; now backing out!\n", error_message(retval));
473 if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
474 printf("Group %d block %ld->%ld\n", i, new, old);
475 old = rfs->old_fs->group_desc[i].bg_inode_table;
476 new = fs->group_desc[i].bg_inode_table;
478 err = io_channel_read_blk(fs->io, new,
479 fs->inode_blocks_per_group,
483 err = io_channel_write_blk(fs->io, old,
484 fs->inode_blocks_per_group,
491 * Finally, recalculate the summary information
493 static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs)
503 * First calculate the block statistics
505 for (blk = fs->super->s_first_data_block;
506 blk < fs->super->s_blocks_count; blk++) {
507 if (!ext2fs_fast_test_block_bitmap(fs->block_map, blk)) {
512 if ((count == fs->super->s_blocks_per_group) ||
513 (blk == fs->super->s_blocks_count-1)) {
514 fs->group_desc[group++].bg_free_blocks_count =
520 fs->super->s_free_blocks_count = total_free;
523 * Next, calculate the inode statistics
529 for (ino = 1; ino <= fs->super->s_inodes_count; ino++) {
530 if (!ext2fs_fast_test_inode_bitmap(fs->inode_map, ino)) {
535 if ((count == fs->super->s_inodes_per_group) ||
536 (ino == fs->super->s_inodes_count)) {
537 fs->group_desc[group++].bg_free_inodes_count =
543 fs->super->s_free_inodes_count = total_free;
544 ext2fs_mark_super_dirty(fs);
551 * This is the top-level routine which does the dirty deed....
553 errcode_t resize_fs(ext2_filsys fs, blk_t new_size, int flags)
559 retval = ext2fs_read_bitmaps(fs);
564 * Create the data structure
566 rfs = malloc(sizeof(struct ext2_resize_struct));
569 memset(rfs, 0, sizeof(struct ext2_resize_struct));
574 retval = ext2fs_dup_handle(fs, &rfs->new_fs);
578 retval = adjust_superblock(rfs, new_size);
582 retval = determine_relocations(rfs);
586 if (rfs->flags & RESIZE_DEBUG_BMOVE)
587 printf("Number of free blocks: %d, Needed: %d\n",
588 fs->super->s_free_blocks_count, rfs->needed_blocks);
590 if (rfs->needed_blocks > fs->super->s_free_blocks_count) {
595 bmove_flags = EXT2_BMOVE_GET_DBLIST;
596 if (rfs->flags & RESIZE_DEBUG_BMOVE)
597 bmove_flags |= EXT2_BMOVE_DEBUG;
598 retval = ext2fs_move_blocks(rfs->old_fs, rfs->reserve_blocks,
599 rfs->new_fs->block_map, bmove_flags);
603 retval = ext2fs_inode_move(rfs);
607 retval = move_itables(rfs);
611 retval = ext2fs_calculate_summary_stats(rfs->new_fs);
615 retval = ext2fs_close(rfs->new_fs);
621 ext2fs_free(rfs->old_fs);
623 free(rfs->itable_buf);
630 ext2fs_free(rfs->new_fs);
632 free(rfs->itable_buf);