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

Subversion Repositories c0or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
/*
2
 * Memfs file operations
3
 *
4
 * Copyright (C) 2008 Bahadir Balban
5
 */
6
#include <fs.h>
7
#include <vfs.h>
8
#include <file.h>
9
#include <memfs/memfs.h>
10
#include <stdio.h>
11
#include <string.h>
12
#include <l4/macros.h>
13
#include <l4/api/errno.h>
14
#include INC_GLUE(memory.h)
15
 
16
 
17
#if 0
18
 
19
/*
20
 * FIXME: read_write() could be more layered using these functions.
21
 */
22
void *memfs_read_block(struct vnode *v, int blknum)
23
{
24
        void *buf = vfs_alloc_block();
25
 
26
        if (!buf)
27
                return PTR_ERR(-ENOMEM);
28
 
29
        if(!v->block[blknum])
30
                return PTR_ERR(-EEXIST);
31
 
32
        memcpy(buf, &v->block[blknum], v->sb->blocksize);
33
        return buf;
34
}
35
 
36
int memfs_write_block(struct vnode *v, int blknum, void *buf)
37
{
38
        if(!v->block[blknum])
39
                return -EEXIST;
40
 
41
        memcpy(&v->block[blknum], buf, v->sb->blocksize);
42
        return 0;
43
}
44
#endif
45
 
46
/*
47
 * Handles both read and writes since most details are common.
48
 *
49
 * TODO: Think about whether to use inode or the vnode's fields (e.g. size)
50
 * and when updated, which one is to be updated first. Normally if you use and
51
 * update inode, then you sync vnode via read_vnode. but this is not really meant for
52
 * this use, its meant for retrieving an unknown inode under the vnode with valid vnum.
53
 * here we already have the inode.
54
 */
55
int memfs_file_read_write(struct vnode *v, unsigned int pfn,
56
                          unsigned int npages, void *buf, int wr)
57
{
58
        struct memfs_inode *i;
59
        struct memfs_superblock *memfs_sb;
60
        unsigned int start, end, count;
61
        u32 blocksize;
62
 
63
        /* Don't support different block and page sizes for now */
64
        BUG_ON(v->sb->blocksize != PAGE_SIZE);
65
 
66
        /* Buffer must be page aligned */
67
        BUG_ON(!is_page_aligned(buf));
68
 
69
        /* Low-level fs refs must be valid */
70
        BUG_ON(!(i = v->inode));
71
        BUG_ON(!(memfs_sb = v->sb->fs_super));
72
        blocksize = v->sb->blocksize;
73
 
74
        /* Check filesystem per-file size limit */
75
        if ((pfn + npages) > memfs_sb->fmaxblocks) {
76
                printf("%s: fslimit: Trying to %s outside maximum file range: %x-%x\n",
77
                       __FUNCTION__, (wr) ? "write" : "read", pfn, pfn + npages);
78
                return -EINVAL; /* Same error that posix llseek returns */
79
        }
80
 
81
        /* Read-specific operations */
82
        if (!wr) {
83
                /* Find read boundaries from expected range and file's current range */
84
                start = pfn < __pfn(v->size) ? pfn : __pfn(v->size);
85
                end = pfn + npages < __pfn(page_align_up(v->size))
86
                      ? pfn + npages : __pfn(page_align_up(v->size));
87
                count = end - start;
88
 
89
                /* Copy the data from inode blocks into page buffer */
90
                for (int x = start, bufpage = 0; x < end; x++, bufpage++)
91
                        memcpy(((void *)buf) + (bufpage * blocksize),
92
                               i->block[x], blocksize);
93
                return (int)(count * blocksize);
94
        } else { /* Write-specific operations */
95
                /* Is the write beyond current file size? */
96
                if (v->size < ((pfn + npages) * (blocksize))) {
97
                        unsigned long pagediff = pfn + npages - __pfn(v->size);
98
                        unsigned long holes;
99
 
100
                        /*
101
                         * If write is not consecutively after the currently
102
                         * last file block, the gap must be filled in by holes.
103
                         */
104
                        if (pfn > __pfn(v->size))
105
                                holes = pfn - __pfn(v->size);
106
                        else
107
                                holes = 0;
108
 
109
                        /* Allocate new blocks */
110
                        for (int x = 0; x < pagediff; x++)
111
                                if (!(i->block[__pfn(v->size) + x] =
112
                                      memfs_alloc_block(v->sb->fs_super)))
113
                                        return -ENOSPC;
114
 
115
                        /* Zero out the holes. FIXME: How do we zero out non-page-aligned bytes?` */
116
                        for (int x = 0; x < holes; x++)
117
                                memset(i->block[__pfn(v->size) + x], 0, blocksize);
118
                }
119
 
120
                /* Copy the data from page buffer into inode blocks */
121
                for (int x = pfn, bufpage = 0; x < pfn + npages; x++, bufpage++)
122
                        memcpy(i->block[x], ((void *)buf) + (bufpage * blocksize), blocksize);
123
        }
124
 
125
        return (int)(npages * blocksize);
126
}
127
 
128
int memfs_file_write(struct vnode *v, unsigned long pfn, unsigned long npages, void *buf)
129
{
130
        return memfs_file_read_write(v, pfn, npages, buf, 1);
131
}
132
 
133
int memfs_file_read(struct vnode *v, unsigned long pfn, unsigned long npages, void *buf)
134
{
135
        return memfs_file_read_write(v, pfn, npages, buf, 0);
136
}
137
 
138
struct file_ops memfs_file_operations = {
139
        .read = memfs_file_read,
140
        .write = memfs_file_write,
141
};
142
 

powered by: WebSVN 2.1.0

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