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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [fs/] [jffs2/] [v2_0/] [src/] [read.c] - Blame information for rev 565

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
/*
2
 * JFFS2 -- Journalling Flash File System, Version 2.
3
 *
4
 * Copyright (C) 2001, 2002 Red Hat, Inc.
5
 *
6
 * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
7
 *
8
 * For licensing information, see the file 'LICENCE' in this directory.
9
 *
10
 * $Id: read.c,v 1.1.1.1 2004-02-14 13:29:20 phoenix Exp $
11
 *
12
 */
13
 
14
#include <linux/kernel.h>
15
#include <linux/slab.h>
16
#include <linux/crc32.h>
17
#include <linux/pagemap.h>
18
#include <linux/mtd/mtd.h>
19
#include "nodelist.h"
20
 
21
int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_full_dnode *fd, unsigned char *buf, int ofs, int len)
22
{
23
        struct jffs2_raw_inode *ri;
24
        size_t readlen;
25
        uint32_t crc;
26
        unsigned char *decomprbuf = NULL;
27
        unsigned char *readbuf = NULL;
28
        int ret = 0;
29
 
30
        ri = jffs2_alloc_raw_inode();
31
        if (!ri)
32
                return -ENOMEM;
33
 
34
        ret = jffs2_flash_read(c, ref_offset(fd->raw), sizeof(*ri), &readlen, (char *)ri);
35
        if (ret) {
36
                jffs2_free_raw_inode(ri);
37
                printk(KERN_WARNING "Error reading node from 0x%08x: %d\n", ref_offset(fd->raw), ret);
38
                return ret;
39
        }
40
        if (readlen != sizeof(*ri)) {
41
                jffs2_free_raw_inode(ri);
42
                printk(KERN_WARNING "Short read from 0x%08x: wanted 0x%zx bytes, got 0x%zx\n",
43
                       ref_offset(fd->raw), sizeof(*ri), readlen);
44
                return -EIO;
45
        }
46
        crc = crc32(0, ri, sizeof(*ri)-8);
47
 
48
        D1(printk(KERN_DEBUG "Node read from %08x: node_crc %08x, calculated CRC %08x. dsize %x, csize %x, offset %x, buf %p\n",
49
                  ref_offset(fd->raw), je32_to_cpu(ri->node_crc),
50
                  crc, je32_to_cpu(ri->dsize), je32_to_cpu(ri->csize),
51
                  je32_to_cpu(ri->offset), buf));
52
        if (crc != je32_to_cpu(ri->node_crc)) {
53
                printk(KERN_WARNING "Node CRC %08x != calculated CRC %08x for node at %08x\n",
54
                       je32_to_cpu(ri->node_crc), crc, ref_offset(fd->raw));
55
                ret = -EIO;
56
                goto out_ri;
57
        }
58
        /* There was a bug where we wrote hole nodes out with csize/dsize
59
           swapped. Deal with it */
60
        if (ri->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(ri->dsize) &&
61
            je32_to_cpu(ri->csize)) {
62
                ri->dsize = ri->csize;
63
                ri->csize = cpu_to_je32(0);
64
        }
65
 
66
        D1(if(ofs + len > je32_to_cpu(ri->dsize)) {
67
                printk(KERN_WARNING "jffs2_read_dnode() asked for %d bytes at %d from %d-byte node\n",
68
                       len, ofs, je32_to_cpu(ri->dsize));
69
                ret = -EINVAL;
70
                goto out_ri;
71
        });
72
 
73
 
74
        if (ri->compr == JFFS2_COMPR_ZERO) {
75
                memset(buf, 0, len);
76
                goto out_ri;
77
        }
78
 
79
        /* Cases:
80
           Reading whole node and it's uncompressed - read directly to buffer provided, check CRC.
81
           Reading whole node and it's compressed - read into comprbuf, check CRC and decompress to buffer provided
82
           Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy
83
           Reading partial node and it's compressed - read into readbuf, check checksum, decompress to decomprbuf and copy
84
        */
85
        if (ri->compr == JFFS2_COMPR_NONE && len == je32_to_cpu(ri->dsize)) {
86
                readbuf = buf;
87
        } else {
88
                readbuf = kmalloc(je32_to_cpu(ri->csize), GFP_KERNEL);
89
                if (!readbuf) {
90
                        ret = -ENOMEM;
91
                        goto out_ri;
92
                }
93
        }
94
        if (ri->compr != JFFS2_COMPR_NONE) {
95
                if (len < je32_to_cpu(ri->dsize)) {
96
                        decomprbuf = kmalloc(je32_to_cpu(ri->dsize), GFP_KERNEL);
97
                        if (!decomprbuf) {
98
                                ret = -ENOMEM;
99
                                goto out_readbuf;
100
                        }
101
                } else {
102
                        decomprbuf = buf;
103
                }
104
        } else {
105
                decomprbuf = readbuf;
106
        }
107
 
108
        D2(printk(KERN_DEBUG "Read %d bytes to %p\n", je32_to_cpu(ri->csize),
109
                  readbuf));
110
        ret = jffs2_flash_read(c, (ref_offset(fd->raw)) + sizeof(*ri),
111
                               je32_to_cpu(ri->csize), &readlen, readbuf);
112
 
113
        if (!ret && readlen != je32_to_cpu(ri->csize))
114
                ret = -EIO;
115
        if (ret)
116
                goto out_decomprbuf;
117
 
118
        crc = crc32(0, readbuf, je32_to_cpu(ri->csize));
119
        if (crc != je32_to_cpu(ri->data_crc)) {
120
                printk(KERN_WARNING "Data CRC %08x != calculated CRC %08x for node at %08x\n",
121
                       je32_to_cpu(ri->data_crc), crc, ref_offset(fd->raw));
122
                ret = -EIO;
123
                goto out_decomprbuf;
124
        }
125
        D2(printk(KERN_DEBUG "Data CRC matches calculated CRC %08x\n", crc));
126
        if (ri->compr != JFFS2_COMPR_NONE) {
127
                D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n",
128
                          je32_to_cpu(ri->csize), readbuf, je32_to_cpu(ri->dsize), decomprbuf));
129
                ret = jffs2_decompress(ri->compr, readbuf, decomprbuf, je32_to_cpu(ri->csize), je32_to_cpu(ri->dsize));
130
                if (ret) {
131
                        printk(KERN_WARNING "Error: jffs2_decompress returned %d\n", ret);
132
                        goto out_decomprbuf;
133
                }
134
        }
135
 
136
        if (len < je32_to_cpu(ri->dsize)) {
137
                memcpy(buf, decomprbuf+ofs, len);
138
        }
139
 out_decomprbuf:
140
        if(decomprbuf != buf && decomprbuf != readbuf)
141
                kfree(decomprbuf);
142
 out_readbuf:
143
        if(readbuf != buf)
144
                kfree(readbuf);
145
 out_ri:
146
        jffs2_free_raw_inode(ri);
147
 
148
        return ret;
149
}
150
 
151
int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
152
                           unsigned char *buf, uint32_t offset, uint32_t len)
153
{
154
        uint32_t end = offset + len;
155
        struct jffs2_node_frag *frag;
156
        int ret;
157
 
158
        D1(printk(KERN_DEBUG "jffs2_read_inode_range: ino #%u, range 0x%08x-0x%08x\n",
159
                  f->inocache->ino, offset, offset+len));
160
 
161
        frag = jffs2_lookup_node_frag(&f->fragtree, offset);
162
 
163
        /* XXX FIXME: Where a single physical node actually shows up in two
164
           frags, we read it twice. Don't do that. */
165
        /* Now we're pointing at the first frag which overlaps our page */
166
        while(offset < end) {
167
                D2(printk(KERN_DEBUG "jffs2_read_inode_range: offset %d, end %d\n", offset, end));
168
                if (!frag || frag->ofs > offset) {
169
                        uint32_t holesize = end - offset;
170
                        if (frag) {
171
                                D1(printk(KERN_NOTICE "Eep. Hole in ino #%u fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n", f->inocache->ino, frag->ofs, offset));
172
                                holesize = min(holesize, frag->ofs - offset);
173
                                D1(jffs2_print_frag_list(f));
174
                        }
175
                        D1(printk(KERN_DEBUG "Filling non-frag hole from %d-%d\n", offset, offset+holesize));
176
                        memset(buf, 0, holesize);
177
                        buf += holesize;
178
                        offset += holesize;
179
                        continue;
180
                } else if (frag->ofs < offset && (offset & (PAGE_CACHE_SIZE-1)) != 0) {
181
                        D1(printk(KERN_NOTICE "Eep. Overlap in ino #%u fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n",
182
                                  f->inocache->ino, frag->ofs, offset));
183
                        D1(jffs2_print_frag_list(f));
184
                        memset(buf, 0, end - offset);
185
                        return -EIO;
186
                } else if (!frag->node) {
187
                        uint32_t holeend = min(end, frag->ofs + frag->size);
188
                        D1(printk(KERN_DEBUG "Filling frag hole from %d-%d (frag 0x%x 0x%x)\n", offset, holeend, frag->ofs, frag->ofs + frag->size));
189
                        memset(buf, 0, holeend - offset);
190
                        buf += holeend - offset;
191
                        offset = holeend;
192
                        frag = frag_next(frag);
193
                        continue;
194
                } else {
195
                        uint32_t readlen;
196
                        uint32_t fragofs; /* offset within the frag to start reading */
197
 
198
                        fragofs = offset - frag->ofs;
199
                        readlen = min(frag->size - fragofs, end - offset);
200
                        D1(printk(KERN_DEBUG "Reading %d-%d from node at 0x%08x (%d)\n",
201
                                  frag->ofs+fragofs, frag->ofs+fragofs+readlen,
202
                                  ref_offset(frag->node->raw), ref_flags(frag->node->raw)));
203
                        ret = jffs2_read_dnode(c, frag->node, buf, fragofs + frag->ofs - frag->node->ofs, readlen);
204
                        D2(printk(KERN_DEBUG "node read done\n"));
205
                        if (ret) {
206
                                D1(printk(KERN_DEBUG"jffs2_read_inode_range error %d\n",ret));
207
                                memset(buf, 0, readlen);
208
                                return ret;
209
                        }
210
                        buf += readlen;
211
                        offset += readlen;
212
                        frag = frag_next(frag);
213
                        D2(printk(KERN_DEBUG "node read was OK. Looping\n"));
214
                }
215
        }
216
        return 0;
217
}
218
 
219
/* Core function to read symlink target. */
220
char *jffs2_getlink(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
221
{
222
        char *buf;
223
        int ret;
224
 
225
        down(&f->sem);
226
 
227
        if (!f->metadata) {
228
                printk(KERN_NOTICE "No metadata for symlink inode #%u\n", f->inocache->ino);
229
                up(&f->sem);
230
                return ERR_PTR(-EINVAL);
231
        }
232
        buf = kmalloc(f->metadata->size+1, GFP_USER);
233
        if (!buf) {
234
                up(&f->sem);
235
                return ERR_PTR(-ENOMEM);
236
        }
237
        buf[f->metadata->size]=0;
238
 
239
        ret = jffs2_read_dnode(c, f->metadata, buf, 0, f->metadata->size);
240
 
241
        up(&f->sem);
242
 
243
        if (ret) {
244
                kfree(buf);
245
                return ERR_PTR(ret);
246
        }
247
        return buf;
248
}

powered by: WebSVN 2.1.0

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