|
Lines 50-55
typedef unsigned int __u32;
Link Here
|
| 50 |
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) |
50 |
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) |
| 51 |
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) |
51 |
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) |
| 52 |
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) |
52 |
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) |
|
|
53 |
/* Inode flags */ |
| 54 |
#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ |
| 53 |
|
55 |
|
| 54 |
/* include/linux/ext2_fs.h */ |
56 |
/* include/linux/ext2_fs.h */ |
| 55 |
struct ext2_super_block |
57 |
struct ext2_super_block |
|
Lines 235-241
struct ext2_dir_entry
Link Here
|
| 235 |
#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) |
237 |
#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) |
| 236 |
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \ |
238 |
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \ |
| 237 |
~EXT2_DIR_ROUND) |
239 |
~EXT2_DIR_ROUND) |
|
|
240 |
/* linux/ext4_fs_extents.h */ |
| 241 |
/* |
| 242 |
* This is the extent on-disk structure. |
| 243 |
* It's used at the bottom of the tree. |
| 244 |
*/ |
| 245 |
struct ext4_extent { |
| 246 |
__u32 ee_block; /* first logical block extent covers */ |
| 247 |
__u16 ee_len; /* number of blocks covered by extent */ |
| 248 |
__u16 ee_start_hi; /* high 16 bits of physical block */ |
| 249 |
__u32 ee_start; /* low 32 bits of physical block */ |
| 250 |
}; |
| 238 |
|
251 |
|
|
|
252 |
/* |
| 253 |
* This is index on-disk structure. |
| 254 |
* It's used at all the levels except the bottom. |
| 255 |
*/ |
| 256 |
struct ext4_extent_idx { |
| 257 |
__u32 ei_block; /* index covers logical blocks from 'block' */ |
| 258 |
__u32 ei_leaf; /* pointer to the physical block of the next * |
| 259 |
* level. leaf or next index could be there */ |
| 260 |
__u16 ei_leaf_hi; /* high 16 bits of physical block */ |
| 261 |
__u16 ei_unused; |
| 262 |
}; |
| 263 |
|
| 264 |
/* |
| 265 |
* Each block (leaves and indexes), even inode-stored has header. |
| 266 |
*/ |
| 267 |
struct ext4_extent_header { |
| 268 |
__u16 eh_magic; /* probably will support different formats */ |
| 269 |
__u16 eh_entries; /* number of valid entries */ |
| 270 |
__u16 eh_max; /* capacity of store in entries */ |
| 271 |
__u16 eh_depth; /* has tree real underlying blocks? */ |
| 272 |
__u32 eh_generation; /* generation of the tree */ |
| 273 |
}; |
| 274 |
|
| 275 |
#define EXT4_EXT_MAGIC 0xf30a |
| 239 |
|
276 |
|
| 240 |
/* ext2/super.c */ |
277 |
/* ext2/super.c */ |
| 241 |
#define log2(n) ffz(~(n)) |
278 |
#define log2(n) ffz(~(n)) |
|
Lines 327-332
ext2_rdfsb (int fsblock, int buffer)
Link Here
|
| 327 |
EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer); |
364 |
EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer); |
| 328 |
} |
365 |
} |
| 329 |
|
366 |
|
|
|
367 |
/* Walk through extents index tree to find the good leaf */ |
| 368 |
static struct ext4_extent_header * |
| 369 |
ext4_recurse_extent_index(struct ext4_extent_header *extent_block, int logical_block) |
| 370 |
{ |
| 371 |
int i; |
| 372 |
struct ext4_extent_idx *index = (struct ext4_extent_idx *) (extent_block + 1); |
| 373 |
if (extent_block->eh_magic != EXT4_EXT_MAGIC) |
| 374 |
return NULL; |
| 375 |
if (extent_block->eh_depth == 0) |
| 376 |
return extent_block; |
| 377 |
for (i = 0; i < extent_block->eh_entries; i++) |
| 378 |
{ |
| 379 |
if (logical_block < index[i].ei_block) |
| 380 |
break; |
| 381 |
} |
| 382 |
if (i == 0 || !ext2_rdfsb(index[i-1].ei_leaf, DATABLOCK1)) |
| 383 |
return NULL; |
| 384 |
return (ext4_recurse_extent_index((struct ext4_extent_header *) DATABLOCK1, logical_block)); |
| 385 |
} |
| 386 |
|
| 330 |
/* from |
387 |
/* from |
| 331 |
ext2/inode.c:ext2_bmap() |
388 |
ext2/inode.c:ext2_bmap() |
| 332 |
*/ |
389 |
*/ |
|
Lines 355-437
ext2fs_block_map (int logical_block)
Link Here
|
| 355 |
} |
412 |
} |
| 356 |
printf ("logical block %d\n", logical_block); |
413 |
printf ("logical block %d\n", logical_block); |
| 357 |
#endif /* E2DEBUG */ |
414 |
#endif /* E2DEBUG */ |
| 358 |
|
415 |
/* standard ext2 inode */ |
| 359 |
/* if it is directly pointed to by the inode, return that physical addr */ |
416 |
if (!(INODE->i_flags & EXT4_EXTENTS_FL)) |
| 360 |
if (logical_block < EXT2_NDIR_BLOCKS) |
417 |
{ |
| 361 |
{ |
418 |
/* if it is directly pointed to by the inode, return that physical addr */ |
| 362 |
#ifdef E2DEBUG |
419 |
if (logical_block < EXT2_NDIR_BLOCKS) |
| 363 |
printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block])); |
420 |
{ |
| 364 |
printf ("returning %d\n", INODE->i_block[logical_block]); |
421 |
#ifdef E2DEBUG |
| 365 |
#endif /* E2DEBUG */ |
422 |
printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block])); |
| 366 |
return INODE->i_block[logical_block]; |
423 |
printf ("returning %d\n", INODE->i_block[logical_block]); |
| 367 |
} |
424 |
#endif /* E2DEBUG */ |
| 368 |
/* else */ |
425 |
return INODE->i_block[logical_block]; |
| 369 |
logical_block -= EXT2_NDIR_BLOCKS; |
426 |
} |
| 370 |
/* try the indirect block */ |
427 |
/* else */ |
| 371 |
if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK)) |
428 |
logical_block -= EXT2_NDIR_BLOCKS; |
| 372 |
{ |
429 |
/* try the indirect block */ |
| 373 |
if (mapblock1 != 1 |
430 |
if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK)) |
| 374 |
&& !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1)) |
431 |
{ |
| 375 |
{ |
432 |
if (mapblock1 != 1 && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1)) |
| 376 |
errnum = ERR_FSYS_CORRUPT; |
433 |
{ |
| 377 |
return -1; |
434 |
errnum = ERR_FSYS_CORRUPT; |
| 378 |
} |
435 |
return -1; |
| 379 |
mapblock1 = 1; |
436 |
} |
| 380 |
return ((__u32 *) DATABLOCK1)[logical_block]; |
437 |
mapblock1 = 1; |
| 381 |
} |
438 |
return ((__u32 *) DATABLOCK1)[logical_block]; |
| 382 |
/* else */ |
439 |
} |
| 383 |
logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK); |
440 |
/* else */ |
| 384 |
/* now try the double indirect block */ |
441 |
logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK); |
| 385 |
if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2))) |
442 |
/* now try the double indirect block */ |
| 386 |
{ |
443 |
if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2))) |
| 387 |
int bnum; |
444 |
{ |
| 388 |
if (mapblock1 != 2 |
445 |
int bnum; |
| 389 |
&& !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1)) |
446 |
if (mapblock1 != 2 && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1)) |
| 390 |
{ |
447 |
{ |
| 391 |
errnum = ERR_FSYS_CORRUPT; |
448 |
errnum = ERR_FSYS_CORRUPT; |
| 392 |
return -1; |
449 |
return -1; |
| 393 |
} |
450 |
} |
| 394 |
mapblock1 = 2; |
451 |
mapblock1 = 2; |
| 395 |
if ((bnum = (((__u32 *) DATABLOCK1) |
452 |
if ((bnum = (((__u32 *) DATABLOCK1) [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)])) != mapblock2 && !ext2_rdfsb (bnum, DATABLOCK2)) |
| 396 |
[logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)])) |
453 |
{ |
| 397 |
!= mapblock2 |
454 |
errnum = ERR_FSYS_CORRUPT; |
| 398 |
&& !ext2_rdfsb (bnum, DATABLOCK2)) |
455 |
return -1; |
| 399 |
{ |
456 |
} |
| 400 |
errnum = ERR_FSYS_CORRUPT; |
457 |
mapblock2 = bnum; |
| 401 |
return -1; |
458 |
return ((__u32 *) DATABLOCK2) [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; |
| 402 |
} |
459 |
} |
| 403 |
mapblock2 = bnum; |
460 |
/* else */ |
| 404 |
return ((__u32 *) DATABLOCK2) |
461 |
mapblock2 = -1; |
| 405 |
[logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; |
462 |
logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)); |
| 406 |
} |
463 |
if (mapblock1 != 3 && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1)) |
| 407 |
/* else */ |
464 |
{ |
| 408 |
mapblock2 = -1; |
465 |
errnum = ERR_FSYS_CORRUPT; |
| 409 |
logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)); |
466 |
return -1; |
| 410 |
if (mapblock1 != 3 |
467 |
} |
| 411 |
&& !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1)) |
468 |
mapblock1 = 3; |
| 412 |
{ |
469 |
if (!ext2_rdfsb (((__u32 *) DATABLOCK1) [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)], DATABLOCK2)) |
| 413 |
errnum = ERR_FSYS_CORRUPT; |
470 |
{ |
| 414 |
return -1; |
471 |
errnum = ERR_FSYS_CORRUPT; |
| 415 |
} |
472 |
return -1; |
| 416 |
mapblock1 = 3; |
473 |
} |
| 417 |
if (!ext2_rdfsb (((__u32 *) DATABLOCK1) |
474 |
if (!ext2_rdfsb (((__u32 *) DATABLOCK2) [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)) & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)], DATABLOCK2)) |
| 418 |
[logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) |
475 |
{ |
| 419 |
* 2)], |
476 |
errnum = ERR_FSYS_CORRUPT; |
| 420 |
DATABLOCK2)) |
477 |
return -1; |
| 421 |
{ |
478 |
} |
| 422 |
errnum = ERR_FSYS_CORRUPT; |
479 |
return ((__u32 *) DATABLOCK2) |
| 423 |
return -1; |
480 |
[logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; |
| 424 |
} |
481 |
} |
| 425 |
if (!ext2_rdfsb (((__u32 *) DATABLOCK2) |
482 |
/* inode is in extents format */ |
| 426 |
[(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)) |
483 |
else |
| 427 |
& (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)], |
484 |
{ |
| 428 |
DATABLOCK2)) |
485 |
int i; |
| 429 |
{ |
486 |
struct ext4_extent_header *extent_hdr = ext4_recurse_extent_index((struct ext4_extent_header *) INODE->i_block, logical_block); |
|
|
487 |
struct ext4_extent *extent = (struct ext4_extent *) (extent_hdr + 1); |
| 488 |
if ( extent_hdr == NULL || extent_hdr->eh_magic != EXT4_EXT_MAGIC) |
| 489 |
{ |
| 490 |
errnum = ERR_FSYS_CORRUPT; |
| 491 |
return -1; |
| 492 |
} |
| 493 |
for (i = 0; i<extent_hdr->eh_entries; i++) |
| 494 |
{ |
| 495 |
if (extent[i].ee_block <= logical_block && logical_block < extent[i].ee_block + extent[i].ee_len && !(extent[i].ee_len>>15)) |
| 496 |
return (logical_block - extent[i].ee_block + extent[i].ee_start); |
| 497 |
} |
| 498 |
/* We should not arrive here */ |
| 430 |
errnum = ERR_FSYS_CORRUPT; |
499 |
errnum = ERR_FSYS_CORRUPT; |
| 431 |
return -1; |
500 |
return -1; |
| 432 |
} |
501 |
} |
| 433 |
return ((__u32 *) DATABLOCK2) |
|
|
| 434 |
[logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; |
| 435 |
} |
502 |
} |
| 436 |
|
503 |
|
| 437 |
/* preconditions: all preconds of ext2fs_block_map */ |
504 |
/* preconditions: all preconds of ext2fs_block_map */ |