67
68
* This is the top-level routine which does the dirty deed....
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,
72
73
unsigned long max_val))
82
83
* Create the data structure
84
retval = ext2fs_get_mem(sizeof(struct ext2_resize_struct),
85
retval = ext2fs_get_mem(sizeof(struct ext2_resize_struct), &rfs);
88
88
memset(rfs, 0, sizeof(struct ext2_resize_struct));
346
if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
347
old_desc_blocks = fs->super->s_first_meta_bg;
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,
355
363
numblocks = fs->super->s_blocks_per_group;
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);
367
ext2fs_mark_block_bitmap(fs->block_map, group_block);
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)) {
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;
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,
361
adjblocks = 1 + fs->desc_blocks;
389
group_block + has_super);
363
392
adjblocks += 2 + fs->inode_blocks_per_group;
365
394
numblocks -= adjblocks;
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;
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);
435
474
* Mark this group's copy of the superblock
437
476
ext2fs_mark_block_bitmap(bmap, block);
440
* Mark this group's copy of the descriptors
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;
480
if (!(fs->super->s_feature_incompat &
481
EXT2_FEATURE_INCOMPAT_META_BG) ||
482
(meta_bg < fs->super->s_first_meta_bg)) {
485
* Mark this group's copy of the descriptors
487
for (j = 0; j < old_desc_blocks; j++)
488
ext2fs_mark_block_bitmap(bmap,
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,
447
502
* Mark the blocks used for the inode table
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;
452
507
ext2fs_mark_block_bitmap(bmap, b);
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.
530
static void mark_fs_metablock(ext2_resize_t rfs,
531
ext2fs_block_bitmap meta_bmap,
532
int group, blk_t blk)
534
ext2_filsys fs = rfs->new_fs;
536
ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk);
537
ext2fs_mark_block_bitmap(fs->block_map, blk);
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.
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++;
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.
475
566
static errcode_t blocks_to_move(ext2_resize_t rfs)
477
int i, j, max_groups;
478
blk_t blk, group_blk;
479
unsigned long old_blocks, new_blocks;
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);
519
old_blocks = old_fs->desc_blocks;
520
new_blocks = fs->desc_blocks;
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;
616
old_blocks = old_fs->desc_blocks;
617
new_blocks = fs->desc_blocks;
522
620
if (old_blocks == new_blocks) {
554
652
* If we're increasing the number of descriptor blocks, life
555
653
* gets interesting....
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))
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);
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.
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,
583
!ext2fs_test_block_bitmap(meta_bmap, blk)) {
584
ext2fs_mark_block_bitmap(rfs->move_blocks,
586
rfs->needed_blocks++;
657
has_super = ext2fs_bg_has_super(fs, i);
659
mark_fs_metablock(rfs, meta_bmap, i, group_blk);
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)) {
666
for (blk = group_blk+1;
667
blk < group_blk + 1 + new_blocks; blk++)
668
mark_fs_metablock(rfs, meta_bmap,
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);
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;
753
845
int to_move, moved;
846
ext2_badblocks_list badblock_list = 0;
849
retval = ext2fs_read_bb_inode(old_fs, &badblock_list);
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);
777
875
if (!ext2fs_test_block_bitmap(rfs->move_blocks, blk))
877
if (ext2fs_badblocks_list_test(badblock_list, blk)) {
878
ext2fs_badblocks_list_del(badblock_list, blk);
780
883
new_blk = get_new_block(rfs);
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)
869
983
struct process_block_struct *pb;
870
984
errcode_t retval;
902
1016
* Progress callback
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)
907
1022
ext2_resize_t rfs = (ext2_resize_t) priv_data;
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;
965
1079
start_to_move = (rfs->new_fs->group_desc_count *
992
1106
pb.is_dir = LINUX_S_ISDIR(inode.i_mode);
1109
if (inode.i_file_acl && rfs->bmap) {
1110
new_block = ext2fs_extent_translate(rfs->bmap,
1113
inode.i_file_acl = new_block;
1114
retval = ext2fs_write_inode(rfs->old_fs,
1116
if (retval) goto errout;
995
1120
if (ext2fs_inode_has_valid_blocks(&inode) &&
996
1121
(rfs->bmap || pb.is_dir)) {
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)),
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;
1085
1216
if (is->rfs->progress && offset == 0) {
1086
1217
io_channel_flush(is->rfs->old_fs->io);
1108
1239
dirent->inode = new_inode;
1241
/* Update the directory mtime and ctime */
1242
retval = ext2fs_read_inode(is->rfs->old_fs, dir, &inode);
1244
inode.i_mtime = inode.i_ctime = time(0);
1245
ext2fs_write_inode(is->rfs->old_fs, dir, &inode);
1110
1248
return DIRENT_CHANGED;