aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiu Aleaxander <Aleaxander@gmail.com>2009-05-11 16:47:51 +0800
committerLiu Aleaxander <Aleaxander@gmail.com>2009-05-11 16:47:51 +0800
commit0d701f8a814792f5db473d417648c2e5a9f6a20c (patch)
treea6ef6f1800fe043aa9a812714b5b7fb01946ba13
parentdcc79fb69015fd7aed1db14544b155969f4d1783 (diff)
downloaddevel-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--Makefile2
-rw-r--r--README69
-rwxr-xr-xa.outbin27449 -> 26239 bytes
-rw-r--r--cache.c21
-rw-r--r--cache.h10
-rw-r--r--disklab.c20
-rw-r--r--disklab.h5
-rw-r--r--extlinux.c151
-rw-r--r--main.c2
9 files changed, 177 insertions, 103 deletions
diff --git a/Makefile b/Makefile
index cb8eb69..30c89bc 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/README b/README
index 32fb39b..3bd0ba0 100644
--- a/README
+++ b/README
@@ -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,
diff --git a/a.out b/a.out
index 227f57a..db21112 100755
--- a/a.out
+++ b/a.out
Binary files differ
diff --git a/cache.c b/cache.c
index bfcdf29..6fdbd25 100644
--- a/cache.c
+++ b/cache.c
@@ -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 */
diff --git a/cache.h b/cache.h
index 33e07b6..4b3abc6 100644
--- a/cache.h
+++ b/cache.h
@@ -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 */
diff --git a/disklab.c b/disklab.c
index a3abe36..c0673ef 100644
--- a/disklab.c
+++ b/disklab.c
@@ -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;
}
diff --git a/disklab.h b/disklab.h
index b57bc7a..2b22849 100644
--- a/disklab.h
+++ b/disklab.h
@@ -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 */
diff --git a/extlinux.c b/extlinux.c
index ac1d59c..b1e108c 100644
--- a/extlinux.c
+++ b/extlinux.c
@@ -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);
}
diff --git a/main.c b/main.c
index 3dbcfa2..9d1cb3c 100644
--- a/main.c
+++ b/main.c
@@ -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");