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