xref: /openbmc/linux/fs/jffs2/readinode.c (revision 9afc9a8a)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * JFFS2 -- Journalling Flash File System, Version 2.
31da177e4SLinus Torvalds  *
4c00c310eSDavid Woodhouse  * Copyright © 2001-2007 Red Hat, Inc.
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Created by David Woodhouse <dwmw2@infradead.org>
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  * For licensing information, see the file 'LICENCE' in this directory.
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  */
111da177e4SLinus Torvalds 
125a528957SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
135a528957SJoe Perches 
141da177e4SLinus Torvalds #include <linux/kernel.h>
15737b7661SAndrew Lunn #include <linux/sched.h>
161da177e4SLinus Torvalds #include <linux/slab.h>
171da177e4SLinus Torvalds #include <linux/fs.h>
181da177e4SLinus Torvalds #include <linux/crc32.h>
191da177e4SLinus Torvalds #include <linux/pagemap.h>
201da177e4SLinus Torvalds #include <linux/mtd/mtd.h>
211da177e4SLinus Torvalds #include <linux/compiler.h>
221da177e4SLinus Torvalds #include "nodelist.h"
231da177e4SLinus Torvalds 
24f97117d1SArtem B. Bityutskiy /*
25df8e96f3SDavid Woodhouse  * Check the data CRC of the node.
26df8e96f3SDavid Woodhouse  *
27df8e96f3SDavid Woodhouse  * Returns: 0 if the data CRC is correct;
28df8e96f3SDavid Woodhouse  * 	    1 - if incorrect;
2925985edcSLucas De Marchi  *	    error code if an error occurred.
30f97117d1SArtem B. Bityutskiy  */
check_node_data(struct jffs2_sb_info * c,struct jffs2_tmp_dnode_info * tn)31df8e96f3SDavid Woodhouse static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
321da177e4SLinus Torvalds {
33df8e96f3SDavid Woodhouse 	struct jffs2_raw_node_ref *ref = tn->fn->raw;
34df8e96f3SDavid Woodhouse 	int err = 0, pointed = 0;
35df8e96f3SDavid Woodhouse 	struct jffs2_eraseblock *jeb;
36df8e96f3SDavid Woodhouse 	unsigned char *buffer;
37df8e96f3SDavid Woodhouse 	uint32_t crc, ofs, len;
38df8e96f3SDavid Woodhouse 	size_t retlen;
391da177e4SLinus Torvalds 
40df8e96f3SDavid Woodhouse 	BUG_ON(tn->csize == 0);
411da177e4SLinus Torvalds 
42df8e96f3SDavid Woodhouse 	/* Calculate how many bytes were already checked */
43df8e96f3SDavid Woodhouse 	ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode);
4492525726SDavid Woodhouse 	len = tn->csize;
45df8e96f3SDavid Woodhouse 
4692525726SDavid Woodhouse 	if (jffs2_is_writebuffered(c)) {
4792525726SDavid Woodhouse 		int adj = ofs % c->wbuf_pagesize;
4892525726SDavid Woodhouse 		if (likely(adj))
4992525726SDavid Woodhouse 			adj = c->wbuf_pagesize - adj;
5092525726SDavid Woodhouse 
5192525726SDavid Woodhouse 		if (adj >= tn->csize) {
52df8e96f3SDavid Woodhouse 			dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n",
53df8e96f3SDavid Woodhouse 				      ref_offset(ref), tn->csize, ofs);
54df8e96f3SDavid Woodhouse 			goto adj_acc;
55f97117d1SArtem B. Bityutskiy 		}
561da177e4SLinus Torvalds 
5792525726SDavid Woodhouse 		ofs += adj;
5892525726SDavid Woodhouse 		len -= adj;
5992525726SDavid Woodhouse 	}
60df8e96f3SDavid Woodhouse 
61df8e96f3SDavid Woodhouse 	dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n",
62df8e96f3SDavid Woodhouse 		ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len);
63df8e96f3SDavid Woodhouse 
64df8e96f3SDavid Woodhouse #ifndef __ECOS
65df8e96f3SDavid Woodhouse 	/* TODO: instead, incapsulate point() stuff to jffs2_flash_read(),
66df8e96f3SDavid Woodhouse 	 * adding and jffs2_flash_read_end() interface. */
6710934478SArtem Bityutskiy 	err = mtd_point(c->mtd, ofs, len, &retlen, (void **)&buffer, NULL);
68c2056e1eSAlexey Korolev 	if (!err && retlen < len) {
69df8e96f3SDavid Woodhouse 		JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
707219778aSArtem Bityutskiy 		mtd_unpoint(c->mtd, ofs, retlen);
7110934478SArtem Bityutskiy 	} else if (err) {
7210934478SArtem Bityutskiy 		if (err != -EOPNOTSUPP)
73df8e96f3SDavid Woodhouse 			JFFS2_WARNING("MTD point failed: error code %d.\n", err);
7410934478SArtem Bityutskiy 	} else
75df8e96f3SDavid Woodhouse 		pointed = 1; /* succefully pointed to device */
76df8e96f3SDavid Woodhouse #endif
77df8e96f3SDavid Woodhouse 
78df8e96f3SDavid Woodhouse 	if (!pointed) {
79df8e96f3SDavid Woodhouse 		buffer = kmalloc(len, GFP_KERNEL);
80df8e96f3SDavid Woodhouse 		if (unlikely(!buffer))
81df8e96f3SDavid Woodhouse 			return -ENOMEM;
82df8e96f3SDavid Woodhouse 
83df8e96f3SDavid Woodhouse 		/* TODO: this is very frequent pattern, make it a separate
84df8e96f3SDavid Woodhouse 		 * routine */
85df8e96f3SDavid Woodhouse 		err = jffs2_flash_read(c, ofs, len, &retlen, buffer);
86df8e96f3SDavid Woodhouse 		if (err) {
87df8e96f3SDavid Woodhouse 			JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ofs, err);
88df8e96f3SDavid Woodhouse 			goto free_out;
89df8e96f3SDavid Woodhouse 		}
90df8e96f3SDavid Woodhouse 
91df8e96f3SDavid Woodhouse 		if (retlen != len) {
92df8e96f3SDavid Woodhouse 			JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", ofs, retlen, len);
93df8e96f3SDavid Woodhouse 			err = -EIO;
94df8e96f3SDavid Woodhouse 			goto free_out;
95df8e96f3SDavid Woodhouse 		}
96df8e96f3SDavid Woodhouse 	}
97df8e96f3SDavid Woodhouse 
98df8e96f3SDavid Woodhouse 	/* Continue calculating CRC */
99df8e96f3SDavid Woodhouse 	crc = crc32(tn->partial_crc, buffer, len);
100df8e96f3SDavid Woodhouse 	if(!pointed)
101df8e96f3SDavid Woodhouse 		kfree(buffer);
102df8e96f3SDavid Woodhouse #ifndef __ECOS
103df8e96f3SDavid Woodhouse 	else
1047219778aSArtem Bityutskiy 		mtd_unpoint(c->mtd, ofs, len);
105df8e96f3SDavid Woodhouse #endif
106df8e96f3SDavid Woodhouse 
107df8e96f3SDavid Woodhouse 	if (crc != tn->data_crc) {
108df8e96f3SDavid Woodhouse 		JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n",
109b2e25235SDavid Woodhouse 			     ref_offset(ref), tn->data_crc, crc);
110df8e96f3SDavid Woodhouse 		return 1;
111df8e96f3SDavid Woodhouse 	}
112df8e96f3SDavid Woodhouse 
113df8e96f3SDavid Woodhouse adj_acc:
114df8e96f3SDavid Woodhouse 	jeb = &c->blocks[ref->flash_offset / c->sector_size];
115df8e96f3SDavid Woodhouse 	len = ref_totlen(c, jeb, ref);
116df8e96f3SDavid Woodhouse 	/* If it should be REF_NORMAL, it'll get marked as such when
117df8e96f3SDavid Woodhouse 	   we build the fragtree, shortly. No need to worry about GC
118df8e96f3SDavid Woodhouse 	   moving it while it's marked REF_PRISTINE -- GC won't happen
119df8e96f3SDavid Woodhouse 	   till we've finished checking every inode anyway. */
120df8e96f3SDavid Woodhouse 	ref->flash_offset |= REF_PRISTINE;
121df8e96f3SDavid Woodhouse 	/*
122df8e96f3SDavid Woodhouse 	 * Mark the node as having been checked and fix the
123df8e96f3SDavid Woodhouse 	 * accounting accordingly.
124df8e96f3SDavid Woodhouse 	 */
125df8e96f3SDavid Woodhouse 	spin_lock(&c->erase_completion_lock);
126df8e96f3SDavid Woodhouse 	jeb->used_size += len;
127df8e96f3SDavid Woodhouse 	jeb->unchecked_size -= len;
128df8e96f3SDavid Woodhouse 	c->used_size += len;
129df8e96f3SDavid Woodhouse 	c->unchecked_size -= len;
130df8e96f3SDavid Woodhouse 	jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
131df8e96f3SDavid Woodhouse 	spin_unlock(&c->erase_completion_lock);
132df8e96f3SDavid Woodhouse 
133df8e96f3SDavid Woodhouse 	return 0;
134df8e96f3SDavid Woodhouse 
135df8e96f3SDavid Woodhouse free_out:
136df8e96f3SDavid Woodhouse 	if(!pointed)
137df8e96f3SDavid Woodhouse 		kfree(buffer);
138df8e96f3SDavid Woodhouse #ifndef __ECOS
139df8e96f3SDavid Woodhouse 	else
1407219778aSArtem Bityutskiy 		mtd_unpoint(c->mtd, ofs, len);
141df8e96f3SDavid Woodhouse #endif
142df8e96f3SDavid Woodhouse 	return err;
143df8e96f3SDavid Woodhouse }
144df8e96f3SDavid Woodhouse 
145df8e96f3SDavid Woodhouse /*
146df8e96f3SDavid Woodhouse  * Helper function for jffs2_add_older_frag_to_fragtree().
147df8e96f3SDavid Woodhouse  *
148df8e96f3SDavid Woodhouse  * Checks the node if we are in the checking stage.
149df8e96f3SDavid Woodhouse  */
check_tn_node(struct jffs2_sb_info * c,struct jffs2_tmp_dnode_info * tn)150df8e96f3SDavid Woodhouse static int check_tn_node(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
151df8e96f3SDavid Woodhouse {
152df8e96f3SDavid Woodhouse 	int ret;
153df8e96f3SDavid Woodhouse 
154df8e96f3SDavid Woodhouse 	BUG_ON(ref_obsolete(tn->fn->raw));
155df8e96f3SDavid Woodhouse 
156df8e96f3SDavid Woodhouse 	/* We only check the data CRC of unchecked nodes */
157df8e96f3SDavid Woodhouse 	if (ref_flags(tn->fn->raw) != REF_UNCHECKED)
158df8e96f3SDavid Woodhouse 		return 0;
159df8e96f3SDavid Woodhouse 
160df8e96f3SDavid Woodhouse 	dbg_readinode("check node %#04x-%#04x, phys offs %#08x\n",
161df8e96f3SDavid Woodhouse 		      tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw));
162df8e96f3SDavid Woodhouse 
163df8e96f3SDavid Woodhouse 	ret = check_node_data(c, tn);
164df8e96f3SDavid Woodhouse 	if (unlikely(ret < 0)) {
165df8e96f3SDavid Woodhouse 		JFFS2_ERROR("check_node_data() returned error: %d.\n",
166df8e96f3SDavid Woodhouse 			ret);
167df8e96f3SDavid Woodhouse 	} else if (unlikely(ret > 0)) {
168df8e96f3SDavid Woodhouse 		dbg_readinode("CRC error, mark it obsolete.\n");
169df8e96f3SDavid Woodhouse 		jffs2_mark_node_obsolete(c, tn->fn->raw);
170df8e96f3SDavid Woodhouse 	}
171df8e96f3SDavid Woodhouse 
172df8e96f3SDavid Woodhouse 	return ret;
173df8e96f3SDavid Woodhouse }
174df8e96f3SDavid Woodhouse 
jffs2_lookup_tn(struct rb_root * tn_root,uint32_t offset)175df8e96f3SDavid Woodhouse static struct jffs2_tmp_dnode_info *jffs2_lookup_tn(struct rb_root *tn_root, uint32_t offset)
176df8e96f3SDavid Woodhouse {
177df8e96f3SDavid Woodhouse 	struct rb_node *next;
178df8e96f3SDavid Woodhouse 	struct jffs2_tmp_dnode_info *tn = NULL;
179df8e96f3SDavid Woodhouse 
180df8e96f3SDavid Woodhouse 	dbg_readinode("root %p, offset %d\n", tn_root, offset);
181df8e96f3SDavid Woodhouse 
182df8e96f3SDavid Woodhouse 	next = tn_root->rb_node;
183df8e96f3SDavid Woodhouse 
184df8e96f3SDavid Woodhouse 	while (next) {
185df8e96f3SDavid Woodhouse 		tn = rb_entry(next, struct jffs2_tmp_dnode_info, rb);
186df8e96f3SDavid Woodhouse 
187df8e96f3SDavid Woodhouse 		if (tn->fn->ofs < offset)
188df8e96f3SDavid Woodhouse 			next = tn->rb.rb_right;
189df8e96f3SDavid Woodhouse 		else if (tn->fn->ofs >= offset)
190df8e96f3SDavid Woodhouse 			next = tn->rb.rb_left;
191df8e96f3SDavid Woodhouse 		else
192df8e96f3SDavid Woodhouse 			break;
193df8e96f3SDavid Woodhouse 	}
194df8e96f3SDavid Woodhouse 
195df8e96f3SDavid Woodhouse 	return tn;
196df8e96f3SDavid Woodhouse }
197df8e96f3SDavid Woodhouse 
198df8e96f3SDavid Woodhouse 
jffs2_kill_tn(struct jffs2_sb_info * c,struct jffs2_tmp_dnode_info * tn)199df8e96f3SDavid Woodhouse static void jffs2_kill_tn(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
200df8e96f3SDavid Woodhouse {
201df8e96f3SDavid Woodhouse 	jffs2_mark_node_obsolete(c, tn->fn->raw);
202df8e96f3SDavid Woodhouse 	jffs2_free_full_dnode(tn->fn);
203df8e96f3SDavid Woodhouse 	jffs2_free_tmp_dnode_info(tn);
204df8e96f3SDavid Woodhouse }
205df8e96f3SDavid Woodhouse /*
206df8e96f3SDavid Woodhouse  * This function is used when we read an inode. Data nodes arrive in
207df8e96f3SDavid Woodhouse  * arbitrary order -- they may be older or newer than the nodes which
208df8e96f3SDavid Woodhouse  * are already in the tree. Where overlaps occur, the older node can
209df8e96f3SDavid Woodhouse  * be discarded as long as the newer passes the CRC check. We don't
210df8e96f3SDavid Woodhouse  * bother to keep track of holes in this rbtree, and neither do we deal
211df8e96f3SDavid Woodhouse  * with frags -- we can have multiple entries starting at the same
212df8e96f3SDavid Woodhouse  * offset, and the one with the smallest length will come first in the
213df8e96f3SDavid Woodhouse  * ordering.
214df8e96f3SDavid Woodhouse  *
21514c6381eSDavid Woodhouse  * Returns 0 if the node was handled (including marking it obsolete)
216df8e96f3SDavid Woodhouse  *	 < 0 an if error occurred
217df8e96f3SDavid Woodhouse  */
jffs2_add_tn_to_tree(struct jffs2_sb_info * c,struct jffs2_readinode_info * rii,struct jffs2_tmp_dnode_info * tn)218df8e96f3SDavid Woodhouse static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
219df8e96f3SDavid Woodhouse 				struct jffs2_readinode_info *rii,
220df8e96f3SDavid Woodhouse 				struct jffs2_tmp_dnode_info *tn)
221df8e96f3SDavid Woodhouse {
222df8e96f3SDavid Woodhouse 	uint32_t fn_end = tn->fn->ofs + tn->fn->size;
2234c41bd0eSThomas Gleixner 	struct jffs2_tmp_dnode_info *this, *ptn;
224df8e96f3SDavid Woodhouse 
225fcf3cafbSDavid Woodhouse 	dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x\n", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw));
226df8e96f3SDavid Woodhouse 
2274740f496SGeert Uytterhoeven 	/* If a node has zero dsize, we only have to keep it if it might be the
228df8e96f3SDavid Woodhouse 	   node with highest version -- i.e. the one which will end up as f->metadata.
229df8e96f3SDavid Woodhouse 	   Note that such nodes won't be REF_UNCHECKED since there are no data to
230df8e96f3SDavid Woodhouse 	   check anyway. */
231df8e96f3SDavid Woodhouse 	if (!tn->fn->size) {
232df8e96f3SDavid Woodhouse 		if (rii->mdata_tn) {
2330477d24eSDavid Woodhouse 			if (rii->mdata_tn->version < tn->version) {
234df8e96f3SDavid Woodhouse 				/* We had a candidate mdata node already */
235df8e96f3SDavid Woodhouse 				dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version);
236df8e96f3SDavid Woodhouse 				jffs2_kill_tn(c, rii->mdata_tn);
2370477d24eSDavid Woodhouse 			} else {
2380477d24eSDavid Woodhouse 				dbg_readinode("kill new mdata with ver %d (older than existing %d\n",
2390477d24eSDavid Woodhouse 					      tn->version, rii->mdata_tn->version);
2400477d24eSDavid Woodhouse 				jffs2_kill_tn(c, tn);
2410477d24eSDavid Woodhouse 				return 0;
2420477d24eSDavid Woodhouse 			}
243df8e96f3SDavid Woodhouse 		}
244df8e96f3SDavid Woodhouse 		rii->mdata_tn = tn;
245df8e96f3SDavid Woodhouse 		dbg_readinode("keep new mdata with ver %d\n", tn->version);
246df8e96f3SDavid Woodhouse 		return 0;
247df8e96f3SDavid Woodhouse 	}
248df8e96f3SDavid Woodhouse 
249df8e96f3SDavid Woodhouse 	/* Find the earliest node which _may_ be relevant to this one */
250df8e96f3SDavid Woodhouse 	this = jffs2_lookup_tn(&rii->tn_root, tn->fn->ofs);
2511c979645SDavid Woodhouse 	if (this) {
252df8e96f3SDavid Woodhouse 		/* If the node is coincident with another at a lower address,
253df8e96f3SDavid Woodhouse 		   back up until the other node is found. It may be relevant */
2544c41bd0eSThomas Gleixner 		while (this->overlapped) {
2554c41bd0eSThomas Gleixner 			ptn = tn_prev(this);
2564c41bd0eSThomas Gleixner 			if (!ptn) {
2574c41bd0eSThomas Gleixner 				/*
2584c41bd0eSThomas Gleixner 				 * We killed a node which set the overlapped
2594c41bd0eSThomas Gleixner 				 * flags during the scan. Fix it up.
2604c41bd0eSThomas Gleixner 				 */
2614c41bd0eSThomas Gleixner 				this->overlapped = 0;
2624c41bd0eSThomas Gleixner 				break;
2634c41bd0eSThomas Gleixner 			}
2644c41bd0eSThomas Gleixner 			this = ptn;
2654c41bd0eSThomas Gleixner 		}
266df8e96f3SDavid Woodhouse 		dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole");
2671c979645SDavid Woodhouse 	}
268df8e96f3SDavid Woodhouse 
269df8e96f3SDavid Woodhouse 	while (this) {
270df8e96f3SDavid Woodhouse 		if (this->fn->ofs > fn_end)
271df8e96f3SDavid Woodhouse 			break;
272df8e96f3SDavid Woodhouse 		dbg_readinode("Ponder this ver %d, 0x%x-0x%x\n",
273df8e96f3SDavid Woodhouse 			      this->version, this->fn->ofs, this->fn->size);
274df8e96f3SDavid Woodhouse 
275df8e96f3SDavid Woodhouse 		if (this->version == tn->version) {
276df8e96f3SDavid Woodhouse 			/* Version number collision means REF_PRISTINE GC. Accept either of them
277df8e96f3SDavid Woodhouse 			   as long as the CRC is correct. Check the one we have already...  */
278df8e96f3SDavid Woodhouse 			if (!check_tn_node(c, this)) {
279df8e96f3SDavid Woodhouse 				/* The one we already had was OK. Keep it and throw away the new one */
280df8e96f3SDavid Woodhouse 				dbg_readinode("Like old node. Throw away new\n");
281df8e96f3SDavid Woodhouse 				jffs2_kill_tn(c, tn);
282df8e96f3SDavid Woodhouse 				return 0;
283df8e96f3SDavid Woodhouse 			} else {
284df8e96f3SDavid Woodhouse 				/* Who cares if the new one is good; keep it for now anyway. */
285df8e96f3SDavid Woodhouse 				dbg_readinode("Like new node. Throw away old\n");
286fcf3cafbSDavid Woodhouse 				rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
287fcf3cafbSDavid Woodhouse 				jffs2_kill_tn(c, this);
288fcf3cafbSDavid Woodhouse 				/* Same overlapping from in front and behind */
289fcf3cafbSDavid Woodhouse 				return 0;
290df8e96f3SDavid Woodhouse 			}
291df8e96f3SDavid Woodhouse 		}
292df8e96f3SDavid Woodhouse 		if (this->version < tn->version &&
293df8e96f3SDavid Woodhouse 		    this->fn->ofs >= tn->fn->ofs &&
294df8e96f3SDavid Woodhouse 		    this->fn->ofs + this->fn->size <= fn_end) {
295df8e96f3SDavid Woodhouse 			/* New node entirely overlaps 'this' */
296df8e96f3SDavid Woodhouse 			if (check_tn_node(c, tn)) {
297df8e96f3SDavid Woodhouse 				dbg_readinode("new node bad CRC\n");
298df8e96f3SDavid Woodhouse 				jffs2_kill_tn(c, tn);
299df8e96f3SDavid Woodhouse 				return 0;
300df8e96f3SDavid Woodhouse 			}
301fcf3cafbSDavid Woodhouse 			/* ... and is good. Kill 'this' and any subsequent nodes which are also overlapped */
3021c979645SDavid Woodhouse 			while (this && this->fn->ofs + this->fn->size <= fn_end) {
303df8e96f3SDavid Woodhouse 				struct jffs2_tmp_dnode_info *next = tn_next(this);
304df8e96f3SDavid Woodhouse 				if (this->version < tn->version) {
305df8e96f3SDavid Woodhouse 					tn_erase(this, &rii->tn_root);
306df8e96f3SDavid Woodhouse 					dbg_readinode("Kill overlapped ver %d, 0x%x-0x%x\n",
307df8e96f3SDavid Woodhouse 						      this->version, this->fn->ofs,
308df8e96f3SDavid Woodhouse 						      this->fn->ofs+this->fn->size);
309df8e96f3SDavid Woodhouse 					jffs2_kill_tn(c, this);
310df8e96f3SDavid Woodhouse 				}
311df8e96f3SDavid Woodhouse 				this = next;
312df8e96f3SDavid Woodhouse 			}
313fcf3cafbSDavid Woodhouse 			dbg_readinode("Done killing overlapped nodes\n");
3141c979645SDavid Woodhouse 			continue;
315df8e96f3SDavid Woodhouse 		}
316df8e96f3SDavid Woodhouse 		if (this->version > tn->version &&
317df8e96f3SDavid Woodhouse 		    this->fn->ofs <= tn->fn->ofs &&
318df8e96f3SDavid Woodhouse 		    this->fn->ofs+this->fn->size >= fn_end) {
319df8e96f3SDavid Woodhouse 			/* New node entirely overlapped by 'this' */
320df8e96f3SDavid Woodhouse 			if (!check_tn_node(c, this)) {
321df8e96f3SDavid Woodhouse 				dbg_readinode("Good CRC on old node. Kill new\n");
322df8e96f3SDavid Woodhouse 				jffs2_kill_tn(c, tn);
323df8e96f3SDavid Woodhouse 				return 0;
324df8e96f3SDavid Woodhouse 			}
325df8e96f3SDavid Woodhouse 			/* ... but 'this' was bad. Replace it... */
326df8e96f3SDavid Woodhouse 			dbg_readinode("Bad CRC on old overlapping node. Kill it\n");
327fcf3cafbSDavid Woodhouse 			tn_erase(this, &rii->tn_root);
328df8e96f3SDavid Woodhouse 			jffs2_kill_tn(c, this);
329fcf3cafbSDavid Woodhouse 			break;
330df8e96f3SDavid Woodhouse 		}
331df8e96f3SDavid Woodhouse 
332df8e96f3SDavid Woodhouse 		this = tn_next(this);
333df8e96f3SDavid Woodhouse 	}
33496dd8d25SDavid Woodhouse 
335df8e96f3SDavid Woodhouse 	/* We neither completely obsoleted nor were completely
33696dd8d25SDavid Woodhouse 	   obsoleted by an earlier node. Insert into the tree */
337df8e96f3SDavid Woodhouse 	{
33896dd8d25SDavid Woodhouse 		struct rb_node *parent;
33996dd8d25SDavid Woodhouse 		struct rb_node **link = &rii->tn_root.rb_node;
3401c979645SDavid Woodhouse 		struct jffs2_tmp_dnode_info *insert_point = NULL;
341df8e96f3SDavid Woodhouse 
342df8e96f3SDavid Woodhouse 		while (*link) {
343df8e96f3SDavid Woodhouse 			parent = *link;
344df8e96f3SDavid Woodhouse 			insert_point = rb_entry(parent, struct jffs2_tmp_dnode_info, rb);
345df8e96f3SDavid Woodhouse 			if (tn->fn->ofs > insert_point->fn->ofs)
346df8e96f3SDavid Woodhouse 				link = &insert_point->rb.rb_right;
347df8e96f3SDavid Woodhouse 			else if (tn->fn->ofs < insert_point->fn->ofs ||
348df8e96f3SDavid Woodhouse 				 tn->fn->size < insert_point->fn->size)
349df8e96f3SDavid Woodhouse 				link = &insert_point->rb.rb_left;
350df8e96f3SDavid Woodhouse 			else
351df8e96f3SDavid Woodhouse 				link = &insert_point->rb.rb_right;
352df8e96f3SDavid Woodhouse 		}
353df8e96f3SDavid Woodhouse 		rb_link_node(&tn->rb, &insert_point->rb, link);
354df8e96f3SDavid Woodhouse 		rb_insert_color(&tn->rb, &rii->tn_root);
355df8e96f3SDavid Woodhouse 	}
3561123e2a8SDavid Woodhouse 
357df8e96f3SDavid Woodhouse 	/* If there's anything behind that overlaps us, note it */
358df8e96f3SDavid Woodhouse 	this = tn_prev(tn);
359df8e96f3SDavid Woodhouse 	if (this) {
360df8e96f3SDavid Woodhouse 		while (1) {
361df8e96f3SDavid Woodhouse 			if (this->fn->ofs + this->fn->size > tn->fn->ofs) {
362df8e96f3SDavid Woodhouse 				dbg_readinode("Node is overlapped by %p (v %d, 0x%x-0x%x)\n",
363df8e96f3SDavid Woodhouse 					      this, this->version, this->fn->ofs,
364df8e96f3SDavid Woodhouse 					      this->fn->ofs+this->fn->size);
365df8e96f3SDavid Woodhouse 				tn->overlapped = 1;
366df8e96f3SDavid Woodhouse 				break;
367df8e96f3SDavid Woodhouse 			}
368df8e96f3SDavid Woodhouse 			if (!this->overlapped)
369df8e96f3SDavid Woodhouse 				break;
3704c41bd0eSThomas Gleixner 
3714c41bd0eSThomas Gleixner 			ptn = tn_prev(this);
3724c41bd0eSThomas Gleixner 			if (!ptn) {
3734c41bd0eSThomas Gleixner 				/*
3744c41bd0eSThomas Gleixner 				 * We killed a node which set the overlapped
3754c41bd0eSThomas Gleixner 				 * flags during the scan. Fix it up.
3764c41bd0eSThomas Gleixner 				 */
3774c41bd0eSThomas Gleixner 				this->overlapped = 0;
3784c41bd0eSThomas Gleixner 				break;
3794c41bd0eSThomas Gleixner 			}
3804c41bd0eSThomas Gleixner 			this = ptn;
381df8e96f3SDavid Woodhouse 		}
382df8e96f3SDavid Woodhouse 	}
383df8e96f3SDavid Woodhouse 
384df8e96f3SDavid Woodhouse 	/* If the new node overlaps anything ahead, note it */
385df8e96f3SDavid Woodhouse 	this = tn_next(tn);
386df8e96f3SDavid Woodhouse 	while (this && this->fn->ofs < fn_end) {
387df8e96f3SDavid Woodhouse 		this->overlapped = 1;
388df8e96f3SDavid Woodhouse 		dbg_readinode("Node ver %d, 0x%x-0x%x is overlapped\n",
389df8e96f3SDavid Woodhouse 			      this->version, this->fn->ofs,
390df8e96f3SDavid Woodhouse 			      this->fn->ofs+this->fn->size);
391df8e96f3SDavid Woodhouse 		this = tn_next(this);
392df8e96f3SDavid Woodhouse 	}
393df8e96f3SDavid Woodhouse 	return 0;
394df8e96f3SDavid Woodhouse }
395df8e96f3SDavid Woodhouse 
396df8e96f3SDavid Woodhouse /* Trivial function to remove the last node in the tree. Which by definition
397bf7ad8eeSMichel Lespinasse    has no right-hand child — so can be removed just by making its left-hand
398bf7ad8eeSMichel Lespinasse    child (if any) take its place under its parent. Since this is only done
399bf7ad8eeSMichel Lespinasse    when we're consuming the whole tree, there's no need to use rb_erase()
400bf7ad8eeSMichel Lespinasse    and let it worry about adjusting colours and balancing the tree. That
401bf7ad8eeSMichel Lespinasse    would just be a waste of time. */
eat_last(struct rb_root * root,struct rb_node * node)402df8e96f3SDavid Woodhouse static void eat_last(struct rb_root *root, struct rb_node *node)
403df8e96f3SDavid Woodhouse {
404df8e96f3SDavid Woodhouse 	struct rb_node *parent = rb_parent(node);
405df8e96f3SDavid Woodhouse 	struct rb_node **link;
406df8e96f3SDavid Woodhouse 
407df8e96f3SDavid Woodhouse 	/* LAST! */
408df8e96f3SDavid Woodhouse 	BUG_ON(node->rb_right);
409df8e96f3SDavid Woodhouse 
410df8e96f3SDavid Woodhouse 	if (!parent)
411df8e96f3SDavid Woodhouse 		link = &root->rb_node;
412df8e96f3SDavid Woodhouse 	else if (node == parent->rb_left)
413df8e96f3SDavid Woodhouse 		link = &parent->rb_left;
414df8e96f3SDavid Woodhouse 	else
415df8e96f3SDavid Woodhouse 		link = &parent->rb_right;
416df8e96f3SDavid Woodhouse 
417df8e96f3SDavid Woodhouse 	*link = node->rb_left;
418df8e96f3SDavid Woodhouse 	if (node->rb_left)
419bf7ad8eeSMichel Lespinasse 		node->rb_left->__rb_parent_color = node->__rb_parent_color;
420df8e96f3SDavid Woodhouse }
421df8e96f3SDavid Woodhouse 
422bf7ad8eeSMichel Lespinasse /* We put the version tree in reverse order, so we can use the same eat_last()
423bf7ad8eeSMichel Lespinasse    function that we use to consume the tmpnode tree (tn_root). */
ver_insert(struct rb_root * ver_root,struct jffs2_tmp_dnode_info * tn)424df8e96f3SDavid Woodhouse static void ver_insert(struct rb_root *ver_root, struct jffs2_tmp_dnode_info *tn)
425df8e96f3SDavid Woodhouse {
426df8e96f3SDavid Woodhouse 	struct rb_node **link = &ver_root->rb_node;
427df8e96f3SDavid Woodhouse 	struct rb_node *parent = NULL;
428df8e96f3SDavid Woodhouse 	struct jffs2_tmp_dnode_info *this_tn;
429df8e96f3SDavid Woodhouse 
430df8e96f3SDavid Woodhouse 	while (*link) {
431df8e96f3SDavid Woodhouse 		parent = *link;
432df8e96f3SDavid Woodhouse 		this_tn = rb_entry(parent, struct jffs2_tmp_dnode_info, rb);
433df8e96f3SDavid Woodhouse 
434df8e96f3SDavid Woodhouse 		if (tn->version > this_tn->version)
435df8e96f3SDavid Woodhouse 			link = &parent->rb_left;
436df8e96f3SDavid Woodhouse 		else
437df8e96f3SDavid Woodhouse 			link = &parent->rb_right;
438df8e96f3SDavid Woodhouse 	}
439df8e96f3SDavid Woodhouse 	dbg_readinode("Link new node at %p (root is %p)\n", link, ver_root);
440df8e96f3SDavid Woodhouse 	rb_link_node(&tn->rb, parent, link);
441df8e96f3SDavid Woodhouse 	rb_insert_color(&tn->rb, ver_root);
442df8e96f3SDavid Woodhouse }
443df8e96f3SDavid Woodhouse 
444df8e96f3SDavid Woodhouse /* Build final, normal fragtree from tn tree. It doesn't matter which order
445df8e96f3SDavid Woodhouse    we add nodes to the real fragtree, as long as they don't overlap. And
446df8e96f3SDavid Woodhouse    having thrown away the majority of overlapped nodes as we went, there
447df8e96f3SDavid Woodhouse    really shouldn't be many sets of nodes which do overlap. If we start at
448df8e96f3SDavid Woodhouse    the end, we can use the overlap markers -- we can just eat nodes which
449df8e96f3SDavid Woodhouse    aren't overlapped, and when we encounter nodes which _do_ overlap we
450df8e96f3SDavid Woodhouse    sort them all into a temporary tree in version order before replaying them. */
jffs2_build_inode_fragtree(struct jffs2_sb_info * c,struct jffs2_inode_info * f,struct jffs2_readinode_info * rii)451df8e96f3SDavid Woodhouse static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c,
452df8e96f3SDavid Woodhouse 				      struct jffs2_inode_info *f,
453df8e96f3SDavid Woodhouse 				      struct jffs2_readinode_info *rii)
454df8e96f3SDavid Woodhouse {
455df8e96f3SDavid Woodhouse 	struct jffs2_tmp_dnode_info *pen, *last, *this;
456df8e96f3SDavid Woodhouse 	struct rb_root ver_root = RB_ROOT;
457df8e96f3SDavid Woodhouse 	uint32_t high_ver = 0;
458df8e96f3SDavid Woodhouse 
459df8e96f3SDavid Woodhouse 	if (rii->mdata_tn) {
460df8e96f3SDavid Woodhouse 		dbg_readinode("potential mdata is ver %d at %p\n", rii->mdata_tn->version, rii->mdata_tn);
461df8e96f3SDavid Woodhouse 		high_ver = rii->mdata_tn->version;
462df8e96f3SDavid Woodhouse 		rii->latest_ref = rii->mdata_tn->fn->raw;
463df8e96f3SDavid Woodhouse 	}
464df8e96f3SDavid Woodhouse #ifdef JFFS2_DBG_READINODE_MESSAGES
465df8e96f3SDavid Woodhouse 	this = tn_last(&rii->tn_root);
466df8e96f3SDavid Woodhouse 	while (this) {
467df8e96f3SDavid Woodhouse 		dbg_readinode("tn %p ver %d range 0x%x-0x%x ov %d\n", this, this->version, this->fn->ofs,
468df8e96f3SDavid Woodhouse 			      this->fn->ofs+this->fn->size, this->overlapped);
469df8e96f3SDavid Woodhouse 		this = tn_prev(this);
470df8e96f3SDavid Woodhouse 	}
471df8e96f3SDavid Woodhouse #endif
472df8e96f3SDavid Woodhouse 	pen = tn_last(&rii->tn_root);
473df8e96f3SDavid Woodhouse 	while ((last = pen)) {
474df8e96f3SDavid Woodhouse 		pen = tn_prev(last);
475df8e96f3SDavid Woodhouse 
476df8e96f3SDavid Woodhouse 		eat_last(&rii->tn_root, &last->rb);
477df8e96f3SDavid Woodhouse 		ver_insert(&ver_root, last);
478df8e96f3SDavid Woodhouse 
4794c41bd0eSThomas Gleixner 		if (unlikely(last->overlapped)) {
4804c41bd0eSThomas Gleixner 			if (pen)
481df8e96f3SDavid Woodhouse 				continue;
4824c41bd0eSThomas Gleixner 			/*
4834c41bd0eSThomas Gleixner 			 * We killed a node which set the overlapped
4844c41bd0eSThomas Gleixner 			 * flags during the scan. Fix it up.
4854c41bd0eSThomas Gleixner 			 */
4864c41bd0eSThomas Gleixner 			last->overlapped = 0;
4874c41bd0eSThomas Gleixner 		}
488df8e96f3SDavid Woodhouse 
489df8e96f3SDavid Woodhouse 		/* Now we have a bunch of nodes in reverse version
490df8e96f3SDavid Woodhouse 		   order, in the tree at ver_root. Most of the time,
491df8e96f3SDavid Woodhouse 		   there'll actually be only one node in the 'tree',
492df8e96f3SDavid Woodhouse 		   in fact. */
493df8e96f3SDavid Woodhouse 		this = tn_last(&ver_root);
494df8e96f3SDavid Woodhouse 
495df8e96f3SDavid Woodhouse 		while (this) {
496df8e96f3SDavid Woodhouse 			struct jffs2_tmp_dnode_info *vers_next;
497df8e96f3SDavid Woodhouse 			int ret;
498df8e96f3SDavid Woodhouse 			vers_next = tn_prev(this);
499df8e96f3SDavid Woodhouse 			eat_last(&ver_root, &this->rb);
500df8e96f3SDavid Woodhouse 			if (check_tn_node(c, this)) {
5011123e2a8SDavid Woodhouse 				dbg_readinode("node ver %d, 0x%x-0x%x failed CRC\n",
502df8e96f3SDavid Woodhouse 					     this->version, this->fn->ofs,
503df8e96f3SDavid Woodhouse 					     this->fn->ofs+this->fn->size);
504df8e96f3SDavid Woodhouse 				jffs2_kill_tn(c, this);
505df8e96f3SDavid Woodhouse 			} else {
506df8e96f3SDavid Woodhouse 				if (this->version > high_ver) {
507df8e96f3SDavid Woodhouse 					/* Note that this is different from the other
508df8e96f3SDavid Woodhouse 					   highest_version, because this one is only
509df8e96f3SDavid Woodhouse 					   counting _valid_ nodes which could give the
510df8e96f3SDavid Woodhouse 					   latest inode metadata */
511df8e96f3SDavid Woodhouse 					high_ver = this->version;
512df8e96f3SDavid Woodhouse 					rii->latest_ref = this->fn->raw;
513df8e96f3SDavid Woodhouse 				}
5141123e2a8SDavid Woodhouse 				dbg_readinode("Add %p (v %d, 0x%x-0x%x, ov %d) to fragtree\n",
515df8e96f3SDavid Woodhouse 					     this, this->version, this->fn->ofs,
516df8e96f3SDavid Woodhouse 					     this->fn->ofs+this->fn->size, this->overlapped);
517df8e96f3SDavid Woodhouse 
518df8e96f3SDavid Woodhouse 				ret = jffs2_add_full_dnode_to_inode(c, f, this->fn);
519df8e96f3SDavid Woodhouse 				if (ret) {
520df8e96f3SDavid Woodhouse 					/* Free the nodes in vers_root; let the caller
521df8e96f3SDavid Woodhouse 					   deal with the rest */
522df8e96f3SDavid Woodhouse 					JFFS2_ERROR("Add node to tree failed %d\n", ret);
523df8e96f3SDavid Woodhouse 					while (1) {
524df8e96f3SDavid Woodhouse 						vers_next = tn_prev(this);
525df8e96f3SDavid Woodhouse 						if (check_tn_node(c, this))
526df8e96f3SDavid Woodhouse 							jffs2_mark_node_obsolete(c, this->fn->raw);
527df8e96f3SDavid Woodhouse 						jffs2_free_full_dnode(this->fn);
528df8e96f3SDavid Woodhouse 						jffs2_free_tmp_dnode_info(this);
529df8e96f3SDavid Woodhouse 						this = vers_next;
530df8e96f3SDavid Woodhouse 						if (!this)
531df8e96f3SDavid Woodhouse 							break;
532df8e96f3SDavid Woodhouse 						eat_last(&ver_root, &vers_next->rb);
533df8e96f3SDavid Woodhouse 					}
534df8e96f3SDavid Woodhouse 					return ret;
535df8e96f3SDavid Woodhouse 				}
536df8e96f3SDavid Woodhouse 				jffs2_free_tmp_dnode_info(this);
537df8e96f3SDavid Woodhouse 			}
538df8e96f3SDavid Woodhouse 			this = vers_next;
539df8e96f3SDavid Woodhouse 		}
540df8e96f3SDavid Woodhouse 	}
541df8e96f3SDavid Woodhouse 	return 0;
542f97117d1SArtem B. Bityutskiy }
543f97117d1SArtem B. Bityutskiy 
jffs2_free_tmp_dnode_info_list(struct rb_root * list)544f97117d1SArtem B. Bityutskiy static void jffs2_free_tmp_dnode_info_list(struct rb_root *list)
545f97117d1SArtem B. Bityutskiy {
546e8bbeeb7SCody P Schafer 	struct jffs2_tmp_dnode_info *tn, *next;
547f97117d1SArtem B. Bityutskiy 
548e8bbeeb7SCody P Schafer 	rbtree_postorder_for_each_entry_safe(tn, next, list, rb) {
549f97117d1SArtem B. Bityutskiy 			jffs2_free_full_dnode(tn->fn);
550f97117d1SArtem B. Bityutskiy 			jffs2_free_tmp_dnode_info(tn);
551f97117d1SArtem B. Bityutskiy 	}
552e8bbeeb7SCody P Schafer 
553bcc54e2aSVenkatesh Pallipadi 	*list = RB_ROOT;
554f97117d1SArtem B. Bityutskiy }
5551da177e4SLinus Torvalds 
jffs2_free_full_dirent_list(struct jffs2_full_dirent * fd)556f97117d1SArtem B. Bityutskiy static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd)
557f97117d1SArtem B. Bityutskiy {
558f97117d1SArtem B. Bityutskiy 	struct jffs2_full_dirent *next;
559f97117d1SArtem B. Bityutskiy 
560f97117d1SArtem B. Bityutskiy 	while (fd) {
561f97117d1SArtem B. Bityutskiy 		next = fd->next;
562f97117d1SArtem B. Bityutskiy 		jffs2_free_full_dirent(fd);
563f97117d1SArtem B. Bityutskiy 		fd = next;
564f97117d1SArtem B. Bityutskiy 	}
565f97117d1SArtem B. Bityutskiy }
566f97117d1SArtem B. Bityutskiy 
567f97117d1SArtem B. Bityutskiy /* Returns first valid node after 'ref'. May return 'ref' */
jffs2_first_valid_node(struct jffs2_raw_node_ref * ref)568f97117d1SArtem B. Bityutskiy static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_ref *ref)
569f97117d1SArtem B. Bityutskiy {
570f97117d1SArtem B. Bityutskiy 	while (ref && ref->next_in_ino) {
571f97117d1SArtem B. Bityutskiy 		if (!ref_obsolete(ref))
572f97117d1SArtem B. Bityutskiy 			return ref;
573733802d9SArtem B. Bityutskiy 		dbg_noderef("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref));
574f97117d1SArtem B. Bityutskiy 		ref = ref->next_in_ino;
575f97117d1SArtem B. Bityutskiy 	}
576f97117d1SArtem B. Bityutskiy 	return NULL;
577f97117d1SArtem B. Bityutskiy }
578f97117d1SArtem B. Bityutskiy 
579f97117d1SArtem B. Bityutskiy /*
580f97117d1SArtem B. Bityutskiy  * Helper function for jffs2_get_inode_nodes().
581f97117d1SArtem B. Bityutskiy  * It is called every time an directory entry node is found.
582f97117d1SArtem B. Bityutskiy  *
58314c6381eSDavid Woodhouse  * Returns: 0 on success;
584f97117d1SArtem B. Bityutskiy  * 	    negative error code on failure.
585f97117d1SArtem B. Bityutskiy  */
read_direntry(struct jffs2_sb_info * c,struct jffs2_raw_node_ref * ref,struct jffs2_raw_dirent * rd,size_t read,struct jffs2_readinode_info * rii)5861e0da3cbSArtem B. Bityutskiy static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
587df8e96f3SDavid Woodhouse 				struct jffs2_raw_dirent *rd, size_t read,
588df8e96f3SDavid Woodhouse 				struct jffs2_readinode_info *rii)
589f97117d1SArtem B. Bityutskiy {
590f97117d1SArtem B. Bityutskiy 	struct jffs2_full_dirent *fd;
5911046d880SDavid Woodhouse 	uint32_t crc;
592f97117d1SArtem B. Bityutskiy 
593f97117d1SArtem B. Bityutskiy 	/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
594f97117d1SArtem B. Bityutskiy 	BUG_ON(ref_obsolete(ref));
595f97117d1SArtem B. Bityutskiy 
5961046d880SDavid Woodhouse 	crc = crc32(0, rd, sizeof(*rd) - 8);
5971046d880SDavid Woodhouse 	if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
5981046d880SDavid Woodhouse 		JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n",
5991046d880SDavid Woodhouse 			     ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
600df8e96f3SDavid Woodhouse 		jffs2_mark_node_obsolete(c, ref);
601df8e96f3SDavid Woodhouse 		return 0;
6021046d880SDavid Woodhouse 	}
6031046d880SDavid Woodhouse 
6041046d880SDavid Woodhouse 	/* If we've never checked the CRCs on this node, check them now */
6051046d880SDavid Woodhouse 	if (ref_flags(ref) == REF_UNCHECKED) {
6061046d880SDavid Woodhouse 		struct jffs2_eraseblock *jeb;
6071046d880SDavid Woodhouse 		int len;
6081046d880SDavid Woodhouse 
609f97117d1SArtem B. Bityutskiy 		/* Sanity check */
610f97117d1SArtem B. Bityutskiy 		if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
611e0d60137SArtem B. Bityutskiy 			JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
612f97117d1SArtem B. Bityutskiy 				    ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
613df8e96f3SDavid Woodhouse 			jffs2_mark_node_obsolete(c, ref);
614df8e96f3SDavid Woodhouse 			return 0;
615f97117d1SArtem B. Bityutskiy 		}
616f97117d1SArtem B. Bityutskiy 
6171046d880SDavid Woodhouse 		jeb = &c->blocks[ref->flash_offset / c->sector_size];
6181046d880SDavid Woodhouse 		len = ref_totlen(c, jeb, ref);
6191046d880SDavid Woodhouse 
6201046d880SDavid Woodhouse 		spin_lock(&c->erase_completion_lock);
6211046d880SDavid Woodhouse 		jeb->used_size += len;
6221046d880SDavid Woodhouse 		jeb->unchecked_size -= len;
6231046d880SDavid Woodhouse 		c->used_size += len;
6241046d880SDavid Woodhouse 		c->unchecked_size -= len;
62543dfa07fSDavid Woodhouse 		ref->flash_offset = ref_offset(ref) | dirent_node_state(rd);
6261046d880SDavid Woodhouse 		spin_unlock(&c->erase_completion_lock);
6271046d880SDavid Woodhouse 	}
6281046d880SDavid Woodhouse 
629f97117d1SArtem B. Bityutskiy 	fd = jffs2_alloc_full_dirent(rd->nsize + 1);
630f97117d1SArtem B. Bityutskiy 	if (unlikely(!fd))
631f97117d1SArtem B. Bityutskiy 		return -ENOMEM;
632f97117d1SArtem B. Bityutskiy 
633f97117d1SArtem B. Bityutskiy 	fd->raw = ref;
634f97117d1SArtem B. Bityutskiy 	fd->version = je32_to_cpu(rd->version);
635f97117d1SArtem B. Bityutskiy 	fd->ino = je32_to_cpu(rd->ino);
636f97117d1SArtem B. Bityutskiy 	fd->type = rd->type;
637f97117d1SArtem B. Bityutskiy 
638df8e96f3SDavid Woodhouse 	if (fd->version > rii->highest_version)
639df8e96f3SDavid Woodhouse 		rii->highest_version = fd->version;
640df8e96f3SDavid Woodhouse 
641f97117d1SArtem B. Bityutskiy 	/* Pick out the mctime of the latest dirent */
642df8e96f3SDavid Woodhouse 	if(fd->version > rii->mctime_ver && je32_to_cpu(rd->mctime)) {
643df8e96f3SDavid Woodhouse 		rii->mctime_ver = fd->version;
644df8e96f3SDavid Woodhouse 		rii->latest_mctime = je32_to_cpu(rd->mctime);
645f97117d1SArtem B. Bityutskiy 	}
646f97117d1SArtem B. Bityutskiy 
647f97117d1SArtem B. Bityutskiy 	/*
648f97117d1SArtem B. Bityutskiy 	 * Copy as much of the name as possible from the raw
649f97117d1SArtem B. Bityutskiy 	 * dirent we've already read from the flash.
650f97117d1SArtem B. Bityutskiy 	 */
651f97117d1SArtem B. Bityutskiy 	if (read > sizeof(*rd))
652f97117d1SArtem B. Bityutskiy 		memcpy(&fd->name[0], &rd->name[0],
653f97117d1SArtem B. Bityutskiy 		       min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) ));
654f97117d1SArtem B. Bityutskiy 
655f97117d1SArtem B. Bityutskiy 	/* Do we need to copy any more of the name directly from the flash? */
656f97117d1SArtem B. Bityutskiy 	if (rd->nsize + sizeof(*rd) > read) {
657f97117d1SArtem B. Bityutskiy 		/* FIXME: point() */
658f97117d1SArtem B. Bityutskiy 		int err;
659f97117d1SArtem B. Bityutskiy 		int already = read - sizeof(*rd);
660f97117d1SArtem B. Bityutskiy 
661f97117d1SArtem B. Bityutskiy 		err = jffs2_flash_read(c, (ref_offset(ref)) + read,
662f97117d1SArtem B. Bityutskiy 				rd->nsize - already, &read, &fd->name[already]);
663eb042ec3SWei Fang 		if (unlikely(read != rd->nsize - already) && likely(!err)) {
664eb042ec3SWei Fang 			jffs2_free_full_dirent(fd);
665eb042ec3SWei Fang 			JFFS2_ERROR("short read: wanted %d bytes, got %zd\n",
666eb042ec3SWei Fang 				    rd->nsize - already, read);
667f97117d1SArtem B. Bityutskiy 			return -EIO;
668eb042ec3SWei Fang 		}
669f97117d1SArtem B. Bityutskiy 
670f97117d1SArtem B. Bityutskiy 		if (unlikely(err)) {
671e0d60137SArtem B. Bityutskiy 			JFFS2_ERROR("read remainder of name: error %d\n", err);
672f97117d1SArtem B. Bityutskiy 			jffs2_free_full_dirent(fd);
673f97117d1SArtem B. Bityutskiy 			return -EIO;
674f97117d1SArtem B. Bityutskiy 		}
675*9afc9a8aSZhe Li 
676*9afc9a8aSZhe Li #ifdef CONFIG_JFFS2_SUMMARY
677*9afc9a8aSZhe Li 		/*
678*9afc9a8aSZhe Li 		 * we use CONFIG_JFFS2_SUMMARY because without it, we
679*9afc9a8aSZhe Li 		 * have checked it while mounting
680*9afc9a8aSZhe Li 		 */
681*9afc9a8aSZhe Li 		crc = crc32(0, fd->name, rd->nsize);
682*9afc9a8aSZhe Li 		if (unlikely(crc != je32_to_cpu(rd->name_crc))) {
683*9afc9a8aSZhe Li 			JFFS2_NOTICE("name CRC failed on dirent node at"
684*9afc9a8aSZhe Li 			   "%#08x: read %#08x,calculated %#08x\n",
685*9afc9a8aSZhe Li 			   ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
686*9afc9a8aSZhe Li 			jffs2_mark_node_obsolete(c, ref);
687*9afc9a8aSZhe Li 			jffs2_free_full_dirent(fd);
688*9afc9a8aSZhe Li 			return 0;
689*9afc9a8aSZhe Li 		}
690*9afc9a8aSZhe Li #endif
691f97117d1SArtem B. Bityutskiy 	}
692f97117d1SArtem B. Bityutskiy 
6938387ff25SLinus Torvalds 	fd->nhash = full_name_hash(NULL, fd->name, rd->nsize);
694f97117d1SArtem B. Bityutskiy 	fd->next = NULL;
695f97117d1SArtem B. Bityutskiy 	fd->name[rd->nsize] = '\0';
696f97117d1SArtem B. Bityutskiy 
697f97117d1SArtem B. Bityutskiy 	/*
698f97117d1SArtem B. Bityutskiy 	 * Wheee. We now have a complete jffs2_full_dirent structure, with
699f97117d1SArtem B. Bityutskiy 	 * the name in it and everything. Link it into the list
700f97117d1SArtem B. Bityutskiy 	 */
701df8e96f3SDavid Woodhouse 	jffs2_add_fd_to_list(c, fd, &rii->fds);
702f97117d1SArtem B. Bityutskiy 
703f97117d1SArtem B. Bityutskiy 	return 0;
704f97117d1SArtem B. Bityutskiy }
705f97117d1SArtem B. Bityutskiy 
706f97117d1SArtem B. Bityutskiy /*
707f97117d1SArtem B. Bityutskiy  * Helper function for jffs2_get_inode_nodes().
708f97117d1SArtem B. Bityutskiy  * It is called every time an inode node is found.
709f97117d1SArtem B. Bityutskiy  *
71014c6381eSDavid Woodhouse  * Returns: 0 on success (possibly after marking a bad node obsolete);
711f97117d1SArtem B. Bityutskiy  * 	    negative error code on failure.
712f97117d1SArtem B. Bityutskiy  */
read_dnode(struct jffs2_sb_info * c,struct jffs2_raw_node_ref * ref,struct jffs2_raw_inode * rd,int rdlen,struct jffs2_readinode_info * rii)7131e0da3cbSArtem B. Bityutskiy static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
714df8e96f3SDavid Woodhouse 			     struct jffs2_raw_inode *rd, int rdlen,
715df8e96f3SDavid Woodhouse 			     struct jffs2_readinode_info *rii)
716f97117d1SArtem B. Bityutskiy {
717f97117d1SArtem B. Bityutskiy 	struct jffs2_tmp_dnode_info *tn;
7181e0da3cbSArtem B. Bityutskiy 	uint32_t len, csize;
71914c6381eSDavid Woodhouse 	int ret = 0;
7201046d880SDavid Woodhouse 	uint32_t crc;
721f97117d1SArtem B. Bityutskiy 
722f97117d1SArtem B. Bityutskiy 	/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
723f97117d1SArtem B. Bityutskiy 	BUG_ON(ref_obsolete(ref));
724f97117d1SArtem B. Bityutskiy 
7251046d880SDavid Woodhouse 	crc = crc32(0, rd, sizeof(*rd) - 8);
7261046d880SDavid Woodhouse 	if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
7271046d880SDavid Woodhouse 		JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n",
7281046d880SDavid Woodhouse 			     ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
729df8e96f3SDavid Woodhouse 		jffs2_mark_node_obsolete(c, ref);
730df8e96f3SDavid Woodhouse 		return 0;
7311046d880SDavid Woodhouse 	}
7321046d880SDavid Woodhouse 
7331e0da3cbSArtem B. Bityutskiy 	tn = jffs2_alloc_tmp_dnode_info();
7341e0da3cbSArtem B. Bityutskiy 	if (!tn) {
735fb6a82c9SRandy Dunlap 		JFFS2_ERROR("failed to allocate tn (%zu bytes).\n", sizeof(*tn));
7361e0da3cbSArtem B. Bityutskiy 		return -ENOMEM;
7371e0da3cbSArtem B. Bityutskiy 	}
7381e0da3cbSArtem B. Bityutskiy 
7391e0da3cbSArtem B. Bityutskiy 	tn->partial_crc = 0;
7401e0da3cbSArtem B. Bityutskiy 	csize = je32_to_cpu(rd->csize);
7411e0da3cbSArtem B. Bityutskiy 
742f97117d1SArtem B. Bityutskiy 	/* If we've never checked the CRCs on this node, check them now */
743f97117d1SArtem B. Bityutskiy 	if (ref_flags(ref) == REF_UNCHECKED) {
744f97117d1SArtem B. Bityutskiy 
745f97117d1SArtem B. Bityutskiy 		/* Sanity checks */
746f97117d1SArtem B. Bityutskiy 		if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) ||
747f97117d1SArtem B. Bityutskiy 		    unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) {
748e0d60137SArtem B. Bityutskiy 			JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref));
749737b7661SAndrew Lunn 			jffs2_dbg_dump_node(c, ref_offset(ref));
75014c6381eSDavid Woodhouse 			jffs2_mark_node_obsolete(c, ref);
7511e0da3cbSArtem B. Bityutskiy 			goto free_out;
752f97117d1SArtem B. Bityutskiy 		}
753f97117d1SArtem B. Bityutskiy 
7541e0da3cbSArtem B. Bityutskiy 		if (jffs2_is_writebuffered(c) && csize != 0) {
7551e0da3cbSArtem B. Bityutskiy 			/* At this point we are supposed to check the data CRC
7561e0da3cbSArtem B. Bityutskiy 			 * of our unchecked node. But thus far, we do not
7571e0da3cbSArtem B. Bityutskiy 			 * know whether the node is valid or obsolete. To
7581e0da3cbSArtem B. Bityutskiy 			 * figure this out, we need to walk all the nodes of
7591e0da3cbSArtem B. Bityutskiy 			 * the inode and build the inode fragtree. We don't
7601e0da3cbSArtem B. Bityutskiy 			 * want to spend time checking data of nodes which may
7611e0da3cbSArtem B. Bityutskiy 			 * later be found to be obsolete. So we put off the full
7621e0da3cbSArtem B. Bityutskiy 			 * data CRC checking until we have read all the inode
7631e0da3cbSArtem B. Bityutskiy 			 * nodes and have started building the fragtree.
7641e0da3cbSArtem B. Bityutskiy 			 *
7651e0da3cbSArtem B. Bityutskiy 			 * The fragtree is being built starting with nodes
7661e0da3cbSArtem B. Bityutskiy 			 * having the highest version number, so we'll be able
7671e0da3cbSArtem B. Bityutskiy 			 * to detect whether a node is valid (i.e., it is not
7681e0da3cbSArtem B. Bityutskiy 			 * overlapped by a node with higher version) or not.
7691e0da3cbSArtem B. Bityutskiy 			 * And we'll be able to check only those nodes, which
7701e0da3cbSArtem B. Bityutskiy 			 * are not obsolete.
7711e0da3cbSArtem B. Bityutskiy 			 *
7721e0da3cbSArtem B. Bityutskiy 			 * Of course, this optimization only makes sense in case
773e1b8513dSRobert P. J. Day 			 * of NAND flashes (or other flashes with
7741e0da3cbSArtem B. Bityutskiy 			 * !jffs2_can_mark_obsolete()), since on NOR flashes
7751e0da3cbSArtem B. Bityutskiy 			 * nodes are marked obsolete physically.
7761e0da3cbSArtem B. Bityutskiy 			 *
7771e0da3cbSArtem B. Bityutskiy 			 * Since NAND flashes (or other flashes with
7781e0da3cbSArtem B. Bityutskiy 			 * jffs2_is_writebuffered(c)) are anyway read by
7791e0da3cbSArtem B. Bityutskiy 			 * fractions of c->wbuf_pagesize, and we have just read
7801e0da3cbSArtem B. Bityutskiy 			 * the node header, it is likely that the starting part
7811e0da3cbSArtem B. Bityutskiy 			 * of the node data is also read when we read the
7821e0da3cbSArtem B. Bityutskiy 			 * header. So we don't mind to check the CRC of the
7831e0da3cbSArtem B. Bityutskiy 			 * starting part of the data of the node now, and check
7841e0da3cbSArtem B. Bityutskiy 			 * the second part later (in jffs2_check_node_data()).
7851e0da3cbSArtem B. Bityutskiy 			 * Of course, we will not need to re-read and re-check
7861e0da3cbSArtem B. Bityutskiy 			 * the NAND page which we have just read. This is why we
7871e0da3cbSArtem B. Bityutskiy 			 * read the whole NAND page at jffs2_get_inode_nodes(),
7881e0da3cbSArtem B. Bityutskiy 			 * while we needed only the node header.
7891e0da3cbSArtem B. Bityutskiy 			 */
7901e0da3cbSArtem B. Bityutskiy 			unsigned char *buf;
791f97117d1SArtem B. Bityutskiy 
7921e0da3cbSArtem B. Bityutskiy 			/* 'buf' will point to the start of data */
7931e0da3cbSArtem B. Bityutskiy 			buf = (unsigned char *)rd + sizeof(*rd);
7941e0da3cbSArtem B. Bityutskiy 			/* len will be the read data length */
7951e0da3cbSArtem B. Bityutskiy 			len = min_t(uint32_t, rdlen - sizeof(*rd), csize);
796280562b2SArtem B. Bityutskiy 			tn->partial_crc = crc32(0, buf, len);
797f97117d1SArtem B. Bityutskiy 
798733802d9SArtem B. Bityutskiy 			dbg_readinode("Calculates CRC (%#08x) for %d bytes, csize %d\n", tn->partial_crc, len, csize);
799f97117d1SArtem B. Bityutskiy 
8001e0da3cbSArtem B. Bityutskiy 			/* If we actually calculated the whole data CRC
8011e0da3cbSArtem B. Bityutskiy 			 * and it is wrong, drop the node. */
8023c091337SArtem B. Bityutskiy 			if (len >= csize && unlikely(tn->partial_crc != je32_to_cpu(rd->data_crc))) {
80339243508SArtem B. Bityutskiy 				JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n",
80439243508SArtem B. Bityutskiy 					ref_offset(ref), tn->partial_crc, je32_to_cpu(rd->data_crc));
80514c6381eSDavid Woodhouse 				jffs2_mark_node_obsolete(c, ref);
8061e0da3cbSArtem B. Bityutskiy 				goto free_out;
80739243508SArtem B. Bityutskiy 			}
808f97117d1SArtem B. Bityutskiy 
8091e0da3cbSArtem B. Bityutskiy 		} else if (csize == 0) {
8101e0da3cbSArtem B. Bityutskiy 			/*
8111e0da3cbSArtem B. Bityutskiy 			 * We checked the header CRC. If the node has no data, adjust
8121e0da3cbSArtem B. Bityutskiy 			 * the space accounting now. For other nodes this will be done
8131e0da3cbSArtem B. Bityutskiy 			 * later either when the node is marked obsolete or when its
8141e0da3cbSArtem B. Bityutskiy 			 * data is checked.
8151e0da3cbSArtem B. Bityutskiy 			 */
8161e0da3cbSArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb;
8171e0da3cbSArtem B. Bityutskiy 
818733802d9SArtem B. Bityutskiy 			dbg_readinode("the node has no data.\n");
819f97117d1SArtem B. Bityutskiy 			jeb = &c->blocks[ref->flash_offset / c->sector_size];
820f97117d1SArtem B. Bityutskiy 			len = ref_totlen(c, jeb, ref);
821f97117d1SArtem B. Bityutskiy 
822f97117d1SArtem B. Bityutskiy 			spin_lock(&c->erase_completion_lock);
823f97117d1SArtem B. Bityutskiy 			jeb->used_size += len;
824f97117d1SArtem B. Bityutskiy 			jeb->unchecked_size -= len;
825f97117d1SArtem B. Bityutskiy 			c->used_size += len;
826f97117d1SArtem B. Bityutskiy 			c->unchecked_size -= len;
827f97117d1SArtem B. Bityutskiy 			ref->flash_offset = ref_offset(ref) | REF_NORMAL;
828f97117d1SArtem B. Bityutskiy 			spin_unlock(&c->erase_completion_lock);
829f97117d1SArtem B. Bityutskiy 		}
830f97117d1SArtem B. Bityutskiy 	}
831f97117d1SArtem B. Bityutskiy 
832f97117d1SArtem B. Bityutskiy 	tn->fn = jffs2_alloc_full_dnode();
833f97117d1SArtem B. Bityutskiy 	if (!tn->fn) {
834e0d60137SArtem B. Bityutskiy 		JFFS2_ERROR("alloc fn failed\n");
8351e0da3cbSArtem B. Bityutskiy 		ret = -ENOMEM;
8361e0da3cbSArtem B. Bityutskiy 		goto free_out;
837f97117d1SArtem B. Bityutskiy 	}
838f97117d1SArtem B. Bityutskiy 
839f97117d1SArtem B. Bityutskiy 	tn->version = je32_to_cpu(rd->version);
840f97117d1SArtem B. Bityutskiy 	tn->fn->ofs = je32_to_cpu(rd->offset);
8411e0da3cbSArtem B. Bityutskiy 	tn->data_crc = je32_to_cpu(rd->data_crc);
8421e0da3cbSArtem B. Bityutskiy 	tn->csize = csize;
843f97117d1SArtem B. Bityutskiy 	tn->fn->raw = ref;
844df8e96f3SDavid Woodhouse 	tn->overlapped = 0;
845df8e96f3SDavid Woodhouse 
846df8e96f3SDavid Woodhouse 	if (tn->version > rii->highest_version)
847df8e96f3SDavid Woodhouse 		rii->highest_version = tn->version;
848f97117d1SArtem B. Bityutskiy 
849f97117d1SArtem B. Bityutskiy 	/* There was a bug where we wrote hole nodes out with
850f97117d1SArtem B. Bityutskiy 	   csize/dsize swapped. Deal with it */
8511e0da3cbSArtem B. Bityutskiy 	if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && csize)
8521e0da3cbSArtem B. Bityutskiy 		tn->fn->size = csize;
853f97117d1SArtem B. Bityutskiy 	else // normal case...
854f97117d1SArtem B. Bityutskiy 		tn->fn->size = je32_to_cpu(rd->dsize);
855f97117d1SArtem B. Bityutskiy 
8562c61cb25SDavid Woodhouse 	dbg_readinode2("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n",
8572c61cb25SDavid Woodhouse 		       ref_offset(ref), je32_to_cpu(rd->version),
8582c61cb25SDavid Woodhouse 		       je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize);
859f97117d1SArtem B. Bityutskiy 
860df8e96f3SDavid Woodhouse 	ret = jffs2_add_tn_to_tree(c, rii, tn);
861f97117d1SArtem B. Bityutskiy 
862df8e96f3SDavid Woodhouse 	if (ret) {
863df8e96f3SDavid Woodhouse 		jffs2_free_full_dnode(tn->fn);
8641e0da3cbSArtem B. Bityutskiy 	free_out:
8651e0da3cbSArtem B. Bityutskiy 		jffs2_free_tmp_dnode_info(tn);
8661e0da3cbSArtem B. Bityutskiy 		return ret;
867f97117d1SArtem B. Bityutskiy 	}
8682c61cb25SDavid Woodhouse #ifdef JFFS2_DBG_READINODE2_MESSAGES
8692c61cb25SDavid Woodhouse 	dbg_readinode2("After adding ver %d:\n", je32_to_cpu(rd->version));
870df8e96f3SDavid Woodhouse 	tn = tn_first(&rii->tn_root);
871df8e96f3SDavid Woodhouse 	while (tn) {
8722c61cb25SDavid Woodhouse 		dbg_readinode2("%p: v %d r 0x%x-0x%x ov %d\n",
873df8e96f3SDavid Woodhouse 			       tn, tn->version, tn->fn->ofs,
874df8e96f3SDavid Woodhouse 			       tn->fn->ofs+tn->fn->size, tn->overlapped);
875df8e96f3SDavid Woodhouse 		tn = tn_next(tn);
876df8e96f3SDavid Woodhouse 	}
877df8e96f3SDavid Woodhouse #endif
878df8e96f3SDavid Woodhouse 	return 0;
879df8e96f3SDavid Woodhouse }
880f97117d1SArtem B. Bityutskiy 
881f97117d1SArtem B. Bityutskiy /*
882f97117d1SArtem B. Bityutskiy  * Helper function for jffs2_get_inode_nodes().
883f97117d1SArtem B. Bityutskiy  * It is called every time an unknown node is found.
884f97117d1SArtem B. Bityutskiy  *
8853877f0b6SDavid Woodhouse  * Returns: 0 on success;
886f97117d1SArtem B. Bityutskiy  * 	    negative error code on failure.
887f97117d1SArtem B. Bityutskiy  */
read_unknown(struct jffs2_sb_info * c,struct jffs2_raw_node_ref * ref,struct jffs2_unknown_node * un)8881e0da3cbSArtem B. Bityutskiy static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, struct jffs2_unknown_node *un)
889f97117d1SArtem B. Bityutskiy {
890f97117d1SArtem B. Bityutskiy 	/* We don't mark unknown nodes as REF_UNCHECKED */
891c7258a44SDavid Woodhouse 	if (ref_flags(ref) == REF_UNCHECKED) {
892c7258a44SDavid Woodhouse 		JFFS2_ERROR("REF_UNCHECKED but unknown node at %#08x\n",
893c7258a44SDavid Woodhouse 			    ref_offset(ref));
894c7258a44SDavid Woodhouse 		JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n",
895c7258a44SDavid Woodhouse 			    je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
896c7258a44SDavid Woodhouse 			    je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc));
897df8e96f3SDavid Woodhouse 		jffs2_mark_node_obsolete(c, ref);
898df8e96f3SDavid Woodhouse 		return 0;
899c7258a44SDavid Woodhouse 	}
900f97117d1SArtem B. Bityutskiy 
901f97117d1SArtem B. Bityutskiy 	un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
902f97117d1SArtem B. Bityutskiy 
903f97117d1SArtem B. Bityutskiy 	switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
904f97117d1SArtem B. Bityutskiy 
905f97117d1SArtem B. Bityutskiy 	case JFFS2_FEATURE_INCOMPAT:
906e0d60137SArtem B. Bityutskiy 		JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n",
907f97117d1SArtem B. Bityutskiy 			    je16_to_cpu(un->nodetype), ref_offset(ref));
908f97117d1SArtem B. Bityutskiy 		/* EEP */
909f97117d1SArtem B. Bityutskiy 		BUG();
910f97117d1SArtem B. Bityutskiy 		break;
911f97117d1SArtem B. Bityutskiy 
912f97117d1SArtem B. Bityutskiy 	case JFFS2_FEATURE_ROCOMPAT:
913e0d60137SArtem B. Bityutskiy 		JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n",
914f97117d1SArtem B. Bityutskiy 			    je16_to_cpu(un->nodetype), ref_offset(ref));
915f97117d1SArtem B. Bityutskiy 		BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
916f97117d1SArtem B. Bityutskiy 		break;
917f97117d1SArtem B. Bityutskiy 
918f97117d1SArtem B. Bityutskiy 	case JFFS2_FEATURE_RWCOMPAT_COPY:
919e0d60137SArtem B. Bityutskiy 		JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
920f97117d1SArtem B. Bityutskiy 			     je16_to_cpu(un->nodetype), ref_offset(ref));
921f97117d1SArtem B. Bityutskiy 		break;
922f97117d1SArtem B. Bityutskiy 
923f97117d1SArtem B. Bityutskiy 	case JFFS2_FEATURE_RWCOMPAT_DELETE:
924e0d60137SArtem B. Bityutskiy 		JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
925f97117d1SArtem B. Bityutskiy 			     je16_to_cpu(un->nodetype), ref_offset(ref));
926df8e96f3SDavid Woodhouse 		jffs2_mark_node_obsolete(c, ref);
927df8e96f3SDavid Woodhouse 		return 0;
928f97117d1SArtem B. Bityutskiy 	}
929f97117d1SArtem B. Bityutskiy 
930f97117d1SArtem B. Bityutskiy 	return 0;
931f97117d1SArtem B. Bityutskiy }
932f97117d1SArtem B. Bityutskiy 
9331e0da3cbSArtem B. Bityutskiy /*
9341e0da3cbSArtem B. Bityutskiy  * Helper function for jffs2_get_inode_nodes().
9351e0da3cbSArtem B. Bityutskiy  * The function detects whether more data should be read and reads it if yes.
9361e0da3cbSArtem B. Bityutskiy  *
937af901ca1SAndré Goddard Rosa  * Returns: 0 on success;
9381e0da3cbSArtem B. Bityutskiy  * 	    negative error code on failure.
9391e0da3cbSArtem B. Bityutskiy  */
read_more(struct jffs2_sb_info * c,struct jffs2_raw_node_ref * ref,int needed_len,int * rdlen,unsigned char * buf)9401e0da3cbSArtem B. Bityutskiy static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
94110731f83SArtem Bityutskiy 		     int needed_len, int *rdlen, unsigned char *buf)
9421e0da3cbSArtem B. Bityutskiy {
94310731f83SArtem Bityutskiy 	int err, to_read = needed_len - *rdlen;
9441e0da3cbSArtem B. Bityutskiy 	size_t retlen;
9451e0da3cbSArtem B. Bityutskiy 	uint32_t offs;
9461e0da3cbSArtem B. Bityutskiy 
9471e0da3cbSArtem B. Bityutskiy 	if (jffs2_is_writebuffered(c)) {
94810731f83SArtem Bityutskiy 		int rem = to_read % c->wbuf_pagesize;
9491e0da3cbSArtem B. Bityutskiy 
95010731f83SArtem Bityutskiy 		if (rem)
95110731f83SArtem Bityutskiy 			to_read += c->wbuf_pagesize - rem;
95210731f83SArtem Bityutskiy 	}
9531e0da3cbSArtem B. Bityutskiy 
9541e0da3cbSArtem B. Bityutskiy 	/* We need to read more data */
9551e0da3cbSArtem B. Bityutskiy 	offs = ref_offset(ref) + *rdlen;
9561e0da3cbSArtem B. Bityutskiy 
95710731f83SArtem Bityutskiy 	dbg_readinode("read more %d bytes\n", to_read);
9581e0da3cbSArtem B. Bityutskiy 
95910731f83SArtem Bityutskiy 	err = jffs2_flash_read(c, offs, to_read, &retlen, buf + *rdlen);
9601e0da3cbSArtem B. Bityutskiy 	if (err) {
9611e0da3cbSArtem B. Bityutskiy 		JFFS2_ERROR("can not read %d bytes from 0x%08x, "
96210731f83SArtem Bityutskiy 			"error code: %d.\n", to_read, offs, err);
9631e0da3cbSArtem B. Bityutskiy 		return err;
9641e0da3cbSArtem B. Bityutskiy 	}
9651e0da3cbSArtem B. Bityutskiy 
96610731f83SArtem Bityutskiy 	if (retlen < to_read) {
967fb6a82c9SRandy Dunlap 		JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n",
96810731f83SArtem Bityutskiy 				offs, retlen, to_read);
9691e0da3cbSArtem B. Bityutskiy 		return -EIO;
9701e0da3cbSArtem B. Bityutskiy 	}
9711e0da3cbSArtem B. Bityutskiy 
97210731f83SArtem Bityutskiy 	*rdlen += to_read;
9731e0da3cbSArtem B. Bityutskiy 	return 0;
9741e0da3cbSArtem B. Bityutskiy }
9751e0da3cbSArtem B. Bityutskiy 
976f97117d1SArtem B. Bityutskiy /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated
977df8e96f3SDavid Woodhouse    with this ino. Perform a preliminary ordering on data nodes, throwing away
978df8e96f3SDavid Woodhouse    those which are completely obsoleted by newer ones. The naïve approach we
979df8e96f3SDavid Woodhouse    use to take of just returning them _all_ in version order will cause us to
980df8e96f3SDavid Woodhouse    run out of memory in certain degenerate cases. */
jffs2_get_inode_nodes(struct jffs2_sb_info * c,struct jffs2_inode_info * f,struct jffs2_readinode_info * rii)981f97117d1SArtem B. Bityutskiy static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
982df8e96f3SDavid Woodhouse 				 struct jffs2_readinode_info *rii)
983f97117d1SArtem B. Bityutskiy {
984f97117d1SArtem B. Bityutskiy 	struct jffs2_raw_node_ref *ref, *valid_ref;
9851e0da3cbSArtem B. Bityutskiy 	unsigned char *buf = NULL;
9861e0da3cbSArtem B. Bityutskiy 	union jffs2_node_union *node;
987f97117d1SArtem B. Bityutskiy 	size_t retlen;
9881e0da3cbSArtem B. Bityutskiy 	int len, err;
989f97117d1SArtem B. Bityutskiy 
990df8e96f3SDavid Woodhouse 	rii->mctime_ver = 0;
991f97117d1SArtem B. Bityutskiy 
992733802d9SArtem B. Bityutskiy 	dbg_readinode("ino #%u\n", f->inocache->ino);
993f97117d1SArtem B. Bityutskiy 
9941e0da3cbSArtem B. Bityutskiy 	/* FIXME: in case of NOR and available ->point() this
9951e0da3cbSArtem B. Bityutskiy 	 * needs to be fixed. */
99610731f83SArtem Bityutskiy 	len = sizeof(union jffs2_node_union) + c->wbuf_pagesize;
9971e0da3cbSArtem B. Bityutskiy 	buf = kmalloc(len, GFP_KERNEL);
9981e0da3cbSArtem B. Bityutskiy 	if (!buf)
9991e0da3cbSArtem B. Bityutskiy 		return -ENOMEM;
10001e0da3cbSArtem B. Bityutskiy 
1001f97117d1SArtem B. Bityutskiy 	spin_lock(&c->erase_completion_lock);
1002f97117d1SArtem B. Bityutskiy 	valid_ref = jffs2_first_valid_node(f->inocache->nodes);
10031e0da3cbSArtem B. Bityutskiy 	if (!valid_ref && f->inocache->ino != 1)
10041e0da3cbSArtem B. Bityutskiy 		JFFS2_WARNING("Eep. No valid nodes for ino #%u.\n", f->inocache->ino);
1005f97117d1SArtem B. Bityutskiy 	while (valid_ref) {
1006f97117d1SArtem B. Bityutskiy 		/* We can hold a pointer to a non-obsolete node without the spinlock,
1007f97117d1SArtem B. Bityutskiy 		   but _obsolete_ nodes may disappear at any time, if the block
1008f97117d1SArtem B. Bityutskiy 		   they're in gets erased. So if we mark 'ref' obsolete while we're
1009f97117d1SArtem B. Bityutskiy 		   not holding the lock, it can go away immediately. For that reason,
1010f97117d1SArtem B. Bityutskiy 		   we find the next valid node first, before processing 'ref'.
1011f97117d1SArtem B. Bityutskiy 		*/
1012f97117d1SArtem B. Bityutskiy 		ref = valid_ref;
1013f97117d1SArtem B. Bityutskiy 		valid_ref = jffs2_first_valid_node(ref->next_in_ino);
1014f97117d1SArtem B. Bityutskiy 		spin_unlock(&c->erase_completion_lock);
1015f97117d1SArtem B. Bityutskiy 
1016f97117d1SArtem B. Bityutskiy 		cond_resched();
1017f97117d1SArtem B. Bityutskiy 
10181e0da3cbSArtem B. Bityutskiy 		/*
10191e0da3cbSArtem B. Bityutskiy 		 * At this point we don't know the type of the node we're going
10201e0da3cbSArtem B. Bityutskiy 		 * to read, so we do not know the size of its header. In order
102110731f83SArtem Bityutskiy 		 * to minimize the amount of flash IO we assume the header is
102210731f83SArtem Bityutskiy 		 * of size = JFFS2_MIN_NODE_HEADER.
10231e0da3cbSArtem B. Bityutskiy 		 */
10241e0da3cbSArtem B. Bityutskiy 		len = JFFS2_MIN_NODE_HEADER;
102510731f83SArtem Bityutskiy 		if (jffs2_is_writebuffered(c)) {
102610731f83SArtem Bityutskiy 			int end, rem;
102710731f83SArtem Bityutskiy 
102810731f83SArtem Bityutskiy 			/*
102910731f83SArtem Bityutskiy 			 * We are about to read JFFS2_MIN_NODE_HEADER bytes,
103010731f83SArtem Bityutskiy 			 * but this flash has some minimal I/O unit. It is
103110731f83SArtem Bityutskiy 			 * possible that we'll need to read more soon, so read
103210731f83SArtem Bityutskiy 			 * up to the next min. I/O unit, in order not to
103310731f83SArtem Bityutskiy 			 * re-read the same min. I/O unit twice.
103410731f83SArtem Bityutskiy 			 */
103510731f83SArtem Bityutskiy 			end = ref_offset(ref) + len;
103610731f83SArtem Bityutskiy 			rem = end % c->wbuf_pagesize;
103710731f83SArtem Bityutskiy 			if (rem)
103810731f83SArtem Bityutskiy 				end += c->wbuf_pagesize - rem;
103910731f83SArtem Bityutskiy 			len = end - ref_offset(ref);
10401e0da3cbSArtem B. Bityutskiy 		}
10411e0da3cbSArtem B. Bityutskiy 
1042733802d9SArtem B. Bityutskiy 		dbg_readinode("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref));
10431e0da3cbSArtem B. Bityutskiy 
1044f97117d1SArtem B. Bityutskiy 		/* FIXME: point() */
104510731f83SArtem Bityutskiy 		err = jffs2_flash_read(c, ref_offset(ref), len, &retlen, buf);
1046f97117d1SArtem B. Bityutskiy 		if (err) {
1047df2e301fSJean Delvare 			JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ref_offset(ref), err);
1048f97117d1SArtem B. Bityutskiy 			goto free_out;
1049f97117d1SArtem B. Bityutskiy 		}
1050f97117d1SArtem B. Bityutskiy 
10511e0da3cbSArtem B. Bityutskiy 		if (retlen < len) {
1052fb6a82c9SRandy Dunlap 			JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", ref_offset(ref), retlen, len);
1053f97117d1SArtem B. Bityutskiy 			err = -EIO;
1054f97117d1SArtem B. Bityutskiy 			goto free_out;
1055f97117d1SArtem B. Bityutskiy 		}
1056f97117d1SArtem B. Bityutskiy 
105710731f83SArtem Bityutskiy 		node = (union jffs2_node_union *)buf;
10581e0da3cbSArtem B. Bityutskiy 
10593877f0b6SDavid Woodhouse 		/* No need to mask in the valid bit; it shouldn't be invalid */
10603877f0b6SDavid Woodhouse 		if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) {
10613877f0b6SDavid Woodhouse 			JFFS2_NOTICE("Node header CRC failed at %#08x. {%04x,%04x,%08x,%08x}\n",
10623877f0b6SDavid Woodhouse 				     ref_offset(ref), je16_to_cpu(node->u.magic),
10633877f0b6SDavid Woodhouse 				     je16_to_cpu(node->u.nodetype),
10643877f0b6SDavid Woodhouse 				     je32_to_cpu(node->u.totlen),
10653877f0b6SDavid Woodhouse 				     je32_to_cpu(node->u.hdr_crc));
10663877f0b6SDavid Woodhouse 			jffs2_dbg_dump_node(c, ref_offset(ref));
10673877f0b6SDavid Woodhouse 			jffs2_mark_node_obsolete(c, ref);
10683877f0b6SDavid Woodhouse 			goto cont;
10693877f0b6SDavid Woodhouse 		}
10700dec4c8bSJoakim Tjernlund 		if (je16_to_cpu(node->u.magic) != JFFS2_MAGIC_BITMASK) {
10710dec4c8bSJoakim Tjernlund 			/* Not a JFFS2 node, whinge and move on */
10720dec4c8bSJoakim Tjernlund 			JFFS2_NOTICE("Wrong magic bitmask 0x%04x in node header at %#08x.\n",
10730dec4c8bSJoakim Tjernlund 				     je16_to_cpu(node->u.magic), ref_offset(ref));
1074c7258a44SDavid Woodhouse 			jffs2_mark_node_obsolete(c, ref);
1075c7258a44SDavid Woodhouse 			goto cont;
1076c7258a44SDavid Woodhouse 		}
10773877f0b6SDavid Woodhouse 
10781e0da3cbSArtem B. Bityutskiy 		switch (je16_to_cpu(node->u.nodetype)) {
10791e0da3cbSArtem B. Bityutskiy 
10801e0da3cbSArtem B. Bityutskiy 		case JFFS2_NODETYPE_DIRENT:
10811e0da3cbSArtem B. Bityutskiy 
1082ea55d307SArtem Bityutskiy 			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent) &&
1083ea55d307SArtem Bityutskiy 			    len < sizeof(struct jffs2_raw_dirent)) {
108410731f83SArtem Bityutskiy 				err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf);
10851e0da3cbSArtem B. Bityutskiy 				if (unlikely(err))
10861e0da3cbSArtem B. Bityutskiy 					goto free_out;
10871e0da3cbSArtem B. Bityutskiy 			}
10881e0da3cbSArtem B. Bityutskiy 
1089df8e96f3SDavid Woodhouse 			err = read_direntry(c, ref, &node->d, retlen, rii);
1090df8e96f3SDavid Woodhouse 			if (unlikely(err))
1091f97117d1SArtem B. Bityutskiy 				goto free_out;
1092f97117d1SArtem B. Bityutskiy 
1093f97117d1SArtem B. Bityutskiy 			break;
1094f97117d1SArtem B. Bityutskiy 
1095f97117d1SArtem B. Bityutskiy 		case JFFS2_NODETYPE_INODE:
1096f97117d1SArtem B. Bityutskiy 
1097ea55d307SArtem Bityutskiy 			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode) &&
1098ea55d307SArtem Bityutskiy 			    len < sizeof(struct jffs2_raw_inode)) {
109910731f83SArtem Bityutskiy 				err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf);
11001e0da3cbSArtem B. Bityutskiy 				if (unlikely(err))
1101f97117d1SArtem B. Bityutskiy 					goto free_out;
1102f97117d1SArtem B. Bityutskiy 			}
1103f97117d1SArtem B. Bityutskiy 
1104df8e96f3SDavid Woodhouse 			err = read_dnode(c, ref, &node->i, len, rii);
1105df8e96f3SDavid Woodhouse 			if (unlikely(err))
1106f97117d1SArtem B. Bityutskiy 				goto free_out;
1107f97117d1SArtem B. Bityutskiy 
11081da177e4SLinus Torvalds 			break;
11091da177e4SLinus Torvalds 
11101da177e4SLinus Torvalds 		default:
1111ea55d307SArtem Bityutskiy 			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node) &&
1112ea55d307SArtem Bityutskiy 			    len < sizeof(struct jffs2_unknown_node)) {
111310731f83SArtem Bityutskiy 				err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf);
11141e0da3cbSArtem B. Bityutskiy 				if (unlikely(err))
11151e0da3cbSArtem B. Bityutskiy 					goto free_out;
11161da177e4SLinus Torvalds 			}
11171da177e4SLinus Torvalds 
11181e0da3cbSArtem B. Bityutskiy 			err = read_unknown(c, ref, &node->u);
111914c6381eSDavid Woodhouse 			if (unlikely(err))
1120f97117d1SArtem B. Bityutskiy 				goto free_out;
1121f97117d1SArtem B. Bityutskiy 
11221da177e4SLinus Torvalds 		}
11233877f0b6SDavid Woodhouse 	cont:
1124f97117d1SArtem B. Bityutskiy 		spin_lock(&c->erase_completion_lock);
11251da177e4SLinus Torvalds 	}
11261e0da3cbSArtem B. Bityutskiy 
1127f97117d1SArtem B. Bityutskiy 	spin_unlock(&c->erase_completion_lock);
11281e0da3cbSArtem B. Bityutskiy 	kfree(buf);
1129f97117d1SArtem B. Bityutskiy 
1130df8e96f3SDavid Woodhouse 	f->highest_version = rii->highest_version;
1131df8e96f3SDavid Woodhouse 
1132733802d9SArtem B. Bityutskiy 	dbg_readinode("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n",
1133df8e96f3SDavid Woodhouse 		      f->inocache->ino, rii->highest_version, rii->latest_mctime,
1134df8e96f3SDavid Woodhouse 		      rii->mctime_ver);
1135f97117d1SArtem B. Bityutskiy 	return 0;
1136f97117d1SArtem B. Bityutskiy 
1137f97117d1SArtem B. Bityutskiy  free_out:
1138df8e96f3SDavid Woodhouse 	jffs2_free_tmp_dnode_info_list(&rii->tn_root);
1139df8e96f3SDavid Woodhouse 	jffs2_free_full_dirent_list(rii->fds);
1140df8e96f3SDavid Woodhouse 	rii->fds = NULL;
11411e0da3cbSArtem B. Bityutskiy 	kfree(buf);
1142f97117d1SArtem B. Bityutskiy 	return err;
11431da177e4SLinus Torvalds }
11441da177e4SLinus Torvalds 
jffs2_do_read_inode_internal(struct jffs2_sb_info * c,struct jffs2_inode_info * f,struct jffs2_raw_inode * latest_node)11451da177e4SLinus Torvalds static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
11461da177e4SLinus Torvalds 					struct jffs2_inode_info *f,
11471da177e4SLinus Torvalds 					struct jffs2_raw_inode *latest_node)
11481da177e4SLinus Torvalds {
1149df8e96f3SDavid Woodhouse 	struct jffs2_readinode_info rii;
115061c4b237SDavid Woodhouse 	uint32_t crc, new_size;
11511da177e4SLinus Torvalds 	size_t retlen;
11521da177e4SLinus Torvalds 	int ret;
11531da177e4SLinus Torvalds 
115427c72b04SDavid Woodhouse 	dbg_readinode("ino #%u pino/nlink is %d\n", f->inocache->ino,
115527c72b04SDavid Woodhouse 		      f->inocache->pino_nlink);
11561da177e4SLinus Torvalds 
1157df8e96f3SDavid Woodhouse 	memset(&rii, 0, sizeof(rii));
1158df8e96f3SDavid Woodhouse 
11591da177e4SLinus Torvalds 	/* Grab all nodes relevant to this ino */
1160df8e96f3SDavid Woodhouse 	ret = jffs2_get_inode_nodes(c, f, &rii);
11611da177e4SLinus Torvalds 
11621da177e4SLinus Torvalds 	if (ret) {
1163e0d60137SArtem B. Bityutskiy 		JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret);
11641da177e4SLinus Torvalds 		if (f->inocache->state == INO_STATE_READING)
11651da177e4SLinus Torvalds 			jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
11661da177e4SLinus Torvalds 		return ret;
11671da177e4SLinus Torvalds 	}
11681da177e4SLinus Torvalds 
1169df8e96f3SDavid Woodhouse 	ret = jffs2_build_inode_fragtree(c, f, &rii);
11701e0da3cbSArtem B. Bityutskiy 	if (ret) {
1171df8e96f3SDavid Woodhouse 		JFFS2_ERROR("Failed to build final fragtree for inode #%u: error %d\n",
1172df8e96f3SDavid Woodhouse 			    f->inocache->ino, ret);
1173df8e96f3SDavid Woodhouse 		if (f->inocache->state == INO_STATE_READING)
1174df8e96f3SDavid Woodhouse 			jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
1175df8e96f3SDavid Woodhouse 		jffs2_free_tmp_dnode_info_list(&rii.tn_root);
1176df8e96f3SDavid Woodhouse 		/* FIXME: We could at least crc-check them all */
1177df8e96f3SDavid Woodhouse 		if (rii.mdata_tn) {
1178df8e96f3SDavid Woodhouse 			jffs2_free_full_dnode(rii.mdata_tn->fn);
1179df8e96f3SDavid Woodhouse 			jffs2_free_tmp_dnode_info(rii.mdata_tn);
1180df8e96f3SDavid Woodhouse 			rii.mdata_tn = NULL;
11811e0da3cbSArtem B. Bityutskiy 		}
1182df8e96f3SDavid Woodhouse 		return ret;
11831da177e4SLinus Torvalds 	}
1184df8e96f3SDavid Woodhouse 
1185df8e96f3SDavid Woodhouse 	if (rii.mdata_tn) {
1186df8e96f3SDavid Woodhouse 		if (rii.mdata_tn->fn->raw == rii.latest_ref) {
1187df8e96f3SDavid Woodhouse 			f->metadata = rii.mdata_tn->fn;
1188df8e96f3SDavid Woodhouse 			jffs2_free_tmp_dnode_info(rii.mdata_tn);
1189df8e96f3SDavid Woodhouse 		} else {
1190df8e96f3SDavid Woodhouse 			jffs2_kill_tn(c, rii.mdata_tn);
1191df8e96f3SDavid Woodhouse 		}
1192df8e96f3SDavid Woodhouse 		rii.mdata_tn = NULL;
1193df8e96f3SDavid Woodhouse 	}
1194df8e96f3SDavid Woodhouse 
1195df8e96f3SDavid Woodhouse 	f->dents = rii.fds;
1196df8e96f3SDavid Woodhouse 
1197e0c8e42fSArtem B. Bityutskiy 	jffs2_dbg_fragtree_paranoia_check_nolock(f);
11981da177e4SLinus Torvalds 
1199df8e96f3SDavid Woodhouse 	if (unlikely(!rii.latest_ref)) {
12001da177e4SLinus Torvalds 		/* No data nodes for this inode. */
12011da177e4SLinus Torvalds 		if (f->inocache->ino != 1) {
1202e0d60137SArtem B. Bityutskiy 			JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino);
1203df8e96f3SDavid Woodhouse 			if (!rii.fds) {
12041da177e4SLinus Torvalds 				if (f->inocache->state == INO_STATE_READING)
12051da177e4SLinus Torvalds 					jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
12061da177e4SLinus Torvalds 				return -EIO;
12071da177e4SLinus Torvalds 			}
1208e0d60137SArtem B. Bityutskiy 			JFFS2_NOTICE("but it has children so we fake some modes for it\n");
12091da177e4SLinus Torvalds 		}
12101da177e4SLinus Torvalds 		latest_node->mode = cpu_to_jemode(S_IFDIR|S_IRUGO|S_IWUSR|S_IXUGO);
12111da177e4SLinus Torvalds 		latest_node->version = cpu_to_je32(0);
12121da177e4SLinus Torvalds 		latest_node->atime = latest_node->ctime = latest_node->mtime = cpu_to_je32(0);
12131da177e4SLinus Torvalds 		latest_node->isize = cpu_to_je32(0);
12141da177e4SLinus Torvalds 		latest_node->gid = cpu_to_je16(0);
12151da177e4SLinus Torvalds 		latest_node->uid = cpu_to_je16(0);
12161da177e4SLinus Torvalds 		if (f->inocache->state == INO_STATE_READING)
12171da177e4SLinus Torvalds 			jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
12181da177e4SLinus Torvalds 		return 0;
12191da177e4SLinus Torvalds 	}
12201da177e4SLinus Torvalds 
1221df8e96f3SDavid Woodhouse 	ret = jffs2_flash_read(c, ref_offset(rii.latest_ref), sizeof(*latest_node), &retlen, (void *)latest_node);
12221da177e4SLinus Torvalds 	if (ret || retlen != sizeof(*latest_node)) {
1223e0d60137SArtem B. Bityutskiy 		JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n",
12241da177e4SLinus Torvalds 			ret, retlen, sizeof(*latest_node));
12251da177e4SLinus Torvalds 		/* FIXME: If this fails, there seems to be a memory leak. Find it. */
12261da177e4SLinus Torvalds 		return ret ? ret : -EIO;
12271da177e4SLinus Torvalds 	}
12281da177e4SLinus Torvalds 
12291da177e4SLinus Torvalds 	crc = crc32(0, latest_node, sizeof(*latest_node)-8);
12301da177e4SLinus Torvalds 	if (crc != je32_to_cpu(latest_node->node_crc)) {
1231e0d60137SArtem B. Bityutskiy 		JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n",
1232df8e96f3SDavid Woodhouse 			f->inocache->ino, ref_offset(rii.latest_ref));
12331da177e4SLinus Torvalds 		return -EIO;
12341da177e4SLinus Torvalds 	}
12351da177e4SLinus Torvalds 
12361da177e4SLinus Torvalds 	switch(jemode_to_cpu(latest_node->mode) & S_IFMT) {
12371da177e4SLinus Torvalds 	case S_IFDIR:
1238df8e96f3SDavid Woodhouse 		if (rii.mctime_ver > je32_to_cpu(latest_node->version)) {
12391da177e4SLinus Torvalds 			/* The times in the latest_node are actually older than
12401da177e4SLinus Torvalds 			   mctime in the latest dirent. Cheat. */
1241df8e96f3SDavid Woodhouse 			latest_node->ctime = latest_node->mtime = cpu_to_je32(rii.latest_mctime);
12421da177e4SLinus Torvalds 		}
12431da177e4SLinus Torvalds 		break;
12441da177e4SLinus Torvalds 
12451da177e4SLinus Torvalds 
12461da177e4SLinus Torvalds 	case S_IFREG:
12471da177e4SLinus Torvalds 		/* If it was a regular file, truncate it to the latest node's isize */
124861c4b237SDavid Woodhouse 		new_size = jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize));
124961c4b237SDavid Woodhouse 		if (new_size != je32_to_cpu(latest_node->isize)) {
125061c4b237SDavid Woodhouse 			JFFS2_WARNING("Truncating ino #%u to %d bytes failed because it only had %d bytes to start with!\n",
125161c4b237SDavid Woodhouse 				      f->inocache->ino, je32_to_cpu(latest_node->isize), new_size);
125261c4b237SDavid Woodhouse 			latest_node->isize = cpu_to_je32(new_size);
125361c4b237SDavid Woodhouse 		}
12541da177e4SLinus Torvalds 		break;
12551da177e4SLinus Torvalds 
12561da177e4SLinus Torvalds 	case S_IFLNK:
12571da177e4SLinus Torvalds 		/* Hack to work around broken isize in old symlink code.
12581da177e4SLinus Torvalds 		   Remove this when dwmw2 comes to his senses and stops
12591da177e4SLinus Torvalds 		   symlinks from being an entirely gratuitous special
12601da177e4SLinus Torvalds 		   case. */
12611da177e4SLinus Torvalds 		if (!je32_to_cpu(latest_node->isize))
12621da177e4SLinus Torvalds 			latest_node->isize = latest_node->dsize;
126332f1a95dSArtem B. Bityuckiy 
126432f1a95dSArtem B. Bityuckiy 		if (f->inocache->state != INO_STATE_CHECKING) {
126532f1a95dSArtem B. Bityuckiy 			/* Symlink's inode data is the target path. Read it and
12662b79adccSArtem B. Bityutskiy 			 * keep in RAM to facilitate quick follow symlink
12672b79adccSArtem B. Bityutskiy 			 * operation. */
12687c80c352SXi Wang 			uint32_t csize = je32_to_cpu(latest_node->csize);
12697aaea760SBrian Norris 			if (csize > JFFS2_MAX_NAME_LEN)
12707c80c352SXi Wang 				return -ENAMETOOLONG;
1271b6778fd7SXi Wang 			f->target = kmalloc(csize + 1, GFP_KERNEL);
12722b79adccSArtem B. Bityutskiy 			if (!f->target) {
1273b6778fd7SXi Wang 				JFFS2_ERROR("can't allocate %u bytes of memory for the symlink target path cache\n", csize);
127432f1a95dSArtem B. Bityuckiy 				return -ENOMEM;
127532f1a95dSArtem B. Bityuckiy 			}
127632f1a95dSArtem B. Bityuckiy 
1277df8e96f3SDavid Woodhouse 			ret = jffs2_flash_read(c, ref_offset(rii.latest_ref) + sizeof(*latest_node),
1278b6778fd7SXi Wang 					       csize, &retlen, (char *)f->target);
127932f1a95dSArtem B. Bityuckiy 
1280b6778fd7SXi Wang 			if (ret || retlen != csize) {
1281b6778fd7SXi Wang 				if (retlen != csize)
128232f1a95dSArtem B. Bityuckiy 					ret = -EIO;
12832b79adccSArtem B. Bityutskiy 				kfree(f->target);
12842b79adccSArtem B. Bityutskiy 				f->target = NULL;
1285e670e41aSRoel Kluin 				return ret;
128632f1a95dSArtem B. Bityuckiy 			}
128732f1a95dSArtem B. Bityuckiy 
1288b6778fd7SXi Wang 			f->target[csize] = '\0';
1289733802d9SArtem B. Bityutskiy 			dbg_readinode("symlink's target '%s' cached\n", f->target);
129032f1a95dSArtem B. Bityuckiy 		}
129132f1a95dSArtem B. Bityuckiy 
1292df561f66SGustavo A. R. Silva 		fallthrough;
12931da177e4SLinus Torvalds 
12941da177e4SLinus Torvalds 	case S_IFBLK:
12951da177e4SLinus Torvalds 	case S_IFCHR:
12961da177e4SLinus Torvalds 		/* Certain inode types should have only one data node, and it's
12971da177e4SLinus Torvalds 		   kept as the metadata node */
12981da177e4SLinus Torvalds 		if (f->metadata) {
1299e0d60137SArtem B. Bityutskiy 			JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n",
13001da177e4SLinus Torvalds 			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
13011da177e4SLinus Torvalds 			return -EIO;
13021da177e4SLinus Torvalds 		}
13031da177e4SLinus Torvalds 		if (!frag_first(&f->fragtree)) {
1304e0d60137SArtem B. Bityutskiy 			JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n",
13051da177e4SLinus Torvalds 			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
13061da177e4SLinus Torvalds 			return -EIO;
13071da177e4SLinus Torvalds 		}
13081da177e4SLinus Torvalds 		/* ASSERT: f->fraglist != NULL */
13091da177e4SLinus Torvalds 		if (frag_next(frag_first(&f->fragtree))) {
1310e0d60137SArtem B. Bityutskiy 			JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n",
13111da177e4SLinus Torvalds 			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
13121da177e4SLinus Torvalds 			/* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
13131da177e4SLinus Torvalds 			return -EIO;
13141da177e4SLinus Torvalds 		}
13151da177e4SLinus Torvalds 		/* OK. We're happy */
13161da177e4SLinus Torvalds 		f->metadata = frag_first(&f->fragtree)->node;
13171da177e4SLinus Torvalds 		jffs2_free_node_frag(frag_first(&f->fragtree));
13181da177e4SLinus Torvalds 		f->fragtree = RB_ROOT;
13191da177e4SLinus Torvalds 		break;
13201da177e4SLinus Torvalds 	}
13211da177e4SLinus Torvalds 	if (f->inocache->state == INO_STATE_READING)
13221da177e4SLinus Torvalds 		jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
13231da177e4SLinus Torvalds 
13241da177e4SLinus Torvalds 	return 0;
13251da177e4SLinus Torvalds }
13261da177e4SLinus Torvalds 
1327f97117d1SArtem B. Bityutskiy /* Scan the list of all nodes present for this ino, build map of versions, etc. */
jffs2_do_read_inode(struct jffs2_sb_info * c,struct jffs2_inode_info * f,uint32_t ino,struct jffs2_raw_inode * latest_node)1328f97117d1SArtem B. Bityutskiy int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
1329f97117d1SArtem B. Bityutskiy 			uint32_t ino, struct jffs2_raw_inode *latest_node)
1330f97117d1SArtem B. Bityutskiy {
1331733802d9SArtem B. Bityutskiy 	dbg_readinode("read inode #%u\n", ino);
1332f97117d1SArtem B. Bityutskiy 
1333f97117d1SArtem B. Bityutskiy  retry_inocache:
1334f97117d1SArtem B. Bityutskiy 	spin_lock(&c->inocache_lock);
1335f97117d1SArtem B. Bityutskiy 	f->inocache = jffs2_get_ino_cache(c, ino);
1336f97117d1SArtem B. Bityutskiy 
1337f97117d1SArtem B. Bityutskiy 	if (f->inocache) {
1338f97117d1SArtem B. Bityutskiy 		/* Check its state. We may need to wait before we can use it */
1339f97117d1SArtem B. Bityutskiy 		switch(f->inocache->state) {
1340f97117d1SArtem B. Bityutskiy 		case INO_STATE_UNCHECKED:
1341f97117d1SArtem B. Bityutskiy 		case INO_STATE_CHECKEDABSENT:
1342f97117d1SArtem B. Bityutskiy 			f->inocache->state = INO_STATE_READING;
1343f97117d1SArtem B. Bityutskiy 			break;
1344f97117d1SArtem B. Bityutskiy 
1345f97117d1SArtem B. Bityutskiy 		case INO_STATE_CHECKING:
1346f97117d1SArtem B. Bityutskiy 		case INO_STATE_GC:
1347f97117d1SArtem B. Bityutskiy 			/* If it's in either of these states, we need
1348f97117d1SArtem B. Bityutskiy 			   to wait for whoever's got it to finish and
1349f97117d1SArtem B. Bityutskiy 			   put it back. */
1350733802d9SArtem B. Bityutskiy 			dbg_readinode("waiting for ino #%u in state %d\n", ino, f->inocache->state);
1351f97117d1SArtem B. Bityutskiy 			sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
1352f97117d1SArtem B. Bityutskiy 			goto retry_inocache;
1353f97117d1SArtem B. Bityutskiy 
1354f97117d1SArtem B. Bityutskiy 		case INO_STATE_READING:
1355f97117d1SArtem B. Bityutskiy 		case INO_STATE_PRESENT:
1356f97117d1SArtem B. Bityutskiy 			/* Eep. This should never happen. It can
1357f97117d1SArtem B. Bityutskiy 			happen if Linux calls read_inode() again
1358f97117d1SArtem B. Bityutskiy 			before clear_inode() has finished though. */
1359e0d60137SArtem B. Bityutskiy 			JFFS2_ERROR("Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state);
1360f97117d1SArtem B. Bityutskiy 			/* Fail. That's probably better than allowing it to succeed */
1361f97117d1SArtem B. Bityutskiy 			f->inocache = NULL;
1362f97117d1SArtem B. Bityutskiy 			break;
1363f97117d1SArtem B. Bityutskiy 
1364f97117d1SArtem B. Bityutskiy 		default:
1365f97117d1SArtem B. Bityutskiy 			BUG();
1366f97117d1SArtem B. Bityutskiy 		}
1367f97117d1SArtem B. Bityutskiy 	}
1368f97117d1SArtem B. Bityutskiy 	spin_unlock(&c->inocache_lock);
1369f97117d1SArtem B. Bityutskiy 
1370f97117d1SArtem B. Bityutskiy 	if (!f->inocache && ino == 1) {
1371f97117d1SArtem B. Bityutskiy 		/* Special case - no root inode on medium */
1372f97117d1SArtem B. Bityutskiy 		f->inocache = jffs2_alloc_inode_cache();
1373f97117d1SArtem B. Bityutskiy 		if (!f->inocache) {
1374e0d60137SArtem B. Bityutskiy 			JFFS2_ERROR("cannot allocate inocache for root inode\n");
1375f97117d1SArtem B. Bityutskiy 			return -ENOMEM;
1376f97117d1SArtem B. Bityutskiy 		}
1377733802d9SArtem B. Bityutskiy 		dbg_readinode("creating inocache for root inode\n");
1378f97117d1SArtem B. Bityutskiy 		memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
137927c72b04SDavid Woodhouse 		f->inocache->ino = f->inocache->pino_nlink = 1;
1380f97117d1SArtem B. Bityutskiy 		f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
1381f97117d1SArtem B. Bityutskiy 		f->inocache->state = INO_STATE_READING;
1382f97117d1SArtem B. Bityutskiy 		jffs2_add_ino_cache(c, f->inocache);
1383f97117d1SArtem B. Bityutskiy 	}
1384f97117d1SArtem B. Bityutskiy 	if (!f->inocache) {
13858918821fSColin Ian King 		JFFS2_ERROR("requested to read a nonexistent ino %u\n", ino);
1386f97117d1SArtem B. Bityutskiy 		return -ENOENT;
1387f97117d1SArtem B. Bityutskiy 	}
1388f97117d1SArtem B. Bityutskiy 
1389f97117d1SArtem B. Bityutskiy 	return jffs2_do_read_inode_internal(c, f, latest_node);
1390f97117d1SArtem B. Bityutskiy }
1391f97117d1SArtem B. Bityutskiy 
jffs2_do_crccheck_inode(struct jffs2_sb_info * c,struct jffs2_inode_cache * ic)1392f97117d1SArtem B. Bityutskiy int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
1393f97117d1SArtem B. Bityutskiy {
1394f97117d1SArtem B. Bityutskiy 	struct jffs2_raw_inode n;
13953d375d9eSYan Burman 	struct jffs2_inode_info *f = kzalloc(sizeof(*f), GFP_KERNEL);
1396f97117d1SArtem B. Bityutskiy 	int ret;
1397f97117d1SArtem B. Bityutskiy 
1398f97117d1SArtem B. Bityutskiy 	if (!f)
1399f97117d1SArtem B. Bityutskiy 		return -ENOMEM;
1400f97117d1SArtem B. Bityutskiy 
1401ced22070SDavid Woodhouse 	mutex_init(&f->sem);
1402ced22070SDavid Woodhouse 	mutex_lock(&f->sem);
1403f97117d1SArtem B. Bityutskiy 	f->inocache = ic;
1404f97117d1SArtem B. Bityutskiy 
1405f97117d1SArtem B. Bityutskiy 	ret = jffs2_do_read_inode_internal(c, f, &n);
1406ced22070SDavid Woodhouse 	mutex_unlock(&f->sem);
1407f97117d1SArtem B. Bityutskiy 	jffs2_do_clear_inode(c, f);
14088c5a0366SJean-Christophe DUBOIS 	jffs2_xattr_do_crccheck_inode(c, ic);
1409f97117d1SArtem B. Bityutskiy 	kfree (f);
1410f97117d1SArtem B. Bityutskiy 	return ret;
1411f97117d1SArtem B. Bityutskiy }
1412f97117d1SArtem B. Bityutskiy 
jffs2_do_clear_inode(struct jffs2_sb_info * c,struct jffs2_inode_info * f)14131da177e4SLinus Torvalds void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
14141da177e4SLinus Torvalds {
14151da177e4SLinus Torvalds 	struct jffs2_full_dirent *fd, *fds;
14161da177e4SLinus Torvalds 	int deleted;
14171da177e4SLinus Torvalds 
1418355ed4e1SKaiGai Kohei 	jffs2_xattr_delete_inode(c, f->inocache);
1419ced22070SDavid Woodhouse 	mutex_lock(&f->sem);
142027c72b04SDavid Woodhouse 	deleted = f->inocache && !f->inocache->pino_nlink;
14211da177e4SLinus Torvalds 
142267e345d1SDavid Woodhouse 	if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
142367e345d1SDavid Woodhouse 		jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);
142467e345d1SDavid Woodhouse 
14251da177e4SLinus Torvalds 	if (f->metadata) {
14261da177e4SLinus Torvalds 		if (deleted)
14271da177e4SLinus Torvalds 			jffs2_mark_node_obsolete(c, f->metadata->raw);
14281da177e4SLinus Torvalds 		jffs2_free_full_dnode(f->metadata);
14291da177e4SLinus Torvalds 	}
14301da177e4SLinus Torvalds 
14311da177e4SLinus Torvalds 	jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL);
14321da177e4SLinus Torvalds 
14332b79adccSArtem B. Bityutskiy 	fds = f->dents;
14341da177e4SLinus Torvalds 	while(fds) {
14351da177e4SLinus Torvalds 		fd = fds;
14361da177e4SLinus Torvalds 		fds = fd->next;
14371da177e4SLinus Torvalds 		jffs2_free_full_dirent(fd);
14381da177e4SLinus Torvalds 	}
14391da177e4SLinus Torvalds 
144067e345d1SDavid Woodhouse 	if (f->inocache && f->inocache->state != INO_STATE_CHECKING) {
14411da177e4SLinus Torvalds 		jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
144267e345d1SDavid Woodhouse 		if (f->inocache->nodes == (void *)f->inocache)
144367e345d1SDavid Woodhouse 			jffs2_del_ino_cache(c, f->inocache);
144467e345d1SDavid Woodhouse 	}
14451da177e4SLinus Torvalds 
1446ced22070SDavid Woodhouse 	mutex_unlock(&f->sem);
14471da177e4SLinus Torvalds }
1448