diff options
author | Liu Aleaxander <Aleaxander@gmail.com> | 2009-05-11 16:47:51 +0800 |
---|---|---|
committer | Liu Aleaxander <Aleaxander@gmail.com> | 2009-05-11 16:47:51 +0800 |
commit | 0d701f8a814792f5db473d417648c2e5a9f6a20c (patch) | |
tree | a6ef6f1800fe043aa9a812714b5b7fb01946ba13 | |
parent | dcc79fb69015fd7aed1db14544b155969f4d1783 (diff) | |
download | devel-0d701f8a814792f5db473d417648c2e5a9f6a20c.tar.gz devel-0d701f8a814792f5db473d417648c2e5a9f6a20c.tar.xz devel-0d701f8a814792f5db473d417648c2e5a9f6a20c.zip |
Make cache based on block size and fixed some bugs
well, it's a big change.
1st, make the caceh based on block but not sector
2nd, make the fast symlink check worked.
3rd, totally changed the linsector function.
4th, some little changes.
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | README | 69 | ||||
-rwxr-xr-x | a.out | bin | 27449 -> 26239 bytes | |||
-rw-r--r-- | cache.c | 21 | ||||
-rw-r--r-- | cache.h | 10 | ||||
-rw-r--r-- | disklab.c | 20 | ||||
-rw-r--r-- | disklab.h | 5 | ||||
-rw-r--r-- | extlinux.c | 151 | ||||
-rw-r--r-- | main.c | 2 |
9 files changed, 177 insertions, 103 deletions
@@ -1,2 +1,4 @@ a.out:cache.h cache.c main.c disklab.h disklab.c ext2_fs.h extlinux.c gcc -g cache.c main.c disklab.c extlinux.c +clean: + (rm -f *~ *.o)
\ No newline at end of file @@ -1,4 +1,71 @@ -This is the ext2fs driver, it's a user program. And great thanks to stefab +/************************************************************************ + * This file is updated by the version number, so if you looked at my + * last email, then you don't need to check the README version 0.1 part. + ************************************************************************/ + + + +README version 0.2 +================== + +well, thanks for hpa's pointing, I got the fast symlink check work now. And +according the last email from hpa, I changed the cache based on block size +but not sector size. But for some unknow reason, there would be some wrong +when I do what suggested by hpa about the cache buffer allocation: + + "I would suggest allocating the data buffers for the cache + at cache_init() time instead of doing malloc() later. " + +I debugged it, but nothing found. So I will keep it stay what it orignal was. +When I resolved it, I'll do it. + +well, about that, here's my opoinion: I don't think we should do allocate data +at the cache_init(), 'cause, say we have 0x64 buf slots, then we need allocate +0x64K (assume the block size be 1024B) memory; while during the debugging, I +found that there are only three slots used for opening two file under +boot/extlinux where Syslinux installed. So, we wasted about 0x61K memory. + + +And for another thing, I am considering create a inode cache. although it's +not belong that kind of MUST, but even with a small inode cache, It'll be +more effective. ( well, I'm not sure about this, becasue I find that with +a path, diffrent component has different inode_number, so when opening a little +number of files, it would not be effective. ) +So, if i'm wrong, please correct me. + + +And last, the following comes from the comment of function getfssec(): + + "Alought we have made the buffer data based on block size, + we use sector for implemention; because reading multiple + sectors (then can be multiple blocks) is what the function + do. So, let's be based on sectors." +So, I don't changed all the things based on block size, just made cache +based on block size. + +and here's the main change of this version: + 1) Make fast symlink can be detected. + 2) Cache buffer data based on block size. (So introduces some others change) + 3) I have totally changed the linsector function. + + +and here's the thing need to do: + 1) Make the code more C style, means more structured. + 2) Not sure about the buffer data allocation. + 3) Make this code more stable, more solid. + 4) Add EXT4 support. + + +Well, this is really the last: Sorry to bother and best wishes with you. + + + + + +README version 0.1 +================== + +This is the ext2fs driver, it's a user program. And great thanks to stefanb for the wonderful idea. I have patched the bin program a.out and the sample ext2 fs image ext2.img, Binary files differ@@ -1,5 +1,6 @@ #include "cache.h" #include <stdio.h> +#include <fcntl.h> #include <malloc.h> @@ -13,6 +14,7 @@ */ struct cache_struct cache[CACHE_ENTRIES + 1] = {0,}; +extern int blk_size; /** * cache_init: @@ -29,7 +31,7 @@ void cache_init(void) prev = &cache[CACHE_ENTRIES]; for ( i = 0; i < CACHE_ENTRIES + 1; i++ ) { - cur->sector = 0; + cur->block = 0; cur->prev = prev; prev->next = cur; cur->data = NULL; @@ -43,25 +45,25 @@ void cache_init(void) /** - * get_cache_sector: + * get_cache_block: * - * Check for a particular SECTOR in the sector cache, + * Check for a particular BLOCK in the block cache, * and if it is already there, just do nothing and return; * otherwise load it and updata the relative cache * structre with data pointer. * - * @param: sector, the sector number we want check. + * @param: block, the block number we want check. * @retrun: return the most recent cache structure pointer * */ -struct cache_struct * get_cache_sector(int sector) +struct cache_struct * get_cache_block(__u32 block) { struct cache_struct *cs = &cache[1]; struct cache_struct *head, *last; int i; for ( i = 0; i < CACHE_ENTRIES; i ++ ) { - if ( cs->sector == sector ) + if ( cs->block == block ) goto hit; else cs = &cache[i + 1]; @@ -69,14 +71,11 @@ struct cache_struct * get_cache_sector(int sector) /* we missed it here, so we need to load it */ miss: - /* free the first cache's buffer first */ - if ( cache[0].next->data) - free(cache[0].next->data); /* store it at head of real cache */ cs = cache[0].next; - cs->sector = sector; - cs->data = (void*)getonesec(sector); + cs->block = block; + cs->data = (void*)getoneblk(block); hit: /* remove cs from current position in list */ @@ -4,17 +4,13 @@ #include "types.h" -#define CACHE_ENTRIES 0x04 /* just a test */ +#define CACHE_ENTRIES 0x064 /* just a test */ /* The cache structure */ struct cache_struct { - /* - * This structure is based on secotr and I am thinking - * if we should make it based on block for performace. - */ - __u32 sector; + __u32 block; struct cache_struct *prev; struct cache_struct *next; void *data; @@ -25,6 +21,6 @@ struct cache_struct { /* functions defined in cache.c */ void cache_init(void); -struct cache_struct *get_cache_sector( int ); +struct cache_struct *get_cache_block(__u32 block); #endif /* cache.h */ @@ -1,27 +1,29 @@ +#include "disklab.h" + #include <stdio.h> #include <malloc.h> + extern int fd; +extern int blk_size; -void * getonesec(int sector) +void* getoneblk(__u32 block) { - void *data; int bytes_read; + char *buf; - if ( lseek(fd, sector * 512, SEEK_SET) < 0) {/* ... */ + if ( lseek(fd, block * blk_size, SEEK_SET) < 0) {/* ... */ printf("seek file ext2.img error....\n"); return NULL; } + buf = malloc(blk_size); - data = malloc(512); - - if ( (bytes_read = read(fd, data, 512)) < 512 ) - printf("read %d bytes less than 512B...\n", bytes_read); - + if ( (bytes_read = read(fd, buf, blk_size)) < blk_size ) + printf("read %d bytes less than %dB..\n", bytes_read, blk_size); - return data; + return buf; } @@ -1,10 +1,11 @@ #ifndef _DISKLAB_H -#defein _DISKLAB_H +#define _DISKLAB_H +#include "types.h" /* disk lab functions */ -void *getonesec(int); +void* getoneblk(__u32); #endif /* disklab.h */ @@ -87,12 +87,13 @@ struct open_file_t Files[MAX_OPEN]; __u32 ClustBytesShift, ClustSize, ClustShift; __u32 SecPerClust, ClustMask; -__u32 PtrsPerBlock1, PtrsPerBlock2; +__u32 PtrsPerBlock1, PtrsPerBlock2, PtrsPerBlock3; /* a static value, which is the boot/extlinux's inode number */ __u32 CurrentDir = 13; - +/* for EXTLINUX, we make blk_size be the size of a block */ +int blk_size; @@ -161,10 +162,12 @@ struct open_file_t *allocate_file() file = Files; for (; i < MAX_OPEN; i ++ ) { - if ( file->file_bytesleft == 0 ) /* find it */ + if ( file->file_bytesleft == 0 ) /* found it */ return file; file ++; } + + return NULL; /* not found */ } @@ -219,8 +222,7 @@ struct open_file_t * open_inode(unsigned int inr, __u32 *file_len) __u32 inode_group, inode_offset; __u32 block_num, block_off; - __u32 sector_num, sector_off; - + file = allocate_file(); if ( !file ) @@ -239,29 +241,22 @@ struct open_file_t * open_inode(unsigned int inr, __u32 *file_len) /* finally we get the real block number where the desc stores */ block_num += sb.s_first_data_block + 1; - /* compute the sector number where the group descriptor stores */ - sector_num = (block_num << ClustShift) + (block_off >> SECTOR_SHIFT); - sector_off = block_off & (SECTOR_SIZE - 1 ); - - cs = get_cache_sector(sector_num); - desc = (struct ext2_group_desc *)(cs->data + sector_off); /* got the group desc */ + cs = get_cache_block(block_num); + /* got the group desc */ + desc = (struct ext2_group_desc *)(cs->data + block_off); /* get the inode bytes offset in the inode table */ inode_offset *= sb.s_inode_size; block_num = (inode_offset / ClustSize) + (desc->bg_inode_table); block_off = inode_offset % ClustSize; - - /* compute the sector number where the inode structure stores */ - sector_num = (block_num << ClustShift) + (block_off >> SECTOR_SHIFT); - sector_off = block_off & (SECTOR_SIZE - 1); - - file->file_in_sec = sector_num; - file->file_in_off = sector_off; - cs = get_cache_sector(sector_num); - memcpy(&ThisInode, cs->data + sector_off, EXT2_GOOD_OLD_INODE_SIZE); + cs = get_cache_block(block_num); + memcpy(&ThisInode, cs->data + block_off, EXT2_GOOD_OLD_INODE_SIZE); + /* Finally, we need to convet it to sector for now */ + file->file_in_sec = (block_num<<ClustShift) + (block_off>>SECTOR_SHIFT); + file->file_in_off = block_off & (SECTOR_SIZE - 1); file->file_mode = ThisInode.i_mode; *file_len = file->file_bytesleft = ThisInode.i_size; @@ -296,6 +291,10 @@ void close_file(struct open_file_t *file) * * 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: line_sector, the linear sector number * @param: file, the pointer to open_file_t structure * @@ -303,70 +302,73 @@ void close_file(struct open_file_t *file) */ __u32 linsector(__u32 lin_sector, struct open_file_t *file) { - - struct cache_struct *cs; struct ext2_inode *inode; - __u32 sector; - __u32 the_block; /* the block we are in now */ - __u32 next_block; __u32 block = lin_sector >> ClustShift; - __u32 offset; /* the offset of sector where block number stores */ - - cs = get_cache_sector(file->file_in_sec); - inode = (struct ext2_inode *)((__u32)cs->data + file->file_in_off); + __u32 offset; - offset = (char *)&inode->i_block[block] - (char *)cs->data; - if ( block < EXT2_NDIR_BLOCKS ) - goto direct; - offset = (char *)&inode->i_block[EXT2_IND_BLOCK] - (char *)cs->data; + /* 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; + } + + /* indirect blocks */ block -= EXT2_NDIR_BLOCKS; - if ( block < PtrsPerBlock1 ) - goto ind1; + if ( block < PtrsPerBlock1 ) { + __u32 ind_block = inode->i_block[EXT2_IND_BLOCK]; - offset = (char *)&inode->i_block[EXT2_DIND_BLOCK] - (char *)cs->data; - block -= PtrsPerBlock1; - if ( block < PtrsPerBlock2 ) - goto ind2; - offset = (char *)&inode->i_block[EXT2_TIND_BLOCK] - (char *)cs->data; - block -= PtrsPerBlock2; + cs = get_cache_block(ind_block); - ind3: - the_block = block / PtrsPerBlock2; - next_block = block % PtrsPerBlock2; + block = ((__u32 *)cs->data)[block]; + goto to_sector; + } - sector = (*(__u32 *)(cs->data + offset) << ClustShift) - +(the_block >> (SECTOR_SHIFT - 2)); - cs = get_cache_sector(sector); - - offset = ( the_block & (SECTOR_SIZE >> 2) - 1 ) << 2; - block = next_block; - ind2: - the_block = block / PtrsPerBlock1; - next_block = block % PtrsPerBlock1; + /* double indirect blocks */ + block -= PtrsPerBlock1; + if ( block < PtrsPerBlock2 ) { + __u32 dou_block = inode->i_block[EXT2_DIND_BLOCK]; + cs = get_cache_block(dou_block); + + dou_block = ( (__u32 *)cs->data )[block / PtrsPerBlock1]; + cs = get_cache_block(dou_block); + + block = ( (__u32*)cs->data )[block % PtrsPerBlock1]; + + goto to_sector; + } + - sector = (*(__u32*)(cs->data + offset) << ClustShift) - +(the_block >> (SECTOR_SHIFT - 2)); - cs = get_cache_sector(sector); - offset = ( the_block & (SECTOR_SIZE >> 2) - 1) << 2; - block = next_block; + /* triple indirect block */ + block -= PtrsPerBlock2; + if ( block < PtrsPerBlock3 ) { + __u32 tri_block = inode->i_block[EXT2_TIND_BLOCK]; + cs = get_cache_block(tri_block); + + tri_block = ((__u32*)cs->data)[block / PtrsPerBlock2]; + cs = get_cache_block(tri_block); - ind1: - sector = (*(__u32*)(cs->data + offset) << ClustShift) - +(block >> (SECTOR_SHIFT - 2)); - cs = get_cache_sector(sector); - offset = ( block & (SECTOR_SIZE >> 2) - 1) << 2; + tri_block = ((__u32*)cs->data)[block % PtrsPerBlock2]; + cs = get_cache_block(tri_block); - direct: - sector = (*(__u32*)(cs->data + offset) << ClustShift) - +(lin_sector & ClustMask); + block = ((__u32*)cs->data)[block % PtrsPerBlock1]; + goto to_sector; + } - return sector; -} + /* File too big, can not handle */ + printf("ERROR, file too big\n"); + return 0; + + to_sector: + return ( (block << ClustShift) + (lin_sector & ClustMask) ); +} @@ -377,6 +379,11 @@ __u32 linsector(__u32 lin_sector, struct open_file_t *file) * * Get multiple sectors from a file * + * Alought we have made the buffer data based on block size, + * we use sector for implemention; because reading multiple + * sectors (then can be multiple blocks) is what the function + * do. So, let's be based on sectors. + * * same as above, execpt si is a pointer to a open_file_t * * @param: ES:BX ----> buffer @@ -393,9 +400,6 @@ int getfssec(char *buf, struct open_file_t *file, int sectors, int *have_more) int bytes_read = sectors << SECTOR_SHIFT; - if ( file->file_bytesleft <= 0) - return 0; - sector_left = (file->file_bytesleft + SECTOR_SIZE - 1) >> SECTOR_SHIFT; if ( sectors > sector_left ) sectors = sector_left; @@ -409,7 +413,7 @@ int getfssec(char *buf, struct open_file_t *file, int sectors, int *have_more) do { con_sec_cnt ++; sectors --; - if ( sectors == 0 ) + if ( sectors <= 0 ) break; /*** @@ -695,10 +699,13 @@ void init_fs(struct ext2_super_block *sb) ClustSize = 1 << ClustBytesShift; ClustShift = ClustBytesShift - SECTOR_SHIFT; + blk_size = ClustSize; + SecPerClust = ClustSize >> SECTOR_SHIFT; ClustMask = SecPerClust - 1; PtrsPerBlock1 = 1 << (ClustBytesShift - 2 ); PtrsPerBlock2 = 1 << ( (ClustBytesShift - 2) * 2); + PtrsPerBlock3 = 1 << ( (ClustBytesShift - 2) * 3); } @@ -34,7 +34,7 @@ void print_cache(void) struct cache_struct *cs = cache; for (; i < CACHE_ENTRIES; i++) { cs = cs->next; - printf("%d ", cs->sector); + printf("%d ", cs->block); } printf("\n"); |