~ubuntu-branches/ubuntu/edgy/e2fsprogs/edgy-security

« back to all changes in this revision

Viewing changes to resize/resize2fs.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2004-09-19 09:43:14 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040919094314-ypmsn0h1ke583yda
Tags: 1.35-6ubuntu1
Remove ext3-add-journal.sh script.  It overcomplicates the initrd setup,
and the only problem it solves is to prevent a visible /.journal

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
 */
35
35
 
36
36
#include "resize2fs.h"
 
37
#include <time.h>
37
38
 
38
39
#ifdef __linux__                        /* Kludge for debugging */
39
40
#define RESIZE2FS_DEBUG
66
67
/*
67
68
 * This is the top-level routine which does the dirty deed....
68
69
 */
69
 
errcode_t resize_fs(ext2_filsys fs, blk_t new_size, int flags,
 
70
errcode_t resize_fs(ext2_filsys fs, blk_t *new_size, int flags,
70
71
                    errcode_t (*progress)(ext2_resize_t rfs, int pass,
71
72
                                     unsigned long cur,
72
73
                                     unsigned long max_val))
81
82
        /*
82
83
         * Create the data structure
83
84
         */
84
 
        retval = ext2fs_get_mem(sizeof(struct ext2_resize_struct),
85
 
                                (void **) &rfs);
 
85
        retval = ext2fs_get_mem(sizeof(struct ext2_resize_struct), &rfs);
86
86
        if (retval)
87
87
                return retval;
88
88
        memset(rfs, 0, sizeof(struct ext2_resize_struct));
95
95
        if (retval)
96
96
                goto errout;
97
97
 
98
 
        retval = adjust_superblock(rfs, new_size);
 
98
        retval = adjust_superblock(rfs, *new_size);
99
99
        if (retval)
100
100
                goto errout;
101
101
 
 
102
        *new_size = rfs->new_fs->super->s_blocks_count;
 
103
 
102
104
        retval = blocks_to_move(rfs);
103
105
        if (retval)
104
106
                goto errout;
139
141
        
140
142
        ext2fs_free(rfs->old_fs);
141
143
        if (rfs->itable_buf)
142
 
                ext2fs_free_mem((void **) &rfs->itable_buf);
143
 
        ext2fs_free_mem((void **) &rfs);
 
144
                ext2fs_free_mem(&rfs->itable_buf);
 
145
        ext2fs_free_mem(&rfs);
144
146
        
145
147
        return 0;
146
148
 
148
150
        if (rfs->new_fs)
149
151
                ext2fs_free(rfs->new_fs);
150
152
        if (rfs->itable_buf)
151
 
                ext2fs_free_mem((void **) &rfs->itable_buf);
152
 
        ext2fs_free_mem((void **) &rfs);
 
153
                ext2fs_free_mem(&rfs->itable_buf);
 
154
        ext2fs_free_mem(&rfs);
153
155
        return retval;
154
156
}
155
157
 
175
177
        errcode_t       retval;
176
178
        ext2_ino_t      real_end;
177
179
        blk_t           blk, group_block;
178
 
        unsigned long   i, j;
 
180
        unsigned long   i, j, old_desc_blocks;
179
181
        int             old_numblocks, numblocks, adjblocks;
 
182
        unsigned int    meta_bg, meta_bg_size;
 
183
        int             has_super;
180
184
        unsigned long   max_group;
181
185
        
182
186
        fs = rfs->new_fs;
268
272
                retval = ext2fs_resize_mem(rfs->old_fs->desc_blocks *
269
273
                                           fs->blocksize,
270
274
                                           fs->desc_blocks * fs->blocksize,
271
 
                                           (void **) &fs->group_desc);
 
275
                                           &fs->group_desc);
272
276
                if (retval)
273
277
                        goto errout;
274
278
        }
323
327
         * Initialize the new block group descriptors
324
328
         */
325
329
        retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
326
 
                                (void **) &rfs->itable_buf);
 
330
                                &rfs->itable_buf);
327
331
        if (retval)
328
332
                goto errout;
329
333
 
339
343
                if (retval)
340
344
                        goto errout;
341
345
        }
 
346
        if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
 
347
                old_desc_blocks = fs->super->s_first_meta_bg;
 
348
        else
 
349
                old_desc_blocks = fs->desc_blocks;
342
350
        for (i = rfs->old_fs->group_desc_count;
343
351
             i < fs->group_desc_count; i++) {
344
352
                memset(&fs->group_desc[i], 0,
354
362
                } else
355
363
                        numblocks = fs->super->s_blocks_per_group;
356
364
 
357
 
                if (ext2fs_bg_has_super(fs, i)) {
358
 
                        for (j=0; j < fs->desc_blocks+1; j++)
 
365
                has_super = ext2fs_bg_has_super(fs, i);
 
366
                if (has_super) {
 
367
                        ext2fs_mark_block_bitmap(fs->block_map, group_block);
 
368
                        adjblocks++;
 
369
                }
 
370
                meta_bg_size = (fs->blocksize /
 
371
                                sizeof (struct ext2_group_desc));
 
372
                meta_bg = i / meta_bg_size;
 
373
                if (!(fs->super->s_feature_incompat &
 
374
                      EXT2_FEATURE_INCOMPAT_META_BG) ||
 
375
                    (meta_bg < fs->super->s_first_meta_bg)) {
 
376
                        if (has_super) {
 
377
                                for (j=0; j < old_desc_blocks; j++)
 
378
                                        ext2fs_mark_block_bitmap(fs->block_map,
 
379
                                                         group_block + 1 + j);
 
380
                                adjblocks += old_desc_blocks;
 
381
                        }
 
382
                } else {
 
383
                        if (has_super)
 
384
                                has_super = 1;
 
385
                        if (((i % meta_bg_size) == 0) ||
 
386
                            ((i % meta_bg_size) == 1) ||
 
387
                            ((i % meta_bg_size) == (meta_bg_size-1)))
359
388
                                ext2fs_mark_block_bitmap(fs->block_map,
360
 
                                                         group_block + j);
361
 
                        adjblocks = 1 + fs->desc_blocks;
 
389
                                                 group_block + has_super);
362
390
                }
 
391
                
363
392
                adjblocks += 2 + fs->inode_blocks_per_group;
364
393
                
365
394
                numblocks -= adjblocks;
419
448
                                   ext2fs_block_bitmap *ret_bmap)
420
449
{
421
450
        blk_t                   block, b;
422
 
        int                     i,j;
 
451
        unsigned int            j;
 
452
        dgrp_t                  i;
 
453
        unsigned long           meta_bg, meta_bg_size;
 
454
        int                     has_super;
 
455
        unsigned int            old_desc_blocks;
423
456
        ext2fs_block_bitmap     bmap;
424
457
        errcode_t               retval;
425
458
 
428
461
        if (retval)
429
462
                return retval;
430
463
        
 
464
        meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc));
431
465
        block = fs->super->s_first_data_block;
 
466
        if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
 
467
                old_desc_blocks = fs->super->s_first_meta_bg;
 
468
        else
 
469
                old_desc_blocks = fs->desc_blocks;
432
470
        for (i = 0; i < fs->group_desc_count; i++) {
433
 
                if (ext2fs_bg_has_super(fs, i)) {
 
471
                has_super = ext2fs_bg_has_super(fs, i);
 
472
                if (has_super)
434
473
                        /*
435
474
                         * Mark this group's copy of the superblock
436
475
                         */
437
476
                        ext2fs_mark_block_bitmap(bmap, block);
438
477
                
439
 
                        /*
440
 
                         * Mark this group's copy of the descriptors
441
 
                         */
442
 
                        for (j = 0; j < fs->desc_blocks; j++)
443
 
                                ext2fs_mark_block_bitmap(bmap, block + j + 1);
 
478
                meta_bg = i / meta_bg_size;
 
479
                
 
480
                if (!(fs->super->s_feature_incompat &
 
481
                      EXT2_FEATURE_INCOMPAT_META_BG) ||
 
482
                    (meta_bg < fs->super->s_first_meta_bg)) {
 
483
                        if (has_super) {
 
484
                                /*
 
485
                                 * Mark this group's copy of the descriptors
 
486
                                 */
 
487
                                for (j = 0; j < old_desc_blocks; j++)
 
488
                                        ext2fs_mark_block_bitmap(bmap,
 
489
                                                         block + j + 1);
 
490
                        }
 
491
                } else {
 
492
                        if (has_super)
 
493
                                has_super = 1;
 
494
                        if (((i % meta_bg_size) == 0) ||
 
495
                            ((i % meta_bg_size) == 1) ||
 
496
                            ((i % meta_bg_size) == (meta_bg_size-1)))
 
497
                                ext2fs_mark_block_bitmap(bmap,
 
498
                                                         block + has_super);
444
499
                }
445
 
                
 
500
        
446
501
                /*
447
502
                 * Mark the blocks used for the inode table
448
503
                 */
449
504
                for (j = 0, b = fs->group_desc[i].bg_inode_table;
450
 
                     j < fs->inode_blocks_per_group;
 
505
                     j < (unsigned int) fs->inode_blocks_per_group;
451
506
                     j++, b++)
452
507
                        ext2fs_mark_block_bitmap(bmap, b);
453
508
                            
468
523
}
469
524
 
470
525
/*
 
526
 * This function checks to see if a particular block (either a
 
527
 * superblock or a block group descriptor) overlaps with an inode or
 
528
 * block bitmap block, or with the inode table.
 
529
 */
 
530
static void mark_fs_metablock(ext2_resize_t rfs,
 
531
                              ext2fs_block_bitmap meta_bmap,
 
532
                              int group, blk_t blk)
 
533
{
 
534
        ext2_filsys     fs = rfs->new_fs;
 
535
        
 
536
        ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk);
 
537
        ext2fs_mark_block_bitmap(fs->block_map, blk);
 
538
 
 
539
        /*
 
540
         * Check to see if we overlap with the inode or block bitmap,
 
541
         * or the inode tables.  If not, and the block is in use, then
 
542
         * mark it as a block to be moved.
 
543
         */
 
544
        if (IS_BLOCK_BM(fs, group, blk)) {
 
545
                FS_BLOCK_BM(fs, group) = 0;
 
546
                rfs->needed_blocks++;
 
547
        } else if (IS_INODE_BM(fs, group, blk)) {
 
548
                FS_INODE_BM(fs, group) = 0;
 
549
                rfs->needed_blocks++;
 
550
        } else if (IS_INODE_TB(fs, group, blk)) {
 
551
                FS_INODE_TB(fs, group) = 0;
 
552
                rfs->needed_blocks++;
 
553
        } else if (ext2fs_test_block_bitmap(rfs->old_fs->block_map, blk) &&
 
554
                   !ext2fs_test_block_bitmap(meta_bmap, blk)) {
 
555
                ext2fs_mark_block_bitmap(rfs->move_blocks, blk);
 
556
                rfs->needed_blocks++;
 
557
        }
 
558
}
 
559
 
 
560
 
 
561
/*
471
562
 * This routine marks and unmarks reserved blocks in the new block
472
563
 * bitmap.  It also determines which blocks need to be moved and
473
564
 * places this information into the move_blocks bitmap.
474
565
 */
475
566
static errcode_t blocks_to_move(ext2_resize_t rfs)
476
567
{
477
 
        int     i, j, max_groups;
478
 
        blk_t   blk, group_blk;
479
 
        unsigned long old_blocks, new_blocks;
 
568
        int             j, has_super;
 
569
        dgrp_t          i, max_groups;
 
570
        blk_t           blk, group_blk;
 
571
        unsigned long   old_blocks, new_blocks;
 
572
        unsigned int    meta_bg, meta_bg_size;
480
573
        errcode_t       retval;
481
574
        ext2_filsys     fs, old_fs;
482
575
        ext2fs_block_bitmap     meta_bmap;
516
609
                ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk);
517
610
        }
518
611
        
519
 
        old_blocks = old_fs->desc_blocks;
520
 
        new_blocks = fs->desc_blocks;
521
 
 
 
612
        if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) {
 
613
                old_blocks = old_fs->super->s_first_meta_bg;
 
614
                new_blocks = fs->super->s_first_meta_bg;
 
615
        } else {
 
616
                old_blocks = old_fs->desc_blocks;
 
617
                new_blocks = fs->desc_blocks;
 
618
        }
 
619
        
522
620
        if (old_blocks == new_blocks) {
523
621
                retval = 0;
524
622
                goto errout;
554
652
         * If we're increasing the number of descriptor blocks, life
555
653
         * gets interesting....  
556
654
         */
 
655
        meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc));
557
656
        for (i = 0; i < max_groups; i++) {
558
 
                if (!ext2fs_bg_has_super(fs, i))
559
 
                        goto next_group;
560
 
 
561
 
                for (blk = group_blk;
562
 
                     blk < group_blk + 1 + new_blocks; blk++) {
563
 
                        ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk);
564
 
                        ext2fs_mark_block_bitmap(fs->block_map, blk);
565
 
 
566
 
                        /*
567
 
                         * Check to see if we overlap with the inode
568
 
                         * or block bitmap, or the inode tables.  If
569
 
                         * not, and the block is in use, then mark it
570
 
                         * as a block to be moved.
571
 
                         */
572
 
                        if (IS_BLOCK_BM(fs, i, blk)) {
573
 
                                FS_BLOCK_BM(fs, i) = 0;
574
 
                                rfs->needed_blocks++;
575
 
                        } else if (IS_INODE_BM(fs, i, blk)) {
576
 
                                FS_INODE_BM(fs, i) = 0;
577
 
                                rfs->needed_blocks++;
578
 
                        } else if (IS_INODE_TB(fs, i, blk)) {
579
 
                                FS_INODE_TB(fs, i) = 0;
580
 
                                rfs->needed_blocks++;
581
 
                        } else if (ext2fs_test_block_bitmap(old_fs->block_map,
582
 
                                                            blk) &&
583
 
                                   !ext2fs_test_block_bitmap(meta_bmap, blk)) {
584
 
                                ext2fs_mark_block_bitmap(rfs->move_blocks,
585
 
                                                         blk);
586
 
                                rfs->needed_blocks++;
 
657
                has_super = ext2fs_bg_has_super(fs, i);
 
658
                if (has_super)
 
659
                        mark_fs_metablock(rfs, meta_bmap, i, group_blk);
 
660
 
 
661
                meta_bg = i / meta_bg_size;
 
662
                if (!(fs->super->s_feature_incompat &
 
663
                      EXT2_FEATURE_INCOMPAT_META_BG) ||
 
664
                    (meta_bg < fs->super->s_first_meta_bg)) {
 
665
                        if (has_super) {
 
666
                                for (blk = group_blk+1;
 
667
                                     blk < group_blk + 1 + new_blocks; blk++)
 
668
                                        mark_fs_metablock(rfs, meta_bmap, 
 
669
                                                          i, blk);
587
670
                        }
 
671
                } else {
 
672
                        if (has_super)
 
673
                                has_super = 1;
 
674
                        if (((i % meta_bg_size) == 0) ||
 
675
                            ((i % meta_bg_size) == 1) ||
 
676
                            ((i % meta_bg_size) == (meta_bg_size-1)))
 
677
                                mark_fs_metablock(rfs, meta_bmap, i,
 
678
                                                  group_blk + has_super);
588
679
                }
 
680
 
589
681
                if (fs->group_desc[i].bg_inode_table &&
590
682
                    fs->group_desc[i].bg_inode_bitmap &&
591
683
                    fs->group_desc[i].bg_block_bitmap)
751
843
        errcode_t               retval;
752
844
        int                     size, c;
753
845
        int                     to_move, moved;
 
846
        ext2_badblocks_list     badblock_list = 0;
 
847
        int                     bb_modified = 0;
 
848
        
 
849
        retval = ext2fs_read_bb_inode(old_fs, &badblock_list);
 
850
        if (retval)
 
851
                return retval;
754
852
 
755
853
        new_blk = fs->super->s_first_data_block;
756
854
        if (!rfs->itable_buf) {
757
855
                retval = ext2fs_get_mem(fs->blocksize *
758
856
                                        fs->inode_blocks_per_group,
759
 
                                        (void **) &rfs->itable_buf);
 
857
                                        &rfs->itable_buf);
760
858
                if (retval)
761
859
                        return retval;
762
860
        }
776
874
                        continue;
777
875
                if (!ext2fs_test_block_bitmap(rfs->move_blocks, blk))
778
876
                        continue;
 
877
                if (ext2fs_badblocks_list_test(badblock_list, blk)) {
 
878
                        ext2fs_badblocks_list_del(badblock_list, blk);
 
879
                        bb_modified++;
 
880
                        continue;
 
881
                }
779
882
 
780
883
                new_blk = get_new_block(rfs);
781
884
                if (!new_blk) {
788
891
        }
789
892
        
790
893
        if (to_move == 0) {
 
894
                if (rfs->bmap) {
 
895
                        ext2fs_free_extent_table(rfs->bmap);
 
896
                        rfs->bmap = 0;
 
897
                }
791
898
                retval = 0;
792
899
                goto errout;
793
900
        }
841
948
        }
842
949
 
843
950
errout:
 
951
        if (badblock_list) {
 
952
                if (!retval && bb_modified)
 
953
                        retval = ext2fs_update_bb_inode(old_fs,
 
954
                                                        badblock_list);
 
955
                ext2fs_badblocks_list_free(badblock_list);
 
956
        }
844
957
        return retval;
845
958
}
846
959
 
863
976
};
864
977
 
865
978
static int process_block(ext2_filsys fs, blk_t  *block_nr,
866
 
                         e2_blkcnt_t blockcnt, blk_t ref_block,
867
 
                         int ref_offset, void *priv_data)
 
979
                         e2_blkcnt_t blockcnt, 
 
980
                         blk_t ref_block EXT2FS_ATTR((unused)),
 
981
                         int ref_offset EXT2FS_ATTR((unused)), void *priv_data)
868
982
{
869
983
        struct process_block_struct *pb;
870
984
        errcode_t       retval;
901
1015
/*
902
1016
 * Progress callback
903
1017
 */
904
 
static errcode_t progress_callback(ext2_filsys fs, ext2_inode_scan scan,
 
1018
static errcode_t progress_callback(ext2_filsys fs, 
 
1019
                                   ext2_inode_scan scan EXT2FS_ATTR((unused)),
905
1020
                                   dgrp_t group, void * priv_data)
906
1021
{
907
1022
        ext2_resize_t rfs = (ext2_resize_t) priv_data;
935
1050
        int                     group;
936
1051
        char                    *block_buf = 0;
937
1052
        ext2_ino_t              start_to_move;
938
 
        blk_t                   orig_size;
 
1053
        blk_t                   orig_size, new_block;
939
1054
        
940
1055
        if ((rfs->old_fs->group_desc_count <=
941
1056
             rfs->new_fs->group_desc_count) &&
958
1073
 
959
1074
        retval = ext2fs_init_dblist(rfs->old_fs, 0);
960
1075
        if (retval) goto errout;
961
 
        retval = ext2fs_get_mem(rfs->old_fs->blocksize * 3,
962
 
                                (void **) &block_buf);
 
1076
        retval = ext2fs_get_mem(rfs->old_fs->blocksize * 3, &block_buf);
963
1077
        if (retval) goto errout;
964
1078
 
965
1079
        start_to_move = (rfs->new_fs->group_desc_count *
992
1106
                pb.is_dir = LINUX_S_ISDIR(inode.i_mode);
993
1107
                pb.changed = 0;
994
1108
 
 
1109
                if (inode.i_file_acl && rfs->bmap) {
 
1110
                        new_block = ext2fs_extent_translate(rfs->bmap, 
 
1111
                                                            inode.i_file_acl);
 
1112
                        if (new_block) {
 
1113
                                inode.i_file_acl = new_block;
 
1114
                                retval = ext2fs_write_inode(rfs->old_fs, 
 
1115
                                                            ino, &inode);
 
1116
                                if (retval) goto errout;
 
1117
                        }
 
1118
                }
 
1119
                
995
1120
                if (ext2fs_inode_has_valid_blocks(&inode) &&
996
1121
                    (rfs->bmap || pb.is_dir)) {
997
1122
                        pb.ino = ino;
1028
1153
                        retval = ext2fs_read_inode(rfs->old_fs, ino, &inode);
1029
1154
                        if (retval) goto errout;
1030
1155
                }
 
1156
                inode.i_ctime = time(0);
1031
1157
                retval = ext2fs_write_inode(rfs->old_fs, new_inode, &inode);
1032
1158
                if (retval) goto errout;
1033
1159
 
1057
1183
        if (scan)
1058
1184
                ext2fs_close_inode_scan(scan);
1059
1185
        if (block_buf)
1060
 
                ext2fs_free_mem((void **) &block_buf);
 
1186
                ext2fs_free_mem(&block_buf);
1061
1187
        return retval;
1062
1188
}
1063
1189
 
1075
1201
        int             num;
1076
1202
};
1077
1203
 
1078
 
static int check_and_change_inodes(ext2_ino_t dir, int entry,
 
1204
static int check_and_change_inodes(ext2_ino_t dir, 
 
1205
                                   int entry EXT2FS_ATTR((unused)),
1079
1206
                                   struct ext2_dir_entry *dirent, int offset,
1080
 
                                   int  blocksize, char *buf, void *priv_data)
 
1207
                                   int  blocksize EXT2FS_ATTR((unused)),
 
1208
                                   char *buf EXT2FS_ATTR((unused)), 
 
1209
                                   void *priv_data)
1081
1210
{
1082
1211
        struct istruct *is = (struct istruct *) priv_data;
1083
 
        ext2_ino_t      new_inode;
 
1212
        struct ext2_inode       inode;
 
1213
        ext2_ino_t              new_inode;
 
1214
        errcode_t               retval;
1084
1215
 
1085
1216
        if (is->rfs->progress && offset == 0) {
1086
1217
                io_channel_flush(is->rfs->old_fs->io);
1107
1238
 
1108
1239
        dirent->inode = new_inode;
1109
1240
 
 
1241
        /* Update the directory mtime and ctime */
 
1242
        retval = ext2fs_read_inode(is->rfs->old_fs, dir, &inode);
 
1243
        if (retval == 0) {
 
1244
                inode.i_mtime = inode.i_ctime = time(0);
 
1245
                ext2fs_write_inode(is->rfs->old_fs, dir, &inode);
 
1246
        }
 
1247
 
1110
1248
        return DIRENT_CHANGED;
1111
1249
}
1112
1250
 
1173
1311
 */
1174
1312
static errcode_t move_itables(ext2_resize_t rfs)
1175
1313
{
1176
 
        int             i, n, num, max_groups, size, diff;
 
1314
        int             n, num, size, diff;
 
1315
        dgrp_t          i, max_groups;
1177
1316
        ext2_filsys     fs = rfs->new_fs;
1178
1317
        char            *cp;
1179
1318
        blk_t           old_blk, new_blk;
1186
1325
 
1187
1326
        size = fs->blocksize * fs->inode_blocks_per_group;
1188
1327
        if (!rfs->itable_buf) {
1189
 
                retval = ext2fs_get_mem(size, (void **) &rfs->itable_buf);
 
1328
                retval = ext2fs_get_mem(size, &rfs->itable_buf);
1190
1329
                if (retval)
1191
1330
                        return retval;
1192
1331
        }
1295
1434
{
1296
1435
        blk_t           blk;
1297
1436
        ext2_ino_t      ino;
1298
 
        int             group = 0;
1299
 
        int             count = 0;
 
1437
        unsigned int    group = 0;
 
1438
        unsigned int    count = 0;
1300
1439
        int             total_free = 0;
1301
1440
        int             group_free = 0;
1302
1441