cp: define a FIXME macro that leaves a sclp message
[hvf.git] / cp / fs / bcache.c
blob7023fde49bc2e906130eb17530a431f03b530f53
1 /*
2 * (C) Copyright 2007-2011 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
4 * This file is released under the GPLv2. See the COPYING file for more
5 * details.
6 */
8 #include <list.h>
9 #include <mutex.h>
10 #include <buddy.h>
11 #include <slab.h>
12 #include <edf.h>
13 #include <bdev.h>
14 #include <bcache.h>
16 struct bcache_entry {
17 struct list_head bcache;
19 int level; /* 0 = data */
20 u32 blk;
22 u32 lba;
23 void *data;
26 static struct bcache_entry *__bcache_add(struct file *file, int level, u32 blk,
27 u32 lba)
29 struct bcache_entry *ent;
31 ent = malloc(sizeof(struct bcache_entry), ZONE_NORMAL);
32 if (!ent)
33 return ERR_PTR(-ENOMEM);
35 INIT_LIST_HEAD(&ent->bcache);
36 ent->level = level;
37 ent->blk = blk;
38 ent->lba = lba;
39 ent->data = NULL;
41 list_add_tail(&ent->bcache, &file->bcache);
43 return ent;
46 int bcache_add(struct file *file, int level, u32 blk, u32 lba)
48 struct bcache_entry *ent;
50 ent = __bcache_add(file, level, blk, lba);
52 return IS_ERR(ent) ? PTR_ERR(ent) : 0;
55 void *bcache_read(struct file *file, int level, u32 blk)
57 struct bcache_entry *cur;
58 struct page *page;
59 void *buf;
60 u32 *ptrs;
61 u32 nblk, off;
62 int ret;
64 BUG_ON(level > file->FST.NLVL);
66 list_for_each_entry(cur, &file->bcache, bcache) {
67 if ((cur->level == level) && (cur->blk == blk))
68 goto found;
71 if (level == file->FST.NLVL) {
72 /* we can get the lba for this from the FST */
73 cur = __bcache_add(file, level, 0, file->FST.FOP);
74 if (IS_ERR(cur))
75 return cur;
77 goto found;
78 } else {
79 /* we need to read the pointer block one level up */
80 off = blk % (file->fs->ADT.DBSIZ / 4);
81 nblk = blk / (file->fs->ADT.DBSIZ / 4);
84 * WARNING: recursive call below!
86 * Thankfully, there is a bound on the number of levels - 2
87 * pointer blocks worth & 1 data block level.
89 ptrs = bcache_read(file, level+1, nblk);
90 if (IS_ERR(ptrs))
91 return ptrs;
93 /* add the pointer to the cache */
95 FIXME("since we read the whole block, we should probably "
96 "add all the pointers to the cache");
97 cur = __bcache_add(file, level, blk, ptrs[off]);
98 if (IS_ERR(cur))
99 return cur;
101 goto found;
103 return ERR_PTR(-EFAULT);
105 found:
106 if (cur->data)
107 return cur->data;
109 page = alloc_pages(0, ZONE_NORMAL);
110 if (!page)
111 return ERR_PTR(-ENOMEM);
113 buf = page_to_addr(page);
115 ret = bdev_read_block(file->fs->dev, buf, cur->lba);
116 if (ret) {
117 free_pages(buf, 0);
118 return ERR_PTR(ret);
121 cur->data = buf;
122 return buf;