From f29f1a542c66030636a3a0cf7f518202ed646e14 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Wed, 2 Jun 2010 00:57:09 +0800 Subject: [PATCH] Add the implementation of tfs Tfs, (Thunix file system), my own file system. Signed-off-by: Liu Aleaxander --- Makefile | 2 +- fs/tfs/Makefile | 32 +++++ fs/tfs/balloc.c | 94 ++++++++++++++ fs/tfs/cache.c | 122 ++++++++++++++++++ fs/tfs/dir.c | 235 ++++++++++++++++++++++++++++++++++ fs/tfs/file.c | 167 ++++++++++++++++++++++++ fs/tfs/ialloc.c | 102 +++++++++++++++ fs/tfs/inode.c | 361 ++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/tfs/super.c | 48 +++++++ fs/tfs/tfs_diskio.c | 18 +++ include/fd.h | 4 +- include/stdio.h | 7 +- include/string.h | 21 +++ init/Makefile | 4 +- init/init.c | 23 +++- kernel/console.c | 4 +- kernel/fd.c | 2 +- kernel/hexdump.c | 2 +- kernel/shell.c | 2 +- kernel/traps.c | 1 + 20 files changed, 1234 insertions(+), 17 deletions(-) create mode 100644 fs/tfs/Makefile create mode 100644 fs/tfs/balloc.c create mode 100644 fs/tfs/cache.c create mode 100644 fs/tfs/dir.c create mode 100644 fs/tfs/file.c create mode 100644 fs/tfs/ialloc.c create mode 100644 fs/tfs/inode.c create mode 100644 fs/tfs/super.c create mode 100644 fs/tfs/tfs_diskio.c diff --git a/Makefile b/Makefile index 74f453f..41597c8 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CC = gcc -nostdinc -Iinclude -Wall -Wno-unused-function LD = ld LDFLAGS = --oformat binary -N -KERNEL_OBJS = boot/head.o init/init.o kernel/kernel.o mm/mm.o +KERNEL_OBJS = boot/head.o init/init.o kernel/kernel.o mm/mm.o fs/fs.o .PHONY :clean backup release diff --git a/fs/tfs/Makefile b/fs/tfs/Makefile new file mode 100644 index 0000000..1f5f487 --- /dev/null +++ b/fs/tfs/Makefile @@ -0,0 +1,32 @@ +AS = as -I../../include +CC = gcc -nostdinc -I../../include -Wall -Wno-unused +LD = ld +LDFLAGS = --oformat binary -N +CPP =gcc -E -nostdinc -I../../include + +all: tfs.o #mktfs + +OBJS = balloc.o cache.o dir.o file.o ialloc.o inode.o super.o tfs_diskio.o + + +tfs.o: ${OBJS} + ${LD} -r -o $@ ${OBJS} +.c.s: + ${CC} -S -o $*.s $< +.s.o: + ${AS} -o $*.o $< +.c.o: + ${CC} -c -o $*.o $< + +mktfs: balloc.c cache.c dir.c file.c ialloc.c inode.c mktfs.c utils.c + gcc -Wall -Wno-unused -o mktfs balloc.c cache.c dir.c file.c ialloc.c inode.c utils.c + + +clean: + rm -f *.o *.map *~ tmp_make + +dep: + sed '/\#\#\# Dependencies/q' < Makefile > tmp_make + (for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \ + $(CPP) -M $$i;done) >> tmp_make + cp tmp_make Makefile diff --git a/fs/tfs/balloc.c b/fs/tfs/balloc.c new file mode 100644 index 0000000..06fb2f5 --- /dev/null +++ b/fs/tfs/balloc.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include + +static void * tfs_read_block_bitmap(struct tfs_sb_info *sbi) +{ + char *buf = malloc(sbi->s_block_size); + + tfs_bread(sbi, sbi->s_block_bitmap, buf); + + return buf; +} + +/* + * Free a block, return -1 if failed, or return 0 + */ +int tfs_free_block(struct tfs_sb_info *sbi, uint32_t block) +{ + char *bitmap = tfs_read_block_bitmap(sbi); + + if (clear_bit(bitmap, block) == 0) { + printk("ERROR: trying to free an free block!\n"); + free(bitmap); + return -1; + } + + tfs_bwrite(sbi, sbi->s_block_bitmap, bitmap); + free(bitmap); + return block; +} + +int tfs_alloc_block(struct tfs_sb_info *sbi, uint32_t block) +{ + char *bitmap = tfs_read_block_bitmap(sbi); + + /* try the target first */ + if (test_bit(bitmap, block) != 0) + block = find_first_zero(bitmap, bitmap + sbi->s_block_size); + if (block != -1) { + set_bit(bitmap, block); + tfs_bwrite(sbi, sbi->s_block_bitmap, bitmap); + } + + free(bitmap); + return block; +} + +#if 0 /* the deubg part */ +#include +int main(int argc, char *argv[]) +{ + int i; + int block; + struct tfs_sb_info *sbi; + char *fs = argv[1]; + char *command = argv[2]; + char **blocks = argv + 3; + int count = argc - 3; + + if (argc < 4) { + printk("Usage: balloc tfs.img command blocks...\n"); + printk(" alloc, to alloc blocks\n"); + printk(" feee, to free blocks\n"); + return 1; + } + + sbi = tfs_mount_by_fsname(fs); + if (!sbi) { + printk("tfs mount failed!\n"); + return 1; + } + + if (strcmp(command, "alloc") == 0) { + for (i = 0; i < count; i++) { + block = atoi(blocks[i]); + printk("trying to alloc block %u\n", block); + block = tfs_alloc_block(sbi, block); + printk("block number: %u allocated\n", block); + } + } else if (strcmp(command, "free") == 0) { + for (i = 0; i < count; i++) { + block = atoi(blocks[i]); + printk("trying to free block %u\n", block); + block = tfs_free_block(sbi, block); + printk("block number: %u freed\n", block); + } + } else { + printk("Unknown command!\n"); + } + + return 0; +} +#endif diff --git a/fs/tfs/cache.c b/fs/tfs/cache.c new file mode 100644 index 0000000..a068102 --- /dev/null +++ b/fs/tfs/cache.c @@ -0,0 +1,122 @@ +/* + * A simple LRU cache implemention. Even the fstk is a user-space program, + * but we really do need a cache algorithm to make fstk more effective. + * + * This file is from Syslinux_project/core/cache.c. This file can + * be redistributed under the terms of the GNU Public License. + */ + +#include +#include +#include +#include + + +/* The cache data, we just make it be 32K, and it's enough for us */ +#define CACHE_SIZE (32 << 10) + +static char cache_data[CACHE_SIZE]; + +#define MAX_CACHE_ENTRIES 64 /* assume we have a block size as 512 */ +static struct cache_struct cache_head; +static struct cache_struct cache[MAX_CACHE_ENTRIES]; +static int cache_entries = 0; + +/* + * Initialize the cache data structres + */ +void cache_init(struct tfs_sb_info *sbi) +{ + struct cache_struct *prev, *cur; + char *data = cache_data; + int i; + + cache_entries = CACHE_SIZE >> sbi->s_block_shift; + if (cache_entries > MAX_CACHE_ENTRIES) + cache_entries = MAX_CACHE_ENTRIES; + + cache_head.prev = &cache[cache_entries-1]; + cache_head.prev->next = &cache_head; + prev = &cache_head; + + for (i = 0; i < cache_entries; i++) { + cur = &cache[i]; + cur->block = 0; + cur->prev = prev; + prev->next = cur; + cur->data = data; + data += sbi->s_block_size; + prev = cur++; + } +} + + +/* + * 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. + */ +struct cache_struct* get_cache_block(struct tfs_sb_info *sbi, uint32_t block) +{ + struct cache_struct *head = &cache_head; + struct cache_struct *last = head->prev; + /* let's find it from the end, 'cause the endest is the freshest */ + struct cache_struct *cs = head->prev; + int i; + + if (!block) { + printk("ERR: we got a ZERO block number that's not we want!\n"); + return NULL; + } + + /* it's aleardy the freshest, so nothing we need do , just return it */ + if (cs->block == block) + goto out; + + for (i = 0; i < cache_entries; i ++) { + if (cs->block == block) + break; + else + cs = cs->prev; + } + + /* missed, so we need to load it */ + if (i == cache_entries) { + /* store it at the head of real cache */ + cs = head->next; + cs->block = block; + tfs_bread(sbi, block, cs->data); + } + + /* remove cs from current position in list */ + cs->prev->next = cs->next; + cs->next->prev = cs->prev; + + /* add to just before head node */ + last->next = cs; + cs->prev = last; + head->prev = cs; + cs->next = head; +out: + return cs; +} + + +/** + * Just print the sector, and according the LRU algorithm, + * Left most value is the most least secotr, and Right most + * value is the most Recent sector. I see it's a Left Right Used + * (LRU) algorithm; Just kidding:) + */ +void print_cache(void) +{ + int i = 0; + struct cache_struct *cs = &cache_head; + for (; i < cache_entries; i++) { + cs = cs->next; + printk("%d(%p) \n", cs->block, cs->data); + } + + printk("\n"); +} diff --git a/fs/tfs/dir.c b/fs/tfs/dir.c new file mode 100644 index 0000000..1f022f6 --- /dev/null +++ b/fs/tfs/dir.c @@ -0,0 +1,235 @@ +#include +#include +#include + +#include "tfs.h" +#include "cache.h" +#include "dirent.h" + +/* + * NOTE! unlike strncmp, ext2_match_entry returns 1 for success, 0 for failure. + * + * len <= EXT2_NAME_LEN and de != NULL are guaranteed by caller. + */ +static inline int tfs_match_entry (const char * const name, + struct tfs_dir_entry * de) +{ + if (!de->d_inode) + return 0; + return !strncmp(name, de->d_name, strlen(name)); +} + +struct tfs_dir_entry * tfs_find_entry(struct tfs_sb_info *sbi, + const char *dname, + struct inode *inode) +{ + uint32_t block; + int i = 0; + int index = 0; + struct tfs_dir_entry *de; + struct cache_struct *cs; + + block = inode->i_data[index++]; + if (!block) + return NULL; + cs = get_cache_block(sbi, block); + de = (struct tfs_dir_entry *)cs->data; + + while(i < (int)inode->i_size) { + if ((char *)de >= (char *)cs->data + sbi->s_block_size) { + if ((block = inode->i_data[index++]) < sbi->s_data_area) + return NULL; + cs = get_cache_block(sbi, block); + de = (struct tfs_dir_entry *)cs->data; + } + if (tfs_match_entry(dname, de)) + return de; + + de++; + } + + return NULL; +} + +int tfs_add_entry(struct tfs_sb_info *sbi, struct inode *dir, const char *name, int inr, int * dirty) +{ + uint32_t block; + int i = 0, index = 0; + struct cache_struct *cs; + struct tfs_dir_entry *de; + + if (strlen(name) > TFS_NAME_LEN) { + printk("ERROR: file name too long!\n"); + return -1; + } + + if (!(block = dir->i_data[index++])) + goto alloc_new_block; + cs = get_cache_block(sbi, block); + de = (struct tfs_dir_entry *)cs->data; + while (i <= (int)dir->i_size) { + if ((void *)de >= cs->data + sbi->s_block_size) { + if (!(block = dir->i_data[index++])) + break; + cs = get_cache_block(sbi, block); + de = (struct tfs_dir_entry *)cs->data; + } + if (!de->d_inode) + break; + i += sizeof(struct tfs_dir_entry); + de++; + } + + *dirty = 0; + +alloc_new_block: + /* allocate a new block to hold the new entry */ + if (!block) { + block = tfs_alloc_block(sbi, sbi->s_data_area); + dir->i_data[index - 1] = block; + if (block == -1) { + printk("ERROR: allocate new block failed, out of space!\n"); + return -1; + } + cs = get_cache_block(sbi, block); + de = (struct tfs_dir_entry *)cs->data; + memset(cs->data, 0, sbi->s_block_size); + + /* + * This will go through the next if sentence, since if we + * allocated a new entry, then 'i >= dir->i_size' would + * be true. + */ + } + + if (i >= dir->i_size) { + /* Add a new entry at last */ + dir->i_size += sizeof(struct tfs_dir_entry); + + /* tell the caller to update this inode */ + *dirty = 1; + } + + /* + * Else, we find a unused hole, this usually happens when user + * removes a file or directory, so we can just fill up + * the hole, and do not need allocate more space. + */ + de->d_inode = inr; + memcpy(de->d_name, name, strlen(name)); + + /* write the entry back to disk */ + tfs_bwrite(sbi, block, cs->data); + + return 0; +} + + +int tfs_mkdir(struct tfs_sb_info *sbi, const char *path) +{ + struct inode *dir; + struct inode *parent_dir; + int dirty; + int res = 0; + + dir = tfs_mknod(sbi, path, TFS_DIR, &parent_dir); + if (!dir) { + TFS_DEBUG("mknod for path failed!\n"); + return -1; + } + + res = tfs_add_entry(sbi, dir, ".", dir->i_ino, &dirty); + if (res == -1) { + TFS_DEBUG("trying to add '.' under %s failed!\n", path); + goto out; + } + + res = tfs_add_entry(sbi, dir, "..", parent_dir->i_ino, &dirty); + if (res == -1) { + TFS_DEBUG("trying to add .. under %s failed!\n", path); + goto out; + } + + if (dirty) + tfs_iwrite(sbi, dir); +out: + free_inode(dir); + if (this_dir->dd_dir->inode != parent_dir) + free_inode(parent_dir); + + return res; + +} + + +/* for relative path searching */ +DIR *this_dir; + +DIR *tfs_opendir(struct tfs_sb_info *sbi, const char *path) +{ + DIR *dir = malloc(sizeof(*dir)); + + if (!dir) { + printk("malloc for DIR structure error!\n"); + return NULL; + } + + dir->dd_dir = tfs_open(sbi, path); + if (!dir->dd_dir) { + free(dir); + return NULL; + } + + return dir; +} + +/* read one directry entry at a time */ +struct dirent * tfs_readdir(DIR *dir) +{ + struct dirent *dirent; + struct tfs_dir_entry *de; + struct cache_struct *cs; + struct file *file = dir->dd_dir; + struct inode *inode = file->inode; + struct tfs_sb_info *sbi = file->sbi; + int index = file->offset >> sbi->s_block_shift; + uint32_t block; + + if (file->offset >= inode->i_size) + return NULL; + if (!(block = tfs_bmap(inode, index))) + return NULL; + cs = get_cache_block(sbi, block); + de = (struct tfs_dir_entry *)(cs->data + (file->offset & (sbi->s_block_size- 1))); + + if (!(dirent = malloc(sizeof(*dirent)))) { + printk("malloc dirent structure in tfs_readdir error!\n"); + return NULL; + } + memset(dirent, 0, sizeof(*dirent)); + dirent->d_ino = de->d_inode; + dirent->d_off = file->offset; + dirent->d_reclen = sizeof(struct tfs_dir_entry); + dirent->d_type = 0; + memcpy(dirent->d_name, de->d_name, TFS_NAME_LEN); + + file->offset += sizeof(struct tfs_dir_entry); + + return dirent; + +} + +void tfs_closedir(DIR *dir) +{ + if (dir) { + free_inode(dir->dd_dir->inode); + free(dir->dd_dir); + free(dir); + } +} + +#if 0 /* the debug part */ +int main(int argc, char *argv[]) +{ +} +#endif diff --git a/fs/tfs/file.c b/fs/tfs/file.c new file mode 100644 index 0000000..adbf834 --- /dev/null +++ b/fs/tfs/file.c @@ -0,0 +1,167 @@ +#include +#include +#include + +#include "tfs.h" +#include "cache.h" +#include "file.h" + + +struct file *tfs_open(struct tfs_sb_info *sbi, const char *filename) +{ + struct inode *inode; + struct file *file; + + inode = tfs_namei(sbi, filename, LOOKUP_CREATE); + if (!inode) { + printk("ERROR: open file: %s falied!\n", filename); + return NULL; + } + + file = malloc(sizeof(*file)); + if (!file) { + printk("malloc file structure error!\n"); + free_inode(inode); + return NULL; + } + + file->sbi = sbi; + file->inode = inode; + file->offset = 0; + + return file; +} + +uint32_t fstk_lseek(struct file *file, uint32_t off, int mode) +{ + if (mode == SEEK_CUR) + file->offset += off; + else if (mode == SEEK_END) + file->offset = file->inode->i_size + off; + else if (mode == SEEK_SET) + file->offset = off; + else + file->offset = -1; + return file->offset; +} + +int tfs_read(struct file *file, void *buf, uint32_t count) +{ + struct tfs_sb_info *sbi = file->sbi; + int blocks = roundup(count, sbi->s_block_size); + int index = file->offset >> sbi->s_block_shift; + int block = file->inode->i_data[index++]; + int bufoff = file->offset & (sbi->s_block_size - 1); + int bytes_read = 0; + + if (!blocks) + return -1; + if (!block) + return -1; + if (file->offset >= file->inode->i_size) + return -1; + tfs_bread(sbi, block, buf); + bytes_read = sbi->s_block_size - bufoff; + memcpy(buf, buf + bufoff, bytes_read); + buf += bytes_read; + file->offset += bytes_read; + blocks--; + + while (blocks--) { + block = file->inode->i_data[index++]; + if (!block) + break; + tfs_bread(sbi, block, buf); + bytes_read += sbi->s_block_size; + file->offset += sbi->s_block_size; + buf += sbi->s_block_size; + } + + return bytes_read; +} + + +#define min(a, b) ((a) < (b) ? a : b) +int tfs_write(struct file *file, void *buf, uint32_t count) +{ + struct tfs_sb_info *sbi = file->sbi; + struct cache_struct *cs; + int blocks = roundup(count, sbi->s_block_size); + int index = file->offset >> sbi->s_block_shift; + int block; + int bufoff = file->offset & (sbi->s_block_size - 1); + int bytes_written = 0; + + + if (!blocks) + return -1; + + block = tfs_bmap(file->inode, index++); + if (!block) { + if (index - 1 < TFS_N_BLOCKS) { + block = tfs_alloc_block(sbi, sbi->s_data_area); + if (block == -1) { + printk("allocating block for new file faile! OUT OF SPACE!\n"); + return -1; + } + file->inode->i_data[index - 1] = block; + } else { + /* file too big */ + return -1; + } + } + cs = get_cache_block(sbi, block); + bytes_written = min(sbi->s_block_size, count) - bufoff; + memcpy(cs->data + bufoff, buf, bytes_written); + buf += bytes_written; + file->offset += bytes_written; + count -= bytes_written; + file->inode->i_size += bytes_written; + /* write back to disk */ + tfs_bwrite(sbi, block, cs->data); + blocks--; + + while (blocks--) { + int bytes_need; + block = tfs_bmap(file->inode, index++); + if (!block) { + if (index - 1 < TFS_N_BLOCKS) { + block = tfs_alloc_block(sbi, sbi->s_data_area); + if (block == -1) { + printk("allocating block for new file faile: out of space!\n"); + goto err; + } + file->inode->i_data[index - 1] = block; + } else { + /* fle too big */ + goto err; + } + } + bytes_need = min(sbi->s_block_size, count); + cs = get_cache_block(sbi, block); + memcpy(cs->data, buf, bytes_need); + bytes_written += bytes_need; + file->offset += bytes_need; + buf += bytes_need; + file->inode->i_size += bytes_need; + tfs_bwrite(sbi, block, cs->data); + } + +done: + tfs_iwrite(sbi, file->inode); + + return bytes_written; + +err: + bytes_written = -1; + goto done; +} + +void tfs_close(struct file *file) +{ + if (file) { + free_inode(file->inode); + free(file); + } +} + diff --git a/fs/tfs/ialloc.c b/fs/tfs/ialloc.c new file mode 100644 index 0000000..42f5211 --- /dev/null +++ b/fs/tfs/ialloc.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include + + +static void * tfs_read_inode_bitmap(struct tfs_sb_info *sbi) +{ + char *buf = malloc(sbi->s_block_size); + + tfs_bread(sbi, sbi->s_inode_bitmap, buf); + + return buf; +} + +/* + * free an inode, return -1 if failed, or return 9 + */ +int tfs_free_inode(struct tfs_sb_info *sbi, int inr) +{ + char *bitmap = tfs_read_inode_bitmap(sbi); + + /* inode number count from 1 */ + if (clear_bit(bitmap, inr - 1) == 0) { + printk("ERROR: trying to free an unallocated inode!\n"); + free(bitmap); + return -1; + } + + tfs_bwrite(sbi, sbi->s_inode_bitmap, bitmap); + free(bitmap); + return 0; +} + +int tfs_alloc_inode(struct tfs_sb_info *sbi, int inr) +{ + char *bitmap; + + if (inr < 0) { + printk("ERROR: trying to alloc a negtive inode!\n"); + return -1; + } + + bitmap = tfs_read_inode_bitmap(sbi); + /* try the target first */ + if (test_bit(bitmap, inr - 1) != 0) + inr = find_first_zero(bitmap, bitmap + sbi->s_block_size) + 1; + if (inr != -1) { + set_bit(bitmap, inr - 1); + tfs_bwrite(sbi, sbi->s_inode_bitmap, bitmap); + } + + free(bitmap); + return inr; +} + +#if 0 /* the deubg part */ +#include +int main(int argc, char *argv[]) +{ + int i; + int inr; + struct tfs_sb_info *sbi; + char *fs = argv[1]; + char *command = argv[2]; + char **inodes = argv + 3; + int count = argc - 3; + + if (argc < 4) { + printk("Usage: ialloc tfs.img command inodes...\n"); + printk(" alloc, to alloc inodes\n"); + printk(" feee, to free inodes\n"); + return 1; + } + + sbi = tfs_mount_by_fsname(fs); + if (!sbi) { + printk("tfs mount failed!\n"); + return 1; + } + + if (strcmp(command, "alloc") == 0) { + for (i = 0; i < count; i++) { + inr = atoi(inodes[i]); + printk("trying to alloc inode %u\n", inr); + inr = tfs_alloc_inode(sbi, inr); + printk("inode number: %u allocated\n", inr); + } + } else if (strcmp(command, "free") == 0) { + for (i = 0; i < count; i++) { + inr = atoi(inodes[i]); + printk("trying to free inode %u\n", inr); + inr = tfs_free_inode(sbi, inr); + printk("inode number: %d freed\n", inr); + } + } else { + printk("Unknown command!\n"); + } + + return 0; +} +#endif diff --git a/fs/tfs/inode.c b/fs/tfs/inode.c new file mode 100644 index 0000000..2fd75f1 --- /dev/null +++ b/fs/tfs/inode.c @@ -0,0 +1,361 @@ +#include +#include +#include +#include +#include +#include + +#define current_time 0 + + +void free_inode(struct inode *inode) +{ + if(inode->i_data) + free(inode->i_data); + free(inode); +} + +struct inode *new_inode(int mode) +{ + struct inode *inode; + + inode = malloc(sizeof(*inode)); + if (!inode) { + printk("malloc for new inode failed!\n"); + return NULL; + } + memset(inode, 0, sizeof(*inode)); + inode->i_mode = mode; + + inode->i_atime = current_time; + inode->i_ctime = current_time; + inode->i_mtime = current_time; + + inode->i_data = malloc(TFS_N_BLOCKS * sizeof(uint32_t *)); + if (!inode->i_data) { + printk("malloc for inode data failed!\n"); + free(inode); + return NULL; + } + + + return inode; +} + + +/* + * release all the stuff related to the inode + */ +int tfs_release_inode(struct tfs_sb_info *sbi, struct inode *inode) +{ + int inr = inode->i_ino; + + if (!inode) { + printk("ERROR: trying to free a NULL inode!\n"); + return -1; + } + + TFS_DEBUG("trying to release inode: %d\n", inr); + + if (tfs_free_inode(sbi, inr) == -1) { + printk("ERROR: trying to free inode %d failed!\n", inr); + return -1; + } + + free_inode(inode); + return 0; +} + + +struct inode * tfs_new_inode(struct tfs_sb_info *sbi, int mode) +{ + struct inode *inode; + int inr; + + inode = new_inode(mode); + if (!inode) + return NULL; + /* + * allocate it start from TFS_ROOT_INODE, so only the first one + * will get it:) + */ + inr = tfs_alloc_inode(sbi, TFS_ROOT_INODE); + if (inr == -1) { + free(inode); + return NULL; + } + + inode->i_ino = inr; + + return inode; +} + +struct inode * tfs_root_init(struct tfs_sb_info *sbi) +{ + struct inode *inode; + + inode = tfs_new_inode(sbi, TFS_DIR); + if (inode->i_ino != TFS_ROOT_INODE) { + TFS_DEBUG("root init error!\n"); + free_inode(inode); + inode = NULL; + } + + return inode; +} + + +static void tfs_fill_inode(struct inode *inode, struct tfs_inode *tinode) +{ + //inode->i_mode = get_mode(tinode->i_mode); + inode->i_mode = tinode->i_mode; + inode->i_size = tinode->i_size; + inode->i_atime = tinode->i_atime; + inode->i_ctime = tinode->i_ctime; + inode->i_mtime = tinode->i_mtime; + inode->i_dtime = tinode->i_dtime; + inode->i_flags = tinode->i_flags; + + memcpy(inode->i_data, tinode->i_block, TFS_N_BLOCKS * sizeof(uint32_t *)); +} + +static int tfs_read_inode(struct tfs_sb_info *sbi, struct tfs_inode *tinode, int inr) +{ + uint32_t inode_block; + struct cache_struct *cs; + + inode_block = sbi->s_inode_table + (inr - 1) / TFS_INODES_PER_BLOCK(sbi); + cs = get_cache_block(sbi, inode_block); + if (!cs) + return -1; + + memcpy(tinode, cs->data + ((inr - 1) % TFS_INODES_PER_BLOCK(sbi)) * sizeof(*tinode), sizeof(*tinode)); + + return 0; +} + +struct inode * tfs_iget_by_inr(struct tfs_sb_info *sbi, int inr) +{ + struct inode *inode; + struct tfs_inode tinode; + + if (tfs_read_inode(sbi, &tinode, inr) == -1) { + printk("ERROR: read disk inode error!\n"); + return NULL; + } + + inode = new_inode(0); + if (inode) { + tfs_fill_inode(inode, &tinode); + inode->i_ino = inr; + } + + return inode; +} + +struct inode *tfs_iget_root(struct tfs_sb_info *sbi) +{ + return tfs_iget_by_inr(sbi, TFS_ROOT_INODE); +} + +struct inode *tfs_iget(struct tfs_sb_info * sbi, char *dname, struct inode *dir) +{ + struct tfs_dir_entry *de; + + de = tfs_find_entry(sbi, dname, dir); + if (!de) + return NULL; + + return tfs_iget_by_inr(sbi, de->d_inode); +} + +static void tfs_write_inode(struct tfs_inode *tinode, struct inode *inode) +{ + tinode->i_mode = inode->i_mode; + tinode->i_size = inode->i_size; + tinode->i_atime = inode->i_atime; + tinode->i_ctime = inode->i_ctime; + tinode->i_mtime = inode->i_mtime; + tinode->i_dtime = inode->i_dtime; + tinode->i_flags = inode->i_flags; + + memcpy(tinode->i_block, inode->i_data, TFS_N_BLOCKS * sizeof(uint32_t *)); + tinode->i_reserved[0] = 0; + +} + +int tfs_iwrite(struct tfs_sb_info *sbi, struct inode *inode) +{ + struct cache_struct *cs; + struct tfs_inode *tinode; + uint32_t inode_block; + int res = 0; + + inode_block = sbi->s_inode_table + (inode->i_ino - 1) / TFS_INODES_PER_BLOCK(sbi); + cs = get_cache_block(sbi, inode_block); + if (!cs) + return -1; + tinode = (struct tfs_inode *)cs->data + ((inode->i_ino - 1) % TFS_INODES_PER_BLOCK(sbi)); + tfs_write_inode(tinode, inode); + tfs_bwrite(sbi, inode_block, cs->data); + + return -1; +} + +uint32_t tfs_bmap(struct inode *inode, int index) +{ + if (index >= TFS_N_BLOCKS) { + printk("File too big!\n"); + return 0; + } + + return inode->i_data[index]; +} + + + +struct inode * tfs_namei(struct tfs_sb_info *sbi, const char *name, uint32_t flag) +{ + struct inode *inode; + struct inode *parent; + char part[TFS_NAME_LEN + 1]; + char *p; + + if (*name == '/') { + inode = tfs_iget_root(sbi); + while (*name == '/') + name++; + } else { + inode = this_dir->dd_dir->inode; + + } + parent = inode; + + while (*name) { + p = part; + while (*name && *name != '/') { + if (p >= part + TFS_NAME_LEN) { + printk("ERROR: file name to long!\n"); + return NULL; + } + *p++ = *name++; + } + *p = '\0'; + while (*name && *name == '/') + name++; + if (!*name && (flag & LOOKUP_PARENT)) + return parent; + inode = tfs_iget(sbi, part, parent); + if (!inode) + break; + + if (parent != this_dir->dd_dir->inode) + free_inode(parent); + parent = inode; + if (!*name) + break; + } + + if (!inode && flag & LOOKUP_CREATE) { + inode = __mknod(sbi, parent, part, TFS_FILE); + tfs_iwrite(sbi, inode); + } + + return inode; +} + +static const char *__strrchr(const char *s, int c) +{ + const char *end = s + strlen(s) - 1; + while (*end != c && end >= s) + end--; + if (end < s) + return NULL; + return end; +} + +static const char *get_base_name(const char *path_org) +{ + char *p; + char *path = strdup(path_org); + + p = strrchr(path, '/'); + if (!p) { + free(path); + return path_org; + } + /* the /linux/hello/ case */ + if (*(p + 1) == 0) { + *p = 0; + p--; + while (*p != '/' && p >= path) { + *p = 0; + p--; + } + if (p < path) + return NULL; + } + + return p + 1; +} + +struct inode * __mknod(struct tfs_sb_info *sbi, struct inode *dir, const char *filename, int mode) +{ + struct inode *inode; + struct tfs_dir_entry *de; + int dirty = 0; + + + if ((de = tfs_find_entry(sbi, filename, dir))) { + printk("ERROR: %s exist!\n", filename); + free_inode(dir); + return NULL; + } + + inode = tfs_new_inode(sbi, mode); + if (!inode) + return NULL; + inode->i_mtime = inode->i_atime = current_time; + tfs_iwrite(sbi, inode); + + if (tfs_add_entry(sbi, dir, filename, inode->i_ino, &dirty) == -1) { + TFS_DEBUG("trying to add a new entry: %s faild!\n", filename); + free_inode(dir); + free_inode(inode); + return NULL; + } + if (dirty) + tfs_iwrite(sbi, dir); + + return inode; +} + +struct inode * tfs_mknod(struct tfs_sb_info *sbi, const char *filename, int mode, struct inode **parent_dir) +{ + struct inode *dir; + struct inode *inode; + const char *base_name = get_base_name(filename); + + dir = tfs_namei(sbi, filename, LOOKUP_PARENT); + if (!dir) { + printk("ERROR: path not exist!\n"); + return NULL; + } + + inode = __mknod(sbi, dir, base_name, mode); + if (inode) { + if (parent_dir) + *parent_dir = dir; + else + free_inode(dir); + } + + return inode; +} + + +#if 0 /* the debug part */ +int main(int argc, char *argv[]) +{ +} +#endif diff --git a/fs/tfs/super.c b/fs/tfs/super.c new file mode 100644 index 0000000..80e08dd --- /dev/null +++ b/fs/tfs/super.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include + + +struct tfs_sb_info * tfs_mount(void) +{ + struct tfs_sb_info *sbi; + struct tfs_super_block sb; + + /* Read the sector */ + floppy_read(TFS_SB_SECTOR, &sb); + if (sb.s_magic != TFS_MAGIC) { + printk("Trying to mount not tfs file system!\n"); + return NULL; + } + + sbi = malloc(sizeof(*sbi)); + if (!sbi) { + printk("Malloc from tfs sbi object failed!\n"); + return NULL; + } + + sbi->s_block_shift = sb.s_block_shift; + sbi->s_block_size = 1 << sbi->s_block_shift; + sbi->s_blocks_count = sb.s_blocks_count; + sbi->s_inodes_count = sb.s_inodes_count; + sbi->s_free_blocks_count = sb.s_free_blocks_count; + sbi->s_free_inodes_count = sb.s_free_inodes_count; + + + sbi->s_inode_bitmap = sb.s_inode_bitmap; + sbi->s_block_bitmap = sb.s_block_bitmap; + sbi->s_inode_table = sb.s_inode_table; + sbi->s_data_area = sb.s_data_area; + + sbi->s_inode_bitmap_count = sb.s_block_bitmap - sb.s_inode_bitmap; + sbi->s_block_bitmap_count = sb.s_inode_table - sb.s_block_bitmap; + sbi->s_inode_table_count = sb.s_data_area - sb.s_inode_table; + + + sbi->s_offset = sb.s_offset; + + sbi->s_inodes_per_block = sbi->s_block_size / sizeof(struct tfs_inode); + + return sbi; +} diff --git a/fs/tfs/tfs_diskio.c b/fs/tfs/tfs_diskio.c new file mode 100644 index 0000000..6582bf3 --- /dev/null +++ b/fs/tfs/tfs_diskio.c @@ -0,0 +1,18 @@ +#include +#include +#include + +void tfs_bread(struct tfs_sb_info *sbi, uint32_t block, void *buf) +{ + uint32_t sector = (block << (sbi->s_block_shift - 9)) + sbi->s_offset; + + floppy_reads(sector, buf, 1 << (sbi->s_block_shift - 9)); +} + +void tfs_bwrite(struct tfs_sb_info *sbi, uint32_t block, void *buf) +{ + uint32_t sector = (block << (sbi->s_block_shift - 9)) + sbi->s_offset; + + floppy_writes(sector, buf, 1 << (sbi->s_block_shift - 9)); +} + diff --git a/include/fd.h b/include/fd.h index 39c6b26..a837b5b 100644 --- a/include/fd.h +++ b/include/fd.h @@ -59,13 +59,13 @@ #define DMA_WRITE 0x4A//0x4A - - extern void floppy_interrupt(void); void do_fd_request(int, char*, int ); void floppy_read(int, char *); void floppy_write(int, char *); +void floppy_reads(int, char *, unsigned int); +void floppy_writes(int, char *, unsigned int); void floppy_init(void); #endif diff --git a/include/stdio.h b/include/stdio.h index b724110..e8ca5c5 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -3,8 +3,13 @@ #include + +#ifndef NULL +#define NULL ((void *) 0) +#endif + extern int vsprintf (char *, const char *, va_list); -extern int sprintk (char *, const char *, va_list); +extern int sprintk (char *, const char *, ...); extern int printk(const char *, ...); #endif /* stdio.h */ diff --git a/include/string.h b/include/string.h index a4f6b61..09a8ddd 100644 --- a/include/string.h +++ b/include/string.h @@ -2,6 +2,7 @@ #define _STRING_H 1 #include +#include #ifndef NULL #define NULL ((void *) 0) @@ -71,6 +72,26 @@ static char *strchr (const char *s, int c) return (void *)0; } +static char *strrchr (char *s, int c) +{ + char *end = s + strlen(s) - 1; + + while (*end != c && end >= s) + end--; + if (end < s) + return NULL; + return end; +} + +static char *strdup(const char *str) +{ + char *s = malloc(strlen(str) + 1); + if (!s) + return s; + strcpy(s, str); + return s; +} + static void *memset(void *s, int c, size_t count) { char *xs = s; diff --git a/init/Makefile b/init/Makefile index 5e8c8ae..1c1397e 100644 --- a/init/Makefile +++ b/init/Makefile @@ -1,5 +1,5 @@ AS = as -I../include -CC = gcc -nostdinc -I../include -Wall +CC = gcc -nostdinc -I../include -Wall -Wno-unused LD = ld LDFLAGS = --oformat binary -N @@ -16,4 +16,4 @@ init.o: init.o clean: - rm -f *.o *.map *~ \ No newline at end of file + rm -f *.o *.map *~ diff --git a/init/init.c b/init/init.c index 2f81ff5..094a0ad 100755 --- a/init/init.c +++ b/init/init.c @@ -1,4 +1,5 @@ -/*#include */ +#include +#include #include #include #include @@ -6,17 +7,19 @@ #include #include #include -/*#include */ -#include -#include +#include +#include +#include #include +/*#include */ +//#include +//#include extern void trap_init(void); extern void con_init(void); extern void keyboard_init(void); extern void timer_init(int); extern long kernel_mktime(struct tm*); -extern int printk(char *fmt, ...); extern void timer_interrupt(void); extern void floppy_interrupt(void); //extern void rd_init(void); @@ -142,6 +145,7 @@ void init(void) char ok[] = "[OK]"; unsigned long startup_time; struct tm time; + struct tfs_sb_info *tfs_sbi; cli(); @@ -166,6 +170,15 @@ void init(void) floppy_init(); printk("\t\t%s\n", ok); + printk("mounting tfs image as root fs..."); + tfs_sbi = tfs_mount(); + printk("\t%s\n", ok); + + printk("Cache system initialiaztion..."); + cache_init(tfs_sbi); + printk("\t\t%s\n", ok); + + /* printk("%s", rd_msg); rd_init(); diff --git a/kernel/console.c b/kernel/console.c index 763c152..1161feb 100644 --- a/kernel/console.c +++ b/kernel/console.c @@ -34,8 +34,6 @@ static unsigned short video_erase_char; static void sysbeep(void); -extern int printk(char *fmt, ...); - static inline void gotoxy(unsigned int new_x, unsigned int new_y) { if (new_x > video_num_columns || new_y >= video_num_lines) @@ -79,7 +77,7 @@ static void scrup(void) pos += video_size_row; scr_end += video_size_row; if (scr_end > video_mem_end) { - memcpy((void *)video_mem_start, origin, (video_num_lines - 1) * video_size_row); + memcpy((void *)video_mem_start, (const void *)origin, (video_num_lines - 1) * video_size_row); scr_end -= origin-video_mem_start; pos -= origin-video_mem_start; origin = video_mem_start; diff --git a/kernel/fd.c b/kernel/fd.c index ba4a277..e37179f 100644 --- a/kernel/fd.c +++ b/kernel/fd.c @@ -548,7 +548,7 @@ void Debug_rd(void) void Debug(void) { char str[512 * 10] = "hello word! This is just a floppy writing test"; - char *buf = 0x800000; + char *buf = (char *)0x800000; memcpy(buf, str, sizeof(str)); LOG("STRING addr: %p\n", str); diff --git a/kernel/hexdump.c b/kernel/hexdump.c index 1e78a4d..7653318 100644 --- a/kernel/hexdump.c +++ b/kernel/hexdump.c @@ -8,7 +8,7 @@ #include #include -void hexdump(const void *data, int len) +void hexdump(void *data, int len) { int i = 0; int index = 0; diff --git a/kernel/shell.c b/kernel/shell.c index eec001e..cc77357 100644 --- a/kernel/shell.c +++ b/kernel/shell.c @@ -225,7 +225,7 @@ void run_command(char *command, int argc, char **argv) else if ( is_command(command, "reboot") ) reboot (); -#if 1 +#if 0 else if ( is_command(command, "debug") ) Debug(); #endif diff --git a/kernel/traps.c b/kernel/traps.c index 0a75507..5873a87 100644 --- a/kernel/traps.c +++ b/kernel/traps.c @@ -1,3 +1,4 @@ +#include #include #include #include -- 2.11.4.GIT