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

Subversion Repositories openrisc_me

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

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: readinode.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/fs.h>
17
#include <linux/crc32.h>
18
#include <linux/pagemap.h>
19
#include <linux/mtd/mtd.h>
20
#include <linux/compiler.h>
21
#include "nodelist.h"
22
 
23
static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_node_frag *newfrag);
24
 
25
#if CONFIG_JFFS2_FS_DEBUG >= 1
26
static void jffs2_print_fragtree(struct rb_root *list, int permitbug)
27
{
28
        struct jffs2_node_frag *this = frag_first(list);
29
        uint32_t lastofs = 0;
30
        int buggy = 0;
31
 
32
        while(this) {
33
                if (this->node)
34
                        printk(KERN_DEBUG "frag %04x-%04x: 0x%08x(%d) on flash (*%p). left (%p), right (%p), parent (%p)\n",
35
                               this->ofs, this->ofs+this->size, ref_offset(this->node->raw), ref_flags(this->node->raw),
36
                               this, frag_left(this), frag_right(this), frag_parent(this));
37
                else
38
                        printk(KERN_DEBUG "frag %04x-%04x: hole (*%p). left (%p} right (%p), parent (%p)\n", this->ofs,
39
                               this->ofs+this->size, this, frag_left(this), frag_right(this), frag_parent(this));
40
                if (this->ofs != lastofs)
41
                        buggy = 1;
42
                lastofs = this->ofs+this->size;
43
                this = frag_next(this);
44
        }
45
        if (buggy && !permitbug) {
46
                printk(KERN_CRIT "Frag tree got a hole in it\n");
47
                BUG();
48
        }
49
}
50
 
51
void jffs2_print_frag_list(struct jffs2_inode_info *f)
52
{
53
        jffs2_print_fragtree(&f->fragtree, 0);
54
 
55
        if (f->metadata) {
56
                printk(KERN_DEBUG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
57
        }
58
}
59
#endif /* D1 */
60
 
61
static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this)
62
{
63
        if (this->node) {
64
                this->node->frags--;
65
                if (!this->node->frags) {
66
                        /* The node has no valid frags left. It's totally obsoleted */
67
                        D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) obsolete\n",
68
                                  ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size));
69
                        jffs2_mark_node_obsolete(c, this->node->raw);
70
                        jffs2_free_full_dnode(this->node);
71
                } else {
72
                        D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n",
73
                                  ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size,
74
                                  this->node->frags));
75
                        mark_ref_normal(this->node->raw);
76
                }
77
 
78
        }
79
        jffs2_free_node_frag(this);
80
}
81
 
82
/* Given an inode, probably with existing list of fragments, add the new node
83
 * to the fragment list.
84
 */
85
int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn)
86
{
87
        int ret;
88
        struct jffs2_node_frag *newfrag;
89
 
90
        D1(printk(KERN_DEBUG "jffs2_add_full_dnode_to_inode(ino #%u, f %p, fn %p)\n", f->inocache->ino, f, fn));
91
 
92
        newfrag = jffs2_alloc_node_frag();
93
        if (unlikely(!newfrag))
94
                return -ENOMEM;
95
 
96
        D2(printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n",
97
                  fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag));
98
 
99
        if (unlikely(!fn->size)) {
100
                jffs2_free_node_frag(newfrag);
101
                return 0;
102
        }
103
 
104
        newfrag->ofs = fn->ofs;
105
        newfrag->size = fn->size;
106
        newfrag->node = fn;
107
        newfrag->node->frags = 1;
108
 
109
        ret = jffs2_add_frag_to_fragtree(c, &f->fragtree, newfrag);
110
        if (ret)
111
                return ret;
112
 
113
        /* If we now share a page with other nodes, mark either previous
114
           or next node REF_NORMAL, as appropriate.  */
115
        if (newfrag->ofs & (PAGE_CACHE_SIZE-1)) {
116
                struct jffs2_node_frag *prev = frag_prev(newfrag);
117
 
118
                mark_ref_normal(fn->raw);
119
                /* If we don't start at zero there's _always_ a previous */
120
                if (prev->node)
121
                        mark_ref_normal(prev->node->raw);
122
        }
123
 
124
        if ((newfrag->ofs+newfrag->size) & (PAGE_CACHE_SIZE-1)) {
125
                struct jffs2_node_frag *next = frag_next(newfrag);
126
 
127
                if (next) {
128
                        mark_ref_normal(fn->raw);
129
                        if (next->node)
130
                                mark_ref_normal(next->node->raw);
131
                }
132
        }
133
        D2(jffs2_print_frag_list(f));
134
        return 0;
135
}
136
 
137
/* Doesn't set inode->i_size */
138
static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_node_frag *newfrag)
139
{
140
        struct jffs2_node_frag *this;
141
        uint32_t lastend;
142
 
143
        /* Skip all the nodes which are completed before this one starts */
144
        this = jffs2_lookup_node_frag(list, newfrag->node->ofs);
145
 
146
        if (this) {
147
                D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n",
148
                          this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this));
149
                lastend = this->ofs + this->size;
150
        } else {
151
                D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave no frag\n"));
152
                lastend = 0;
153
        }
154
 
155
        /* See if we ran off the end of the list */
156
        if (lastend <= newfrag->ofs) {
157
                /* We did */
158
 
159
                /* Check if 'this' node was on the same page as the new node.
160
                   If so, both 'this' and the new node get marked REF_NORMAL so
161
                   the GC can take a look.
162
                */
163
                if ((lastend-1) >> PAGE_CACHE_SHIFT == newfrag->ofs >> PAGE_CACHE_SHIFT) {
164
                        if (this->node)
165
                                mark_ref_normal(this->node->raw);
166
                        mark_ref_normal(newfrag->node->raw);
167
                }
168
 
169
                if (lastend < newfrag->node->ofs) {
170
                        /* ... and we need to put a hole in before the new node */
171
                        struct jffs2_node_frag *holefrag = jffs2_alloc_node_frag();
172
                        if (!holefrag)
173
                                return -ENOMEM;
174
                        holefrag->ofs = lastend;
175
                        holefrag->size = newfrag->node->ofs - lastend;
176
                        holefrag->node = NULL;
177
                        if (this) {
178
                                /* By definition, the 'this' node has no right-hand child,
179
                                   because there are no frags with offset greater than it.
180
                                   So that's where we want to put the hole */
181
                                D2(printk(KERN_DEBUG "Adding hole frag (%p) on right of node at (%p)\n", holefrag, this));
182
                                rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right);
183
                        } else {
184
                                D2(printk(KERN_DEBUG "Adding hole frag (%p) at root of tree\n", holefrag));
185
                                rb_link_node(&holefrag->rb, NULL, &list->rb_node);
186
                        }
187
                        rb_insert_color(&holefrag->rb, list);
188
                        this = holefrag;
189
                }
190
                if (this) {
191
                        /* By definition, the 'this' node has no right-hand child,
192
                           because there are no frags with offset greater than it.
193
                           So that's where we want to put the hole */
194
                        D2(printk(KERN_DEBUG "Adding new frag (%p) on right of node at (%p)\n", newfrag, this));
195
                        rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right);
196
                } else {
197
                        D2(printk(KERN_DEBUG "Adding new frag (%p) at root of tree\n", newfrag));
198
                        rb_link_node(&newfrag->rb, NULL, &list->rb_node);
199
                }
200
                rb_insert_color(&newfrag->rb, list);
201
                return 0;
202
        }
203
 
204
        D2(printk(KERN_DEBUG "j_a_f_d_t_f: dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n",
205
                  this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this));
206
 
207
        /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes,
208
         * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs
209
         */
210
        if (newfrag->ofs > this->ofs) {
211
                /* This node isn't completely obsoleted. The start of it remains valid */
212
 
213
                /* Mark the new node and the partially covered node REF_NORMAL -- let
214
                   the GC take a look at them */
215
                mark_ref_normal(newfrag->node->raw);
216
                if (this->node)
217
                        mark_ref_normal(this->node->raw);
218
 
219
                if (this->ofs + this->size > newfrag->ofs + newfrag->size) {
220
                        /* The new node splits 'this' frag into two */
221
                        struct jffs2_node_frag *newfrag2 = jffs2_alloc_node_frag();
222
                        if (!newfrag2) {
223
                                jffs2_free_node_frag(newfrag);
224
                                return -ENOMEM;
225
                        }
226
                        D2(printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size);
227
                        if (this->node)
228
                                printk("phys 0x%08x\n", ref_offset(this->node->raw));
229
                        else
230
                                printk("hole\n");
231
                           )
232
 
233
                        /* New second frag pointing to this's node */
234
                        newfrag2->ofs = newfrag->ofs + newfrag->size;
235
                        newfrag2->size = (this->ofs+this->size) - newfrag2->ofs;
236
                        newfrag2->node = this->node;
237
                        if (this->node)
238
                                this->node->frags++;
239
 
240
                        /* Adjust size of original 'this' */
241
                        this->size = newfrag->ofs - this->ofs;
242
 
243
                        /* Now, we know there's no node with offset
244
                           greater than this->ofs but smaller than
245
                           newfrag2->ofs or newfrag->ofs, for obvious
246
                           reasons. So we can do a tree insert from
247
                           'this' to insert newfrag, and a tree insert
248
                           from newfrag to insert newfrag2. */
249
                        jffs2_fragtree_insert(newfrag, this);
250
                        rb_insert_color(&newfrag->rb, list);
251
 
252
                        jffs2_fragtree_insert(newfrag2, newfrag);
253
                        rb_insert_color(&newfrag2->rb, list);
254
 
255
                        return 0;
256
                }
257
                /* New node just reduces 'this' frag in size, doesn't split it */
258
                this->size = newfrag->ofs - this->ofs;
259
 
260
                /* Again, we know it lives down here in the tree */
261
                jffs2_fragtree_insert(newfrag, this);
262
                rb_insert_color(&newfrag->rb, list);
263
        } else {
264
                /* New frag starts at the same point as 'this' used to. Replace
265
                   it in the tree without doing a delete and insertion */
266
                D2(printk(KERN_DEBUG "Inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n",
267
                          newfrag, newfrag->ofs, newfrag->ofs+newfrag->size,
268
                          this, this->ofs, this->ofs+this->size));
269
 
270
                rb_replace_node(&this->rb, &newfrag->rb, list);
271
 
272
                if (newfrag->ofs + newfrag->size >= this->ofs+this->size) {
273
                        D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size));
274
                        jffs2_obsolete_node_frag(c, this);
275
                } else {
276
                        this->ofs += newfrag->size;
277
                        this->size -= newfrag->size;
278
 
279
                        jffs2_fragtree_insert(this, newfrag);
280
                        rb_insert_color(&this->rb, list);
281
                        return 0;
282
                }
283
        }
284
        /* OK, now we have newfrag added in the correct place in the tree, but
285
           frag_next(newfrag) may be a fragment which is overlapped by it
286
        */
287
        while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) {
288
                /* 'this' frag is obsoleted completely. */
289
                D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x) and removing from tree\n", this, this->ofs, this->ofs+this->size));
290
                rb_erase(&this->rb, list);
291
                jffs2_obsolete_node_frag(c, this);
292
        }
293
        /* Now we're pointing at the first frag which isn't totally obsoleted by
294
           the new frag */
295
 
296
        if (!this || newfrag->ofs + newfrag->size == this->ofs) {
297
                return 0;
298
        }
299
        /* Still some overlap but we don't need to move it in the tree */
300
        this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size);
301
        this->ofs = newfrag->ofs + newfrag->size;
302
 
303
        /* And mark them REF_NORMAL so the GC takes a look at them */
304
        if (this->node)
305
                mark_ref_normal(this->node->raw);
306
        mark_ref_normal(newfrag->node->raw);
307
 
308
        return 0;
309
}
310
 
311
void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size)
312
{
313
        struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size);
314
 
315
        D1(printk(KERN_DEBUG "Truncating fraglist to 0x%08x bytes\n", size));
316
 
317
        /* We know frag->ofs <= size. That's what lookup does for us */
318
        if (frag && frag->ofs != size) {
319
                if (frag->ofs+frag->size >= size) {
320
                        D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size));
321
                        frag->size = size - frag->ofs;
322
                }
323
                frag = frag_next(frag);
324
        }
325
        while (frag && frag->ofs >= size) {
326
                struct jffs2_node_frag *next = frag_next(frag);
327
 
328
                D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size));
329
                frag_erase(frag, list);
330
                jffs2_obsolete_node_frag(c, frag);
331
                frag = next;
332
        }
333
}
334
 
335
/* Scan the list of all nodes present for this ino, build map of versions, etc. */
336
 
337
static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
338
                                        struct jffs2_inode_info *f,
339
                                        struct jffs2_raw_inode *latest_node);
340
 
341
int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
342
                        uint32_t ino, struct jffs2_raw_inode *latest_node)
343
{
344
        D2(printk(KERN_DEBUG "jffs2_do_read_inode(): getting inocache\n"));
345
 
346
 retry_inocache:
347
        spin_lock(&c->inocache_lock);
348
        f->inocache = jffs2_get_ino_cache(c, ino);
349
 
350
        D2(printk(KERN_DEBUG "jffs2_do_read_inode(): Got inocache at %p\n", f->inocache));
351
 
352
        if (f->inocache) {
353
                /* Check its state. We may need to wait before we can use it */
354
                switch(f->inocache->state) {
355
                case INO_STATE_UNCHECKED:
356
                case INO_STATE_CHECKEDABSENT:
357
                        f->inocache->state = INO_STATE_READING;
358
                        break;
359
 
360
                case INO_STATE_CHECKING:
361
                case INO_STATE_GC:
362
                        /* If it's in either of these states, we need
363
                           to wait for whoever's got it to finish and
364
                           put it back. */
365
                        D1(printk(KERN_DEBUG "jffs2_get_ino_cache_read waiting for ino #%u in state %d\n",
366
                                  ino, f->inocache->state));
367
                        sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
368
                        goto retry_inocache;
369
 
370
                case INO_STATE_READING:
371
                case INO_STATE_PRESENT:
372
                        /* Eep. This should never happen. It can
373
                        happen if Linux calls read_inode() again
374
                        before clear_inode() has finished though. */
375
                        printk(KERN_WARNING "Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state);
376
                        /* Fail. That's probably better than allowing it to succeed */
377
                        f->inocache = NULL;
378
                        break;
379
 
380
                default:
381
                        BUG();
382
                }
383
        }
384
        spin_unlock(&c->inocache_lock);
385
        if (!f->inocache && ino == 1) {
386
                /* Special case - no root inode on medium */
387
                f->inocache = jffs2_alloc_inode_cache();
388
                if (!f->inocache) {
389
                        printk(KERN_CRIT "jffs2_do_read_inode(): Cannot allocate inocache for root inode\n");
390
                        return -ENOMEM;
391
                }
392
                D1(printk(KERN_DEBUG "jffs2_do_read_inode(): Creating inocache for root inode\n"));
393
                memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
394
                f->inocache->ino = f->inocache->nlink = 1;
395
                f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
396
                f->inocache->state = INO_STATE_READING;
397
                jffs2_add_ino_cache(c, f->inocache);
398
        }
399
        if (!f->inocache) {
400
                printk(KERN_WARNING "jffs2_do_read_inode() on nonexistent ino %u\n", ino);
401
                return -ENOENT;
402
        }
403
 
404
        return jffs2_do_read_inode_internal(c, f, latest_node);
405
}
406
 
407
int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
408
{
409
        struct jffs2_raw_inode n;
410
        struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL);
411
 
412
        if (!f)
413
                return -ENOMEM;
414
 
415
        memset(f, 0, sizeof(*f));
416
        init_MUTEX_LOCKED(&f->sem);
417
        f->inocache = ic;
418
 
419
        return jffs2_do_read_inode_internal(c, f, &n);
420
}
421
 
422
static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
423
                                        struct jffs2_inode_info *f,
424
                                        struct jffs2_raw_inode *latest_node)
425
{
426
        struct jffs2_tmp_dnode_info *tn_list, *tn;
427
        struct jffs2_full_dirent *fd_list;
428
        struct jffs2_full_dnode *fn = NULL;
429
        uint32_t crc;
430
        uint32_t latest_mctime, mctime_ver;
431
        uint32_t mdata_ver = 0;
432
        size_t retlen;
433
        int ret;
434
 
435
        D1(printk(KERN_DEBUG "jffs2_do_read_inode_internal(): ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink));
436
 
437
        /* Grab all nodes relevant to this ino */
438
        ret = jffs2_get_inode_nodes(c, f->inocache->ino, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver);
439
 
440
        if (ret) {
441
                printk(KERN_CRIT "jffs2_get_inode_nodes() for ino %u returned %d\n", f->inocache->ino, ret);
442
                if (f->inocache->state == INO_STATE_READING)
443
                        jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
444
                return ret;
445
        }
446
        f->dents = fd_list;
447
 
448
        while (tn_list) {
449
                tn = tn_list;
450
 
451
                fn = tn->fn;
452
 
453
                if (f->metadata && tn->version > mdata_ver) {
454
                        D1(printk(KERN_DEBUG "Obsoleting old metadata at 0x%08x\n", ref_offset(f->metadata->raw)));
455
                        jffs2_mark_node_obsolete(c, f->metadata->raw);
456
                        jffs2_free_full_dnode(f->metadata);
457
                        f->metadata = NULL;
458
 
459
                        mdata_ver = 0;
460
                }
461
 
462
                if (fn->size) {
463
                        jffs2_add_full_dnode_to_inode(c, f, fn);
464
                } else {
465
                        /* Zero-sized node at end of version list. Just a metadata update */
466
                        D1(printk(KERN_DEBUG "metadata @%08x: ver %d\n", ref_offset(fn->raw), tn->version));
467
                        f->metadata = fn;
468
                        mdata_ver = tn->version;
469
                }
470
                tn_list = tn->next;
471
                jffs2_free_tmp_dnode_info(tn);
472
        }
473
        if (!fn) {
474
                /* No data nodes for this inode. */
475
                if (f->inocache->ino != 1) {
476
                        printk(KERN_WARNING "jffs2_do_read_inode(): No data nodes found for ino #%u\n", f->inocache->ino);
477
                        if (!fd_list) {
478
                                if (f->inocache->state == INO_STATE_READING)
479
                                        jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
480
                                return -EIO;
481
                        }
482
                        printk(KERN_WARNING "jffs2_do_read_inode(): But it has children so we fake some modes for it\n");
483
                }
484
                latest_node->mode = cpu_to_jemode(S_IFDIR|S_IRUGO|S_IWUSR|S_IXUGO);
485
                latest_node->version = cpu_to_je32(0);
486
                latest_node->atime = latest_node->ctime = latest_node->mtime = cpu_to_je32(0);
487
                latest_node->isize = cpu_to_je32(0);
488
                latest_node->gid = cpu_to_je16(0);
489
                latest_node->uid = cpu_to_je16(0);
490
                if (f->inocache->state == INO_STATE_READING)
491
                        jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
492
                return 0;
493
        }
494
 
495
        ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node);
496
        if (ret || retlen != sizeof(*latest_node)) {
497
                printk(KERN_NOTICE "MTD read in jffs2_do_read_inode() failed: Returned %d, %zd of %zd bytes read\n",
498
                       ret, retlen, sizeof(*latest_node));
499
                /* FIXME: If this fails, there seems to be a memory leak. Find it. */
500
                up(&f->sem);
501
                jffs2_do_clear_inode(c, f);
502
                return ret?ret:-EIO;
503
        }
504
 
505
        crc = crc32(0, latest_node, sizeof(*latest_node)-8);
506
        if (crc != je32_to_cpu(latest_node->node_crc)) {
507
                printk(KERN_NOTICE "CRC failed for read_inode of inode %u at physical location 0x%x\n", f->inocache->ino, ref_offset(fn->raw));
508
                up(&f->sem);
509
                jffs2_do_clear_inode(c, f);
510
                return -EIO;
511
        }
512
 
513
        switch(jemode_to_cpu(latest_node->mode) & S_IFMT) {
514
        case S_IFDIR:
515
                if (mctime_ver > je32_to_cpu(latest_node->version)) {
516
                        /* The times in the latest_node are actually older than
517
                           mctime in the latest dirent. Cheat. */
518
                        latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime);
519
                }
520
                break;
521
 
522
 
523
        case S_IFREG:
524
                /* If it was a regular file, truncate it to the latest node's isize */
525
                jffs2_truncate_fraglist(c, &f->fragtree, je32_to_cpu(latest_node->isize));
526
                break;
527
 
528
        case S_IFLNK:
529
                /* Hack to work around broken isize in old symlink code.
530
                   Remove this when dwmw2 comes to his senses and stops
531
                   symlinks from being an entirely gratuitous special
532
                   case. */
533
                if (!je32_to_cpu(latest_node->isize))
534
                        latest_node->isize = latest_node->dsize;
535
                /* fall through... */
536
 
537
        case S_IFBLK:
538
        case S_IFCHR:
539
                /* Certain inode types should have only one data node, and it's
540
                   kept as the metadata node */
541
                if (f->metadata) {
542
                        printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had metadata node\n",
543
                               f->inocache->ino, jemode_to_cpu(latest_node->mode));
544
                        up(&f->sem);
545
                        jffs2_do_clear_inode(c, f);
546
                        return -EIO;
547
                }
548
                if (!frag_first(&f->fragtree)) {
549
                        printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o has no fragments\n",
550
                               f->inocache->ino, jemode_to_cpu(latest_node->mode));
551
                        up(&f->sem);
552
                        jffs2_do_clear_inode(c, f);
553
                        return -EIO;
554
                }
555
                /* ASSERT: f->fraglist != NULL */
556
                if (frag_next(frag_first(&f->fragtree))) {
557
                        printk(KERN_WARNING "Argh. Special inode #%u with mode 0x%x had more than one node\n",
558
                               f->inocache->ino, jemode_to_cpu(latest_node->mode));
559
                        /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
560
                        up(&f->sem);
561
                        jffs2_do_clear_inode(c, f);
562
                        return -EIO;
563
                }
564
                /* OK. We're happy */
565
                f->metadata = frag_first(&f->fragtree)->node;
566
                jffs2_free_node_frag(frag_first(&f->fragtree));
567
                f->fragtree = RB_ROOT;
568
                break;
569
        }
570
        if (f->inocache->state == INO_STATE_READING)
571
                jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
572
 
573
        return 0;
574
}
575
 
576
void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
577
{
578
        struct jffs2_full_dirent *fd, *fds;
579
        /* I don't think we care about the potential race due to reading this
580
           without f->sem. It can never get undeleted. */
581
        int deleted = f->inocache && !f->inocache->nlink;
582
 
583
        /* If it's a deleted inode, grab the alloc_sem. This prevents
584
           jffs2_garbage_collect_pass() from deciding that it wants to
585
           garbage collect one of the nodes we're just about to mark
586
           obsolete -- by the time we drop alloc_sem and return, all
587
           the nodes are marked obsolete, and jffs2_g_c_pass() won't
588
           call iget() for the inode in question.
589
 
590
           We also used to do this to keep the temporary BUG() in
591
           jffs2_mark_node_obsolete() from triggering.
592
        */
593
        if(deleted)
594
                down(&c->alloc_sem);
595
 
596
        down(&f->sem);
597
 
598
        if (f->metadata) {
599
                if (deleted)
600
                        jffs2_mark_node_obsolete(c, f->metadata->raw);
601
                jffs2_free_full_dnode(f->metadata);
602
        }
603
 
604
        jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL);
605
 
606
        fds = f->dents;
607
 
608
        while(fds) {
609
                fd = fds;
610
                fds = fd->next;
611
                jffs2_free_full_dirent(fd);
612
        }
613
 
614
        if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
615
                jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
616
 
617
        up(&f->sem);
618
 
619
        if(deleted)
620
                up(&c->alloc_sem);
621
}

powered by: WebSVN 2.1.0

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