From: AceVest Date: Thu, 10 Jul 2014 15:02:51 +0000 (+0800) Subject: add ext2 read inode and search file in directory X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zlib_tech.html?a=commitdiff_plain;h=7e3bec7f43f23ae355195469cd4d9e9685a8ecaf;p=kernel.git add ext2 read inode and search file in directory --- diff --git a/fs/ext2.c b/fs/ext2.c index 45cf95a..ffd6ef4 100644 --- a/fs/ext2.c +++ b/fs/ext2.c @@ -8,15 +8,95 @@ */ #include "system.h" #include "fs.h" +#include "mm.h" #include "ext2.h" struct { ext2_sb_t ext2_sb; + ext2_gd_t *ext2_gd; } ext2_fs; extern void blk_rw(dev_t dev, u64_t offset, u32_t scnt, char *buf); -#define BLKRW(offset, blkcnt, buf) do { blk_rw(system.root_dev, offset, (blkcnt)*EXT2_BLOCK_SIZE, buf); } while(0) +#define BLKRW(blkid, blkcnt, buf) do { blk_rw(system.root_dev, (blkid)*EXT2_BLOCK_SIZE, (blkcnt)*EXT2_BLOCK_SIZE, buf); } while(0) + +kmem_cache_t *ext2_block_cache; +kmem_cache_t *ext2_inode_cache; + +ext2_inode_t ext2_root_inode; + +void *ext2_alloc_block() +{ + return (void *) kmem_cache_alloc(ext2_block_cache, 0); +} + +void *ext2_free_block(void *blk) +{ + kmem_cache_free(ext2_block_cache, blk); +} + +void *ext2_alloc_inode() +{ + return (void *) kmem_cache_alloc(ext2_inode_cache, 0); +} + +#define ext2_gd(n) ((ext2_gd_t*)(EXT2_GD) + (n)) +void ext2_read_inode(unsigned int ino, ext2_inode_t *inode) +{ + void *blk = ext2_alloc_block(); + assert(blk != 0); + + unsigned int in; // inode number + unsigned int gn; // group number + unsigned int gi; // inode index in group + + gn = (ino-1) / EXT2_INODES_PER_GROUP; + gi = (ino-1) % EXT2_INODES_PER_GROUP; + + unsigned int blkid = gi / EXT2_INODES_PER_BLOCK; // inode blkid + unsigned int inoff = gi % EXT2_INODES_PER_BLOCK; // inode offset + + blkid += ext2_gd(gn)->bg_inode_table; + inoff *= EXT2_INODE_SIZE; + + printk("group %u %u blkid %u blkoff %u\n", gn, gi, blkid, inoff); + + BLKRW(blkid, 1, blk); + + memcpy(inode, blk+inoff, EXT2_INODE_SIZE); + + ext2_free_block(blk); +} + +unsigned int ext2_search_indir(const char *name, const ext2_inode_t *inode) +{ + unsigned int ino = 0; + + void *blk = ext2_alloc_block(); + assert(blk != 0); + + BLKRW(inode->i_block[0], 1, blk); // only support the first direct blocks + + ext2_dirent_t *dirent = (ext2_dirent_t *) blk; + while(dirent->name_len != 0) + { + dirent->name[dirent->name_len] = 0; + printk(" dirent %s inode %u rec_len %u name_len %u type %02d\n", + dirent->name, dirent->inode, dirent->rec_len, dirent->name_len, dirent->file_type); + + if(strcmp(name, dirent->name) == 0) + { + ino = dirent->inode; + break; + } + + dirent = (ext2_dirent_t *) (((unsigned int)dirent) + dirent->rec_len); + } + + ext2_free_block(blk); + + return ino; +} void ext2_setup_fs() { @@ -26,7 +106,7 @@ void ext2_setup_fs() if(buf == 0) panic("out of memory"); - BLKRW(EXT2_SB_OFFSET, 1, buf); + BLKRW(1, 1, buf); // now blocksize == 1024, so blkid == 1 memcpy(EXT2_SB, buf, sizeof(*(EXT2_SB))); @@ -42,6 +122,42 @@ void ext2_setup_fs() printk(" block size %u log block size %u first data block %u\n", EXT2_BLOCK_SIZE, EXT2_SB->s_log_block_size, EXT2_SB->s_first_data_block); printk(" blocks per group %u inodes per group %u\n", EXT2_SB->s_blocks_per_group, EXT2_SB->s_inodes_per_group); + + + ext2_block_cache = kmem_cache_create("ext2_block_cache", EXT2_BLOCK_SIZE, EXT2_BLOCK_SIZE); + if(0 == ext2_block_cache) + panic("setup ext2 block cache failed. out of memory"); + + ext2_inode_cache = kmem_cache_create("ext2_inode_cache", EXT2_INODE_SIZE, EXT2_INODE_SIZE); + if(0 == ext2_inode_cache) + panic("setup ext2 inode cache failed. out of memory"); + + ext2_fs.ext2_gd = ext2_alloc_block(); + assert(ext2_fs.ext2_gd != 0); + + BLKRW(EXT2_SB->s_first_data_block+1, 1, (char *)ext2_fs.ext2_gd); + + unsigned int gps = EXT2_SB->s_blocks_count / EXT2_SB->s_blocks_per_group; + gps += (EXT2_SB->s_blocks_count % EXT2_SB->s_blocks_per_group) ? 1 : 0; + unsigned int i; + for(i=0; ibg_inode_table, ext2_gd(i)->bg_free_blocks_count, ext2_gd(i)->bg_free_inodes_count, ext2_gd(i)->bg_used_dirs_count); + } + + + ext2_read_inode(2, &ext2_root_inode); + printk("root inode size %u \n", ext2_root_inode.i_size); + printk("root blocks %u \n", ext2_root_inode.i_blocks); + + static ext2_inode_t boot_inode; + static ext2_inode_t krnl_inode; + + ext2_read_inode(ext2_search_indir("boot", &ext2_root_inode), &boot_inode); + ext2_read_inode(ext2_search_indir("Kernel", &boot_inode), &krnl_inode); + printk("krnl inode size %u \n", krnl_inode.i_size); + printk("krnl blocks %u \n", krnl_inode.i_blocks); } diff --git a/include/ext2.h b/include/ext2.h index 4a4d525..7583166 100644 --- a/include/ext2.h +++ b/include/ext2.h @@ -33,6 +33,7 @@ #define EXT2_MIN_BLOCK_LOG_SIZE 10 #define EXT2_SB (&ext2_fs.ext2_sb) +#define EXT2_GD (ext2_fs.ext2_gd) #define EXT2_BLOCK_SIZE (EXT2_MIN_BLOCK_SIZE << (EXT2_SB)->s_log_block_size) #define EXT2_SECT_PER_BLOCK (EXT2_BLOCK_SIZE/512) @@ -141,14 +142,13 @@ typedef struct ext2_group_descriptor u16 bg_used_dirs_count; u16 bg_pad; u32 bg_reserved[3]; -} GroupDesc,*pGroupDesc; +} ext2_gd_t; #define EXT2_NDIR_BLOCKS (12) -#define EXT2_IND_BLOCK (EXT2_NDIR_BLOCKS) -#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) -#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) -#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) - +#define EXT2_IND_BLOCK (EXT2_NDIR_BLOCKS) +#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) +#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) +#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) typedef struct ext2_inode { @@ -169,7 +169,7 @@ typedef struct ext2_inode u32 i_file_acl; u32 i_dir_acl; u32 i_faddr; - u8 i_osd2[12]; + u8 i_osd2[12]; } ext2_inode_t; diff --git a/lib/libc.S b/lib/libc.S index 2bd52c1..90807ba 100644 --- a/lib/libc.S +++ b/lib/libc.S @@ -16,7 +16,7 @@ _start: call main - add $12, %esp + addl $12, %esp nop nop