OpenCores
URL https://opencores.org/ocsvn/c0or1k/c0or1k/trunk

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [conts/] [posix/] [mm0/] [fs/] [memfs/] [memfs.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
/*
2
 * A simple read/writeable memory-only filesystem.
3
 *
4
 * Copyright (C) 2007, 2008 Bahadir Balban
5
 */
6
#include <init.h>
7
#include <fs.h>
8
#include <vfs.h>
9
#include <task.h>
10
#include <stdio.h>
11
#include <memfs/memfs.h>
12
#include <memfs/vnode.h>
13
#include <lib/idpool.h>
14
#include <l4/macros.h>
15
#include <l4/types.h>
16
#include <l4/api/errno.h>
17
#include INC_GLUE(memory.h)
18
 
19
struct memfs_superblock *memfs_superblock;
20
 
21
/* Initialise allocation caches as part of superblock initialisation */
22
int memfs_init_caches(struct memfs_superblock *sb)
23
{
24
        void *free_block;
25
        struct mem_cache *block_cache;
26
        struct mem_cache *inode_cache;
27
 
28
        /* Use the whole filesystem space to initialise block cache */
29
        free_block = (void *)sb + sizeof(*sb);
30
        block_cache = mem_cache_init(free_block, sb->fssize - sizeof(*sb),
31
                                     sb->blocksize, 1);
32
        list_insert(&block_cache->list, &sb->block_cache_list);
33
 
34
        /* Allocate a block and initialise it as first inode cache */
35
        free_block = mem_cache_alloc(block_cache);
36
        inode_cache = mem_cache_init(free_block, sb->blocksize,
37
                                     sizeof(struct memfs_inode), 0);
38
        list_insert(&inode_cache->list, &sb->inode_cache_list);
39
 
40
        return 0;
41
}
42
 
43
/*
44
 * Given an empty block buffer, initialises a filesystem there.
45
 */
46
int memfs_format_filesystem(void *buffer)
47
{
48
        struct memfs_superblock *sb = buffer;   /* Buffer is the first block */
49
 
50
        /* Zero initialise the superblock area */
51
        memset(sb, 0, sizeof(*sb));
52
 
53
        /* Initialise filesystem parameters */
54
        sb->magic = MEMFS_MAGIC;
55
        memcpy(sb->name, MEMFS_NAME, MEMFS_NAME_SIZE);
56
        sb->blocksize = MEMFS_BLOCK_SIZE;
57
        sb->fmaxblocks = MEMFS_FMAX_BLOCKS;
58
        sb->fssize = MEMFS_TOTAL_SIZE;
59
 
60
        /* Initialise block and inode index pools */
61
        sb->ipool = id_pool_new_init(MEMFS_TOTAL_INODES);
62
        sb->bpool = id_pool_new_init(MEMFS_TOTAL_BLOCKS);
63
 
64
        /* Initialise bitmap allocation lists for blocks and inodes */
65
        link_init(&sb->block_cache_list);
66
        link_init(&sb->inode_cache_list);
67
        memfs_init_caches(sb);
68
 
69
        return 0;
70
}
71
 
72
/* Allocates a block of unused buffer */
73
void *memfs_alloc_block(struct memfs_superblock *sb)
74
{
75
        struct mem_cache *cache;
76
 
77
        list_foreach_struct(cache, &sb->block_cache_list, list) {
78
                if (cache->free)
79
                        return mem_cache_zalloc(cache);
80
                else
81
                        continue;
82
        }
83
        return PTR_ERR(-ENOSPC);
84
}
85
 
86
/*
87
 * Even though on a list, block allocation is currently from a single cache.
88
 * This frees a block back to the free buffer cache.
89
 */
90
int memfs_free_block(struct memfs_superblock *sb, void *block)
91
{
92
        struct mem_cache *c, *tmp;
93
 
94
        list_foreach_removable_struct(c, tmp, &sb->block_cache_list, list)
95
                if (!mem_cache_free(c, block))
96
                        return 0;
97
                else
98
                        return -EINVAL;
99
        return -EINVAL;
100
}
101
 
102
struct superblock *memfs_get_superblock(void *block);
103
 
104
struct file_system_type memfs_fstype = {
105
        .name = "memfs",
106
        .magic = MEMFS_MAGIC,
107
        .ops = {
108
                .get_superblock = memfs_get_superblock,
109
        },
110
};
111
 
112
/*
113
 * Initialise root inode as a directory, as in the mknod() call
114
 * but differently since root is parentless and is the parent of itself.
115
 */
116
int memfs_init_rootdir(struct superblock *sb)
117
{
118
        struct memfs_superblock *msb = sb->fs_super;
119
        struct dentry *d;
120
        struct vnode *v;
121
 
122
        /*
123
         * Create the root vnode. Since this is memfs, root vnode is
124
         * not read-in but dynamically created here. We expect this
125
         * first vnode to have vnum = 0.
126
         */
127
        v = sb->root = sb->ops->alloc_vnode(sb);
128
        msb->root_vnum = sb->root->vnum;
129
        BUG_ON(msb->root_vnum == 0);
130
 
131
        /* Initialise fields */
132
        vfs_set_type(v, S_IFDIR);
133
 
134
        /* Allocate a new vfs dentry */
135
        if (!(d = vfs_alloc_dentry()))
136
                return -ENOMEM;
137
 
138
        /*
139
         * Initialise root dentry.
140
         *
141
         * NOTE: Root's parent is itself.
142
         * Here's how it looks like in structures:
143
         * root's parent is root. But root's child is not root.
144
         *
145
         * NOTE: Root has no name. This helps since splitpath
146
         * cuts out the '/' and "" is left for root name search.
147
         */
148
        strncpy(d->name, VFS_STR_ROOTDIR, VFS_DNAME_MAX);
149
        d->ops = generic_dentry_operations;
150
        d->parent = d;
151
        d->vnode = v;
152
 
153
        /* Associate dentry with its vnode */
154
        list_insert(&d->vref, &d->vnode->dentries);
155
 
156
        /* Add both vnode and dentry to their flat caches */
157
        list_insert(&d->cache_list, &dentry_cache);
158
        list_insert(&v->cache_list, &vnode_cache);
159
 
160
        return 0;
161
}
162
 
163
/* Copies fs-specific superblock into generic vfs superblock */
164
struct superblock *memfs_fill_superblock(struct memfs_superblock *sb,
165
                                         struct superblock *vfs_sb)
166
{
167
        vfs_sb->fs = &memfs_fstype;
168
        vfs_sb->ops = &memfs_superblock_operations;
169
        vfs_sb->fs_super = sb;
170
        vfs_sb->fssize = sb->fssize;
171
        vfs_sb->blocksize = sb->blocksize;
172
 
173
        /* We initialise the root vnode as the root directory */
174
        memfs_init_rootdir(vfs_sb);
175
 
176
        return vfs_sb;
177
}
178
 
179
/*
180
 * Probes block buffer for a valid memfs superblock, if found,
181
 * allocates and copies data to a vfs superblock, and returns it.
182
 */
183
struct superblock *memfs_get_superblock(void *block)
184
{
185
        struct memfs_superblock *sb = block;
186
        struct superblock *vfs_sb;
187
 
188
        // printf("%s: %s: Reading superblock.\n", __TASKNAME__, __FUNCTION__);
189
        /* We don't do sanity checks here, just confirm id. */
190
        if (strcmp(sb->name, "memfs")) {
191
                printf("%s: Name does not match: %s\n", __FUNCTION__, sb->name);
192
                return 0;
193
        }
194
        if (sb->magic != MEMFS_MAGIC) {
195
                printf("%s: Magic number not match: %u\n", __FUNCTION__, sb->magic);
196
                return 0;
197
        }
198
 
199
        /* Allocate a vfs superblock. */
200
        vfs_sb = vfs_alloc_superblock();
201
 
202
        /* Fill generic sb from fs-specific sb */
203
        return memfs_fill_superblock(sb, vfs_sb);
204
}
205
 
206
/* Registers sfs as an available filesystem type */
207
void memfs_register_fstype(struct link *fslist)
208
{
209
        /* Initialise superblock list for this fstype */
210
        link_init(&memfs_fstype.sblist);
211
 
212
        /* Add this fstype to list of available fstypes. */
213
        list_insert(&memfs_fstype.list, fslist);
214
}
215
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.