diff options
author | Liu Aleaxander <Aleaxander@gmail.com> | 2009-05-13 09:14:49 +0800 |
---|---|---|
committer | Liu Aleaxander <Aleaxander@gmail.com> | 2009-05-13 09:14:49 +0800 |
commit | b6985a112b8a0e34d989d4a57555d0d7318c0718 (patch) | |
tree | caddc69b5d23eaeb0e3118bf151775c1247fa9a1 | |
parent | 52ab97cab14939b665d6c66b00564004c3911e65 (diff) | |
download | devel-b6985a112b8a0e34d989d4a57555d0d7318c0718.tar.gz devel-b6985a112b8a0e34d989d4a57555d0d7318c0718.tar.xz devel-b6985a112b8a0e34d989d4a57555d0d7318c0718.zip |
Well, this version added ext4 supported
big changes, ext4 supported
and fixed some bugs
-rwxr-xr-x | a.out | bin | 27056 -> 29385 bytes | |||
-rw-r--r-- | ext2_fs.h | 52 | ||||
-rw-r--r-- | extlinux.c | 164 | ||||
-rw-r--r-- | types.h | 2 |
4 files changed, 181 insertions, 37 deletions
Binary files differ @@ -31,6 +31,11 @@ #define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK+1) #define EXT2_N_BLOCKS (EXT2_TIND_BLOCK+1) + +/* for EXT4 extent */ +#define EXT4_EXT_MAGIC 0xf30a +#define EXT4_EXTENTS_FLAG 0x00080000 + /* * File types and file modes */ @@ -197,6 +202,53 @@ struct ext2_dir_entry { + + +/* + * This is the extent on-disk structure. + * It's used at the bottom of the tree. + */ +struct ext4_extent { + __u32 ee_block; /* first logical block extent covers */ + __u16 ee_len; /* number of blocks covered by extent */ + __u16 ee_start_hi; /* high 16 bits of physical block */ + __u32 ee_start_lo; /* low 32 bits of physical block */ +}; + +/* + * This is index on-disk structure. + * It's used at all the levels except the bottom. + */ +struct ext4_extent_idx { + __u32 ei_block; /* index covers logical blocks from 'block' */ + __u32 ei_leaf_lo; /* pointer to the physical block of the next * + * level. leaf or next index could be there */ + __u16 ei_leaf_hi; /* high 16 bits of physical block */ + __u16 ei_unused; +}; + +/* + * Each block (leaves and indexes), even inode-stored has header. + */ +struct ext4_extent_header { + __u16 eh_magic; /* probably will support different formats */ + __u16 eh_entries; /* number of valid entries */ + __u16 eh_max; /* capacity of store in entries */ + __u16 eh_depth; /* has tree real underlying blocks? */ + __u32 eh_generation; /* generation of the tree */ +}; + + + +#define EXT4_FIRST_EXTENT(header) ( (struct ext4_extent *)(header + 1) ) +#define EXT4_FIRST_INDEX(header) ( (struct ext4_extent_idx *) (header + 1) ) + + + + + + + /* function declartion */ /******************************************************************************* extern struct open_file_t * ext2_read(char *); @@ -257,7 +257,9 @@ void read_inode(__u32 inode_offset, *offset = inode_offset % InodePerBlock; cs = get_cache_block(*block); - inode = (struct ext2_inode *)cs->data + *offset; + + /* well, in EXT4, the inode structure usually be 256 */ + inode = (struct ext2_inode *)(cs->data + (*offset * (sb.s_inode_size))); memcpy(dst, inode, EXT2_GOOD_OLD_INODE_SIZE); /* for file structure */ @@ -336,38 +338,103 @@ void close_file(struct open_file_t *file) } +struct ext4_extent_header * +ext4_find_leaf (struct ext4_extent_header *eh, __u32 block) +{ + struct ext4_extent_idx *index; + struct cache_struct *cs; + __u64 blk; + int i; + char buf[ClustSize]; + + while (1) { + + index = EXT4_FIRST_INDEX(eh); + + if (eh->eh_magic != EXT4_EXT_MAGIC) + return NULL; + + if (eh->eh_depth == 0) + return eh; + + for ( i = 0; i < eh->eh_entries; i++ ) { + if ( block < index[i].ei_block ) + break; + } + + if ( --i < 0 ) + return NULL; + + blk = index[i].ei_leaf_hi; + blk = (blk << 32) + index[i].ei_leaf_lo; + + /* read the blk to memeory */ + cs = get_cache_block(blk); + + eh = (struct ext4_extent_header *)(cs->data); + } +} + +/* handle the ext4 extents to get the phsical block number */ +__u64 linsector_extent(__u32 block, struct ext2_inode *inode) +{ + struct ext4_extent_header *leaf; + struct ext4_extent *ext; + int i; + __u64 start; + + leaf = ext4_find_leaf((struct ext4_extent_header*)inode->i_block,block); + + if (! leaf) { + printf("ERROR, extent leaf not found\n"); + return 0; + } + + + ext = EXT4_FIRST_EXTENT(leaf); + + for ( i = 0; i < leaf->eh_entries; i++ ) { + if ( block < ext[i].ee_block) + break; + } + + + if ( --i < 0 ) { + printf("ERROR, not find the right block\n"); + return 0; + } + + + /* got it */ + block -= ext[i].ee_block; + if ( block >= ext[i].ee_len) + return 0; + + start = ext[i].ee_start_hi; + start = (start << 32) + ext[i].ee_start_lo; + + return start + block; +} + /** - * linsector: - * - * Convert a linear sector index in a file to linear sector number - * - * well, alought this function converts a linear sector number to - * physic sector number, it uses block cache in the implemention. + * linsector_direct: * + * @param: block, the block index + * @param: inode, the inode structure * - * @param: line_sector, the linear sector number - * @param: file, the pointer to open_file_t structure - * - * @return: the linear sector number, aka, the physic sector number + * @return: the physic block number */ -__u32 linsector(__u32 lin_sector, struct open_file_t *file) +__u32 linsector_direct(__u32 block, struct ext2_inode *inode) { struct cache_struct *cs; - struct ext2_inode *inode; - - __u32 block = lin_sector >> ClustShift; __u32 offset; - - /* well, this is what I think the variable ThisInode used for */ - inode = &ThisInode; - + /* direct blocks */ - if ( block < EXT2_NDIR_BLOCKS ) { - block = inode->i_block[block]; - goto to_sector; - } + if ( block < EXT2_NDIR_BLOCKS ) + return inode->i_block[block]; + /* indirect blocks */ block -= EXT2_NDIR_BLOCKS; @@ -377,8 +444,7 @@ __u32 linsector(__u32 lin_sector, struct open_file_t *file) cs = get_cache_block(ind_block); - block = ((__u32 *)cs->data)[block]; - goto to_sector; + return ((__u32 *)cs->data)[block]; } @@ -391,9 +457,7 @@ __u32 linsector(__u32 lin_sector, struct open_file_t *file) dou_block = ( (__u32 *)cs->data )[block / PtrsPerBlock1]; cs = get_cache_block(dou_block); - block = ( (__u32*)cs->data )[block % PtrsPerBlock1]; - - goto to_sector; + return ( (__u32*)cs->data )[block % PtrsPerBlock1]; } @@ -409,20 +473,48 @@ __u32 linsector(__u32 lin_sector, struct open_file_t *file) tri_block = ((__u32*)cs->data)[block % PtrsPerBlock2]; cs = get_cache_block(tri_block); - block = ((__u32*)cs->data)[block % PtrsPerBlock1]; - goto to_sector; + return ((__u32*)cs->data)[block % PtrsPerBlock1]; } /* File too big, can not handle */ printf("ERROR, file too big\n"); return 0; - - to_sector: - return ( (block << ClustShift) + (lin_sector & ClustMask) ); } +/** + * linsector: + * + * Convert a linear sector index in a file to linear sector number + * + * well, alought this function converts a linear sector number to + * physic sector number, it uses block cache in the implemention. + * + * @param: lin_sector, the lineral sector index + * + * @return: physic sector number + */ +__u32 linsector(__u32 lin_sector) +{ + __u32 block = lin_sector >> ClustShift; + struct ext2_inode *inode; + /* well, this is what I think the variable ThisInode used for */ + inode = &ThisInode; + + if (inode->i_flags & EXT4_EXTENTS_FLAG) + block = linsector_extent(block, inode); + else + block = (__u32)linsector_direct(block, inode); + + if ( !block ) { + printf("WARNING: something error happend at linsector..\n"); + return 0; + } + + /* finally convert it to sector */ + return ( (block << ClustShift) + (lin_sector & ClustMask) ); +} /** @@ -459,7 +551,7 @@ int getfssec(char *buf, struct open_file_t *file, int sectors, int *have_more) /* get the frament */ sector_idx = file->file_sector; - next_sector = frag_start = linsector(sector_idx, file); + next_sector = frag_start = linsector(sector_idx); con_sec_cnt = 0; do { @@ -480,7 +572,7 @@ int getfssec(char *buf, struct open_file_t *file, int sectors, int *have_more) */ sector_idx ++; next_sector ++; - }while( next_sector == linsector(sector_idx, file) ); + }while( next_sector == linsector(sectors) ); @@ -753,7 +845,7 @@ void init_fs(struct ext2_super_block *sb) blk_size = ClustSize; DescPerBlock = blk_size / ( 1 << ext2_group_desc_lg2size); - InodePerBlock = blk_size / EXT2_GOOD_OLD_INODE_SIZE; + InodePerBlock = blk_size / sb->s_inode_size; SecPerClust = ClustSize >> SECTOR_SHIFT; ClustMask = SecPerClust - 1; @@ -1,7 +1,7 @@ #ifndef _TYPES_H #define _TYPES_H - +typedef unsigned long long __u64; typedef unsigned int __u32; typedef unsigned short __u16; typedef unsigned char __u8; |