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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [fs/] [jffs2/] [current/] [src/] [readinode.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
/*
2
 * JFFS2 -- Journalling Flash File System, Version 2.
3
 *
4
 * Copyright (C) 2001-2003 Red Hat, Inc.
5
 *
6
 * Created by David Woodhouse <dwmw2@infradead.org>
7
 *
8
 * For licensing information, see the file 'LICENCE' in this directory.
9
 *
10
 * $Id: readinode.c,v 1.132 2005/07/28 14:46:40 dedekind Exp $
11
 *
12
 */
13
 
14
#include <linux/kernel.h>
15
#include <linux/sched.h>
16
#include <linux/slab.h>
17
#include <linux/fs.h>
18
#include <linux/crc32.h>
19
#include <linux/pagemap.h>
20
#include <linux/mtd/mtd.h>
21
#include <linux/compiler.h>
22
#include "nodelist.h"
23
 
24
void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size)
25
{
26
        struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size);
27
 
28
        JFFS2_DBG_FRAGTREE("truncating fragtree to 0x%08x bytes\n", size);
29
 
30
        /* We know frag->ofs <= size. That's what lookup does for us */
31
        if (frag && frag->ofs != size) {
32
                if (frag->ofs+frag->size >= size) {
33
                        JFFS2_DBG_FRAGTREE2("truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size);
34
                        frag->size = size - frag->ofs;
35
                }
36
                frag = frag_next(frag);
37
        }
38
        while (frag && frag->ofs >= size) {
39
                struct jffs2_node_frag *next = frag_next(frag);
40
 
41
                JFFS2_DBG_FRAGTREE("removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size);
42
                frag_erase(frag, list);
43
                jffs2_obsolete_node_frag(c, frag);
44
                frag = next;
45
        }
46
}
47
 
48
/*
49
 * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in
50
 * order of increasing version.
51
 */
52
static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list)
53
{
54
        struct rb_node **p = &list->rb_node;
55
        struct rb_node * parent = NULL;
56
        struct jffs2_tmp_dnode_info *this;
57
 
58
        while (*p) {
59
                parent = *p;
60
                this = rb_entry(parent, struct jffs2_tmp_dnode_info, rb);
61
 
62
                /* There may actually be a collision here, but it doesn't
63
                   actually matter. As long as the two nodes with the same
64
                   version are together, it's all fine. */
65
                if (tn->version < this->version)
66
                        p = &(*p)->rb_left;
67
                else
68
                        p = &(*p)->rb_right;
69
        }
70
 
71
        rb_link_node(&tn->rb, parent, p);
72
        rb_insert_color(&tn->rb, list);
73
}
74
 
75
static void jffs2_free_tmp_dnode_info_list(struct rb_root *list)
76
{
77
        struct rb_node *this;
78
        struct jffs2_tmp_dnode_info *tn;
79
 
80
        this = list->rb_node;
81
 
82
        /* Now at bottom of tree */
83
        while (this) {
84
                if (this->rb_left)
85
                        this = this->rb_left;
86
                else if (this->rb_right)
87
                        this = this->rb_right;
88
                else {
89
                        tn = rb_entry(this, struct jffs2_tmp_dnode_info, rb);
90
                        jffs2_free_full_dnode(tn->fn);
91
                        jffs2_free_tmp_dnode_info(tn);
92
 
93
                        this = this->rb_parent;
94
                        if (!this)
95
                                break;
96
 
97
                        if (this->rb_left == &tn->rb)
98
                                this->rb_left = NULL;
99
                        else if (this->rb_right == &tn->rb)
100
                                this->rb_right = NULL;
101
                        else BUG();
102
                }
103
        }
104
        list->rb_node = NULL;
105
}
106
 
107
static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd)
108
{
109
        struct jffs2_full_dirent *next;
110
 
111
        while (fd) {
112
                next = fd->next;
113
                jffs2_free_full_dirent(fd);
114
                fd = next;
115
        }
116
}
117
 
118
/* Returns first valid node after 'ref'. May return 'ref' */
119
static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_ref *ref)
120
{
121
        while (ref && ref->next_in_ino) {
122
                if (!ref_obsolete(ref))
123
                        return ref;
124
                JFFS2_DBG_NODEREF("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref));
125
                ref = ref->next_in_ino;
126
        }
127
        return NULL;
128
}
129
 
130
/*
131
 * Helper function for jffs2_get_inode_nodes().
132
 * It is called every time an directory entry node is found.
133
 *
134
 * Returns: 0 on succes;
135
 *          1 if the node should be marked obsolete;
136
 *          negative error code on failure.
137
 */
138
static inline int
139
read_direntry(struct jffs2_sb_info *c,
140
              struct jffs2_raw_node_ref *ref,
141
              struct jffs2_raw_dirent *rd,
142
              uint32_t read,
143
              struct jffs2_full_dirent **fdp,
144
              int32_t *latest_mctime,
145
              uint32_t *mctime_ver)
146
{
147
        struct jffs2_full_dirent *fd;
148
 
149
        /* The direntry nodes are checked during the flash scanning */
150
        BUG_ON(ref_flags(ref) == REF_UNCHECKED);
151
        /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
152
        BUG_ON(ref_obsolete(ref));
153
 
154
        /* Sanity check */
155
        if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
156
                JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
157
                       ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
158
                return 1;
159
        }
160
 
161
        fd = jffs2_alloc_full_dirent(rd->nsize + 1);
162
        if (unlikely(!fd))
163
                return -ENOMEM;
164
 
165
        fd->raw = ref;
166
        fd->version = je32_to_cpu(rd->version);
167
        fd->ino = je32_to_cpu(rd->ino);
168
        fd->type = rd->type;
169
 
170
        /* Pick out the mctime of the latest dirent */
171
        if(fd->version > *mctime_ver) {
172
                *mctime_ver = fd->version;
173
                *latest_mctime = je32_to_cpu(rd->mctime);
174
        }
175
 
176
        /*
177
         * Copy as much of the name as possible from the raw
178
         * dirent we've already read from the flash.
179
         */
180
        if (read > sizeof(*rd))
181
                memcpy(&fd->name[0], &rd->name[0],
182
                       min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) ));
183
 
184
        /* Do we need to copy any more of the name directly from the flash? */
185
        if (rd->nsize + sizeof(*rd) > read) {
186
                /* FIXME: point() */
187
                int err;
188
                int already = read - sizeof(*rd);
189
 
190
                err = jffs2_flash_read(c, (ref_offset(ref)) + read,
191
                                rd->nsize - already, &read, &fd->name[already]);
192
                if (unlikely(read != rd->nsize - already) && likely(!err))
193
                        return -EIO;
194
 
195
                if (unlikely(err)) {
196
                        JFFS2_ERROR("read remainder of name: error %d\n", err);
197
                        jffs2_free_full_dirent(fd);
198
                        return -EIO;
199
                }
200
        }
201
 
202
        fd->nhash = full_name_hash(fd->name, rd->nsize);
203
        fd->next = NULL;
204
        fd->name[rd->nsize] = '\0';
205
 
206
        /*
207
         * Wheee. We now have a complete jffs2_full_dirent structure, with
208
         * the name in it and everything. Link it into the list
209
         */
210
        jffs2_add_fd_to_list(c, fd, fdp);
211
 
212
        return 0;
213
}
214
 
215
/*
216
 * Helper function for jffs2_get_inode_nodes().
217
 * It is called every time an inode node is found.
218
 *
219
 * Returns: 0 on succes;
220
 *          1 if the node should be marked obsolete;
221
 *          negative error code on failure.
222
 */
223
static inline int
224
read_dnode(struct jffs2_sb_info *c,
225
           struct jffs2_raw_node_ref *ref,
226
           struct jffs2_raw_inode *rd,
227
           uint32_t read,
228
           struct rb_root *tnp,
229
           int32_t *latest_mctime,
230
           uint32_t *mctime_ver)
231
{
232
        struct jffs2_eraseblock *jeb;
233
        struct jffs2_tmp_dnode_info *tn;
234
 
235
        /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
236
        BUG_ON(ref_obsolete(ref));
237
 
238
        /* If we've never checked the CRCs on this node, check them now */
239
        if (ref_flags(ref) == REF_UNCHECKED) {
240
                uint32_t crc, len;
241
 
242
                crc = crc32(0, rd, sizeof(*rd) - 8);
243
                if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
244
                        JFFS2_NOTICE("header CRC failed on node at %#08x: read %#08x, calculated %#08x\n",
245
                                        ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
246
                        return 1;
247
                }
248
 
249
                /* Sanity checks */
250
                if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) ||
251
                    unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) {
252
                                JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref));
253
                                jffs2_dbg_dump_node(c, ref_offset(ref));
254
                        return 1;
255
                }
256
 
257
                if (rd->compr != JFFS2_COMPR_ZERO && je32_to_cpu(rd->csize)) {
258
                        unsigned char *buf = NULL;
259
                        uint32_t pointed = 0;
260
                        int err;
261
#ifndef __ECOS
262
                        if (c->mtd->point) {
263
                                err = c->mtd->point (c->mtd, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize),
264
                                                     &read, &buf);
265
                                if (unlikely(read < je32_to_cpu(rd->csize)) && likely(!err)) {
266
                                        JFFS2_ERROR("MTD point returned len too short: 0x%zx\n", read);
267
                                        c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd),
268
                                                        je32_to_cpu(rd->csize));
269
                                } else if (unlikely(err)){
270
                                        JFFS2_ERROR("MTD point failed %d\n", err);
271
                                } else
272
                                        pointed = 1; /* succefully pointed to device */
273
                        }
274
#endif                                  
275
                        if(!pointed){
276
                                buf = kmalloc(je32_to_cpu(rd->csize), GFP_KERNEL);
277
                                if (!buf)
278
                                        return -ENOMEM;
279
 
280
                                err = jffs2_flash_read(c, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize),
281
                                                        &read, buf);
282
                                if (unlikely(read != je32_to_cpu(rd->csize)) && likely(!err))
283
                                        err = -EIO;
284
                                if (err) {
285
                                        kfree(buf);
286
                                        return err;
287
                                }
288
                        }
289
                        crc = crc32(0, buf, je32_to_cpu(rd->csize));
290
                        if(!pointed)
291
                                kfree(buf);
292
#ifndef __ECOS
293
                        else
294
                                c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize));
295
#endif
296
 
297
                        if (crc != je32_to_cpu(rd->data_crc)) {
298
                                JFFS2_NOTICE("data CRC failed on node at %#08x: read %#08x, calculated %#08x\n",
299
                                        ref_offset(ref), je32_to_cpu(rd->data_crc), crc);
300
                                return 1;
301
                        }
302
 
303
                }
304
 
305
                /* Mark the node as having been checked and fix the accounting accordingly */
306
                jeb = &c->blocks[ref->flash_offset / c->sector_size];
307
                len = ref_totlen(c, jeb, ref);
308
 
309
                spin_lock(&c->erase_completion_lock);
310
                jeb->used_size += len;
311
                jeb->unchecked_size -= len;
312
                c->used_size += len;
313
                c->unchecked_size -= len;
314
 
315
                /* If node covers at least a whole page, or if it starts at the
316
                   beginning of a page and runs to the end of the file, or if
317
                   it's a hole node, mark it REF_PRISTINE, else REF_NORMAL.
318
 
319
                   If it's actually overlapped, it'll get made NORMAL (or OBSOLETE)
320
                   when the overlapping node(s) get added to the tree anyway.
321
                */
322
                if ((je32_to_cpu(rd->dsize) >= PAGE_CACHE_SIZE) ||
323
                    ( ((je32_to_cpu(rd->offset) & (PAGE_CACHE_SIZE-1))==0) &&
324
                      (je32_to_cpu(rd->dsize) + je32_to_cpu(rd->offset) == je32_to_cpu(rd->isize)))) {
325
                        JFFS2_DBG_READINODE("marking node at %#08x REF_PRISTINE\n", ref_offset(ref));
326
                        ref->flash_offset = ref_offset(ref) | REF_PRISTINE;
327
                } else {
328
                        JFFS2_DBG_READINODE("marking node at %#08x REF_NORMAL\n", ref_offset(ref));
329
                        ref->flash_offset = ref_offset(ref) | REF_NORMAL;
330
                }
331
                spin_unlock(&c->erase_completion_lock);
332
        }
333
 
334
        tn = jffs2_alloc_tmp_dnode_info();
335
        if (!tn) {
336
                JFFS2_ERROR("alloc tn failed\n");
337
                return -ENOMEM;
338
        }
339
 
340
        tn->fn = jffs2_alloc_full_dnode();
341
        if (!tn->fn) {
342
                JFFS2_ERROR("alloc fn failed\n");
343
                jffs2_free_tmp_dnode_info(tn);
344
                return -ENOMEM;
345
        }
346
 
347
        tn->version = je32_to_cpu(rd->version);
348
        tn->fn->ofs = je32_to_cpu(rd->offset);
349
        tn->fn->raw = ref;
350
 
351
        /* There was a bug where we wrote hole nodes out with
352
           csize/dsize swapped. Deal with it */
353
        if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && je32_to_cpu(rd->csize))
354
                tn->fn->size = je32_to_cpu(rd->csize);
355
        else // normal case...
356
                tn->fn->size = je32_to_cpu(rd->dsize);
357
 
358
        JFFS2_DBG_READINODE("dnode @%08x: ver %u, offset %#04x, dsize %#04x\n",
359
                  ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize));
360
 
361
        jffs2_add_tn_to_tree(tn, tnp);
362
 
363
        return 0;
364
}
365
 
366
/*
367
 * Helper function for jffs2_get_inode_nodes().
368
 * It is called every time an unknown node is found.
369
 *
370
 * Returns: 0 on succes;
371
 *          1 if the node should be marked obsolete;
372
 *          negative error code on failure.
373
 */
374
static inline int
375
read_unknown(struct jffs2_sb_info *c,
376
             struct jffs2_raw_node_ref *ref,
377
             struct jffs2_unknown_node *un,
378
             uint32_t read)
379
{
380
        /* We don't mark unknown nodes as REF_UNCHECKED */
381
        BUG_ON(ref_flags(ref) == REF_UNCHECKED);
382
 
383
        un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
384
 
385
        if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) {
386
                /* Hmmm. This should have been caught at scan time. */
387
                JFFS2_NOTICE("node header CRC failed at %#08x. But it must have been OK earlier.\n", ref_offset(ref));
388
                jffs2_dbg_dump_node(c, ref_offset(ref));
389
                return 1;
390
        } else {
391
                switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
392
 
393
                case JFFS2_FEATURE_INCOMPAT:
394
                        JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n",
395
                                je16_to_cpu(un->nodetype), ref_offset(ref));
396
                        /* EEP */
397
                        BUG();
398
                        break;
399
 
400
                case JFFS2_FEATURE_ROCOMPAT:
401
                        JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n",
402
                                        je16_to_cpu(un->nodetype), ref_offset(ref));
403
                        BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
404
                        break;
405
 
406
                case JFFS2_FEATURE_RWCOMPAT_COPY:
407
                        JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
408
                                        je16_to_cpu(un->nodetype), ref_offset(ref));
409
                        break;
410
 
411
                case JFFS2_FEATURE_RWCOMPAT_DELETE:
412
                        JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
413
                                        je16_to_cpu(un->nodetype), ref_offset(ref));
414
                        return 1;
415
                }
416
        }
417
 
418
        return 0;
419
}
420
 
421
/* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated
422
   with this ino, returning the former in order of version */
423
 
424
static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
425
                                 struct rb_root *tnp, struct jffs2_full_dirent **fdp,
426
                                 uint32_t *highest_version, uint32_t *latest_mctime,
427
                                 uint32_t *mctime_ver)
428
{
429
        struct jffs2_raw_node_ref *ref, *valid_ref;
430
        struct rb_root ret_tn = RB_ROOT;
431
        struct jffs2_full_dirent *ret_fd = NULL;
432
        union jffs2_node_union node;
433
        size_t retlen;
434
        int err;
435
 
436
        *mctime_ver = 0;
437
 
438
        JFFS2_DBG_READINODE("ino #%u\n", f->inocache->ino);
439
 
440
        spin_lock(&c->erase_completion_lock);
441
 
442
        valid_ref = jffs2_first_valid_node(f->inocache->nodes);
443
 
444
        if (!valid_ref && (f->inocache->ino != 1))
445
                JFFS2_WARNING("no valid nodes for ino #%u\n", f->inocache->ino);
446
 
447
        while (valid_ref) {
448
                /* We can hold a pointer to a non-obsolete node without the spinlock,
449
                   but _obsolete_ nodes may disappear at any time, if the block
450
                   they're in gets erased. So if we mark 'ref' obsolete while we're
451
                   not holding the lock, it can go away immediately. For that reason,
452
                   we find the next valid node first, before processing 'ref'.
453
                */
454
                ref = valid_ref;
455
                valid_ref = jffs2_first_valid_node(ref->next_in_ino);
456
                spin_unlock(&c->erase_completion_lock);
457
 
458
                cond_resched();
459
 
460
                /* FIXME: point() */
461
                err = jffs2_flash_read(c, (ref_offset(ref)),
462
                                       min_t(uint32_t, ref_totlen(c, NULL, ref), sizeof(node)),
463
                                       &retlen, (void *)&node);
464
                if (err) {
465
                        JFFS2_ERROR("error %d reading node at 0x%08x in get_inode_nodes()\n", err, ref_offset(ref));
466
                        goto free_out;
467
                }
468
 
469
                switch (je16_to_cpu(node.u.nodetype)) {
470
 
471
                case JFFS2_NODETYPE_DIRENT:
472
                        JFFS2_DBG_READINODE("node at %08x (%d) is a dirent node\n", ref_offset(ref), ref_flags(ref));
473
 
474
                        if (retlen < sizeof(node.d)) {
475
                                JFFS2_ERROR("short read dirent at %#08x\n", ref_offset(ref));
476
                                err = -EIO;
477
                                goto free_out;
478
                        }
479
 
480
                        err = read_direntry(c, ref, &node.d, retlen, &ret_fd, latest_mctime, mctime_ver);
481
                        if (err == 1) {
482
                                jffs2_mark_node_obsolete(c, ref);
483
                                break;
484
                        } else if (unlikely(err))
485
                                goto free_out;
486
 
487
                        if (je32_to_cpu(node.d.version) > *highest_version)
488
                                *highest_version = je32_to_cpu(node.d.version);
489
 
490
                        break;
491
 
492
                case JFFS2_NODETYPE_INODE:
493
                        JFFS2_DBG_READINODE("node at %08x (%d) is a data node\n", ref_offset(ref), ref_flags(ref));
494
 
495
                        if (retlen < sizeof(node.i)) {
496
                                JFFS2_ERROR("short read dnode at %#08x\n", ref_offset(ref));
497
                                err = -EIO;
498
                                goto free_out;
499
                        }
500
 
501
                        err = read_dnode(c, ref, &node.i, retlen, &ret_tn, latest_mctime, mctime_ver);
502
                        if (err == 1) {
503
                                jffs2_mark_node_obsolete(c, ref);
504
                                break;
505
                        } else if (unlikely(err))
506
                                goto free_out;
507
 
508
                        if (je32_to_cpu(node.i.version) > *highest_version)
509
                                *highest_version = je32_to_cpu(node.i.version);
510
 
511
                        JFFS2_DBG_READINODE("version %d, highest_version now %d\n",
512
                                        je32_to_cpu(node.i.version), *highest_version);
513
 
514
                        break;
515
 
516
                default:
517
                        /* Check we've managed to read at least the common node header */
518
                        if (retlen < sizeof(struct jffs2_unknown_node)) {
519
                                JFFS2_ERROR("short read unknown node at %#08x\n", ref_offset(ref));
520
                                return -EIO;
521
                        }
522
 
523
                        err = read_unknown(c, ref, &node.u, retlen);
524
                        if (err == 1) {
525
                                jffs2_mark_node_obsolete(c, ref);
526
                                break;
527
                        } else if (unlikely(err))
528
                                goto free_out;
529
 
530
                }
531
                spin_lock(&c->erase_completion_lock);
532
 
533
        }
534
        spin_unlock(&c->erase_completion_lock);
535
        *tnp = ret_tn;
536
        *fdp = ret_fd;
537
 
538
        return 0;
539
 
540
 free_out:
541
        jffs2_free_tmp_dnode_info_list(&ret_tn);
542
        jffs2_free_full_dirent_list(ret_fd);
543
        return err;
544
}
545
 
546
static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
547
                                        struct jffs2_inode_info *f,
548
                                        struct jffs2_raw_inode *latest_node)
549
{
550
        struct jffs2_tmp_dnode_info *tn = NULL;
551
        struct rb_root tn_list;
552
        struct rb_node *rb, *repl_rb;
553
        struct jffs2_full_dirent *fd_list;
554
        struct jffs2_full_dnode *fn = NULL;
555
        uint32_t crc;
556
        uint32_t latest_mctime, mctime_ver;
557
        uint32_t mdata_ver = 0;
558
        size_t retlen;
559
        int ret;
560
 
561
        JFFS2_DBG_READINODE("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink);
562
 
563
        /* Grab all nodes relevant to this ino */
564
        ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver);
565
 
566
        if (ret) {
567
                JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret);
568
                if (f->inocache->state == INO_STATE_READING)
569
                        jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
570
                return ret;
571
        }
572
        f->dents = fd_list;
573
 
574
        rb = rb_first(&tn_list);
575
 
576
        while (rb) {
577
                tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb);
578
                fn = tn->fn;
579
 
580
                if (f->metadata) {
581
                        if (likely(tn->version >= mdata_ver)) {
582
                                JFFS2_DBG_READINODE("obsoleting old metadata at 0x%08x\n", ref_offset(f->metadata->raw));
583
                                jffs2_mark_node_obsolete(c, f->metadata->raw);
584
                                jffs2_free_full_dnode(f->metadata);
585
                                f->metadata = NULL;
586
 
587
                                mdata_ver = 0;
588
                        } else {
589
                                /* This should never happen. */
590
                                JFFS2_ERROR("Er. New metadata at 0x%08x with ver %d is actually older than previous ver %d at 0x%08x\n",
591
                                          ref_offset(fn->raw), tn->version, mdata_ver, ref_offset(f->metadata->raw));
592
                                jffs2_mark_node_obsolete(c, fn->raw);
593
                                jffs2_free_full_dnode(fn);
594
                                /* Fill in latest_node from the metadata, not this one we're about to free... */
595
                                fn = f->metadata;
596
                                goto next_tn;
597
                        }
598
                }
599
 
600
                if (fn->size) {
601
                        jffs2_add_full_dnode_to_inode(c, f, fn);
602
                } else {
603
                        /* Zero-sized node at end of version list. Just a metadata update */
604
                        JFFS2_DBG_READINODE("metadata @%08x: ver %d\n", ref_offset(fn->raw), tn->version);
605
                        f->metadata = fn;
606
                        mdata_ver = tn->version;
607
                }
608
        next_tn:
609
                BUG_ON(rb->rb_left);
610
                if (rb->rb_parent && rb->rb_parent->rb_left == rb) {
611
                        /* We were then left-hand child of our parent. We need
612
                           to move our own right-hand child into our place. */
613
                        repl_rb = rb->rb_right;
614
                        if (repl_rb)
615
                                repl_rb->rb_parent = rb->rb_parent;
616
                } else
617
                        repl_rb = NULL;
618
 
619
                rb = rb_next(rb);
620
 
621
                /* Remove the spent tn from the tree; don't bother rebalancing
622
                   but put our right-hand child in our own place. */
623
                if (tn->rb.rb_parent) {
624
                        if (tn->rb.rb_parent->rb_left == &tn->rb)
625
                                tn->rb.rb_parent->rb_left = repl_rb;
626
                        else if (tn->rb.rb_parent->rb_right == &tn->rb)
627
                                tn->rb.rb_parent->rb_right = repl_rb;
628
                        else BUG();
629
                } else if (tn->rb.rb_right)
630
                        tn->rb.rb_right->rb_parent = NULL;
631
 
632
                jffs2_free_tmp_dnode_info(tn);
633
        }
634
        jffs2_dbg_fragtree_paranoia_check_nolock(f);
635
 
636
        if (!fn) {
637
                /* No data nodes for this inode. */
638
                if (f->inocache->ino != 1) {
639
                        JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino);
640
                        if (!fd_list) {
641
                                if (f->inocache->state == INO_STATE_READING)
642
                                        jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
643
                                return -EIO;
644
                        }
645
                        JFFS2_NOTICE("but it has children so we fake some modes for it\n");
646
                }
647
                latest_node->mode = cpu_to_jemode(S_IFDIR|S_IRUGO|S_IWUSR|S_IXUGO);
648
                latest_node->version = cpu_to_je32(0);
649
                latest_node->atime = latest_node->ctime = latest_node->mtime = cpu_to_je32(0);
650
                latest_node->isize = cpu_to_je32(0);
651
                latest_node->gid = cpu_to_je16(0);
652
                latest_node->uid = cpu_to_je16(0);
653
                if (f->inocache->state == INO_STATE_READING)
654
                        jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
655
                return 0;
656
        }
657
 
658
        ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node);
659
        if (ret || retlen != sizeof(*latest_node)) {
660
                JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n",
661
                        ret, retlen, sizeof(*latest_node));
662
                /* FIXME: If this fails, there seems to be a memory leak. Find it. */
663
                up(&f->sem);
664
                jffs2_do_clear_inode(c, f);
665
                return ret?ret:-EIO;
666
        }
667
 
668
        crc = crc32(0, latest_node, sizeof(*latest_node)-8);
669
        if (crc != je32_to_cpu(latest_node->node_crc)) {
670
                JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n",
671
                        f->inocache->ino, ref_offset(fn->raw));
672
                up(&f->sem);
673
                jffs2_do_clear_inode(c, f);
674
                return -EIO;
675
        }
676
 
677
        switch(jemode_to_cpu(latest_node->mode) & S_IFMT) {
678
        case S_IFDIR:
679
                if (mctime_ver > je32_to_cpu(latest_node->version)) {
680
                        /* The times in the latest_node are actually older than
681
                           mctime in the latest dirent. Cheat. */
682
                        latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime);
683
                }
684
                break;
685
 
686
 
687
        case S_IFREG:
688
                /* If it was a regular file, truncate it to the latest node's isize */
689
                jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize));
690
                break;
691
 
692
        case S_IFLNK:
693
                /* Hack to work around broken isize in old symlink code.
694
                   Remove this when dwmw2 comes to his senses and stops
695
                   symlinks from being an entirely gratuitous special
696
                   case. */
697
                if (!je32_to_cpu(latest_node->isize))
698
                        latest_node->isize = latest_node->dsize;
699
 
700
                if (f->inocache->state != INO_STATE_CHECKING) {
701
                        /* Symlink's inode data is the target path. Read it and
702
                         * keep in RAM to facilitate quick follow symlink
703
                         * operation. */
704
                        f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL);
705
                        if (!f->target) {
706
                                JFFS2_ERROR("can't allocate %d bytes of memory for the symlink target path cache\n", je32_to_cpu(latest_node->csize));
707
                                up(&f->sem);
708
                                jffs2_do_clear_inode(c, f);
709
                                return -ENOMEM;
710
                        }
711
 
712
                        ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node),
713
                                                je32_to_cpu(latest_node->csize), &retlen, (char *)f->target);
714
 
715
                        if (ret  || retlen != je32_to_cpu(latest_node->csize)) {
716
                                if (retlen != je32_to_cpu(latest_node->csize))
717
                                        ret = -EIO;
718
                                kfree(f->target);
719
                                f->target = NULL;
720
                                up(&f->sem);
721
                                jffs2_do_clear_inode(c, f);
722
                                return -ret;
723
                        }
724
 
725
                        f->target[je32_to_cpu(latest_node->csize)] = '\0';
726
                        JFFS2_DBG_READINODE("symlink's target '%s' cached\n", f->target);
727
                }
728
 
729
                /* fall through... */
730
 
731
        case S_IFBLK:
732
        case S_IFCHR:
733
                /* Certain inode types should have only one data node, and it's
734
                   kept as the metadata node */
735
                if (f->metadata) {
736
                        JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n",
737
                               f->inocache->ino, jemode_to_cpu(latest_node->mode));
738
                        up(&f->sem);
739
                        jffs2_do_clear_inode(c, f);
740
                        return -EIO;
741
                }
742
                if (!frag_first(&f->fragtree)) {
743
                        JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n",
744
                               f->inocache->ino, jemode_to_cpu(latest_node->mode));
745
                        up(&f->sem);
746
                        jffs2_do_clear_inode(c, f);
747
                        return -EIO;
748
                }
749
                /* ASSERT: f->fraglist != NULL */
750
                if (frag_next(frag_first(&f->fragtree))) {
751
                        JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n",
752
                               f->inocache->ino, jemode_to_cpu(latest_node->mode));
753
                        /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
754
                        up(&f->sem);
755
                        jffs2_do_clear_inode(c, f);
756
                        return -EIO;
757
                }
758
                /* OK. We're happy */
759
                f->metadata = frag_first(&f->fragtree)->node;
760
                jffs2_free_node_frag(frag_first(&f->fragtree));
761
                f->fragtree = RB_ROOT;
762
                break;
763
        }
764
        if (f->inocache->state == INO_STATE_READING)
765
                jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
766
 
767
        return 0;
768
}
769
 
770
/* Scan the list of all nodes present for this ino, build map of versions, etc. */
771
int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
772
                        uint32_t ino, struct jffs2_raw_inode *latest_node)
773
{
774
        JFFS2_DBG_READINODE("read inode #%u\n", ino);
775
 
776
 retry_inocache:
777
        spin_lock(&c->inocache_lock);
778
        f->inocache = jffs2_get_ino_cache(c, ino);
779
 
780
        if (f->inocache) {
781
                /* Check its state. We may need to wait before we can use it */
782
                switch(f->inocache->state) {
783
                case INO_STATE_UNCHECKED:
784
                case INO_STATE_CHECKEDABSENT:
785
                        f->inocache->state = INO_STATE_READING;
786
                        break;
787
 
788
                case INO_STATE_CHECKING:
789
                case INO_STATE_GC:
790
                        /* If it's in either of these states, we need
791
                           to wait for whoever's got it to finish and
792
                           put it back. */
793
                        JFFS2_DBG_READINODE("waiting for ino #%u in state %d\n", ino, f->inocache->state);
794
                        sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
795
                        goto retry_inocache;
796
 
797
                case INO_STATE_READING:
798
                case INO_STATE_PRESENT:
799
                        /* Eep. This should never happen. It can
800
                        happen if Linux calls read_inode() again
801
                        before clear_inode() has finished though. */
802
                        JFFS2_ERROR("Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state);
803
                        /* Fail. That's probably better than allowing it to succeed */
804
                        f->inocache = NULL;
805
                        break;
806
 
807
                default:
808
                        BUG();
809
                }
810
        }
811
        spin_unlock(&c->inocache_lock);
812
 
813
        if (!f->inocache && ino == 1) {
814
                /* Special case - no root inode on medium */
815
                f->inocache = jffs2_alloc_inode_cache();
816
                if (!f->inocache) {
817
                        JFFS2_ERROR("cannot allocate inocache for root inode\n");
818
                        return -ENOMEM;
819
                }
820
                JFFS2_DBG_READINODE("creating inocache for root inode\n");
821
                memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
822
                f->inocache->ino = f->inocache->nlink = 1;
823
                f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
824
                f->inocache->state = INO_STATE_READING;
825
                jffs2_add_ino_cache(c, f->inocache);
826
        }
827
        if (!f->inocache) {
828
                JFFS2_ERROR("requestied to read an nonexistent ino %u\n", ino);
829
                return -ENOENT;
830
        }
831
 
832
        return jffs2_do_read_inode_internal(c, f, latest_node);
833
}
834
 
835
int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
836
{
837
        struct jffs2_raw_inode n;
838
        struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL);
839
        int ret;
840
 
841
        if (!f)
842
                return -ENOMEM;
843
 
844
        memset(f, 0, sizeof(*f));
845
        init_MUTEX_LOCKED(&f->sem);
846
        f->inocache = ic;
847
 
848
        ret = jffs2_do_read_inode_internal(c, f, &n);
849
        if (!ret) {
850
                up(&f->sem);
851
                jffs2_do_clear_inode(c, f);
852
        }
853
        kfree (f);
854
        return ret;
855
}
856
 
857
void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
858
{
859
        struct jffs2_full_dirent *fd, *fds;
860
        int deleted;
861
 
862
        down(&f->sem);
863
        deleted = f->inocache && !f->inocache->nlink;
864
 
865
        if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
866
                jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);
867
 
868
        if (f->metadata) {
869
                if (deleted)
870
                        jffs2_mark_node_obsolete(c, f->metadata->raw);
871
                jffs2_free_full_dnode(f->metadata);
872
        }
873
 
874
        jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL);
875
 
876
        if (f->target) {
877
                kfree(f->target);
878
                f->target = NULL;
879
        }
880
 
881
        fds = f->dents;
882
        while(fds) {
883
                fd = fds;
884
                fds = fd->next;
885
                jffs2_free_full_dirent(fd);
886
        }
887
 
888
        if (f->inocache && f->inocache->state != INO_STATE_CHECKING) {
889
                jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
890
                if (f->inocache->nodes == (void *)f->inocache)
891
                        jffs2_del_ino_cache(c, f->inocache);
892
        }
893
 
894
        up(&f->sem);
895
}

powered by: WebSVN 2.1.0

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