Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > DoxygenMemory.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: Mke2fs 00003 * FILE: Memory.c 00004 * PROGRAMMER: Matt Wu <mattwu@163.com> 00005 * HOMEPAGE: http://ext2.yeah.net 00006 */ 00007 00008 /* INCLUDES **************************************************************/ 00009 00010 #include "Mke2fs.h" 00011 #include <debug.h> 00012 00013 /* DEFINITIONS ***********************************************************/ 00014 00015 extern char *device_name; 00016 00017 /* FUNCTIONS *************************************************************/ 00018 00019 00020 /* 00021 * Return the group # of an inode number 00022 */ 00023 int ext2_group_of_ino(PEXT2_FILESYS fs, ULONG ino) 00024 { 00025 return (ino - 1) / fs->ext2_sb->s_inodes_per_group; 00026 } 00027 00028 /* 00029 * Return the group # of a block 00030 */ 00031 int ext2_group_of_blk(PEXT2_FILESYS fs, ULONG blk) 00032 { 00033 return (blk - fs->ext2_sb->s_first_data_block) / 00034 fs->ext2_sb->s_blocks_per_group; 00035 } 00036 00037 void ext2_inode_alloc_stats2(PEXT2_FILESYS fs, ULONG ino, 00038 int inuse, int isdir) 00039 { 00040 int group = ext2_group_of_ino(fs, ino); 00041 00042 if (inuse > 0) 00043 ext2_mark_inode_bitmap(fs->inode_map, ino); 00044 else 00045 ext2_unmark_inode_bitmap(fs->inode_map, ino); 00046 00047 fs->group_desc[group].bg_free_inodes_count -= inuse; 00048 00049 if (isdir) 00050 fs->group_desc[group].bg_used_dirs_count += inuse; 00051 00052 fs->ext2_sb->s_free_inodes_count -= inuse; 00053 } 00054 00055 00056 void ext2_inode_alloc_stats(PEXT2_FILESYS fs, ULONG ino, int inuse) 00057 { 00058 ext2_inode_alloc_stats2(fs, ino, inuse, 0); 00059 } 00060 00061 void ext2_block_alloc_stats(PEXT2_FILESYS fs, ULONG blk, int inuse) 00062 { 00063 int group = ext2_group_of_blk(fs, blk); 00064 00065 if (inuse > 0) 00066 ext2_mark_block_bitmap(fs->block_map, blk); 00067 else 00068 ext2_unmark_block_bitmap(fs->block_map, blk); 00069 00070 fs->group_desc[group].bg_free_blocks_count -= inuse; 00071 fs->ext2_sb->s_free_blocks_count -= inuse; 00072 } 00073 00074 00075 bool ext2_allocate_tables(PEXT2_FILESYS Ext2Sys) 00076 { 00077 bool retval; 00078 ULONG i; 00079 00080 for (i = 0; i < Ext2Sys->group_desc_count; i++) 00081 { 00082 retval = ext2_allocate_group_table(Ext2Sys, i, Ext2Sys->block_map); 00083 00084 if (!retval) 00085 return retval; 00086 } 00087 00088 return true; 00089 } 00090 00091 00092 bool ext2_allocate_group_table(PEXT2_FILESYS fs, ULONG group, 00093 PEXT2_BLOCK_BITMAP bmap) 00094 { 00095 bool retval; 00096 ULONG group_blk, start_blk, last_blk, new_blk, blk, j; 00097 00098 group_blk = fs->ext2_sb->s_first_data_block + 00099 (group * fs->ext2_sb->s_blocks_per_group); 00100 00101 last_blk = group_blk + fs->ext2_sb->s_blocks_per_group; 00102 if (last_blk >= fs->ext2_sb->s_blocks_count) 00103 last_blk = fs->ext2_sb->s_blocks_count - 1; 00104 00105 start_blk = group_blk + 3 + fs->desc_blocks; 00106 if (start_blk > last_blk) 00107 start_blk = group_blk; 00108 00109 if (!bmap) 00110 bmap = fs->block_map; 00111 00112 /* 00113 * Allocate the inode table 00114 */ 00115 if (!fs->group_desc[group].bg_inode_table) 00116 { 00117 retval = ext2_get_free_blocks(fs, start_blk, last_blk, 00118 fs->inode_blocks_per_group, 00119 bmap, &new_blk); 00120 if (!retval) 00121 return retval; 00122 00123 for (j=0, blk = new_blk; 00124 j < fs->inode_blocks_per_group; 00125 j++, blk++) 00126 ext2_mark_block_bitmap(bmap, blk); 00127 00128 fs->group_desc[group].bg_inode_table = new_blk; 00129 } 00130 00131 /* 00132 * Allocate the block and inode bitmaps, if necessary 00133 */ 00134 if (fs->stride) 00135 { 00136 start_blk += fs->inode_blocks_per_group; 00137 start_blk += ((fs->stride * group) % 00138 (last_blk - start_blk)); 00139 if (start_blk > last_blk) 00140 /* should never happen */ 00141 start_blk = group_blk; 00142 } 00143 else 00144 { 00145 start_blk = group_blk; 00146 } 00147 00148 if (!fs->group_desc[group].bg_block_bitmap) 00149 { 00150 retval = ext2_get_free_blocks(fs, start_blk, last_blk, 00151 1, bmap, &new_blk); 00152 00153 if (!retval) 00154 retval = ext2_get_free_blocks(fs, group_blk, 00155 last_blk, 1, bmap, &new_blk); 00156 00157 if (!retval) 00158 return retval; 00159 00160 ext2_mark_block_bitmap(bmap, new_blk); 00161 fs->group_desc[group].bg_block_bitmap = new_blk; 00162 } 00163 00164 if (!fs->group_desc[group].bg_inode_bitmap) 00165 { 00166 retval = ext2_get_free_blocks(fs, start_blk, last_blk, 00167 1, bmap, &new_blk); 00168 if (!retval) 00169 retval = ext2_get_free_blocks(fs, group_blk, 00170 last_blk, 1, bmap, &new_blk); 00171 if (!retval) 00172 return retval; 00173 00174 ext2_mark_block_bitmap(bmap, new_blk); 00175 fs->group_desc[group].bg_inode_bitmap = new_blk; 00176 } 00177 00178 return true; 00179 } 00180 00181 00182 bool ext2_get_free_blocks(PEXT2_FILESYS fs, ULONG start, ULONG finish, 00183 int num, PEXT2_BLOCK_BITMAP map, ULONG *ret) 00184 { 00185 ULONG b = start; 00186 00187 if (!map) 00188 map = fs->block_map; 00189 00190 if (!map) 00191 return false; 00192 00193 if (!b) 00194 b = fs->ext2_sb->s_first_data_block; 00195 00196 if (!finish) 00197 finish = start; 00198 00199 if (!num) 00200 num = 1; 00201 00202 do 00203 { 00204 if (b+num-1 > fs->ext2_sb->s_blocks_count) 00205 b = fs->ext2_sb->s_first_data_block; 00206 00207 if (ext2_test_block_bitmap_range(map, b, num)) 00208 { 00209 *ret = b; 00210 return true; 00211 } 00212 00213 b++; 00214 00215 } while (b != finish); 00216 00217 return false; 00218 } 00219 00220 00221 bool write_inode_tables(PEXT2_FILESYS fs) 00222 { 00223 bool retval; 00224 ULONG blk, num; 00225 int i; 00226 00227 for (i = 0; (ULONG)i < fs->group_desc_count; i++) 00228 { 00229 blk = fs->group_desc[i].bg_inode_table; 00230 num = fs->inode_blocks_per_group; 00231 00232 retval = zero_blocks(fs, blk, num, &blk, &num); 00233 if (!retval) 00234 { 00235 DPRINT1("\nMke2fs: Could not write %lu blocks " 00236 "in inode table starting at %lu.\n", 00237 num, blk); 00238 00239 zero_blocks(0, 0, 0, 0, 0); 00240 return false; 00241 } 00242 } 00243 00244 zero_blocks(0, 0, 0, 0, 0); 00245 00246 return true; 00247 } 00248 00249 00250 /* 00251 * Stupid algorithm --- we now just search forward starting from the 00252 * goal. Should put in a smarter one someday.... 00253 */ 00254 bool ext2_new_block(PEXT2_FILESYS fs, ULONG goal, 00255 PEXT2_BLOCK_BITMAP map, ULONG *ret) 00256 { 00257 ULONG i; 00258 00259 if (!map) 00260 map = fs->block_map; 00261 00262 if (!map) 00263 return false; 00264 00265 if (!goal || (goal >= fs->ext2_sb->s_blocks_count)) 00266 goal = fs->ext2_sb->s_first_data_block; 00267 00268 i = goal; 00269 00270 do 00271 { 00272 if (!ext2_test_block_bitmap(map, i)) 00273 { 00274 *ret = i; 00275 return true; 00276 } 00277 00278 i++; 00279 00280 if (i >= fs->ext2_sb->s_blocks_count) 00281 i = fs->ext2_sb->s_first_data_block; 00282 00283 } while (i != goal); 00284 00285 return false; 00286 } 00287 00288 00289 /* 00290 * This function zeros out the allocated block, and updates all of the 00291 * appropriate filesystem records. 00292 */ 00293 bool ext2_alloc_block(PEXT2_FILESYS fs, ULONG goal, ULONG *ret) 00294 { 00295 bool retval; 00296 ULONG block; 00297 char *buf = NULL; 00298 00299 buf = (char *)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, fs->blocksize); 00300 if (!buf) 00301 return false; 00302 00303 if (!fs->block_map) 00304 { 00305 retval = ext2_read_block_bitmap(fs); 00306 if (!retval) 00307 goto fail; 00308 } 00309 00310 retval = ext2_new_block(fs, goal, 0, &block); 00311 00312 if (!retval) 00313 goto fail; 00314 00315 retval = NT_SUCCESS(Ext2WriteDisk( 00316 fs, 00317 ((LONGLONG)block * fs->blocksize), 00318 fs->blocksize, (unsigned char *)buf)); 00319 00320 if (!retval) 00321 { 00322 goto fail; 00323 } 00324 00325 ext2_block_alloc_stats(fs, block, +1); 00326 *ret = block; 00327 00328 if (buf) 00329 { 00330 RtlFreeHeap(RtlGetProcessHeap(), 0, buf); 00331 } 00332 00333 return true; 00334 00335 fail: 00336 00337 if (buf) 00338 { 00339 RtlFreeHeap(RtlGetProcessHeap(), 0, buf); 00340 } 00341 00342 return false; 00343 } 00344 00345 00346 /* 00347 * Create new directory block 00348 */ 00349 bool ext2_new_dir_block(PEXT2_FILESYS fs, ULONG dir_ino, 00350 ULONG parent_ino, char **block) 00351 { 00352 PEXT2_DIR_ENTRY dir = NULL; 00353 char *buf; 00354 int rec_len; 00355 int filetype = 0; 00356 00357 buf = (char *)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, fs->blocksize); 00358 if (!buf) 00359 return false; 00360 00361 dir = (PEXT2_DIR_ENTRY) buf; 00362 dir->rec_len = fs->blocksize; 00363 00364 if (dir_ino) 00365 { 00366 if (fs->ext2_sb->s_feature_incompat & 00367 EXT2_FEATURE_INCOMPAT_FILETYPE) 00368 filetype = EXT2_FT_DIR << 8; 00369 /* 00370 * Set up entry for '.' 00371 */ 00372 dir->inode = dir_ino; 00373 dir->name_len = 1 | filetype; 00374 dir->name[0] = '.'; 00375 rec_len = dir->rec_len - EXT2_DIR_REC_LEN(1); 00376 dir->rec_len = EXT2_DIR_REC_LEN(1); 00377 00378 /* 00379 * Set up entry for '..' 00380 */ 00381 dir = (struct ext2_dir_entry *) (buf + dir->rec_len); 00382 dir->rec_len = rec_len; 00383 dir->inode = parent_ino; 00384 dir->name_len = 2 | filetype; 00385 dir->name[0] = '.'; 00386 dir->name[1] = '.'; 00387 } 00388 00389 *block = buf; 00390 00391 return true; 00392 } 00393 00394 bool ext2_write_block(PEXT2_FILESYS fs, ULONG block, void *inbuf) 00395 { 00396 bool retval = false; 00397 00398 retval = NT_SUCCESS(Ext2WriteDisk( 00399 fs, 00400 ((ULONGLONG)block * fs->blocksize), 00401 fs->blocksize, (unsigned char *)inbuf)); 00402 00403 return retval; 00404 } 00405 00406 bool ext2_read_block(PEXT2_FILESYS fs, ULONG block, void *inbuf) 00407 { 00408 bool retval = false; 00409 00410 retval = NT_SUCCESS(Ext2ReadDisk( 00411 fs, 00412 ((ULONGLONG)block * fs->blocksize), 00413 fs->blocksize, (unsigned char *)inbuf)); 00414 00415 return retval; 00416 } Generated on Fri May 25 2012 04:34:40 for ReactOS by
1.7.6.1
|