blob: f3b12d7fe9ab924f47a70f74230f05b1230be50c [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 *
Artem B. Bityutskiy1e900972005-07-31 09:20:48 +010010 * $Id: readinode.c,v 1.134 2005/07/31 08:20:44 dedekind 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. Bityutskiyf97117d2005-07-27 15:46:14 +010024/*
25 * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in
26 * order of increasing version.
27 */
28static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list)
Linus Torvalds1da177e2005-04-16 15:20:36 -070029{
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +010030 struct rb_node **p = &list->rb_node;
31 struct rb_node * parent = NULL;
32 struct jffs2_tmp_dnode_info *this;
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +010034 while (*p) {
35 parent = *p;
36 this = rb_entry(parent, struct jffs2_tmp_dnode_info, rb);
Linus Torvalds1da177e2005-04-16 15:20:36 -070037
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +010038 /* There may actually be a collision here, but it doesn't
39 actually matter. As long as the two nodes with the same
40 version are together, it's all fine. */
41 if (tn->version < this->version)
42 p = &(*p)->rb_left;
43 else
44 p = &(*p)->rb_right;
45 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +010047 rb_link_node(&tn->rb, parent, p);
48 rb_insert_color(&tn->rb, list);
49}
50
51static void jffs2_free_tmp_dnode_info_list(struct rb_root *list)
52{
53 struct rb_node *this;
54 struct jffs2_tmp_dnode_info *tn;
55
56 this = list->rb_node;
57
58 /* Now at bottom of tree */
59 while (this) {
60 if (this->rb_left)
61 this = this->rb_left;
62 else if (this->rb_right)
63 this = this->rb_right;
64 else {
65 tn = rb_entry(this, struct jffs2_tmp_dnode_info, rb);
66 jffs2_free_full_dnode(tn->fn);
67 jffs2_free_tmp_dnode_info(tn);
68
69 this = this->rb_parent;
70 if (!this)
71 break;
72
73 if (this->rb_left == &tn->rb)
74 this->rb_left = NULL;
75 else if (this->rb_right == &tn->rb)
76 this->rb_right = NULL;
77 else BUG();
78 }
79 }
80 list->rb_node = NULL;
81}
82
83static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd)
84{
85 struct jffs2_full_dirent *next;
86
87 while (fd) {
88 next = fd->next;
89 jffs2_free_full_dirent(fd);
90 fd = next;
91 }
92}
93
94/* Returns first valid node after 'ref'. May return 'ref' */
95static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_ref *ref)
96{
97 while (ref && ref->next_in_ino) {
98 if (!ref_obsolete(ref))
99 return ref;
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100100 JFFS2_DBG_NODEREF("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100101 ref = ref->next_in_ino;
102 }
103 return NULL;
104}
105
106/*
107 * Helper function for jffs2_get_inode_nodes().
108 * It is called every time an directory entry node is found.
109 *
110 * Returns: 0 on succes;
111 * 1 if the node should be marked obsolete;
112 * negative error code on failure.
113 */
114static inline int
115read_direntry(struct jffs2_sb_info *c,
116 struct jffs2_raw_node_ref *ref,
117 struct jffs2_raw_dirent *rd,
118 uint32_t read,
119 struct jffs2_full_dirent **fdp,
120 int32_t *latest_mctime,
121 uint32_t *mctime_ver)
122{
123 struct jffs2_full_dirent *fd;
124
125 /* The direntry nodes are checked during the flash scanning */
126 BUG_ON(ref_flags(ref) == REF_UNCHECKED);
127 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
128 BUG_ON(ref_obsolete(ref));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100130 /* Sanity check */
131 if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100132 JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100133 ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
134 return 1;
135 }
136
137 fd = jffs2_alloc_full_dirent(rd->nsize + 1);
138 if (unlikely(!fd))
139 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100141 fd->raw = ref;
142 fd->version = je32_to_cpu(rd->version);
143 fd->ino = je32_to_cpu(rd->ino);
144 fd->type = rd->type;
145
146 /* Pick out the mctime of the latest dirent */
147 if(fd->version > *mctime_ver) {
148 *mctime_ver = fd->version;
149 *latest_mctime = je32_to_cpu(rd->mctime);
150 }
151
152 /*
153 * Copy as much of the name as possible from the raw
154 * dirent we've already read from the flash.
155 */
156 if (read > sizeof(*rd))
157 memcpy(&fd->name[0], &rd->name[0],
158 min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) ));
159
160 /* Do we need to copy any more of the name directly from the flash? */
161 if (rd->nsize + sizeof(*rd) > read) {
162 /* FIXME: point() */
163 int err;
164 int already = read - sizeof(*rd);
165
166 err = jffs2_flash_read(c, (ref_offset(ref)) + read,
167 rd->nsize - already, &read, &fd->name[already]);
168 if (unlikely(read != rd->nsize - already) && likely(!err))
169 return -EIO;
170
171 if (unlikely(err)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100172 JFFS2_ERROR("read remainder of name: error %d\n", err);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100173 jffs2_free_full_dirent(fd);
174 return -EIO;
175 }
176 }
177
178 fd->nhash = full_name_hash(fd->name, rd->nsize);
179 fd->next = NULL;
180 fd->name[rd->nsize] = '\0';
181
182 /*
183 * Wheee. We now have a complete jffs2_full_dirent structure, with
184 * the name in it and everything. Link it into the list
185 */
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100186 jffs2_add_fd_to_list(c, fd, fdp);
187
188 return 0;
189}
190
191/*
192 * Helper function for jffs2_get_inode_nodes().
193 * It is called every time an inode node is found.
194 *
195 * Returns: 0 on succes;
196 * 1 if the node should be marked obsolete;
197 * negative error code on failure.
198 */
199static inline int
200read_dnode(struct jffs2_sb_info *c,
201 struct jffs2_raw_node_ref *ref,
202 struct jffs2_raw_inode *rd,
203 uint32_t read,
204 struct rb_root *tnp,
205 int32_t *latest_mctime,
206 uint32_t *mctime_ver)
207{
208 struct jffs2_eraseblock *jeb;
209 struct jffs2_tmp_dnode_info *tn;
210
211 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
212 BUG_ON(ref_obsolete(ref));
213
214 /* If we've never checked the CRCs on this node, check them now */
215 if (ref_flags(ref) == REF_UNCHECKED) {
216 uint32_t crc, len;
217
218 crc = crc32(0, rd, sizeof(*rd) - 8);
219 if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100220 JFFS2_NOTICE("header CRC failed on node at %#08x: read %#08x, calculated %#08x\n",
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100221 ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
222 return 1;
223 }
224
225 /* Sanity checks */
226 if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) ||
227 unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100228 JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref));
Andrew Lunn737b7662005-07-30 16:29:30 +0100229 jffs2_dbg_dump_node(c, ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100230 return 1;
231 }
232
233 if (rd->compr != JFFS2_COMPR_ZERO && je32_to_cpu(rd->csize)) {
234 unsigned char *buf = NULL;
235 uint32_t pointed = 0;
236 int err;
237#ifndef __ECOS
238 if (c->mtd->point) {
239 err = c->mtd->point (c->mtd, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize),
240 &read, &buf);
241 if (unlikely(read < je32_to_cpu(rd->csize)) && likely(!err)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100242 JFFS2_ERROR("MTD point returned len too short: 0x%zx\n", read);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100243 c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd),
244 je32_to_cpu(rd->csize));
245 } else if (unlikely(err)){
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100246 JFFS2_ERROR("MTD point failed %d\n", err);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100247 } else
248 pointed = 1; /* succefully pointed to device */
249 }
250#endif
251 if(!pointed){
252 buf = kmalloc(je32_to_cpu(rd->csize), GFP_KERNEL);
253 if (!buf)
254 return -ENOMEM;
255
256 err = jffs2_flash_read(c, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize),
257 &read, buf);
258 if (unlikely(read != je32_to_cpu(rd->csize)) && likely(!err))
259 err = -EIO;
260 if (err) {
261 kfree(buf);
262 return err;
263 }
264 }
265 crc = crc32(0, buf, je32_to_cpu(rd->csize));
266 if(!pointed)
267 kfree(buf);
268#ifndef __ECOS
269 else
270 c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize));
271#endif
272
273 if (crc != je32_to_cpu(rd->data_crc)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100274 JFFS2_NOTICE("data CRC failed on node at %#08x: read %#08x, calculated %#08x\n",
275 ref_offset(ref), je32_to_cpu(rd->data_crc), crc);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100276 return 1;
277 }
278
279 }
280
281 /* Mark the node as having been checked and fix the accounting accordingly */
282 jeb = &c->blocks[ref->flash_offset / c->sector_size];
283 len = ref_totlen(c, jeb, ref);
284
285 spin_lock(&c->erase_completion_lock);
286 jeb->used_size += len;
287 jeb->unchecked_size -= len;
288 c->used_size += len;
289 c->unchecked_size -= len;
290
291 /* If node covers at least a whole page, or if it starts at the
292 beginning of a page and runs to the end of the file, or if
293 it's a hole node, mark it REF_PRISTINE, else REF_NORMAL.
294
295 If it's actually overlapped, it'll get made NORMAL (or OBSOLETE)
296 when the overlapping node(s) get added to the tree anyway.
297 */
298 if ((je32_to_cpu(rd->dsize) >= PAGE_CACHE_SIZE) ||
299 ( ((je32_to_cpu(rd->offset) & (PAGE_CACHE_SIZE-1))==0) &&
300 (je32_to_cpu(rd->dsize) + je32_to_cpu(rd->offset) == je32_to_cpu(rd->isize)))) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100301 JFFS2_DBG_READINODE("marking node at %#08x REF_PRISTINE\n", ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100302 ref->flash_offset = ref_offset(ref) | REF_PRISTINE;
303 } else {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100304 JFFS2_DBG_READINODE("marking node at %#08x REF_NORMAL\n", ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100305 ref->flash_offset = ref_offset(ref) | REF_NORMAL;
306 }
307 spin_unlock(&c->erase_completion_lock);
308 }
309
310 tn = jffs2_alloc_tmp_dnode_info();
311 if (!tn) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100312 JFFS2_ERROR("alloc tn failed\n");
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100313 return -ENOMEM;
314 }
315
316 tn->fn = jffs2_alloc_full_dnode();
317 if (!tn->fn) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100318 JFFS2_ERROR("alloc fn failed\n");
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100319 jffs2_free_tmp_dnode_info(tn);
320 return -ENOMEM;
321 }
322
323 tn->version = je32_to_cpu(rd->version);
324 tn->fn->ofs = je32_to_cpu(rd->offset);
325 tn->fn->raw = ref;
326
327 /* There was a bug where we wrote hole nodes out with
328 csize/dsize swapped. Deal with it */
329 if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && je32_to_cpu(rd->csize))
330 tn->fn->size = je32_to_cpu(rd->csize);
331 else // normal case...
332 tn->fn->size = je32_to_cpu(rd->dsize);
333
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100334 JFFS2_DBG_READINODE("dnode @%08x: ver %u, offset %#04x, dsize %#04x\n",
335 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 +0100336
337 jffs2_add_tn_to_tree(tn, tnp);
338
339 return 0;
340}
341
342/*
343 * Helper function for jffs2_get_inode_nodes().
344 * It is called every time an unknown node is found.
345 *
346 * Returns: 0 on succes;
347 * 1 if the node should be marked obsolete;
348 * negative error code on failure.
349 */
350static inline int
351read_unknown(struct jffs2_sb_info *c,
352 struct jffs2_raw_node_ref *ref,
353 struct jffs2_unknown_node *un,
354 uint32_t read)
355{
356 /* We don't mark unknown nodes as REF_UNCHECKED */
357 BUG_ON(ref_flags(ref) == REF_UNCHECKED);
358
359 un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
360
361 if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) {
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100362 /* Hmmm. This should have been caught at scan time. */
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100363 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 +0100364 jffs2_dbg_dump_node(c, ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100365 return 1;
366 } else {
367 switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
368
369 case JFFS2_FEATURE_INCOMPAT:
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100370 JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n",
371 je16_to_cpu(un->nodetype), ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100372 /* EEP */
373 BUG();
374 break;
375
376 case JFFS2_FEATURE_ROCOMPAT:
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100377 JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n",
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100378 je16_to_cpu(un->nodetype), ref_offset(ref));
379 BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
380 break;
381
382 case JFFS2_FEATURE_RWCOMPAT_COPY:
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100383 JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100384 je16_to_cpu(un->nodetype), ref_offset(ref));
385 break;
386
387 case JFFS2_FEATURE_RWCOMPAT_DELETE:
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100388 JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100389 je16_to_cpu(un->nodetype), ref_offset(ref));
390 return 1;
391 }
392 }
393
394 return 0;
395}
396
397/* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated
398 with this ino, returning the former in order of version */
399
400static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
401 struct rb_root *tnp, struct jffs2_full_dirent **fdp,
402 uint32_t *highest_version, uint32_t *latest_mctime,
403 uint32_t *mctime_ver)
404{
405 struct jffs2_raw_node_ref *ref, *valid_ref;
406 struct rb_root ret_tn = RB_ROOT;
407 struct jffs2_full_dirent *ret_fd = NULL;
408 union jffs2_node_union node;
409 size_t retlen;
410 int err;
411
412 *mctime_ver = 0;
413
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100414 JFFS2_DBG_READINODE("ino #%u\n", f->inocache->ino);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100415
416 spin_lock(&c->erase_completion_lock);
417
418 valid_ref = jffs2_first_valid_node(f->inocache->nodes);
419
420 if (!valid_ref && (f->inocache->ino != 1))
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100421 JFFS2_WARNING("no valid nodes for ino #%u\n", f->inocache->ino);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100422
423 while (valid_ref) {
424 /* We can hold a pointer to a non-obsolete node without the spinlock,
425 but _obsolete_ nodes may disappear at any time, if the block
426 they're in gets erased. So if we mark 'ref' obsolete while we're
427 not holding the lock, it can go away immediately. For that reason,
428 we find the next valid node first, before processing 'ref'.
429 */
430 ref = valid_ref;
431 valid_ref = jffs2_first_valid_node(ref->next_in_ino);
432 spin_unlock(&c->erase_completion_lock);
433
434 cond_resched();
435
436 /* FIXME: point() */
437 err = jffs2_flash_read(c, (ref_offset(ref)),
438 min_t(uint32_t, ref_totlen(c, NULL, ref), sizeof(node)),
439 &retlen, (void *)&node);
440 if (err) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100441 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 +0100442 goto free_out;
443 }
444
445 switch (je16_to_cpu(node.u.nodetype)) {
446
447 case JFFS2_NODETYPE_DIRENT:
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100448 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 +0100449
450 if (retlen < sizeof(node.d)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100451 JFFS2_ERROR("short read dirent at %#08x\n", ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100452 err = -EIO;
453 goto free_out;
454 }
455
456 err = read_direntry(c, ref, &node.d, retlen, &ret_fd, latest_mctime, mctime_ver);
457 if (err == 1) {
458 jffs2_mark_node_obsolete(c, ref);
459 break;
460 } else if (unlikely(err))
461 goto free_out;
462
463 if (je32_to_cpu(node.d.version) > *highest_version)
464 *highest_version = je32_to_cpu(node.d.version);
465
466 break;
467
468 case JFFS2_NODETYPE_INODE:
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100469 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 +0100470
471 if (retlen < sizeof(node.i)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100472 JFFS2_ERROR("short read dnode at %#08x\n", ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100473 err = -EIO;
474 goto free_out;
475 }
476
477 err = read_dnode(c, ref, &node.i, retlen, &ret_tn, latest_mctime, mctime_ver);
478 if (err == 1) {
479 jffs2_mark_node_obsolete(c, ref);
480 break;
481 } else if (unlikely(err))
482 goto free_out;
483
484 if (je32_to_cpu(node.i.version) > *highest_version)
485 *highest_version = je32_to_cpu(node.i.version);
486
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100487 JFFS2_DBG_READINODE("version %d, highest_version now %d\n",
488 je32_to_cpu(node.i.version), *highest_version);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100489
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 break;
491
492 default:
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100493 /* Check we've managed to read at least the common node header */
494 if (retlen < sizeof(struct jffs2_unknown_node)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100495 JFFS2_ERROR("short read unknown node at %#08x\n", ref_offset(ref));
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100496 return -EIO;
497 }
498
499 err = read_unknown(c, ref, &node.u, retlen);
500 if (err == 1) {
501 jffs2_mark_node_obsolete(c, ref);
502 break;
503 } else if (unlikely(err))
504 goto free_out;
505
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 }
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100507 spin_lock(&c->erase_completion_lock);
508
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 }
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100510 spin_unlock(&c->erase_completion_lock);
511 *tnp = ret_tn;
512 *fdp = ret_fd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100514 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100516 free_out:
517 jffs2_free_tmp_dnode_info_list(&ret_tn);
518 jffs2_free_full_dirent_list(ret_fd);
519 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520}
521
522static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
523 struct jffs2_inode_info *f,
524 struct jffs2_raw_inode *latest_node)
525{
David Woodhouse9dee7502005-07-05 22:03:10 +0100526 struct jffs2_tmp_dnode_info *tn = NULL;
527 struct rb_root tn_list;
528 struct rb_node *rb, *repl_rb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 struct jffs2_full_dirent *fd_list;
530 struct jffs2_full_dnode *fn = NULL;
531 uint32_t crc;
532 uint32_t latest_mctime, mctime_ver;
533 uint32_t mdata_ver = 0;
534 size_t retlen;
535 int ret;
536
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100537 JFFS2_DBG_READINODE("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
539 /* Grab all nodes relevant to this ino */
540 ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver);
541
542 if (ret) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100543 JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 if (f->inocache->state == INO_STATE_READING)
545 jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
546 return ret;
547 }
548 f->dents = fd_list;
549
David Woodhouse9dee7502005-07-05 22:03:10 +0100550 rb = rb_first(&tn_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551
David Woodhouse9dee7502005-07-05 22:03:10 +0100552 while (rb) {
553 tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 fn = tn->fn;
555
556 if (f->metadata) {
557 if (likely(tn->version >= mdata_ver)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100558 JFFS2_DBG_READINODE("obsoleting old metadata at 0x%08x\n", ref_offset(f->metadata->raw));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 jffs2_mark_node_obsolete(c, f->metadata->raw);
560 jffs2_free_full_dnode(f->metadata);
561 f->metadata = NULL;
562
563 mdata_ver = 0;
564 } else {
565 /* This should never happen. */
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100566 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 -0700567 ref_offset(fn->raw), tn->version, mdata_ver, ref_offset(f->metadata->raw));
568 jffs2_mark_node_obsolete(c, fn->raw);
569 jffs2_free_full_dnode(fn);
570 /* Fill in latest_node from the metadata, not this one we're about to free... */
571 fn = f->metadata;
572 goto next_tn;
573 }
574 }
575
576 if (fn->size) {
577 jffs2_add_full_dnode_to_inode(c, f, fn);
578 } else {
579 /* Zero-sized node at end of version list. Just a metadata update */
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100580 JFFS2_DBG_READINODE("metadata @%08x: ver %d\n", ref_offset(fn->raw), tn->version);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 f->metadata = fn;
582 mdata_ver = tn->version;
583 }
584 next_tn:
David Woodhouse9dee7502005-07-05 22:03:10 +0100585 BUG_ON(rb->rb_left);
David Woodhouse9dee7502005-07-05 22:03:10 +0100586 if (rb->rb_parent && rb->rb_parent->rb_left == rb) {
587 /* We were then left-hand child of our parent. We need
588 to move our own right-hand child into our place. */
589 repl_rb = rb->rb_right;
590 if (repl_rb)
591 repl_rb->rb_parent = rb->rb_parent;
592 } else
593 repl_rb = NULL;
594
595 rb = rb_next(rb);
596
597 /* Remove the spent tn from the tree; don't bother rebalancing
598 but put our right-hand child in our own place. */
599 if (tn->rb.rb_parent) {
600 if (tn->rb.rb_parent->rb_left == &tn->rb)
601 tn->rb.rb_parent->rb_left = repl_rb;
602 else if (tn->rb.rb_parent->rb_right == &tn->rb)
603 tn->rb.rb_parent->rb_right = repl_rb;
604 else BUG();
605 } else if (tn->rb.rb_right)
606 tn->rb.rb_right->rb_parent = NULL;
607
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 jffs2_free_tmp_dnode_info(tn);
609 }
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100610 jffs2_dbg_fragtree_paranoia_check_nolock(f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
612 if (!fn) {
613 /* No data nodes for this inode. */
614 if (f->inocache->ino != 1) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100615 JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 if (!fd_list) {
617 if (f->inocache->state == INO_STATE_READING)
618 jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
619 return -EIO;
620 }
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100621 JFFS2_NOTICE("but it has children so we fake some modes for it\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 }
623 latest_node->mode = cpu_to_jemode(S_IFDIR|S_IRUGO|S_IWUSR|S_IXUGO);
624 latest_node->version = cpu_to_je32(0);
625 latest_node->atime = latest_node->ctime = latest_node->mtime = cpu_to_je32(0);
626 latest_node->isize = cpu_to_je32(0);
627 latest_node->gid = cpu_to_je16(0);
628 latest_node->uid = cpu_to_je16(0);
629 if (f->inocache->state == INO_STATE_READING)
630 jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
631 return 0;
632 }
633
634 ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node);
635 if (ret || retlen != sizeof(*latest_node)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100636 JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n",
637 ret, retlen, sizeof(*latest_node));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 /* FIXME: If this fails, there seems to be a memory leak. Find it. */
639 up(&f->sem);
640 jffs2_do_clear_inode(c, f);
641 return ret?ret:-EIO;
642 }
643
644 crc = crc32(0, latest_node, sizeof(*latest_node)-8);
645 if (crc != je32_to_cpu(latest_node->node_crc)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100646 JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n",
647 f->inocache->ino, ref_offset(fn->raw));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 up(&f->sem);
649 jffs2_do_clear_inode(c, f);
650 return -EIO;
651 }
652
653 switch(jemode_to_cpu(latest_node->mode) & S_IFMT) {
654 case S_IFDIR:
655 if (mctime_ver > je32_to_cpu(latest_node->version)) {
656 /* The times in the latest_node are actually older than
657 mctime in the latest dirent. Cheat. */
658 latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime);
659 }
660 break;
661
662
663 case S_IFREG:
664 /* If it was a regular file, truncate it to the latest node's isize */
Artem B. Bityutskiyf302cd02005-07-24 16:29:59 +0100665 jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 break;
667
668 case S_IFLNK:
669 /* Hack to work around broken isize in old symlink code.
670 Remove this when dwmw2 comes to his senses and stops
671 symlinks from being an entirely gratuitous special
672 case. */
673 if (!je32_to_cpu(latest_node->isize))
674 latest_node->isize = latest_node->dsize;
Artem B. Bityuckiy32f1a952005-03-01 10:50:52 +0000675
676 if (f->inocache->state != INO_STATE_CHECKING) {
677 /* Symlink's inode data is the target path. Read it and
Artem B. Bityutskiy2b79adc2005-07-17 12:13:51 +0100678 * keep in RAM to facilitate quick follow symlink
679 * operation. */
680 f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL);
681 if (!f->target) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100682 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 +0000683 up(&f->sem);
684 jffs2_do_clear_inode(c, f);
685 return -ENOMEM;
686 }
687
688 ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node),
Artem B. Bityutskiy2b79adc2005-07-17 12:13:51 +0100689 je32_to_cpu(latest_node->csize), &retlen, (char *)f->target);
Artem B. Bityuckiy32f1a952005-03-01 10:50:52 +0000690
691 if (ret || retlen != je32_to_cpu(latest_node->csize)) {
692 if (retlen != je32_to_cpu(latest_node->csize))
693 ret = -EIO;
Artem B. Bityutskiy2b79adc2005-07-17 12:13:51 +0100694 kfree(f->target);
695 f->target = NULL;
Artem B. Bityuckiy32f1a952005-03-01 10:50:52 +0000696 up(&f->sem);
697 jffs2_do_clear_inode(c, f);
698 return -ret;
699 }
700
Artem B. Bityutskiy2b79adc2005-07-17 12:13:51 +0100701 f->target[je32_to_cpu(latest_node->csize)] = '\0';
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100702 JFFS2_DBG_READINODE("symlink's target '%s' cached\n", f->target);
Artem B. Bityuckiy32f1a952005-03-01 10:50:52 +0000703 }
704
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 /* fall through... */
706
707 case S_IFBLK:
708 case S_IFCHR:
709 /* Certain inode types should have only one data node, and it's
710 kept as the metadata node */
711 if (f->metadata) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100712 JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 f->inocache->ino, jemode_to_cpu(latest_node->mode));
714 up(&f->sem);
715 jffs2_do_clear_inode(c, f);
716 return -EIO;
717 }
718 if (!frag_first(&f->fragtree)) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100719 JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 f->inocache->ino, jemode_to_cpu(latest_node->mode));
721 up(&f->sem);
722 jffs2_do_clear_inode(c, f);
723 return -EIO;
724 }
725 /* ASSERT: f->fraglist != NULL */
726 if (frag_next(frag_first(&f->fragtree))) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100727 JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 f->inocache->ino, jemode_to_cpu(latest_node->mode));
729 /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
730 up(&f->sem);
731 jffs2_do_clear_inode(c, f);
732 return -EIO;
733 }
734 /* OK. We're happy */
735 f->metadata = frag_first(&f->fragtree)->node;
736 jffs2_free_node_frag(frag_first(&f->fragtree));
737 f->fragtree = RB_ROOT;
738 break;
739 }
740 if (f->inocache->state == INO_STATE_READING)
741 jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
742
743 return 0;
744}
745
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100746/* Scan the list of all nodes present for this ino, build map of versions, etc. */
747int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
748 uint32_t ino, struct jffs2_raw_inode *latest_node)
749{
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100750 JFFS2_DBG_READINODE("read inode #%u\n", ino);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100751
752 retry_inocache:
753 spin_lock(&c->inocache_lock);
754 f->inocache = jffs2_get_ino_cache(c, ino);
755
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100756 if (f->inocache) {
757 /* Check its state. We may need to wait before we can use it */
758 switch(f->inocache->state) {
759 case INO_STATE_UNCHECKED:
760 case INO_STATE_CHECKEDABSENT:
761 f->inocache->state = INO_STATE_READING;
762 break;
763
764 case INO_STATE_CHECKING:
765 case INO_STATE_GC:
766 /* If it's in either of these states, we need
767 to wait for whoever's got it to finish and
768 put it back. */
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100769 JFFS2_DBG_READINODE("waiting for ino #%u in state %d\n", ino, f->inocache->state);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100770 sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
771 goto retry_inocache;
772
773 case INO_STATE_READING:
774 case INO_STATE_PRESENT:
775 /* Eep. This should never happen. It can
776 happen if Linux calls read_inode() again
777 before clear_inode() has finished though. */
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100778 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 +0100779 /* Fail. That's probably better than allowing it to succeed */
780 f->inocache = NULL;
781 break;
782
783 default:
784 BUG();
785 }
786 }
787 spin_unlock(&c->inocache_lock);
788
789 if (!f->inocache && ino == 1) {
790 /* Special case - no root inode on medium */
791 f->inocache = jffs2_alloc_inode_cache();
792 if (!f->inocache) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100793 JFFS2_ERROR("cannot allocate inocache for root inode\n");
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100794 return -ENOMEM;
795 }
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100796 JFFS2_DBG_READINODE("creating inocache for root inode\n");
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100797 memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
798 f->inocache->ino = f->inocache->nlink = 1;
799 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
800 f->inocache->state = INO_STATE_READING;
801 jffs2_add_ino_cache(c, f->inocache);
802 }
803 if (!f->inocache) {
Artem B. Bityutskiye0d60132005-07-28 15:46:43 +0100804 JFFS2_ERROR("requestied to read an nonexistent ino %u\n", ino);
Artem B. Bityutskiyf97117d2005-07-27 15:46:14 +0100805 return -ENOENT;
806 }
807
808 return jffs2_do_read_inode_internal(c, f, latest_node);
809}
810
811int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
812{
813 struct jffs2_raw_inode n;
814 struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL);
815 int ret;
816
817 if (!f)
818 return -ENOMEM;
819
820 memset(f, 0, sizeof(*f));
821 init_MUTEX_LOCKED(&f->sem);
822 f->inocache = ic;
823
824 ret = jffs2_do_read_inode_internal(c, f, &n);
825 if (!ret) {
826 up(&f->sem);
827 jffs2_do_clear_inode(c, f);
828 }
829 kfree (f);
830 return ret;
831}
832
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
834{
835 struct jffs2_full_dirent *fd, *fds;
836 int deleted;
837
838 down(&f->sem);
839 deleted = f->inocache && !f->inocache->nlink;
840
David Woodhouse67e345d2005-02-27 23:01:36 +0000841 if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
842 jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);
843
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 if (f->metadata) {
845 if (deleted)
846 jffs2_mark_node_obsolete(c, f->metadata->raw);
847 jffs2_free_full_dnode(f->metadata);
848 }
849
850 jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL);
851
Artem B. Bityutskiy2b79adc2005-07-17 12:13:51 +0100852 if (f->target) {
853 kfree(f->target);
854 f->target = NULL;
855 }
856
857 fds = f->dents;
858 while(fds) {
859 fd = fds;
860 fds = fd->next;
861 jffs2_free_full_dirent(fd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 }
863
David Woodhouse67e345d2005-02-27 23:01:36 +0000864 if (f->inocache && f->inocache->state != INO_STATE_CHECKING) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
David Woodhouse67e345d2005-02-27 23:01:36 +0000866 if (f->inocache->nodes == (void *)f->inocache)
867 jffs2_del_ino_cache(c, f->inocache);
868 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869
870 up(&f->sem);
871}