blob: 8c6665d0e334f02ed60390802081f6716e737c8c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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 *
Andrew Lunn737b7662005-07-30 16:29:30 +010010 * $Id: readinode.c,v 1.133 2005/07/30 15:28:24 lunn Exp $
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 *
12 */
13
14#include <linux/kernel.h>
Andrew Lunn737b7662005-07-30 16:29:30 +010015#include <linux/sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#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
Artem B. Bityutskiyf302cd02005-07-24 16:29:59 +010024void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size)
Linus Torvalds1da177e2005-04-16 15:20:36 -070025{
26 struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size);
27
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +010028 JFFS2_DBG_FRAGTREE("truncating fragtree to 0x%08x bytes\n", size);
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
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) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +010033 JFFS2_DBG_FRAGTREE2("truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size);
Linus Torvalds1da177e2005-04-16 15:20:36 -070034 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
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +010041 JFFS2_DBG_FRAGTREE("removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size);
Linus Torvalds1da177e2005-04-16 15:20:36 -070042 frag_erase(frag, list);
43 jffs2_obsolete_node_frag(c, frag);
44 frag = next;
45 }
46}
47
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +010048/*
49 * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in
50 * order of increasing version.
51 */
52static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list)
Linus Torvalds1da177e2005-04-16 15:20:36 -070053{
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +010054 struct rb_node **p = &list->rb_node;
55 struct rb_node * parent = NULL;
56 struct jffs2_tmp_dnode_info *this;
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +010058 while (*p) {
59 parent = *p;
60 this = rb_entry(parent, struct jffs2_tmp_dnode_info, rb);
Linus Torvalds1da177e2005-04-16 15:20:36 -070061
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +010062 /* 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 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +010071 rb_link_node(&tn->rb, parent, p);
72 rb_insert_color(&tn->rb, list);
73}
74
75static 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
107static 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' */
119static 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;
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100124 JFFS2_DBG_NODEREF("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100125 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 */
138static inline int
139read_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));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100154 /* Sanity check */
155 if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100156 JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100157 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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100165 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)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100196 JFFS2_ERROR("read remainder of name: error %d\n", err);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100197 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 */
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100210 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 */
223static inline int
224read_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))) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100244 JFFS2_NOTICE("header CRC failed on node at %#08x: read %#08x, calculated %#08x\n",
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100245 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)))) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100252 JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref));
Andrew Lunn737b7662005-07-30 16:29:30 +0100253 jffs2_dbg_dump_node(c, ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100254 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)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100266 JFFS2_ERROR("MTD point returned len too short: 0x%zx\n", read);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100267 c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd),
268 je32_to_cpu(rd->csize));
269 } else if (unlikely(err)){
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100270 JFFS2_ERROR("MTD point failed %d\n", err);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100271 } 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)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100298 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);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100300 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)))) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100325 JFFS2_DBG_READINODE("marking node at %#08x REF_PRISTINE\n", ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100326 ref->flash_offset = ref_offset(ref) | REF_PRISTINE;
327 } else {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100328 JFFS2_DBG_READINODE("marking node at %#08x REF_NORMAL\n", ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100329 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) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100336 JFFS2_ERROR("alloc tn failed\n");
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100337 return -ENOMEM;
338 }
339
340 tn->fn = jffs2_alloc_full_dnode();
341 if (!tn->fn) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100342 JFFS2_ERROR("alloc fn failed\n");
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100343 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
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100358 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));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100360
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 */
374static inline int
375read_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)) {
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100386 /* Hmmm. This should have been caught at scan time. */
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100387 JFFS2_NOTICE("node header CRC failed at %#08x. But it must have been OK earlier.\n", ref_offset(ref));
Andrew Lunn737b7662005-07-30 16:29:30 +0100388 jffs2_dbg_dump_node(c, ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100389 return 1;
390 } else {
391 switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
392
393 case JFFS2_FEATURE_INCOMPAT:
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100394 JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n",
395 je16_to_cpu(un->nodetype), ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100396 /* EEP */
397 BUG();
398 break;
399
400 case JFFS2_FEATURE_ROCOMPAT:
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100401 JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n",
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100402 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:
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100407 JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100408 je16_to_cpu(un->nodetype), ref_offset(ref));
409 break;
410
411 case JFFS2_FEATURE_RWCOMPAT_DELETE:
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100412 JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100413 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
424static 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
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100438 JFFS2_DBG_READINODE("ino #%u\n", f->inocache->ino);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100439
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))
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100445 JFFS2_WARNING("no valid nodes for ino #%u\n", f->inocache->ino);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100446
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) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100465 JFFS2_ERROR("error %d reading node at 0x%08x in get_inode_nodes()\n", err, ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100466 goto free_out;
467 }
468
469 switch (je16_to_cpu(node.u.nodetype)) {
470
471 case JFFS2_NODETYPE_DIRENT:
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100472 JFFS2_DBG_READINODE("node at %08x (%d) is a dirent node\n", ref_offset(ref), ref_flags(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100473
474 if (retlen < sizeof(node.d)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100475 JFFS2_ERROR("short read dirent at %#08x\n", ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100476 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:
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100493 JFFS2_DBG_READINODE("node at %08x (%d) is a data node\n", ref_offset(ref), ref_flags(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100494
495 if (retlen < sizeof(node.i)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100496 JFFS2_ERROR("short read dnode at %#08x\n", ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100497 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
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100511 JFFS2_DBG_READINODE("version %d, highest_version now %d\n",
512 je32_to_cpu(node.i.version), *highest_version);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100513
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 break;
515
516 default:
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100517 /* Check we've managed to read at least the common node header */
518 if (retlen < sizeof(struct jffs2_unknown_node)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100519 JFFS2_ERROR("short read unknown node at %#08x\n", ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100520 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 }
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100531 spin_lock(&c->erase_completion_lock);
532
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 }
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100534 spin_unlock(&c->erase_completion_lock);
535 *tnp = ret_tn;
536 *fdp = ret_fd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100538 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100540 free_out:
541 jffs2_free_tmp_dnode_info_list(&ret_tn);
542 jffs2_free_full_dirent_list(ret_fd);
543 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544}
545
546static 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{
David Woodhouse9dee7502005-07-05 22:03:10 +0100550 struct jffs2_tmp_dnode_info *tn = NULL;
551 struct rb_root tn_list;
552 struct rb_node *rb, *repl_rb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 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
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100561 JFFS2_DBG_READINODE("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562
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) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100567 JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 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
David Woodhouse9dee7502005-07-05 22:03:10 +0100574 rb = rb_first(&tn_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575
David Woodhouse9dee7502005-07-05 22:03:10 +0100576 while (rb) {
577 tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 fn = tn->fn;
579
580 if (f->metadata) {
581 if (likely(tn->version >= mdata_ver)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100582 JFFS2_DBG_READINODE("obsoleting old metadata at 0x%08x\n", ref_offset(f->metadata->raw));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 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. */
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100590 JFFS2_ERROR("Er. New metadata at 0x%08x with ver %d is actually older than previous ver %d at 0x%08x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 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 */
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100604 JFFS2_DBG_READINODE("metadata @%08x: ver %d\n", ref_offset(fn->raw), tn->version);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 f->metadata = fn;
606 mdata_ver = tn->version;
607 }
608 next_tn:
David Woodhouse9dee7502005-07-05 22:03:10 +0100609 BUG_ON(rb->rb_left);
David Woodhouse9dee7502005-07-05 22:03:10 +0100610 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 jffs2_free_tmp_dnode_info(tn);
633 }
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100634 jffs2_dbg_fragtree_paranoia_check_nolock(f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
636 if (!fn) {
637 /* No data nodes for this inode. */
638 if (f->inocache->ino != 1) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100639 JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 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 }
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100645 JFFS2_NOTICE("but it has children so we fake some modes for it\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 }
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)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100660 JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n",
661 ret, retlen, sizeof(*latest_node));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 /* 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)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100670 JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n",
671 f->inocache->ino, ref_offset(fn->raw));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 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 */
Artem B. Bityutskiyf302cd02005-07-24 16:29:59 +0100689 jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 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;
Artem B. Bityuckiy32f1a952005-03-01 10:50:52 +0000699
700 if (f->inocache->state != INO_STATE_CHECKING) {
701 /* Symlink's inode data is the target path. Read it and
Artem B. Bityutskiy2b79adc2005-07-17 12:13:51 +0100702 * 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) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100706 JFFS2_ERROR("can't allocate %d bytes of memory for the symlink target path cache\n", je32_to_cpu(latest_node->csize));
Artem B. Bityuckiy32f1a952005-03-01 10:50:52 +0000707 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),
Artem B. Bityutskiy2b79adc2005-07-17 12:13:51 +0100713 je32_to_cpu(latest_node->csize), &retlen, (char *)f->target);
Artem B. Bityuckiy32f1a952005-03-01 10:50:52 +0000714
715 if (ret || retlen != je32_to_cpu(latest_node->csize)) {
716 if (retlen != je32_to_cpu(latest_node->csize))
717 ret = -EIO;
Artem B. Bityutskiy2b79adc2005-07-17 12:13:51 +0100718 kfree(f->target);
719 f->target = NULL;
Artem B. Bityuckiy32f1a952005-03-01 10:50:52 +0000720 up(&f->sem);
721 jffs2_do_clear_inode(c, f);
722 return -ret;
723 }
724
Artem B. Bityutskiy2b79adc2005-07-17 12:13:51 +0100725 f->target[je32_to_cpu(latest_node->csize)] = '\0';
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100726 JFFS2_DBG_READINODE("symlink's target '%s' cached\n", f->target);
Artem B. Bityuckiy32f1a952005-03-01 10:50:52 +0000727 }
728
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 /* 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) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100736 JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 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)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100743 JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 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))) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100751 JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 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
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100770/* Scan the list of all nodes present for this ino, build map of versions, etc. */
771int 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{
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100774 JFFS2_DBG_READINODE("read inode #%u\n", ino);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100775
776 retry_inocache:
777 spin_lock(&c->inocache_lock);
778 f->inocache = jffs2_get_ino_cache(c, ino);
779
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100780 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. */
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100793 JFFS2_DBG_READINODE("waiting for ino #%u in state %d\n", ino, f->inocache->state);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100794 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. */
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100802 JFFS2_ERROR("Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100803 /* 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) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100817 JFFS2_ERROR("cannot allocate inocache for root inode\n");
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100818 return -ENOMEM;
819 }
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100820 JFFS2_DBG_READINODE("creating inocache for root inode\n");
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100821 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) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100828 JFFS2_ERROR("requestied to read an nonexistent ino %u\n", ino);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100829 return -ENOENT;
830 }
831
832 return jffs2_do_read_inode_internal(c, f, latest_node);
833}
834
835int 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857void 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
David Woodhouse67e345d2005-02-27 23:01:36 +0000865 if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
866 jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);
867
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 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
Artem B. Bityutskiy2b79adc2005-07-17 12:13:51 +0100876 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 }
887
David Woodhouse67e345d2005-02-27 23:01:36 +0000888 if (f->inocache && f->inocache->state != INO_STATE_CHECKING) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
David Woodhouse67e345d2005-02-27 23:01:36 +0000890 if (f->inocache->nodes == (void *)f->inocache)
891 jffs2_del_ino_cache(c, f->inocache);
892 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893
894 up(&f->sem);
895}