Whamcloud - gitweb
Fix 32-bit overflow problems: dgrp_t * s_blocks_per_group
[tools/e2fsprogs.git] / resize / resize2fs.c
1 /*
2  * resize2fs.c --- ext2 main routine
3  *
4  * Copyright (C) 1997, 1998 by Theodore Ts'o and
5  *      PowerQuest, Inc.
6  *
7  * Copyright (C) 1999, 2000 by Theosore Ts'o
8  *
9  * %Begin-Header%
10  * This file may be redistributed under the terms of the GNU Public
11  * License.
12  * %End-Header%
13  */
14
15 /*
16  * Resizing a filesystem consists of the following phases:
17  *
18  *      1.  Adjust superblock and write out new parts of the inode
19  *              table
20  *      2.  Determine blocks which need to be relocated, and copy the
21  *              contents of blocks from their old locations to the new ones.
22  *      3.  Scan the inode table, doing the following:
23  *              a.  If blocks have been moved, update the block
24  *                      pointers in the inodes and indirect blocks to
25  *                      point at the new block locations.
26  *              b.  If parts of the inode table need to be evacuated,
27  *                      copy inodes from their old locations to their
28  *                      new ones.
29  *              c.  If (b) needs to be done, note which blocks contain
30  *                      directory information, since we will need to
31  *                      update the directory information.
32  *      4.  Update the directory blocks with the new inode locations.
33  *      5.  Move the inode tables, if necessary.
34  */
35
36 #include "config.h"
37 #include "resize2fs.h"
38 #include <time.h>
39
40 #ifdef __linux__                        /* Kludge for debugging */
41 #define RESIZE2FS_DEBUG
42 #endif
43
44 static void fix_uninit_block_bitmaps(ext2_filsys fs);
45 static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size);
46 static errcode_t blocks_to_move(ext2_resize_t rfs);
47 static errcode_t block_mover(ext2_resize_t rfs);
48 static errcode_t inode_scan_and_fix(ext2_resize_t rfs);
49 static errcode_t inode_ref_fix(ext2_resize_t rfs);
50 static errcode_t move_itables(ext2_resize_t rfs);
51 static errcode_t fix_resize_inode(ext2_filsys fs);
52 static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs);
53 static errcode_t fix_sb_journal_backup(ext2_filsys fs);
54
55 /*
56  * Some helper CPP macros
57  */
58 #define IS_BLOCK_BM(fs, i, blk) ((blk) == ext2fs_block_bitmap_loc((fs),(i)))
59 #define IS_INODE_BM(fs, i, blk) ((blk) == ext2fs_inode_bitmap_loc((fs),(i)))
60
61 #define IS_INODE_TB(fs, i, blk) (((blk) >= ext2fs_inode_table_loc((fs), (i))) && \
62                                  ((blk) < (ext2fs_inode_table_loc((fs), (i)) + \
63                                            (fs)->inode_blocks_per_group)))
64
65 int lazy_itable_init;
66
67 /*
68  * This is the top-level routine which does the dirty deed....
69  */
70 errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
71             errcode_t (*progress)(ext2_resize_t rfs, int pass,
72                                           unsigned long cur,
73                                           unsigned long max_val))
74 {
75         ext2_resize_t   rfs;
76         errcode_t       retval;
77         struct resource_track   rtrack, overall_track;
78
79         /*
80          * Create the data structure
81          */
82         retval = ext2fs_get_mem(sizeof(struct ext2_resize_struct), &rfs);
83         if (retval)
84                 return retval;
85
86         memset(rfs, 0, sizeof(struct ext2_resize_struct));
87         fs->priv_data = rfs;
88         rfs->old_fs = fs;
89         rfs->flags = flags;
90         rfs->itable_buf  = 0;
91         rfs->progress = progress;
92
93         init_resource_track(&overall_track, "overall resize2fs", fs->io);
94         init_resource_track(&rtrack, "read_bitmaps", fs->io);
95         retval = ext2fs_read_bitmaps(fs);
96         if (retval)
97                 goto errout;
98         print_resource_track(rfs, &rtrack, fs->io);
99
100         fs->super->s_state |= EXT2_ERROR_FS;
101         ext2fs_mark_super_dirty(fs);
102         ext2fs_flush(fs);
103
104         init_resource_track(&rtrack, "fix_uninit_block_bitmaps 1", fs->io);
105         fix_uninit_block_bitmaps(fs);
106         print_resource_track(rfs, &rtrack, fs->io);
107         retval = ext2fs_dup_handle(fs, &rfs->new_fs);
108         if (retval)
109                 goto errout;
110
111         init_resource_track(&rtrack, "adjust_superblock", fs->io);
112         retval = adjust_superblock(rfs, *new_size);
113         if (retval)
114                 goto errout;
115         print_resource_track(rfs, &rtrack, fs->io);
116
117
118         init_resource_track(&rtrack, "fix_uninit_block_bitmaps 2", fs->io);
119         fix_uninit_block_bitmaps(rfs->new_fs);
120         print_resource_track(rfs, &rtrack, fs->io);
121         /* Clear the block bitmap uninit flag for the last block group */
122         ext2fs_bg_flags_clear(rfs->new_fs, rfs->new_fs->group_desc_count - 1,
123                              EXT2_BG_BLOCK_UNINIT);
124
125         *new_size = ext2fs_blocks_count(rfs->new_fs->super);
126
127         init_resource_track(&rtrack, "blocks_to_move", fs->io);
128         retval = blocks_to_move(rfs);
129         if (retval)
130                 goto errout;
131         print_resource_track(rfs, &rtrack, fs->io);
132
133 #ifdef RESIZE2FS_DEBUG
134         if (rfs->flags & RESIZE_DEBUG_BMOVE)
135                 printf("Number of free blocks: %llu/%llu, Needed: %llu\n",
136                        ext2fs_free_blocks_count(rfs->old_fs->super),
137                        ext2fs_free_blocks_count(rfs->new_fs->super),
138                        rfs->needed_blocks);
139 #endif
140
141         init_resource_track(&rtrack, "block_mover", fs->io);
142         retval = block_mover(rfs);
143         if (retval)
144                 goto errout;
145         print_resource_track(rfs, &rtrack, fs->io);
146
147         init_resource_track(&rtrack, "inode_scan_and_fix", fs->io);
148         retval = inode_scan_and_fix(rfs);
149         if (retval)
150                 goto errout;
151         print_resource_track(rfs, &rtrack, fs->io);
152
153         init_resource_track(&rtrack, "inode_ref_fix", fs->io);
154         retval = inode_ref_fix(rfs);
155         if (retval)
156                 goto errout;
157         print_resource_track(rfs, &rtrack, fs->io);
158
159         init_resource_track(&rtrack, "move_itables", fs->io);
160         retval = move_itables(rfs);
161         if (retval)
162                 goto errout;
163         print_resource_track(rfs, &rtrack, fs->io);
164
165         init_resource_track(&rtrack, "calculate_summary_stats", fs->io);
166         retval = ext2fs_calculate_summary_stats(rfs->new_fs);
167         if (retval)
168                 goto errout;
169         print_resource_track(rfs, &rtrack, fs->io);
170
171         init_resource_track(&rtrack, "fix_resize_inode", fs->io);
172         retval = fix_resize_inode(rfs->new_fs);
173         if (retval)
174                 goto errout;
175         print_resource_track(rfs, &rtrack, fs->io);
176
177         init_resource_track(&rtrack, "fix_sb_journal_backup", fs->io);
178         retval = fix_sb_journal_backup(rfs->new_fs);
179         if (retval)
180                 goto errout;
181         print_resource_track(rfs, &rtrack, fs->io);
182
183         rfs->new_fs->super->s_state &= ~EXT2_ERROR_FS;
184         rfs->new_fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
185
186         print_resource_track(rfs, &overall_track, fs->io);
187         retval = ext2fs_close(rfs->new_fs);
188         if (retval)
189                 goto errout;
190
191         rfs->flags = flags;
192
193         ext2fs_free(rfs->old_fs);
194         if (rfs->itable_buf)
195                 ext2fs_free_mem(&rfs->itable_buf);
196         if (rfs->reserve_blocks)
197                 ext2fs_free_block_bitmap(rfs->reserve_blocks);
198         if (rfs->move_blocks)
199                 ext2fs_free_block_bitmap(rfs->move_blocks);
200         ext2fs_free_mem(&rfs);
201
202         return 0;
203
204 errout:
205         if (rfs->new_fs)
206                 ext2fs_free(rfs->new_fs);
207         if (rfs->itable_buf)
208                 ext2fs_free_mem(&rfs->itable_buf);
209         ext2fs_free_mem(&rfs);
210         return retval;
211 }
212
213 /*
214  * Clean up the bitmaps for unitialized bitmaps
215  */
216 static void fix_uninit_block_bitmaps(ext2_filsys fs)
217 {
218         blk64_t         blk, lblk;
219         dgrp_t          g;
220         int             i;
221
222         if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
223                                          EXT4_FEATURE_RO_COMPAT_GDT_CSUM)))
224                 return;
225
226         for (g=0; g < fs->group_desc_count; g++) {
227                 if (!(ext2fs_bg_flags_test(fs, g, EXT2_BG_BLOCK_UNINIT)))
228                         continue;
229
230                 blk = ext2fs_group_first_block2(fs, g);
231                 lblk = ext2fs_group_last_block2(fs, g);
232                 ext2fs_unmark_block_bitmap_range2(fs->block_map, blk,
233                                                   lblk - blk + 1);
234
235                 ext2fs_reserve_super_and_bgd(fs, g, fs->block_map);
236                 ext2fs_mark_block_bitmap2(fs->block_map,
237                                           ext2fs_block_bitmap_loc(fs, g));
238                 ext2fs_mark_block_bitmap2(fs->block_map,
239                                           ext2fs_inode_bitmap_loc(fs, g));
240                 for (i = 0, blk = ext2fs_inode_table_loc(fs, g);
241                      i < (unsigned int) fs->inode_blocks_per_group;
242                      i++, blk++)
243                         ext2fs_mark_block_bitmap2(fs->block_map, blk);
244         }
245 }
246
247 /* --------------------------------------------------------------------
248  *
249  * Resize processing, phase 1.
250  *
251  * In this phase we adjust the in-memory superblock information, and
252  * initialize any new parts of the inode table.  The new parts of the
253  * inode table are created in virgin disk space, so we can abort here
254  * without any side effects.
255  * --------------------------------------------------------------------
256  */
257
258 /*
259  * If the group descriptor's bitmap and inode table blocks are valid,
260  * release them in the new filesystem data structure, and mark them as
261  * reserved so the old inode table blocks don't get overwritten.
262  */
263 static void free_gdp_blocks(ext2_filsys fs,
264                             ext2fs_block_bitmap reserve_blocks,
265                             struct ext2_group_desc *gdp)
266 {
267         blk_t   blk;
268         int     j;
269
270         if (gdp->bg_block_bitmap &&
271             (gdp->bg_block_bitmap < ext2fs_blocks_count(fs->super))) {
272                 ext2fs_block_alloc_stats(fs, gdp->bg_block_bitmap, -1);
273                 ext2fs_mark_block_bitmap2(reserve_blocks,
274                                          gdp->bg_block_bitmap);
275         }
276
277         if (gdp->bg_inode_bitmap &&
278             (gdp->bg_inode_bitmap < ext2fs_blocks_count(fs->super))) {
279                 ext2fs_block_alloc_stats(fs, gdp->bg_inode_bitmap, -1);
280                 ext2fs_mark_block_bitmap2(reserve_blocks,
281                                          gdp->bg_inode_bitmap);
282         }
283
284         if (gdp->bg_inode_table == 0 ||
285             (gdp->bg_inode_table >= ext2fs_blocks_count(fs->super)))
286                 return;
287
288         for (blk = gdp->bg_inode_table, j = 0;
289              j < fs->inode_blocks_per_group; j++, blk++) {
290                 if (blk >= ext2fs_blocks_count(fs->super))
291                         break;
292                 ext2fs_block_alloc_stats(fs, blk, -1);
293                 ext2fs_mark_block_bitmap2(reserve_blocks, blk);
294         }
295 }
296
297 /*
298  * This routine is shared by the online and offline resize routines.
299  * All of the information which is adjusted in memory is done here.
300  *
301  * The reserve_blocks parameter is only needed when shrinking the
302  * filesystem.
303  */
304 errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
305                          ext2fs_block_bitmap reserve_blocks, blk64_t new_size)
306 {
307         errcode_t       retval;
308         blk64_t         overhead = 0;
309         blk64_t         rem;
310         blk64_t         blk, group_block;
311         blk64_t         real_end;
312         blk64_t         old_numblocks, numblocks, adjblocks;
313         unsigned long   i, j, old_desc_blocks;
314         unsigned int    meta_bg, meta_bg_size;
315         int             has_super, csum_flag;
316         unsigned long long new_inodes;  /* u64 to check for overflow */
317         double          percent;
318
319         ext2fs_blocks_count_set(fs->super, new_size);
320
321 retry:
322         fs->group_desc_count = ext2fs_div64_ceil(ext2fs_blocks_count(fs->super) -
323                                        fs->super->s_first_data_block,
324                                        EXT2_BLOCKS_PER_GROUP(fs->super));
325         if (fs->group_desc_count == 0)
326                 return EXT2_ET_TOOSMALL;
327         fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
328                                           EXT2_DESC_PER_BLOCK(fs->super));
329
330         /*
331          * Overhead is the number of bookkeeping blocks per group.  It
332          * includes the superblock backup, the group descriptor
333          * backups, the inode bitmap, the block bitmap, and the inode
334          * table.
335          */
336         overhead = (int) (2 + fs->inode_blocks_per_group);
337
338         if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1))
339                 overhead += 1 + fs->desc_blocks +
340                         fs->super->s_reserved_gdt_blocks;
341
342         /*
343          * See if the last group is big enough to support the
344          * necessary data structures.  If not, we need to get rid of
345          * it.
346          */
347         rem = (ext2fs_blocks_count(fs->super) - fs->super->s_first_data_block) %
348                 fs->super->s_blocks_per_group;
349         if ((fs->group_desc_count == 1) && rem && (rem < overhead))
350                 return EXT2_ET_TOOSMALL;
351         if ((fs->group_desc_count > 1) && rem && (rem < overhead+50)) {
352                 ext2fs_blocks_count_set(fs->super,
353                                         ext2fs_blocks_count(fs->super) - rem);
354                 goto retry;
355         }
356         /*
357          * Adjust the number of inodes
358          */
359         new_inodes =(unsigned long long) fs->super->s_inodes_per_group * fs->group_desc_count;
360         if (new_inodes > ~0U) {
361                 fprintf(stderr, _("inodes (%llu) must be less than %u"),
362                                    new_inodes, ~0U);
363                 return EXT2_ET_TOO_MANY_INODES;
364         }
365         fs->super->s_inodes_count = fs->super->s_inodes_per_group *
366                 fs->group_desc_count;
367
368         /*
369          * Adjust the number of free blocks
370          */
371         blk = ext2fs_blocks_count(old_fs->super);
372         if (blk > ext2fs_blocks_count(fs->super))
373                 ext2fs_free_blocks_count_set(fs->super, 
374                         ext2fs_free_blocks_count(fs->super) -
375                         (blk - ext2fs_blocks_count(fs->super)));
376         else
377                 ext2fs_free_blocks_count_set(fs->super, 
378                         ext2fs_free_blocks_count(fs->super) +
379                         (ext2fs_blocks_count(fs->super) - blk));
380
381         /*
382          * Adjust the number of reserved blocks
383          */
384         percent = (ext2fs_r_blocks_count(old_fs->super) * 100.0) /
385                 ext2fs_blocks_count(old_fs->super);
386         ext2fs_r_blocks_count_set(fs->super,
387                                   (percent * ext2fs_blocks_count(fs->super) /
388                                    100.0));
389
390         /*
391          * Adjust the bitmaps for size
392          */
393         retval = ext2fs_resize_inode_bitmap2(fs->super->s_inodes_count,
394                                             fs->super->s_inodes_count,
395                                             fs->inode_map);
396         if (retval) goto errout;
397
398         real_end = (((blk64_t) EXT2_BLOCKS_PER_GROUP(fs->super) *
399                      fs->group_desc_count)) - 1 +
400                 fs->super->s_first_data_block;
401         retval = ext2fs_resize_block_bitmap2(ext2fs_blocks_count(fs->super)-1,
402                                             real_end, fs->block_map);
403
404         if (retval) goto errout;
405
406         /*
407          * Reallocate the group descriptors as necessary.
408          */
409         if (old_fs->desc_blocks != fs->desc_blocks) {
410                 retval = ext2fs_resize_mem(old_fs->desc_blocks *
411                                            fs->blocksize,
412                                            fs->desc_blocks * fs->blocksize,
413                                            &fs->group_desc);
414                 if (retval)
415                         goto errout;
416                 if (fs->desc_blocks > old_fs->desc_blocks)
417                         memset((char *) fs->group_desc +
418                                (old_fs->desc_blocks * fs->blocksize), 0,
419                                (fs->desc_blocks - old_fs->desc_blocks) *
420                                fs->blocksize);
421         }
422
423         /*
424          * If the resize_inode feature is set, and we are changing the
425          * number of descriptor blocks, then adjust
426          * s_reserved_gdt_blocks if possible to avoid needing to move
427          * the inode table either now or in the future.
428          */
429         if ((fs->super->s_feature_compat &
430              EXT2_FEATURE_COMPAT_RESIZE_INODE) &&
431             (old_fs->desc_blocks != fs->desc_blocks)) {
432                 int new;
433
434                 new = ((int) fs->super->s_reserved_gdt_blocks) +
435                         (old_fs->desc_blocks - fs->desc_blocks);
436                 if (new < 0)
437                         new = 0;
438                 if (new > (int) fs->blocksize/4)
439                         new = fs->blocksize/4;
440                 fs->super->s_reserved_gdt_blocks = new;
441         }
442
443         /*
444          * If we are shrinking the number of block groups, we're done
445          * and can exit now.
446          */
447         if (old_fs->group_desc_count > fs->group_desc_count) {
448                 /*
449                  * Check the block groups that we are chopping off
450                  * and free any blocks associated with their metadata
451                  */
452                 for (i = fs->group_desc_count;
453                      i < old_fs->group_desc_count; i++) {
454                         free_gdp_blocks(fs, reserve_blocks,
455                                         ext2fs_group_desc(old_fs,
456                                                 old_fs->group_desc, i));
457                 }
458                 retval = 0;
459                 goto errout;
460         }
461
462         /*
463          * Fix the count of the last (old) block group
464          */
465         old_numblocks = (ext2fs_blocks_count(old_fs->super) -
466                          old_fs->super->s_first_data_block) %
467                                  old_fs->super->s_blocks_per_group;
468         if (!old_numblocks)
469                 old_numblocks = old_fs->super->s_blocks_per_group;
470         if (old_fs->group_desc_count == fs->group_desc_count) {
471                 numblocks = (ext2fs_blocks_count(fs->super) -
472                              fs->super->s_first_data_block) %
473                         fs->super->s_blocks_per_group;
474                 if (!numblocks)
475                         numblocks = fs->super->s_blocks_per_group;
476         } else
477                 numblocks = fs->super->s_blocks_per_group;
478         i = old_fs->group_desc_count - 1;
479         ext2fs_bg_free_blocks_count_set(fs, i, ext2fs_bg_free_blocks_count(fs, i) + (numblocks - old_numblocks));
480         ext2fs_group_desc_csum_set(fs, i);
481
482         /*
483          * If the number of block groups is staying the same, we're
484          * done and can exit now.  (If the number block groups is
485          * shrinking, we had exited earlier.)
486          */
487         if (old_fs->group_desc_count >= fs->group_desc_count) {
488                 retval = 0;
489                 goto errout;
490         }
491
492         /*
493          * Initialize the new block group descriptors
494          */
495         group_block = ext2fs_group_first_block2(fs,
496                                                 old_fs->group_desc_count);
497         csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
498                                                EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
499         if (access("/sys/fs/ext4/features/lazy_itable_init", F_OK) == 0)
500                 lazy_itable_init = 1;
501         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
502                 old_desc_blocks = fs->super->s_first_meta_bg;
503         else
504                 old_desc_blocks = fs->desc_blocks +
505                         fs->super->s_reserved_gdt_blocks;
506         for (i = old_fs->group_desc_count;
507              i < fs->group_desc_count; i++) {
508                 memset(ext2fs_group_desc(fs, fs->group_desc, i), 0,
509                        sizeof(struct ext2_group_desc));
510                 adjblocks = 0;
511
512                 ext2fs_bg_flags_zap(fs, i);
513                 if (csum_flag) {
514                         ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
515                         if (!lazy_itable_init)
516                                 ext2fs_bg_flags_set(fs, i,
517                                                     EXT2_BG_INODE_ZEROED);
518                         ext2fs_bg_itable_unused_set(fs, i,
519                                         fs->super->s_inodes_per_group);
520                 }
521
522                 numblocks = ext2fs_group_blocks_count(fs, i);
523                 if ((i < fs->group_desc_count - 1) && csum_flag)
524                         ext2fs_bg_flags_set(fs, i, EXT2_BG_BLOCK_UNINIT);
525
526                 has_super = ext2fs_bg_has_super(fs, i);
527                 if (has_super) {
528                         ext2fs_block_alloc_stats2(fs, group_block, +1);
529                         adjblocks++;
530                 }
531                 meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
532                 meta_bg = i / meta_bg_size;
533                 if (!(fs->super->s_feature_incompat &
534                       EXT2_FEATURE_INCOMPAT_META_BG) ||
535                     (meta_bg < fs->super->s_first_meta_bg)) {
536                         if (has_super) {
537                                 for (j=0; j < old_desc_blocks; j++)
538                                         ext2fs_block_alloc_stats2(fs,
539                                                  group_block + 1 + j, +1);
540                                 adjblocks += old_desc_blocks;
541                         }
542                 } else {
543                         if (has_super)
544                                 has_super = 1;
545                         if (((i % meta_bg_size) == 0) ||
546                             ((i % meta_bg_size) == 1) ||
547                             ((i % meta_bg_size) == (meta_bg_size-1)))
548                                 ext2fs_block_alloc_stats2(fs,
549                                                  group_block + has_super, +1);
550                 }
551
552                 adjblocks += 2 + fs->inode_blocks_per_group;
553
554                 numblocks -= adjblocks;
555                 ext2fs_free_blocks_count_set(fs->super,
556                              ext2fs_free_blocks_count(fs->super) - adjblocks);
557                 fs->super->s_free_inodes_count +=
558                         fs->super->s_inodes_per_group;
559                 ext2fs_bg_free_blocks_count_set(fs, i, numblocks);
560                 ext2fs_bg_free_inodes_count_set(fs, i,
561                                                 fs->super->s_inodes_per_group);
562                 ext2fs_bg_used_dirs_count_set(fs, i, 0);
563                 ext2fs_group_desc_csum_set(fs, i);
564
565                 retval = ext2fs_allocate_group_table(fs, i, 0);
566                 if (retval) goto errout;
567
568                 group_block += fs->super->s_blocks_per_group;
569         }
570         retval = 0;
571
572 errout:
573         return (retval);
574 }
575
576 /*
577  * This routine adjusts the superblock and other data structures, both
578  * in disk as well as in memory...
579  */
580 static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
581 {
582         ext2_filsys fs;
583         int             adj = 0;
584         errcode_t       retval;
585         blk64_t         group_block;
586         unsigned long   i;
587         unsigned long   max_group;
588
589         fs = rfs->new_fs;
590         ext2fs_mark_super_dirty(fs);
591         ext2fs_mark_bb_dirty(fs);
592         ext2fs_mark_ib_dirty(fs);
593
594         retval = ext2fs_allocate_block_bitmap(fs, _("reserved blocks"),
595                                               &rfs->reserve_blocks);
596         if (retval)
597                 return retval;
598
599         retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size);
600         if (retval)
601                 goto errout;
602
603         /*
604          * Check to make sure there are enough inodes
605          */
606         if ((rfs->old_fs->super->s_inodes_count -
607              rfs->old_fs->super->s_free_inodes_count) >
608             rfs->new_fs->super->s_inodes_count) {
609                 retval = ENOSPC;
610                 goto errout;
611         }
612
613         /*
614          * If we are shrinking the number block groups, we're done and
615          * can exit now.
616          */
617         if (rfs->old_fs->group_desc_count > fs->group_desc_count) {
618                 retval = 0;
619                 goto errout;
620         }
621
622         /*
623          * If the number of block groups is staying the same, we're
624          * done and can exit now.  (If the number block groups is
625          * shrinking, we had exited earlier.)
626          */
627         if (rfs->old_fs->group_desc_count >= fs->group_desc_count) {
628                 retval = 0;
629                 goto errout;
630         }
631
632         /*
633          * If we are using uninit_bg (aka GDT_CSUM) and the kernel
634          * supports lazy inode initialization, we can skip
635          * initializing the inode table.
636          */
637         if (lazy_itable_init &&
638             EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
639                                        EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
640                 retval = 0;
641                 goto errout;
642         }
643
644         /*
645          * Initialize the inode table
646          */
647         retval = ext2fs_get_array(fs->blocksize, fs->inode_blocks_per_group,
648                                 &rfs->itable_buf);
649         if (retval)
650                 goto errout;
651
652         memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group);
653         group_block = ext2fs_group_first_block2(fs,
654                                                 rfs->old_fs->group_desc_count);
655         adj = rfs->old_fs->group_desc_count;
656         max_group = fs->group_desc_count - adj;
657         if (rfs->progress) {
658                 retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
659                                        0, max_group);
660                 if (retval)
661                         goto errout;
662         }
663         for (i = rfs->old_fs->group_desc_count;
664              i < fs->group_desc_count; i++) {
665                 /*
666                  * Write out the new inode table
667                  */
668                 retval = io_channel_write_blk64(fs->io,
669                                                 ext2fs_inode_table_loc(fs, i),
670                                                 fs->inode_blocks_per_group,
671                                                 rfs->itable_buf);
672                 if (retval) goto errout;
673
674                 io_channel_flush(fs->io);
675                 if (rfs->progress) {
676                         retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
677                                                i - adj + 1, max_group);
678                         if (retval)
679                                 goto errout;
680                 }
681                 group_block += fs->super->s_blocks_per_group;
682         }
683         io_channel_flush(fs->io);
684         retval = 0;
685
686 errout:
687         return retval;
688 }
689
690 /* --------------------------------------------------------------------
691  *
692  * Resize processing, phase 2.
693  *
694  * In this phase we adjust determine which blocks need to be moved, in
695  * blocks_to_move().  We then copy the blocks to their ultimate new
696  * destinations using block_mover().  Since we are copying blocks to
697  * their new locations, again during this pass we can abort without
698  * any problems.
699  * --------------------------------------------------------------------
700  */
701
702 /*
703  * This helper function creates a block bitmap with all of the
704  * filesystem meta-data blocks.
705  */
706 static errcode_t mark_table_blocks(ext2_filsys fs,
707                                    ext2fs_block_bitmap bmap)
708 {
709         dgrp_t                  i;
710
711         for (i = 0; i < fs->group_desc_count; i++) {
712                 ext2fs_reserve_super_and_bgd(fs, i, bmap);
713
714                 /*
715                  * Mark the blocks used for the inode table
716                  */
717                 ext2fs_mark_block_bitmap_range2(bmap,
718                                           ext2fs_inode_table_loc(fs, i),
719                                           fs->inode_blocks_per_group);
720
721                 /*
722                  * Mark block used for the block bitmap
723                  */
724                 ext2fs_mark_block_bitmap2(bmap,
725                                          ext2fs_block_bitmap_loc(fs, i));
726
727                 /*
728                  * Mark block used for the inode bitmap
729                  */
730                 ext2fs_mark_block_bitmap2(bmap,
731                                          ext2fs_inode_bitmap_loc(fs, i));
732         }
733         return 0;
734 }
735
736 /*
737  * This function checks to see if a particular block (either a
738  * superblock or a block group descriptor) overlaps with an inode or
739  * block bitmap block, or with the inode table.
740  */
741 static void mark_fs_metablock(ext2_resize_t rfs,
742                               ext2fs_block_bitmap meta_bmap,
743                               int group, blk64_t blk)
744 {
745         ext2_filsys     fs = rfs->new_fs;
746
747         ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
748         ext2fs_block_alloc_stats2(fs, blk, +1);
749
750         /*
751          * Check to see if we overlap with the inode or block bitmap,
752          * or the inode tables.  If not, and the block is in use, then
753          * mark it as a block to be moved.
754          */
755         if (IS_BLOCK_BM(fs, group, blk)) {
756                 ext2fs_block_bitmap_loc_set(fs, group, 0);
757                 rfs->needed_blocks++;
758                 return;
759         }
760         if (IS_INODE_BM(fs, group, blk)) {
761                 ext2fs_inode_bitmap_loc_set(fs, group, 0);
762                 rfs->needed_blocks++;
763                 return;
764         }
765         if (IS_INODE_TB(fs, group, blk)) {
766                 ext2fs_inode_table_loc_set(fs, group, 0);
767                 rfs->needed_blocks++;
768                 return;
769         }
770         if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) {
771                 dgrp_t i;
772
773                 for (i=0; i < rfs->old_fs->group_desc_count; i++) {
774                         if (IS_BLOCK_BM(fs, i, blk)) {
775                                 ext2fs_block_bitmap_loc_set(fs, i, 0);
776                                 rfs->needed_blocks++;
777                                 return;
778                         }
779                         if (IS_INODE_BM(fs, i, blk)) {
780                                 ext2fs_inode_bitmap_loc_set(fs, i, 0);
781                                 rfs->needed_blocks++;
782                                 return;
783                         }
784                         if (IS_INODE_TB(fs, i, blk)) {
785                                 ext2fs_inode_table_loc_set(fs, i, 0);
786                                 rfs->needed_blocks++;
787                                 return;
788                         }
789                 }
790         }
791         if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
792                                        EXT4_FEATURE_RO_COMPAT_GDT_CSUM) &&
793                    (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT))) {
794                 /*
795                  * If the block bitmap is uninitialized, which means
796                  * nothing other than standard metadata in use.
797                  */
798                 return;
799         } else if (ext2fs_test_block_bitmap2(rfs->old_fs->block_map, blk) &&
800                    !ext2fs_test_block_bitmap2(meta_bmap, blk)) {
801                 ext2fs_mark_block_bitmap2(rfs->move_blocks, blk);
802                 rfs->needed_blocks++;
803         }
804 }
805
806
807 /*
808  * This routine marks and unmarks reserved blocks in the new block
809  * bitmap.  It also determines which blocks need to be moved and
810  * places this information into the move_blocks bitmap.
811  */
812 static errcode_t blocks_to_move(ext2_resize_t rfs)
813 {
814         int             j, has_super;
815         dgrp_t          i, max_groups, g;
816         blk64_t         blk, group_blk;
817         blk64_t         old_blocks, new_blocks;
818         unsigned int    meta_bg, meta_bg_size;
819         errcode_t       retval;
820         ext2_filsys     fs, old_fs;
821         ext2fs_block_bitmap     meta_bmap;
822         int             flex_bg;
823
824         fs = rfs->new_fs;
825         old_fs = rfs->old_fs;
826         if (ext2fs_blocks_count(old_fs->super) > ext2fs_blocks_count(fs->super))
827                 fs = rfs->old_fs;
828
829         retval = ext2fs_allocate_block_bitmap(fs, _("blocks to be moved"),
830                                               &rfs->move_blocks);
831         if (retval)
832                 return retval;
833
834         retval = ext2fs_allocate_block_bitmap(fs, _("meta-data blocks"),
835                                               &meta_bmap);
836         if (retval)
837                 return retval;
838
839         retval = mark_table_blocks(old_fs, meta_bmap);
840         if (retval)
841                 return retval;
842
843         fs = rfs->new_fs;
844
845         /*
846          * If we're shrinking the filesystem, we need to move all of
847          * the blocks that don't fit any more
848          */
849         for (blk = ext2fs_blocks_count(fs->super);
850              blk < ext2fs_blocks_count(old_fs->super); blk++) {
851                 g = ext2fs_group_of_blk2(fs, blk);
852                 if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
853                                                EXT4_FEATURE_RO_COMPAT_GDT_CSUM) &&
854                     ext2fs_bg_flags_test(old_fs, g, EXT2_BG_BLOCK_UNINIT)) {
855                         /*
856                          * The block bitmap is uninitialized, so skip
857                          * to the next block group.
858                          */
859                         blk = ext2fs_group_first_block2(fs, g+1) - 1;
860                         continue;
861                 }
862                 if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
863                     !ext2fs_test_block_bitmap2(meta_bmap, blk)) {
864                         ext2fs_mark_block_bitmap2(rfs->move_blocks, blk);
865                         rfs->needed_blocks++;
866                 }
867                 ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
868         }
869
870         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) {
871                 old_blocks = old_fs->super->s_first_meta_bg;
872                 new_blocks = fs->super->s_first_meta_bg;
873         } else {
874                 old_blocks = old_fs->desc_blocks + old_fs->super->s_reserved_gdt_blocks;
875                 new_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
876         }
877
878         if (old_blocks == new_blocks) {
879                 retval = 0;
880                 goto errout;
881         }
882
883         max_groups = fs->group_desc_count;
884         if (max_groups > old_fs->group_desc_count)
885                 max_groups = old_fs->group_desc_count;
886         group_blk = old_fs->super->s_first_data_block;
887         /*
888          * If we're reducing the number of descriptor blocks, this
889          * makes life easy.  :-)   We just have to mark some extra
890          * blocks as free.
891          */
892         if (old_blocks > new_blocks) {
893                 for (i = 0; i < max_groups; i++) {
894                         if (!ext2fs_bg_has_super(fs, i)) {
895                                 group_blk += fs->super->s_blocks_per_group;
896                                 continue;
897                         }
898                         for (blk = group_blk+1+new_blocks;
899                              blk < group_blk+1+old_blocks; blk++) {
900                                 ext2fs_block_alloc_stats2(fs, blk, -1);
901                                 rfs->needed_blocks--;
902                         }
903                         group_blk += fs->super->s_blocks_per_group;
904                 }
905                 retval = 0;
906                 goto errout;
907         }
908         /*
909          * If we're increasing the number of descriptor blocks, life
910          * gets interesting....
911          */
912         meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
913         flex_bg = fs->super->s_feature_incompat &
914                 EXT4_FEATURE_INCOMPAT_FLEX_BG;
915         /* first reserve all of the existing fs meta blocks */
916         for (i = 0; i < max_groups; i++) {
917                 has_super = ext2fs_bg_has_super(fs, i);
918                 if (has_super)
919                         mark_fs_metablock(rfs, meta_bmap, i, group_blk);
920
921                 meta_bg = i / meta_bg_size;
922                 if (!(fs->super->s_feature_incompat &
923                       EXT2_FEATURE_INCOMPAT_META_BG) ||
924                     (meta_bg < fs->super->s_first_meta_bg)) {
925                         if (has_super) {
926                                 for (blk = group_blk+1;
927                                      blk < group_blk + 1 + new_blocks; blk++)
928                                         mark_fs_metablock(rfs, meta_bmap,
929                                                           i, blk);
930                         }
931                 } else {
932                         if (has_super)
933                                 has_super = 1;
934                         if (((i % meta_bg_size) == 0) ||
935                             ((i % meta_bg_size) == 1) ||
936                             ((i % meta_bg_size) == (meta_bg_size-1)))
937                                 mark_fs_metablock(rfs, meta_bmap, i,
938                                                   group_blk + has_super);
939                 }
940
941                 /*
942                  * Reserve the existing meta blocks that we know
943                  * aren't to be moved.
944                  *
945                  * For flex_bg file systems, in order to avoid
946                  * overwriting fs metadata (especially inode table
947                  * blocks) belonging to a different block group when
948                  * we are relocating the inode tables, we need to
949                  * reserve all existing fs metadata blocks.
950                  */
951                 if (ext2fs_block_bitmap_loc(fs, i))
952                         ext2fs_mark_block_bitmap2(rfs->reserve_blocks,
953                                  ext2fs_block_bitmap_loc(fs, i));
954                 else if (flex_bg && i < old_fs->group_desc_count)
955                         ext2fs_mark_block_bitmap2(rfs->reserve_blocks,
956                                  ext2fs_block_bitmap_loc(old_fs, i));
957
958                 if (ext2fs_inode_bitmap_loc(fs, i))
959                         ext2fs_mark_block_bitmap2(rfs->reserve_blocks,
960                                  ext2fs_inode_bitmap_loc(fs, i));
961                 else if (flex_bg && i < old_fs->group_desc_count)
962                         ext2fs_mark_block_bitmap2(rfs->reserve_blocks,
963                                  ext2fs_inode_bitmap_loc(old_fs, i));
964
965                 if (ext2fs_inode_table_loc(fs, i))
966                         ext2fs_mark_block_bitmap_range2(rfs->reserve_blocks,
967                                         ext2fs_inode_table_loc(fs, i),
968                                         fs->inode_blocks_per_group);
969                 else if (flex_bg && i < old_fs->group_desc_count)
970                         ext2fs_mark_block_bitmap_range2(rfs->reserve_blocks,
971                                         ext2fs_inode_table_loc(old_fs, i),
972                                         old_fs->inode_blocks_per_group);
973
974                 group_blk += rfs->new_fs->super->s_blocks_per_group;
975         }
976
977         /* Allocate the missing data structures */
978         for (i = 0; i < max_groups; i++) {
979                 if (ext2fs_inode_table_loc(fs, i) &&
980                     ext2fs_inode_bitmap_loc(fs, i) &&
981                     ext2fs_block_bitmap_loc(fs, i))
982                         continue;
983
984                 retval = ext2fs_allocate_group_table(fs, i,
985                                                      rfs->reserve_blocks);
986                 if (retval)
987                         goto errout;
988
989                 /*
990                  * For those structures that have changed, we need to
991                  * do bookkeepping.
992                  */
993                 if (ext2fs_block_bitmap_loc(old_fs, i) !=
994                     (blk = ext2fs_block_bitmap_loc(fs, i))) {
995                         ext2fs_block_alloc_stats2(fs, blk, +1);
996                         if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
997                             !ext2fs_test_block_bitmap2(meta_bmap, blk))
998                                 ext2fs_mark_block_bitmap2(rfs->move_blocks,
999                                                          blk);
1000                 }
1001                 if (ext2fs_inode_bitmap_loc(old_fs, i) !=
1002                     (blk = ext2fs_inode_bitmap_loc(fs, i))) {
1003                         ext2fs_block_alloc_stats2(fs, blk, +1);
1004                         if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
1005                             !ext2fs_test_block_bitmap2(meta_bmap, blk))
1006                                 ext2fs_mark_block_bitmap2(rfs->move_blocks,
1007                                                          blk);
1008                 }
1009
1010                 /*
1011                  * The inode table, if we need to relocate it, is
1012                  * handled specially.  We have to reserve the blocks
1013                  * for both the old and the new inode table, since we
1014                  * can't have the inode table be destroyed during the
1015                  * block relocation phase.
1016                  */
1017                 if (ext2fs_inode_table_loc(fs, i) == ext2fs_inode_table_loc(old_fs, i))
1018                         continue;       /* inode table not moved */
1019
1020                 rfs->needed_blocks += fs->inode_blocks_per_group;
1021
1022                 /*
1023                  * Mark the new inode table as in use in the new block
1024                  * allocation bitmap, and move any blocks that might
1025                  * be necessary.
1026                  */
1027                 for (blk = ext2fs_inode_table_loc(fs, i), j=0;
1028                      j < fs->inode_blocks_per_group ; j++, blk++) {
1029                         ext2fs_block_alloc_stats2(fs, blk, +1);
1030                         if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
1031                             !ext2fs_test_block_bitmap2(meta_bmap, blk))
1032                                 ext2fs_mark_block_bitmap2(rfs->move_blocks,
1033                                                          blk);
1034                 }
1035
1036                 /*
1037                  * Make sure the old inode table is reserved in the
1038                  * block reservation bitmap.
1039                  */
1040                 for (blk = ext2fs_inode_table_loc(rfs->old_fs, i), j=0;
1041                      j < fs->inode_blocks_per_group ; j++, blk++)
1042                         ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
1043         }
1044         retval = 0;
1045
1046 errout:
1047         if (meta_bmap)
1048                 ext2fs_free_block_bitmap(meta_bmap);
1049
1050         return retval;
1051 }
1052
1053 /*
1054  * This helper function tries to allocate a new block.  We try to
1055  * avoid hitting the original group descriptor blocks at least at
1056  * first, since we want to make it possible to recover from a badly
1057  * aborted resize operation as much as possible.
1058  *
1059  * In the future, I may further modify this routine to balance out
1060  * where we get the new blocks across the various block groups.
1061  * Ideally we would allocate blocks that corresponded with the block
1062  * group of the containing inode, and keep contiguous blocks
1063  * together.  However, this very difficult to do efficiently, since we
1064  * don't have the necessary information up front.
1065  */
1066
1067 #define AVOID_OLD       1
1068 #define DESPERATION     2
1069
1070 static void init_block_alloc(ext2_resize_t rfs)
1071 {
1072         rfs->alloc_state = AVOID_OLD;
1073         rfs->new_blk = rfs->new_fs->super->s_first_data_block;
1074 #if 0
1075         /* HACK for testing */
1076         if (ext2fs_blocks_count(rfs->new_fs->super) >
1077             ext2fs_blocks_count(rfs->old_fs->super))
1078                 rfs->new_blk = ext2fs_blocks_count(rfs->old_fs->super);
1079 #endif
1080 }
1081
1082 static blk64_t get_new_block(ext2_resize_t rfs)
1083 {
1084         ext2_filsys     fs = rfs->new_fs;
1085
1086         while (1) {
1087                 if (rfs->new_blk >= ext2fs_blocks_count(fs->super)) {
1088                         if (rfs->alloc_state == DESPERATION)
1089                                 return 0;
1090
1091 #ifdef RESIZE2FS_DEBUG
1092                         if (rfs->flags & RESIZE_DEBUG_BMOVE)
1093                                 printf("Going into desperation mode "
1094                                        "for block allocations\n");
1095 #endif
1096                         rfs->alloc_state = DESPERATION;
1097                         rfs->new_blk = fs->super->s_first_data_block;
1098                         continue;
1099                 }
1100                 if (ext2fs_test_block_bitmap2(fs->block_map, rfs->new_blk) ||
1101                     ext2fs_test_block_bitmap2(rfs->reserve_blocks,
1102                                              rfs->new_blk) ||
1103                     ((rfs->alloc_state == AVOID_OLD) &&
1104                      (rfs->new_blk < ext2fs_blocks_count(rfs->old_fs->super)) &&
1105                      ext2fs_test_block_bitmap2(rfs->old_fs->block_map,
1106                                               rfs->new_blk))) {
1107                         rfs->new_blk++;
1108                         continue;
1109                 }
1110                 return rfs->new_blk;
1111         }
1112 }
1113
1114 static errcode_t resize2fs_get_alloc_block(ext2_filsys fs, blk64_t goal,
1115                                            blk64_t *ret)
1116 {
1117         ext2_resize_t rfs = (ext2_resize_t) fs->priv_data;
1118         blk64_t blk;
1119
1120         blk = get_new_block(rfs);
1121         if (!blk)
1122                 return ENOSPC;
1123
1124 #ifdef RESIZE2FS_DEBUG
1125         if (rfs->flags & 0xF)
1126                 printf("get_alloc_block allocating %llu\n", blk);
1127 #endif
1128
1129         ext2fs_mark_block_bitmap2(rfs->old_fs->block_map, blk);
1130         ext2fs_mark_block_bitmap2(rfs->new_fs->block_map, blk);
1131         *ret = (blk64_t) blk;
1132         return 0;
1133 }
1134
1135 static errcode_t block_mover(ext2_resize_t rfs)
1136 {
1137         blk64_t                 blk, old_blk, new_blk;
1138         ext2_filsys             fs = rfs->new_fs;
1139         ext2_filsys             old_fs = rfs->old_fs;
1140         errcode_t               retval;
1141         __u64                   size;
1142         int                     c;
1143         int                     to_move, moved;
1144         ext2_badblocks_list     badblock_list = 0;
1145         int                     bb_modified = 0;
1146
1147         fs->get_alloc_block = resize2fs_get_alloc_block;
1148         old_fs->get_alloc_block = resize2fs_get_alloc_block;
1149
1150         retval = ext2fs_read_bb_inode(old_fs, &badblock_list);
1151         if (retval)
1152                 return retval;
1153
1154         new_blk = fs->super->s_first_data_block;
1155         if (!rfs->itable_buf) {
1156                 retval = ext2fs_get_array(fs->blocksize,
1157                                         fs->inode_blocks_per_group,
1158                                         &rfs->itable_buf);
1159                 if (retval)
1160                         return retval;
1161         }
1162         retval = ext2fs_create_extent_table(&rfs->bmap, 0);
1163         if (retval)
1164                 return retval;
1165
1166         /*
1167          * The first step is to figure out where all of the blocks
1168          * will go.
1169          */
1170         to_move = moved = 0;
1171         init_block_alloc(rfs);
1172         for (blk = old_fs->super->s_first_data_block;
1173              blk < ext2fs_blocks_count(old_fs->super); blk++) {
1174                 if (!ext2fs_test_block_bitmap2(old_fs->block_map, blk))
1175                         continue;
1176                 if (!ext2fs_test_block_bitmap2(rfs->move_blocks, blk))
1177                         continue;
1178                 if (ext2fs_badblocks_list_test(badblock_list, blk)) {
1179                         ext2fs_badblocks_list_del(badblock_list, blk);
1180                         bb_modified++;
1181                         continue;
1182                 }
1183
1184                 new_blk = get_new_block(rfs);
1185                 if (!new_blk) {
1186                         retval = ENOSPC;
1187                         goto errout;
1188                 }
1189                 ext2fs_block_alloc_stats2(fs, new_blk, +1);
1190                 ext2fs_add_extent_entry(rfs->bmap, blk, new_blk);
1191                 to_move++;
1192         }
1193
1194         if (to_move == 0) {
1195                 if (rfs->bmap) {
1196                         ext2fs_free_extent_table(rfs->bmap);
1197                         rfs->bmap = 0;
1198                 }
1199                 retval = 0;
1200                 goto errout;
1201         }
1202
1203         /*
1204          * Step two is to actually move the blocks
1205          */
1206         retval =  ext2fs_iterate_extent(rfs->bmap, 0, 0, 0);
1207         if (retval) goto errout;
1208
1209         if (rfs->progress) {
1210                 retval = (rfs->progress)(rfs, E2_RSZ_BLOCK_RELOC_PASS,
1211                                          0, to_move);
1212                 if (retval)
1213                         goto errout;
1214         }
1215         while (1) {
1216                 retval = ext2fs_iterate_extent(rfs->bmap, &old_blk, &new_blk, &size);
1217                 if (retval) goto errout;
1218                 if (!size)
1219                         break;
1220 #ifdef RESIZE2FS_DEBUG
1221                 if (rfs->flags & RESIZE_DEBUG_BMOVE)
1222                         printf("Moving %llu blocks %llu->%llu\n",
1223                                size, old_blk, new_blk);
1224 #endif
1225                 do {
1226                         c = size;
1227                         if (c > fs->inode_blocks_per_group)
1228                                 c = fs->inode_blocks_per_group;
1229                         retval = io_channel_read_blk64(fs->io, old_blk, c,
1230                                                        rfs->itable_buf);
1231                         if (retval) goto errout;
1232                         retval = io_channel_write_blk64(fs->io, new_blk, c,
1233                                                         rfs->itable_buf);
1234                         if (retval) goto errout;
1235                         size -= c;
1236                         new_blk += c;
1237                         old_blk += c;
1238                         moved += c;
1239                         if (rfs->progress) {
1240                                 io_channel_flush(fs->io);
1241                                 retval = (rfs->progress)(rfs,
1242                                                 E2_RSZ_BLOCK_RELOC_PASS,
1243                                                 moved, to_move);
1244                                 if (retval)
1245                                         goto errout;
1246                         }
1247                 } while (size > 0);
1248                 io_channel_flush(fs->io);
1249         }
1250
1251 errout:
1252         if (badblock_list) {
1253                 if (!retval && bb_modified)
1254                         retval = ext2fs_update_bb_inode(old_fs,
1255                                                         badblock_list);
1256                 ext2fs_badblocks_list_free(badblock_list);
1257         }
1258         return retval;
1259 }
1260
1261
1262 /* --------------------------------------------------------------------
1263  *
1264  * Resize processing, phase 3
1265  *
1266  * --------------------------------------------------------------------
1267  */
1268
1269
1270 struct process_block_struct {
1271         ext2_resize_t           rfs;
1272         ext2_ino_t              ino;
1273         struct ext2_inode *     inode;
1274         errcode_t               error;
1275         int                     is_dir;
1276         int                     changed;
1277 };
1278
1279 static int process_block(ext2_filsys fs, blk64_t        *block_nr,
1280                          e2_blkcnt_t blockcnt,
1281                          blk64_t ref_block EXT2FS_ATTR((unused)),
1282                          int ref_offset EXT2FS_ATTR((unused)), void *priv_data)
1283 {
1284         struct process_block_struct *pb;
1285         errcode_t       retval;
1286         blk64_t         block, new_block;
1287         int             ret = 0;
1288
1289         pb = (struct process_block_struct *) priv_data;
1290         block = *block_nr;
1291         if (pb->rfs->bmap) {
1292                 new_block = ext2fs_extent_translate(pb->rfs->bmap, block);
1293                 if (new_block) {
1294                         *block_nr = new_block;
1295                         ret |= BLOCK_CHANGED;
1296                         pb->changed = 1;
1297 #ifdef RESIZE2FS_DEBUG
1298                         if (pb->rfs->flags & RESIZE_DEBUG_BMOVE)
1299                                 printf("ino=%u, blockcnt=%lld, %llu->%llu\n",
1300                                        pb->ino, blockcnt, block, new_block);
1301 #endif
1302                         block = new_block;
1303                 }
1304         }
1305         if (pb->is_dir) {
1306                 retval = ext2fs_add_dir_block2(fs->dblist, pb->ino,
1307                                                block, (int) blockcnt);
1308                 if (retval) {
1309                         pb->error = retval;
1310                         ret |= BLOCK_ABORT;
1311                 }
1312         }
1313         return ret;
1314 }
1315
1316 /*
1317  * Progress callback
1318  */
1319 static errcode_t progress_callback(ext2_filsys fs,
1320                                    ext2_inode_scan scan EXT2FS_ATTR((unused)),
1321                                    dgrp_t group, void * priv_data)
1322 {
1323         ext2_resize_t rfs = (ext2_resize_t) priv_data;
1324         errcode_t               retval;
1325
1326         /*
1327          * This check is to protect against old ext2 libraries.  It
1328          * shouldn't be needed against new libraries.
1329          */
1330         if ((group+1) == 0)
1331                 return 0;
1332
1333         if (rfs->progress) {
1334                 io_channel_flush(fs->io);
1335                 retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS,
1336                                          group+1, fs->group_desc_count);
1337                 if (retval)
1338                         return retval;
1339         }
1340
1341         return 0;
1342 }
1343
1344 static errcode_t inode_scan_and_fix(ext2_resize_t rfs)
1345 {
1346         struct process_block_struct     pb;
1347         ext2_ino_t              ino, new_inode;
1348         struct ext2_inode       *inode = NULL;
1349         ext2_inode_scan         scan = NULL;
1350         errcode_t               retval;
1351         char                    *block_buf = 0;
1352         ext2_ino_t              start_to_move;
1353         blk64_t                 orig_size;
1354         blk64_t                 new_block;
1355         int                     inode_size;
1356
1357         if ((rfs->old_fs->group_desc_count <=
1358              rfs->new_fs->group_desc_count) &&
1359             !rfs->bmap)
1360                 return 0;
1361
1362         /*
1363          * Save the original size of the old filesystem, and
1364          * temporarily set the size to be the new size if the new size
1365          * is larger.  We need to do this to avoid catching an error
1366          * by the block iterator routines
1367          */
1368         orig_size = ext2fs_blocks_count(rfs->old_fs->super);
1369         if (orig_size < ext2fs_blocks_count(rfs->new_fs->super))
1370                 ext2fs_blocks_count_set(rfs->old_fs->super,
1371                                 ext2fs_blocks_count(rfs->new_fs->super));
1372
1373         retval = ext2fs_open_inode_scan(rfs->old_fs, 0, &scan);
1374         if (retval) goto errout;
1375
1376         retval = ext2fs_init_dblist(rfs->old_fs, 0);
1377         if (retval) goto errout;
1378         retval = ext2fs_get_array(rfs->old_fs->blocksize, 3, &block_buf);
1379         if (retval) goto errout;
1380
1381         start_to_move = (rfs->new_fs->group_desc_count *
1382                          rfs->new_fs->super->s_inodes_per_group);
1383
1384         if (rfs->progress) {
1385                 retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS,
1386                                          0, rfs->old_fs->group_desc_count);
1387                 if (retval)
1388                         goto errout;
1389         }
1390         ext2fs_set_inode_callback(scan, progress_callback, (void *) rfs);
1391         pb.rfs = rfs;
1392         pb.inode = inode;
1393         pb.error = 0;
1394         new_inode = EXT2_FIRST_INODE(rfs->new_fs->super);
1395         inode_size = EXT2_INODE_SIZE(rfs->new_fs->super);
1396         inode = malloc(inode_size);
1397         if (!inode) {
1398                 retval = ENOMEM;
1399                 goto errout;
1400         }
1401         /*
1402          * First, copy all of the inodes that need to be moved
1403          * elsewhere in the inode table
1404          */
1405         while (1) {
1406                 retval = ext2fs_get_next_inode_full(scan, &ino, inode, inode_size);
1407                 if (retval) goto errout;
1408                 if (!ino)
1409                         break;
1410
1411                 if (inode->i_links_count == 0 && ino != EXT2_RESIZE_INO)
1412                         continue; /* inode not in use */
1413
1414                 pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
1415                 pb.changed = 0;
1416
1417                 if (ext2fs_file_acl_block(rfs->old_fs, inode) && rfs->bmap) {
1418                         new_block = ext2fs_extent_translate(rfs->bmap,
1419                                 ext2fs_file_acl_block(rfs->old_fs, inode));
1420                         if (new_block) {
1421                                 ext2fs_file_acl_block_set(rfs->old_fs, inode,
1422                                                           new_block);
1423                                 retval = ext2fs_write_inode_full(rfs->old_fs,
1424                                                             ino, inode, inode_size);
1425                                 if (retval) goto errout;
1426                         }
1427                 }
1428
1429                 if (ext2fs_inode_has_valid_blocks2(rfs->old_fs, inode) &&
1430                     (rfs->bmap || pb.is_dir)) {
1431                         pb.ino = ino;
1432                         retval = ext2fs_block_iterate3(rfs->old_fs,
1433                                                        ino, 0, block_buf,
1434                                                        process_block, &pb);
1435                         if (retval)
1436                                 goto errout;
1437                         if (pb.error) {
1438                                 retval = pb.error;
1439                                 goto errout;
1440                         }
1441                 }
1442
1443                 if (ino <= start_to_move)
1444                         continue; /* Don't need to move it. */
1445
1446                 /*
1447                  * Find a new inode
1448                  */
1449                 retval = ext2fs_new_inode(rfs->new_fs, 0, 0, 0, &new_inode);
1450                 if (retval)
1451                         goto errout;
1452
1453                 ext2fs_inode_alloc_stats2(rfs->new_fs, new_inode, +1,
1454                                           pb.is_dir);
1455                 if (pb.changed) {
1456                         /* Get the new version of the inode */
1457                         retval = ext2fs_read_inode_full(rfs->old_fs, ino,
1458                                                 inode, inode_size);
1459                         if (retval) goto errout;
1460                 }
1461                 inode->i_ctime = time(0);
1462                 retval = ext2fs_write_inode_full(rfs->old_fs, new_inode,
1463                                                 inode, inode_size);
1464                 if (retval) goto errout;
1465
1466 #ifdef RESIZE2FS_DEBUG
1467                 if (rfs->flags & RESIZE_DEBUG_INODEMAP)
1468                         printf("Inode moved %u->%u\n", ino, new_inode);
1469 #endif
1470                 if (!rfs->imap) {
1471                         retval = ext2fs_create_extent_table(&rfs->imap, 0);
1472                         if (retval)
1473                                 goto errout;
1474                 }
1475                 ext2fs_add_extent_entry(rfs->imap, ino, new_inode);
1476         }
1477         io_channel_flush(rfs->old_fs->io);
1478
1479 errout:
1480         ext2fs_blocks_count_set(rfs->old_fs->super, orig_size);
1481         if (rfs->bmap) {
1482                 ext2fs_free_extent_table(rfs->bmap);
1483                 rfs->bmap = 0;
1484         }
1485         if (scan)
1486                 ext2fs_close_inode_scan(scan);
1487         if (block_buf)
1488                 ext2fs_free_mem(&block_buf);
1489         free(inode);
1490         return retval;
1491 }
1492
1493 /* --------------------------------------------------------------------
1494  *
1495  * Resize processing, phase 4.
1496  *
1497  * --------------------------------------------------------------------
1498  */
1499
1500 struct istruct {
1501         ext2_resize_t rfs;
1502         errcode_t       err;
1503         unsigned int    max_dirs;
1504         unsigned int    num;
1505 };
1506
1507 static int check_and_change_inodes(ext2_ino_t dir,
1508                                    int entry EXT2FS_ATTR((unused)),
1509                                    struct ext2_dir_entry *dirent, int offset,
1510                                    int  blocksize EXT2FS_ATTR((unused)),
1511                                    char *buf EXT2FS_ATTR((unused)),
1512                                    void *priv_data)
1513 {
1514         struct istruct *is = (struct istruct *) priv_data;
1515         struct ext2_inode       inode;
1516         ext2_ino_t              new_inode;
1517         errcode_t               retval;
1518
1519         if (is->rfs->progress && offset == 0) {
1520                 io_channel_flush(is->rfs->old_fs->io);
1521                 is->err = (is->rfs->progress)(is->rfs,
1522                                               E2_RSZ_INODE_REF_UPD_PASS,
1523                                               ++is->num, is->max_dirs);
1524                 if (is->err)
1525                         return DIRENT_ABORT;
1526         }
1527
1528         if (!dirent->inode)
1529                 return 0;
1530
1531         new_inode = ext2fs_extent_translate(is->rfs->imap, dirent->inode);
1532
1533         if (!new_inode)
1534                 return 0;
1535 #ifdef RESIZE2FS_DEBUG
1536         if (is->rfs->flags & RESIZE_DEBUG_INODEMAP)
1537                 printf("Inode translate (dir=%u, name=%.*s, %u->%u)\n",
1538                        dir, dirent->name_len&0xFF, dirent->name,
1539                        dirent->inode, new_inode);
1540 #endif
1541
1542         dirent->inode = new_inode;
1543
1544         /* Update the directory mtime and ctime */
1545         retval = ext2fs_read_inode(is->rfs->old_fs, dir, &inode);
1546         if (retval == 0) {
1547                 inode.i_mtime = inode.i_ctime = time(0);
1548                 is->err = ext2fs_write_inode(is->rfs->old_fs, dir, &inode);
1549                 if (is->err)
1550                         return DIRENT_ABORT;
1551         }
1552
1553         return DIRENT_CHANGED;
1554 }
1555
1556 static errcode_t inode_ref_fix(ext2_resize_t rfs)
1557 {
1558         errcode_t               retval;
1559         struct istruct          is;
1560
1561         if (!rfs->imap)
1562                 return 0;
1563
1564         /*
1565          * Now, we iterate over all of the directories to update the
1566          * inode references
1567          */
1568         is.num = 0;
1569         is.max_dirs = ext2fs_dblist_count2(rfs->old_fs->dblist);
1570         is.rfs = rfs;
1571         is.err = 0;
1572
1573         if (rfs->progress) {
1574                 retval = (rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS,
1575                                          0, is.max_dirs);
1576                 if (retval)
1577                         goto errout;
1578         }
1579
1580         retval = ext2fs_dblist_dir_iterate(rfs->old_fs->dblist,
1581                                            DIRENT_FLAG_INCLUDE_EMPTY, 0,
1582                                            check_and_change_inodes, &is);
1583         if (retval)
1584                 goto errout;
1585         if (is.err) {
1586                 retval = is.err;
1587                 goto errout;
1588         }
1589
1590         if (rfs->progress && (is.num < is.max_dirs))
1591                 (rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS,
1592                                 is.max_dirs, is.max_dirs);
1593
1594 errout:
1595         ext2fs_free_extent_table(rfs->imap);
1596         rfs->imap = 0;
1597         return retval;
1598 }
1599
1600
1601 /* --------------------------------------------------------------------
1602  *
1603  * Resize processing, phase 5.
1604  *
1605  * In this phase we actually move the inode table around, and then
1606  * update the summary statistics.  This is scary, since aborting here
1607  * will potentially scramble the filesystem.  (We are moving the
1608  * inode tables around in place, and so the potential for lost data,
1609  * or at the very least scrambling the mapping between filenames and
1610  * inode numbers is very high in case of a power failure here.)
1611  * --------------------------------------------------------------------
1612  */
1613
1614
1615 /*
1616  * A very scary routine --- this one moves the inode table around!!!
1617  *
1618  * After this you have to use the rfs->new_fs file handle to read and
1619  * write inodes.
1620  */
1621 static errcode_t move_itables(ext2_resize_t rfs)
1622 {
1623         int             n, num, size;
1624         long long       diff;
1625         dgrp_t          i, max_groups;
1626         ext2_filsys     fs = rfs->new_fs;
1627         char            *cp;
1628         blk64_t         old_blk, new_blk, blk;
1629         errcode_t       retval;
1630         int             j, to_move, moved;
1631
1632         max_groups = fs->group_desc_count;
1633         if (max_groups > rfs->old_fs->group_desc_count)
1634                 max_groups = rfs->old_fs->group_desc_count;
1635
1636         size = fs->blocksize * fs->inode_blocks_per_group;
1637         if (!rfs->itable_buf) {
1638                 retval = ext2fs_get_mem(size, &rfs->itable_buf);
1639                 if (retval)
1640                         return retval;
1641         }
1642
1643         /*
1644          * Figure out how many inode tables we need to move
1645          */
1646         to_move = moved = 0;
1647         for (i=0; i < max_groups; i++)
1648                 if (ext2fs_inode_table_loc(rfs->old_fs, i) !=
1649                     ext2fs_inode_table_loc(fs, i))
1650                         to_move++;
1651
1652         if (to_move == 0)
1653                 return 0;
1654
1655         if (rfs->progress) {
1656                 retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS,
1657                                        0, to_move);
1658                 if (retval)
1659                         goto errout;
1660         }
1661
1662         rfs->old_fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
1663
1664         for (i=0; i < max_groups; i++) {
1665                 old_blk = ext2fs_inode_table_loc(rfs->old_fs, i);
1666                 new_blk = ext2fs_inode_table_loc(fs, i);
1667                 diff = new_blk - old_blk;
1668
1669 #ifdef RESIZE2FS_DEBUG
1670                 if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
1671                         printf("Itable move group %d block %llu->%llu (diff %lld)\n",
1672                                i, old_blk, new_blk, diff);
1673 #endif
1674
1675                 if (!diff)
1676                         continue;
1677
1678                 retval = io_channel_read_blk64(fs->io, old_blk,
1679                                                fs->inode_blocks_per_group,
1680                                                rfs->itable_buf);
1681                 if (retval)
1682                         goto errout;
1683                 /*
1684                  * The end of the inode table segment often contains
1685                  * all zeros, and we're often only moving the inode
1686                  * table down a block or two.  If so, we can optimize
1687                  * things by not rewriting blocks that we know to be zero
1688                  * already.
1689                  */
1690                 for (cp = rfs->itable_buf+size-1, n=0; n < size; n++, cp--)
1691                         if (*cp)
1692                                 break;
1693                 n = n >> EXT2_BLOCK_SIZE_BITS(fs->super);
1694 #ifdef RESIZE2FS_DEBUG
1695                 if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
1696                         printf("%d blocks of zeros...\n", n);
1697 #endif
1698                 num = fs->inode_blocks_per_group;
1699                 if (n > diff)
1700                         num -= n;
1701
1702                 retval = io_channel_write_blk64(fs->io, new_blk,
1703                                                 num, rfs->itable_buf);
1704                 if (retval) {
1705                         io_channel_write_blk64(fs->io, old_blk,
1706                                                num, rfs->itable_buf);
1707                         goto errout;
1708                 }
1709                 if (n > diff) {
1710                         retval = io_channel_write_blk64(fs->io,
1711                               old_blk + fs->inode_blocks_per_group,
1712                               diff, (rfs->itable_buf +
1713                                      (fs->inode_blocks_per_group - diff) *
1714                                      fs->blocksize));
1715                         if (retval)
1716                                 goto errout;
1717                 }
1718
1719                 for (blk = ext2fs_inode_table_loc(rfs->old_fs, i), j=0;
1720                      j < fs->inode_blocks_per_group ; j++, blk++)
1721                         ext2fs_block_alloc_stats2(fs, blk, -1);
1722
1723                 ext2fs_inode_table_loc_set(rfs->old_fs, i, new_blk);
1724                 ext2fs_group_desc_csum_set(rfs->old_fs, i);
1725                 ext2fs_mark_super_dirty(rfs->old_fs);
1726                 ext2fs_flush(rfs->old_fs);
1727
1728                 if (rfs->progress) {
1729                         retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS,
1730                                                ++moved, to_move);
1731                         if (retval)
1732                                 goto errout;
1733                 }
1734         }
1735         mark_table_blocks(fs, fs->block_map);
1736         ext2fs_flush(fs);
1737 #ifdef RESIZE2FS_DEBUG
1738         if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
1739                 printf("Inode table move finished.\n");
1740 #endif
1741         return 0;
1742
1743 errout:
1744         return retval;
1745 }
1746
1747 /*
1748  * Fix the resize inode
1749  */
1750 static errcode_t fix_resize_inode(ext2_filsys fs)
1751 {
1752         struct ext2_inode       inode;
1753         errcode_t               retval;
1754         char                    *block_buf = NULL;
1755
1756         if (!(fs->super->s_feature_compat &
1757               EXT2_FEATURE_COMPAT_RESIZE_INODE))
1758                 return 0;
1759
1760         retval = ext2fs_get_mem(fs->blocksize, &block_buf);
1761         if (retval) goto errout;
1762
1763         retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
1764         if (retval) goto errout;
1765
1766         ext2fs_iblk_set(fs, &inode, 1);
1767
1768         retval = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode);
1769         if (retval) goto errout;
1770
1771         if (!inode.i_block[EXT2_DIND_BLOCK]) {
1772                 /*
1773                  * Avoid zeroing out block #0; that's rude.  This
1774                  * should never happen anyway since the filesystem
1775                  * should be fsck'ed and we assume it is consistent.
1776                  */
1777                 fprintf(stderr,
1778                         _("Should never happen: resize inode corrupt!\n"));
1779                 exit(1);
1780         }
1781
1782         memset(block_buf, 0, fs->blocksize);
1783
1784         retval = io_channel_write_blk64(fs->io, inode.i_block[EXT2_DIND_BLOCK],
1785                                         1, block_buf);
1786         if (retval) goto errout;
1787
1788         retval = ext2fs_create_resize_inode(fs);
1789         if (retval)
1790                 goto errout;
1791
1792 errout:
1793         if (block_buf)
1794                 ext2fs_free_mem(&block_buf);
1795         return retval;
1796 }
1797
1798 /*
1799  * Finally, recalculate the summary information
1800  */
1801 static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs)
1802 {
1803         blk64_t         blk;
1804         ext2_ino_t      ino;
1805         unsigned int    group = 0;
1806         unsigned int    count = 0;
1807         blk64_t         total_blocks_free = 0;
1808         int             total_inodes_free = 0;
1809         int             group_free = 0;
1810         int             uninit = 0;
1811         blk64_t         super_blk, old_desc_blk, new_desc_blk;
1812         int             old_desc_blocks;
1813
1814         /*
1815          * First calculate the block statistics
1816          */
1817         uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT);
1818         ext2fs_super_and_bgd_loc2(fs, group, &super_blk, &old_desc_blk,
1819                                   &new_desc_blk, 0);
1820         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
1821                 old_desc_blocks = fs->super->s_first_meta_bg;
1822         else
1823                 old_desc_blocks = fs->desc_blocks +
1824                         fs->super->s_reserved_gdt_blocks;
1825         for (blk = fs->super->s_first_data_block;
1826              blk < ext2fs_blocks_count(fs->super); blk++) {
1827                 if ((uninit &&
1828                      !((blk == super_blk) ||
1829                        ((old_desc_blk && old_desc_blocks &&
1830                          (blk >= old_desc_blk) &&
1831                          (blk < old_desc_blk + old_desc_blocks))) ||
1832                        ((new_desc_blk && (blk == new_desc_blk))) ||
1833                        (blk == ext2fs_block_bitmap_loc(fs, group)) ||
1834                        (blk == ext2fs_inode_bitmap_loc(fs, group)) ||
1835                        ((blk >= ext2fs_inode_table_loc(fs, group) &&
1836                          (blk < ext2fs_inode_table_loc(fs, group)
1837                           + fs->inode_blocks_per_group))))) ||
1838                     (!ext2fs_fast_test_block_bitmap2(fs->block_map, blk))) {
1839                         group_free++;
1840                         total_blocks_free++;
1841                 }
1842                 count++;
1843                 if ((count == fs->super->s_blocks_per_group) ||
1844                     (blk == ext2fs_blocks_count(fs->super)-1)) {
1845                         ext2fs_bg_free_blocks_count_set(fs, group, group_free);
1846                         ext2fs_group_desc_csum_set(fs, group);
1847                         group++;
1848                         if (group >= fs->group_desc_count)
1849                                 break;
1850                         count = 0;
1851                         group_free = 0;
1852                         uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT);
1853                         ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
1854                                                   &old_desc_blk,
1855                                                   &new_desc_blk, 0);
1856                         if (fs->super->s_feature_incompat &
1857                             EXT2_FEATURE_INCOMPAT_META_BG)
1858                                 old_desc_blocks = fs->super->s_first_meta_bg;
1859                         else
1860                                 old_desc_blocks = fs->desc_blocks +
1861                                         fs->super->s_reserved_gdt_blocks;
1862                 }
1863         }
1864         ext2fs_free_blocks_count_set(fs->super, total_blocks_free);
1865
1866         /*
1867          * Next, calculate the inode statistics
1868          */
1869         group_free = 0;
1870         count = 0;
1871         group = 0;
1872
1873         /* Protect loop from wrap-around if s_inodes_count maxed */
1874         uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT);
1875         for (ino = 1; ino <= fs->super->s_inodes_count && ino > 0; ino++) {
1876                 if (uninit ||
1877                     !ext2fs_fast_test_inode_bitmap2(fs->inode_map, ino)) {
1878                         group_free++;
1879                         total_inodes_free++;
1880                 }
1881                 count++;
1882                 if ((count == fs->super->s_inodes_per_group) ||
1883                     (ino == fs->super->s_inodes_count)) {
1884                         ext2fs_bg_free_inodes_count_set(fs, group, group_free);
1885                         ext2fs_group_desc_csum_set(fs, group);
1886                         group++;
1887                         if (group >= fs->group_desc_count)
1888                                 break;
1889                         count = 0;
1890                         group_free = 0;
1891                         uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT);
1892                 }
1893         }
1894         fs->super->s_free_inodes_count = total_inodes_free;
1895         ext2fs_mark_super_dirty(fs);
1896         return 0;
1897 }
1898
1899 /*
1900  *  Journal may have been relocated; update the backup journal blocks
1901  *  in the superblock.
1902  */
1903 static errcode_t fix_sb_journal_backup(ext2_filsys fs)
1904 {
1905         errcode_t         retval;
1906         struct ext2_inode inode;
1907
1908         if (!(fs->super->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
1909                 return 0;
1910
1911         /* External journal? Nothing to do. */
1912         if (fs->super->s_journal_dev && !fs->super->s_journal_inum)
1913                 return 0;
1914
1915         retval = ext2fs_read_inode(fs, fs->super->s_journal_inum, &inode);
1916         if (retval)
1917                 return retval;
1918         memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4);
1919         fs->super->s_jnl_blocks[15] = inode.i_size_high;
1920         fs->super->s_jnl_blocks[16] = inode.i_size;
1921         fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
1922         ext2fs_mark_super_dirty(fs);
1923         return 0;
1924 }
1925
1926 static int calc_group_overhead(ext2_filsys fs, blk64_t grp,
1927                                int old_desc_blocks)
1928 {
1929         blk64_t super_blk, old_desc_blk, new_desc_blk;
1930         int overhead;
1931
1932         /* inode table blocks plus allocation bitmaps */
1933         overhead = fs->inode_blocks_per_group + 2;
1934
1935         ext2fs_super_and_bgd_loc2(fs, grp, &super_blk,
1936                                   &old_desc_blk, &new_desc_blk, 0);
1937         if ((grp == 0) || super_blk)
1938                 overhead++;
1939         if (old_desc_blk)
1940                 overhead += old_desc_blocks;
1941         else if (new_desc_blk)
1942                 overhead++;
1943         return overhead;
1944 }
1945
1946
1947 /*
1948  * calcluate the minimum number of blocks the given fs can be resized to
1949  */
1950 blk64_t calculate_minimum_resize_size(ext2_filsys fs)
1951 {
1952         ext2_ino_t inode_count;
1953         blk64_t blks_needed, groups, data_blocks;
1954         blk64_t grp, data_needed, last_start;
1955         blk64_t overhead = 0;
1956         int old_desc_blocks;
1957         int extra_groups = 0;
1958         int flexbg_size = 1 << fs->super->s_log_groups_per_flex;
1959
1960         /*
1961          * first figure out how many group descriptors we need to
1962          * handle the number of inodes we have
1963          */
1964         inode_count = fs->super->s_inodes_count -
1965                 fs->super->s_free_inodes_count;
1966         blks_needed = ext2fs_div_ceil(inode_count,
1967                                       fs->super->s_inodes_per_group) *
1968                 EXT2_BLOCKS_PER_GROUP(fs->super);
1969         groups = ext2fs_div64_ceil(blks_needed,
1970                                    EXT2_BLOCKS_PER_GROUP(fs->super));
1971
1972         /*
1973          * number of old-style block group descriptor blocks
1974          */
1975         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
1976                 old_desc_blocks = fs->super->s_first_meta_bg;
1977         else
1978                 old_desc_blocks = fs->desc_blocks +
1979                         fs->super->s_reserved_gdt_blocks;
1980
1981         /* calculate how many blocks are needed for data */
1982         data_needed = ext2fs_blocks_count(fs->super) -
1983                 ext2fs_free_blocks_count(fs->super);
1984
1985         for (grp = 0; grp < fs->group_desc_count; grp++)
1986                 data_needed -= calc_group_overhead(fs, grp, old_desc_blocks);
1987
1988         /*
1989          * For ext4 we need to allow for up to a flex_bg worth of
1990          * inode tables of slack space so the resize operation can be
1991          * guaranteed to finish.
1992          */
1993         if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) {
1994                 extra_groups = flexbg_size - (groups & (flexbg_size - 1));
1995                 data_needed += fs->inode_blocks_per_group * extra_groups;
1996                 extra_groups = groups % flexbg_size;
1997         }
1998
1999         /*
2000          * figure out how many data blocks we have given the number of groups
2001          * we need for our inodes
2002          */
2003         data_blocks = groups * EXT2_BLOCKS_PER_GROUP(fs->super);
2004         last_start = 0;
2005         for (grp = 0; grp < groups; grp++) {
2006                 overhead = calc_group_overhead(fs, grp, old_desc_blocks);
2007
2008                 /*
2009                  * we want to keep track of how much data we can store in
2010                  * the groups leading up to the last group so we can determine
2011                  * how big the last group needs to be
2012                  */
2013                 if (grp != (groups - 1))
2014                         last_start += EXT2_BLOCKS_PER_GROUP(fs->super) -
2015                                 overhead;
2016
2017                 data_blocks -= overhead;
2018         }
2019
2020         /*
2021          * if we need more group descriptors in order to accomodate our data
2022          * then we need to add them here
2023          */
2024         while (data_needed > data_blocks) {
2025                 blk64_t remainder = data_needed - data_blocks;
2026                 blk64_t extra_grps;
2027
2028                 /* figure out how many more groups we need for the data */
2029                 extra_grps = ext2fs_div64_ceil(remainder,
2030                                                EXT2_BLOCKS_PER_GROUP(fs->super));
2031
2032                 data_blocks += extra_grps * EXT2_BLOCKS_PER_GROUP(fs->super);
2033
2034                 /* ok we have to account for the last group */
2035                 overhead = calc_group_overhead(fs, groups-1, old_desc_blocks);
2036                 last_start += EXT2_BLOCKS_PER_GROUP(fs->super) - overhead;
2037
2038                 for (grp = groups; grp < groups+extra_grps; grp++) {
2039                         overhead = calc_group_overhead(fs, grp,
2040                                                        old_desc_blocks);
2041
2042                         /*
2043                          * again, we need to see how much data we cram into
2044                          * all of the groups leading up to the last group
2045                          */
2046                         if (grp != (groups + extra_grps - 1))
2047                                 last_start += EXT2_BLOCKS_PER_GROUP(fs->super)
2048                                         - overhead;
2049
2050                         data_blocks -= overhead;
2051                 }
2052
2053                 groups += extra_grps;
2054                 extra_groups += extra_grps;
2055                 if (fs->super->s_feature_incompat
2056                         & EXT4_FEATURE_INCOMPAT_FLEX_BG
2057                     && extra_groups > flexbg_size) {
2058                         /*
2059                          * For ext4 we need to allow for up to a flex_bg worth
2060                          * of inode tables of slack space so the resize
2061                          * operation can be guaranteed to finish.
2062                          */
2063                         extra_groups = flexbg_size -
2064                                                 (groups & (flexbg_size - 1));
2065                         data_needed += (fs->inode_blocks_per_group *
2066                                         extra_groups);
2067                         extra_groups = groups % flexbg_size;
2068                 }
2069         }
2070
2071         /* now for the fun voodoo */
2072         overhead = calc_group_overhead(fs, groups-1, old_desc_blocks);
2073
2074         /*
2075          * if this is the case then the last group is going to have data in it
2076          * so we need to adjust the size of the last group accordingly
2077          */
2078         if (last_start < data_needed) {
2079                 blk64_t remainder = data_needed - last_start;
2080
2081                 /*
2082                  * 50 is a magic number that mkfs/resize uses to see if its
2083                  * even worth making/resizing the fs.  basically you need to
2084                  * have at least 50 blocks in addition to the blocks needed
2085                  * for the metadata in the last group
2086                  */
2087                 if (remainder > 50)
2088                         overhead += remainder;
2089                 else
2090                         overhead += 50;
2091         } else
2092                 overhead += 50;
2093
2094         overhead += fs->super->s_first_data_block;
2095
2096         /*
2097          * since our last group doesn't have to be BLOCKS_PER_GROUP large, we
2098          * only do groups-1, and then add the number of blocks needed to
2099          * handle the group descriptor metadata+data that we need
2100          */
2101         blks_needed = (groups-1) * EXT2_BLOCKS_PER_GROUP(fs->super);
2102         blks_needed += overhead;
2103
2104         /*
2105          * If at this point we've already added up more "needed" than
2106          * the current size, just return current size as minimum.
2107          */
2108         if (blks_needed >= ext2fs_blocks_count(fs->super))
2109                 return ext2fs_blocks_count(fs->super);
2110         /*
2111          * We need to reserve a few extra blocks if extents are
2112          * enabled, in case we need to grow the extent tree.  The more
2113          * we shrink the file system, the more space we need.
2114          */
2115         if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS)
2116                 blks_needed += (ext2fs_blocks_count(fs->super) - 
2117                                 blks_needed)/500;
2118
2119         return blks_needed;
2120 }