Mercurial > hvf > hvf-old
changeset 511:162125ad17ee
cp/fs: added a block caching layer
This commit (sadly) fails to build.
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Mon, 25 Apr 2011 09:15:18 -0400 |
parents | 679ce2a155bf |
children | cb3926aac584 |
files | cp/fs/Makefile cp/fs/bcache.c cp/include/bcache.h |
diffstat | 3 files changed, 141 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/cp/fs/Makefile Mon Apr 25 09:10:57 2011 -0400 +++ b/cp/fs/Makefile Mon Apr 25 09:15:18 2011 -0400 @@ -1,1 +1,1 @@ -objs-fs := bdev.o edf.o +objs-fs := bdev.o edf.o bcache.o
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cp/fs/bcache.c Mon Apr 25 09:15:18 2011 -0400 @@ -0,0 +1,124 @@ +/* + * (C) Copyright 2007-2011 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * + * This file is released under the GPLv2. See the COPYING file for more + * details. + */ + +#include <list.h> +#include <mutex.h> +#include <buddy.h> +#include <slab.h> +#include <edf.h> +#include <bdev.h> +#include <bcache.h> + +struct bcache_entry { + struct list_head bcache; + + int level; /* 0 = data */ + u32 blk; + + u32 lba; + void *data; +}; + +static struct bcache_entry *__bcache_add(struct file *file, int level, u32 blk, + u32 lba) +{ + struct bcache_entry *ent; + + ent = malloc(sizeof(struct bcache_entry), ZONE_NORMAL); + if (!ent) + return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&ent->bcache); + ent->level = level; + ent->blk = blk; + ent->lba = lba; + ent->data = NULL; + + list_add_tail(&ent->bcache, &file->bcache); + + return ent; +} + +int bcache_add(struct file *file, int level, u32 blk, u32 lba) +{ + struct bcache_entry *ent; + + ent = __bcache_add(file, level, blk, lba); + + return IS_ERR(ent) ? PTR_ERR(ent) : 0; +} + +void *bcache_read(struct file *file, int level, u32 blk) +{ + struct bcache_entry *cur; + struct page *page; + void *buf; + u32 *ptrs; + u32 nblk, off; + int ret; + + BUG_ON(level > file->FST.NLVL); + + list_for_each_entry(cur, &file->bcache, bcache) { + if ((cur->level == level) && (cur->blk == blk)) + goto found; + } + + if (level == file->FST.NLVL) { + /* we can get the lba for this from the FST */ + cur = __bcache_add(file, level, 0, file->FST.FOP); + if (IS_ERR(cur)) + return cur; + + goto found; + } else { + /* we need to read the pointer block one level up */ + off = blk % (file->fs->ADT.DBSIZ / 4); + nblk = blk / (file->fs->ADT.DBSIZ / 4); + + /* + * WARNING: recursive call below! + * + * Thankfully, there is a bound on the number of levels - 2 + * pointer blocks worth & 1 data block level. + */ + ptrs = bcache_read(file, level+1, nblk); + if (IS_ERR(ptrs)) + return ptrs; + + /* add the pointer to the cache + * + * FIXME: since we read the whole block, we should probably + * add all the pointers to the cache + */ + cur = __bcache_add(file, level, blk, ptrs[off]); + if (IS_ERR(cur)) + return cur; + + goto found; + } + return ERR_PTR(-EFAULT); + +found: + if (cur->data) + return cur->data; + + page = alloc_pages(0, ZONE_NORMAL); + if (!page) + return ERR_PTR(-ENOMEM); + + buf = page_to_addr(page); + + ret = bdev_read_block(file->fs->dev, buf, cur->lba); + if (ret) { + free_pages(buf, 0); + return ERR_PTR(ret); + } + + cur->data = buf; + return buf; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cp/include/bcache.h Mon Apr 25 09:15:18 2011 -0400 @@ -0,0 +1,16 @@ +/* + * (C) Copyright 2007-2011 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * + * This file is released under the GPLv2. See the COPYING file for more + * details. + */ + +#ifndef __BCACHE_H +#define __BCACHE_H + +#include <edf.h> + +extern int bcache_add(struct file *file, int level, u32 blk, u32 lba); +extern void *bcache_read(struct file *file, int level, u32 blk); + +#endif