1 /* 2 ext2_meta.c -- ext2 metadata mover 3 Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <config.h> 20 21 #ifndef DISCOVER_ONLY 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include "ext2.h" 26 27 int ext2_metadata_push(struct ext2_fs *fs, blk_t newsize) 28 { 29 int i; 30 int newgdblocks; 31 blk_t newitoffset; 32 33 newgdblocks = ped_div_round_up (newsize 34 - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb), 35 EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)); 36 newgdblocks = ped_div_round_up (newgdblocks 37 * sizeof(struct ext2_group_desc), 38 fs->blocksize); 39 newitoffset = newgdblocks + 3; 40 41 if (newitoffset <= fs->itoffset) 42 return 1; 43 44 for (i=0;i<fs->numgroups;i++) 45 { 46 blk_t diff; 47 blk_t j; 48 blk_t fromblock; 49 blk_t start; 50 51 start = (i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)) 52 + EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); 53 54 if (EXT2_GROUP_INODE_TABLE(fs->gd[i]) >= start + newitoffset 55 && EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]) >= start + newitoffset - 2 56 && EXT2_GROUP_INODE_BITMAP(fs->gd[i]) >= start + newitoffset - 1) 57 continue; 58 59 diff = newitoffset - (EXT2_GROUP_INODE_TABLE(fs->gd[i]) - start); 60 61 /* inode table */ 62 fromblock = EXT2_GROUP_INODE_TABLE(fs->gd[i]) + fs->inodeblocks; 63 64 if (fs->opt_debug) 65 { 66 for (j=0;j<diff;j++) 67 if (!ext2_get_block_state(fs, fromblock+j)) 68 { 69 fprintf(stderr, 70 "error: block relocator " 71 "should have relocated " 72 "%i\n", 73 fromblock); 74 75 return 0; 76 } 77 } 78 79 for (j=0;j<diff;j++) 80 if (!ext2_set_block_state(fs, fromblock+j, 1, 0)) 81 return 0; 82 83 if (!ext2_move_blocks(fs, 84 EXT2_GROUP_INODE_TABLE(fs->gd[i]), 85 fs->inodeblocks, 86 EXT2_GROUP_INODE_TABLE(fs->gd[i]) + diff)) 87 return 0; 88 fs->gd[i].bg_inode_table = PED_CPU_TO_LE32 ( 89 EXT2_GROUP_INODE_TABLE(fs->gd[i]) + diff); 90 fs->metadirty |= EXT2_META_GD; 91 92 if (fs->opt_safe) 93 if (!ext2_sync(fs)) 94 return 0; 95 96 /* block bitmap and inode bitmap */ 97 fromblock = EXT2_GROUP_INODE_TABLE(fs->gd[i]); 98 if (ext2_is_group_sparse(fs, i)) 99 { 100 if (!ext2_copy_block(fs, 101 EXT2_GROUP_INODE_BITMAP(fs->gd[i]), 102 EXT2_GROUP_INODE_BITMAP(fs->gd[i]) + diff)) 103 return 0; 104 fs->gd[i].bg_inode_bitmap = PED_CPU_TO_LE32 ( 105 EXT2_GROUP_INODE_BITMAP(fs->gd[i]) + diff); 106 fs->metadirty |= EXT2_META_GD; 107 108 if (fs->opt_safe) 109 if (!ext2_sync(fs)) 110 return 0; 111 112 if (!ext2_copy_block(fs, 113 EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]), 114 EXT2_GROUP_BLOCK_BITMAP(fs->gd[i])+diff)) 115 return 0; 116 fs->gd[i].bg_block_bitmap = PED_CPU_TO_LE32 ( 117 EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]) + diff); 118 fs->metadirty |= EXT2_META_GD; 119 120 if (fs->opt_safe) 121 if (!ext2_sync(fs)) 122 return 0; 123 124 fromblock = EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]); 125 } 126 127 ext2_zero_blocks(fs, fromblock-diff, diff); 128 for (j=0;j<diff;j++) 129 if (!ext2_set_block_state(fs, fromblock+j-diff, 0, 0)) 130 return 0; 131 132 if (fs->opt_verbose) 133 fprintf(stderr, 134 "ext2_metadata_push: group %i/%i\r", 135 i+1, fs->numgroups); 136 } 137 138 fs->itoffset = newitoffset; 139 140 if (fs->opt_verbose) 141 fputc ('\n', stderr); 142 143 return 1; 144 } 145 #endif /* !DISCOVER_ONLY */