xref: /openbmc/linux/fs/jffs2/readinode.c (revision 1046d880)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * JFFS2 -- Journalling Flash File System, Version 2.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Copyright (C) 2001-2003 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  *
10182ec4eeSThomas Gleixner  * $Id: readinode.c,v 1.143 2005/11/07 11:14:41 gleixner Exp $
111da177e4SLinus Torvalds  *
121da177e4SLinus Torvalds  */
131da177e4SLinus Torvalds 
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 /*
25f97117d1SArtem B. Bityutskiy  * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in
26f97117d1SArtem B. Bityutskiy  * order of increasing version.
27f97117d1SArtem B. Bityutskiy  */
28f97117d1SArtem B. Bityutskiy static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list)
291da177e4SLinus Torvalds {
30f97117d1SArtem B. Bityutskiy 	struct rb_node **p = &list->rb_node;
31f97117d1SArtem B. Bityutskiy 	struct rb_node * parent = NULL;
32f97117d1SArtem B. Bityutskiy 	struct jffs2_tmp_dnode_info *this;
331da177e4SLinus Torvalds 
34f97117d1SArtem B. Bityutskiy 	while (*p) {
35f97117d1SArtem B. Bityutskiy 		parent = *p;
36f97117d1SArtem B. Bityutskiy 		this = rb_entry(parent, struct jffs2_tmp_dnode_info, rb);
371da177e4SLinus Torvalds 
38f97117d1SArtem B. Bityutskiy 		/* There may actually be a collision here, but it doesn't
39f97117d1SArtem B. Bityutskiy 		   actually matter. As long as the two nodes with the same
40f97117d1SArtem B. Bityutskiy 		   version are together, it's all fine. */
411e0da3cbSArtem B. Bityutskiy 		if (tn->version > this->version)
42f97117d1SArtem B. Bityutskiy 			p = &(*p)->rb_left;
43f97117d1SArtem B. Bityutskiy 		else
44f97117d1SArtem B. Bityutskiy 			p = &(*p)->rb_right;
45f97117d1SArtem B. Bityutskiy 	}
461da177e4SLinus Torvalds 
47f97117d1SArtem B. Bityutskiy 	rb_link_node(&tn->rb, parent, p);
48f97117d1SArtem B. Bityutskiy 	rb_insert_color(&tn->rb, list);
49f97117d1SArtem B. Bityutskiy }
50f97117d1SArtem B. Bityutskiy 
51f97117d1SArtem B. Bityutskiy static void jffs2_free_tmp_dnode_info_list(struct rb_root *list)
52f97117d1SArtem B. Bityutskiy {
53f97117d1SArtem B. Bityutskiy 	struct rb_node *this;
54f97117d1SArtem B. Bityutskiy 	struct jffs2_tmp_dnode_info *tn;
55f97117d1SArtem B. Bityutskiy 
56f97117d1SArtem B. Bityutskiy 	this = list->rb_node;
57f97117d1SArtem B. Bityutskiy 
58f97117d1SArtem B. Bityutskiy 	/* Now at bottom of tree */
59f97117d1SArtem B. Bityutskiy 	while (this) {
60f97117d1SArtem B. Bityutskiy 		if (this->rb_left)
61f97117d1SArtem B. Bityutskiy 			this = this->rb_left;
62f97117d1SArtem B. Bityutskiy 		else if (this->rb_right)
63f97117d1SArtem B. Bityutskiy 			this = this->rb_right;
64f97117d1SArtem B. Bityutskiy 		else {
65f97117d1SArtem B. Bityutskiy 			tn = rb_entry(this, struct jffs2_tmp_dnode_info, rb);
66f97117d1SArtem B. Bityutskiy 			jffs2_free_full_dnode(tn->fn);
67f97117d1SArtem B. Bityutskiy 			jffs2_free_tmp_dnode_info(tn);
68f97117d1SArtem B. Bityutskiy 
69f97117d1SArtem B. Bityutskiy 			this = this->rb_parent;
70f97117d1SArtem B. Bityutskiy 			if (!this)
711da177e4SLinus Torvalds 				break;
721da177e4SLinus Torvalds 
73f97117d1SArtem B. Bityutskiy 			if (this->rb_left == &tn->rb)
74f97117d1SArtem B. Bityutskiy 				this->rb_left = NULL;
75f97117d1SArtem B. Bityutskiy 			else if (this->rb_right == &tn->rb)
76f97117d1SArtem B. Bityutskiy 				this->rb_right = NULL;
77f97117d1SArtem B. Bityutskiy 			else BUG();
78f97117d1SArtem B. Bityutskiy 		}
79f97117d1SArtem B. Bityutskiy 	}
80f97117d1SArtem B. Bityutskiy 	list->rb_node = NULL;
81f97117d1SArtem B. Bityutskiy }
821da177e4SLinus Torvalds 
83f97117d1SArtem B. Bityutskiy static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd)
84f97117d1SArtem B. Bityutskiy {
85f97117d1SArtem B. Bityutskiy 	struct jffs2_full_dirent *next;
86f97117d1SArtem B. Bityutskiy 
87f97117d1SArtem B. Bityutskiy 	while (fd) {
88f97117d1SArtem B. Bityutskiy 		next = fd->next;
89f97117d1SArtem B. Bityutskiy 		jffs2_free_full_dirent(fd);
90f97117d1SArtem B. Bityutskiy 		fd = next;
91f97117d1SArtem B. Bityutskiy 	}
92f97117d1SArtem B. Bityutskiy }
93f97117d1SArtem B. Bityutskiy 
94f97117d1SArtem B. Bityutskiy /* Returns first valid node after 'ref'. May return 'ref' */
95f97117d1SArtem B. Bityutskiy static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_ref *ref)
96f97117d1SArtem B. Bityutskiy {
97f97117d1SArtem B. Bityutskiy 	while (ref && ref->next_in_ino) {
98f97117d1SArtem B. Bityutskiy 		if (!ref_obsolete(ref))
99f97117d1SArtem B. Bityutskiy 			return ref;
100733802d9SArtem B. Bityutskiy 		dbg_noderef("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref));
101f97117d1SArtem B. Bityutskiy 		ref = ref->next_in_ino;
102f97117d1SArtem B. Bityutskiy 	}
103f97117d1SArtem B. Bityutskiy 	return NULL;
104f97117d1SArtem B. Bityutskiy }
105f97117d1SArtem B. Bityutskiy 
106f97117d1SArtem B. Bityutskiy /*
107f97117d1SArtem B. Bityutskiy  * Helper function for jffs2_get_inode_nodes().
108f97117d1SArtem B. Bityutskiy  * It is called every time an directory entry node is found.
109f97117d1SArtem B. Bityutskiy  *
110f97117d1SArtem B. Bityutskiy  * Returns: 0 on succes;
111f97117d1SArtem B. Bityutskiy  * 	    1 if the node should be marked obsolete;
112f97117d1SArtem B. Bityutskiy  * 	    negative error code on failure.
113f97117d1SArtem B. Bityutskiy  */
1141e0da3cbSArtem B. Bityutskiy static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
1150ef675d4SAtsushi Nemoto 				struct jffs2_raw_dirent *rd, size_t read, struct jffs2_full_dirent **fdp,
1161e0da3cbSArtem B. Bityutskiy 				uint32_t *latest_mctime, uint32_t *mctime_ver)
117f97117d1SArtem B. Bityutskiy {
118f97117d1SArtem B. Bityutskiy 	struct jffs2_full_dirent *fd;
1191046d880SDavid Woodhouse 	uint32_t crc;
120f97117d1SArtem B. Bityutskiy 
121f97117d1SArtem B. Bityutskiy 	/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
122f97117d1SArtem B. Bityutskiy 	BUG_ON(ref_obsolete(ref));
123f97117d1SArtem B. Bityutskiy 
1241046d880SDavid Woodhouse 	crc = crc32(0, rd, sizeof(*rd) - 8);
1251046d880SDavid Woodhouse 	if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
1261046d880SDavid Woodhouse 		JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n",
1271046d880SDavid Woodhouse 			     ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
1281046d880SDavid Woodhouse 		return 1;
1291046d880SDavid Woodhouse 	}
1301046d880SDavid Woodhouse 
1311046d880SDavid Woodhouse 	/* If we've never checked the CRCs on this node, check them now */
1321046d880SDavid Woodhouse 	if (ref_flags(ref) == REF_UNCHECKED) {
1331046d880SDavid Woodhouse 		struct jffs2_eraseblock *jeb;
1341046d880SDavid Woodhouse 		int len;
1351046d880SDavid Woodhouse 
136f97117d1SArtem B. Bityutskiy 		/* Sanity check */
137f97117d1SArtem B. Bityutskiy 		if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
138e0d60137SArtem B. Bityutskiy 			JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
139f97117d1SArtem B. Bityutskiy 				    ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
140f97117d1SArtem B. Bityutskiy 			return 1;
141f97117d1SArtem B. Bityutskiy 		}
142f97117d1SArtem B. Bityutskiy 
1431046d880SDavid Woodhouse 		jeb = &c->blocks[ref->flash_offset / c->sector_size];
1441046d880SDavid Woodhouse 		len = ref_totlen(c, jeb, ref);
1451046d880SDavid Woodhouse 
1461046d880SDavid Woodhouse 		spin_lock(&c->erase_completion_lock);
1471046d880SDavid Woodhouse 		jeb->used_size += len;
1481046d880SDavid Woodhouse 		jeb->unchecked_size -= len;
1491046d880SDavid Woodhouse 		c->used_size += len;
1501046d880SDavid Woodhouse 		c->unchecked_size -= len;
1511046d880SDavid Woodhouse 		ref->flash_offset = ref_offset(ref) | REF_PRISTINE;
1521046d880SDavid Woodhouse 		spin_unlock(&c->erase_completion_lock);
1531046d880SDavid Woodhouse 	}
1541046d880SDavid Woodhouse 
155f97117d1SArtem B. Bityutskiy 	fd = jffs2_alloc_full_dirent(rd->nsize + 1);
156f97117d1SArtem B. Bityutskiy 	if (unlikely(!fd))
157f97117d1SArtem B. Bityutskiy 		return -ENOMEM;
158f97117d1SArtem B. Bityutskiy 
159f97117d1SArtem B. Bityutskiy 	fd->raw = ref;
160f97117d1SArtem B. Bityutskiy 	fd->version = je32_to_cpu(rd->version);
161f97117d1SArtem B. Bityutskiy 	fd->ino = je32_to_cpu(rd->ino);
162f97117d1SArtem B. Bityutskiy 	fd->type = rd->type;
163f97117d1SArtem B. Bityutskiy 
164f97117d1SArtem B. Bityutskiy 	/* Pick out the mctime of the latest dirent */
1653a69e0cdSArtem B. Bityutskiy 	if(fd->version > *mctime_ver && je32_to_cpu(rd->mctime)) {
166f97117d1SArtem B. Bityutskiy 		*mctime_ver = fd->version;
167f97117d1SArtem B. Bityutskiy 		*latest_mctime = je32_to_cpu(rd->mctime);
168f97117d1SArtem B. Bityutskiy 	}
169f97117d1SArtem B. Bityutskiy 
170f97117d1SArtem B. Bityutskiy 	/*
171f97117d1SArtem B. Bityutskiy 	 * Copy as much of the name as possible from the raw
172f97117d1SArtem B. Bityutskiy 	 * dirent we've already read from the flash.
173f97117d1SArtem B. Bityutskiy 	 */
174f97117d1SArtem B. Bityutskiy 	if (read > sizeof(*rd))
175f97117d1SArtem B. Bityutskiy 		memcpy(&fd->name[0], &rd->name[0],
176f97117d1SArtem B. Bityutskiy 		       min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) ));
177f97117d1SArtem B. Bityutskiy 
178f97117d1SArtem B. Bityutskiy 	/* Do we need to copy any more of the name directly from the flash? */
179f97117d1SArtem B. Bityutskiy 	if (rd->nsize + sizeof(*rd) > read) {
180f97117d1SArtem B. Bityutskiy 		/* FIXME: point() */
181f97117d1SArtem B. Bityutskiy 		int err;
182f97117d1SArtem B. Bityutskiy 		int already = read - sizeof(*rd);
183f97117d1SArtem B. Bityutskiy 
184f97117d1SArtem B. Bityutskiy 		err = jffs2_flash_read(c, (ref_offset(ref)) + read,
185f97117d1SArtem B. Bityutskiy 				rd->nsize - already, &read, &fd->name[already]);
186f97117d1SArtem B. Bityutskiy 		if (unlikely(read != rd->nsize - already) && likely(!err))
187f97117d1SArtem B. Bityutskiy 			return -EIO;
188f97117d1SArtem B. Bityutskiy 
189f97117d1SArtem B. Bityutskiy 		if (unlikely(err)) {
190e0d60137SArtem B. Bityutskiy 			JFFS2_ERROR("read remainder of name: error %d\n", err);
191f97117d1SArtem B. Bityutskiy 			jffs2_free_full_dirent(fd);
192f97117d1SArtem B. Bityutskiy 			return -EIO;
193f97117d1SArtem B. Bityutskiy 		}
194f97117d1SArtem B. Bityutskiy 	}
195f97117d1SArtem B. Bityutskiy 
196f97117d1SArtem B. Bityutskiy 	fd->nhash = full_name_hash(fd->name, rd->nsize);
197f97117d1SArtem B. Bityutskiy 	fd->next = NULL;
198f97117d1SArtem B. Bityutskiy 	fd->name[rd->nsize] = '\0';
199f97117d1SArtem B. Bityutskiy 
200f97117d1SArtem B. Bityutskiy 	/*
201f97117d1SArtem B. Bityutskiy 	 * Wheee. We now have a complete jffs2_full_dirent structure, with
202f97117d1SArtem B. Bityutskiy 	 * the name in it and everything. Link it into the list
203f97117d1SArtem B. Bityutskiy 	 */
204f97117d1SArtem B. Bityutskiy 	jffs2_add_fd_to_list(c, fd, fdp);
205f97117d1SArtem B. Bityutskiy 
206f97117d1SArtem B. Bityutskiy 	return 0;
207f97117d1SArtem B. Bityutskiy }
208f97117d1SArtem B. Bityutskiy 
209f97117d1SArtem B. Bityutskiy /*
210f97117d1SArtem B. Bityutskiy  * Helper function for jffs2_get_inode_nodes().
211f97117d1SArtem B. Bityutskiy  * It is called every time an inode node is found.
212f97117d1SArtem B. Bityutskiy  *
213f97117d1SArtem B. Bityutskiy  * Returns: 0 on succes;
214f97117d1SArtem B. Bityutskiy  * 	    1 if the node should be marked obsolete;
215f97117d1SArtem B. Bityutskiy  * 	    negative error code on failure.
216f97117d1SArtem B. Bityutskiy  */
2171e0da3cbSArtem B. Bityutskiy static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
2181e0da3cbSArtem B. Bityutskiy 			     struct jffs2_raw_inode *rd, struct rb_root *tnp, int rdlen,
2191e0da3cbSArtem B. Bityutskiy 			     uint32_t *latest_mctime, uint32_t *mctime_ver)
220f97117d1SArtem B. Bityutskiy {
221f97117d1SArtem B. Bityutskiy 	struct jffs2_tmp_dnode_info *tn;
2221e0da3cbSArtem B. Bityutskiy 	uint32_t len, csize;
2231e0da3cbSArtem B. Bityutskiy 	int ret = 1;
2241046d880SDavid Woodhouse 	uint32_t crc;
225f97117d1SArtem B. Bityutskiy 
226f97117d1SArtem B. Bityutskiy 	/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
227f97117d1SArtem B. Bityutskiy 	BUG_ON(ref_obsolete(ref));
228f97117d1SArtem B. Bityutskiy 
2291046d880SDavid Woodhouse 	crc = crc32(0, rd, sizeof(*rd) - 8);
2301046d880SDavid Woodhouse 	if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
2311046d880SDavid Woodhouse 		JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n",
2321046d880SDavid Woodhouse 			     ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
2331046d880SDavid Woodhouse 		return 1;
2341046d880SDavid Woodhouse 	}
2351046d880SDavid Woodhouse 
2361e0da3cbSArtem B. Bityutskiy 	tn = jffs2_alloc_tmp_dnode_info();
2371e0da3cbSArtem B. Bityutskiy 	if (!tn) {
238fb6a82c9SRandy Dunlap 		JFFS2_ERROR("failed to allocate tn (%zu bytes).\n", sizeof(*tn));
2391e0da3cbSArtem B. Bityutskiy 		return -ENOMEM;
2401e0da3cbSArtem B. Bityutskiy 	}
2411e0da3cbSArtem B. Bityutskiy 
2421e0da3cbSArtem B. Bityutskiy 	tn->partial_crc = 0;
2431e0da3cbSArtem B. Bityutskiy 	csize = je32_to_cpu(rd->csize);
2441e0da3cbSArtem B. Bityutskiy 
245f97117d1SArtem B. Bityutskiy 	/* If we've never checked the CRCs on this node, check them now */
246f97117d1SArtem B. Bityutskiy 	if (ref_flags(ref) == REF_UNCHECKED) {
247f97117d1SArtem B. Bityutskiy 
248f97117d1SArtem B. Bityutskiy 		/* Sanity checks */
249f97117d1SArtem B. Bityutskiy 		if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) ||
250f97117d1SArtem B. Bityutskiy 		    unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) {
251e0d60137SArtem B. Bityutskiy 				JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref));
252737b7661SAndrew Lunn 				jffs2_dbg_dump_node(c, ref_offset(ref));
2531e0da3cbSArtem B. Bityutskiy 			goto free_out;
254f97117d1SArtem B. Bityutskiy 		}
255f97117d1SArtem B. Bityutskiy 
2561e0da3cbSArtem B. Bityutskiy 		if (jffs2_is_writebuffered(c) && csize != 0) {
2571e0da3cbSArtem B. Bityutskiy 			/* At this point we are supposed to check the data CRC
2581e0da3cbSArtem B. Bityutskiy 			 * of our unchecked node. But thus far, we do not
2591e0da3cbSArtem B. Bityutskiy 			 * know whether the node is valid or obsolete. To
2601e0da3cbSArtem B. Bityutskiy 			 * figure this out, we need to walk all the nodes of
2611e0da3cbSArtem B. Bityutskiy 			 * the inode and build the inode fragtree. We don't
2621e0da3cbSArtem B. Bityutskiy 			 * want to spend time checking data of nodes which may
2631e0da3cbSArtem B. Bityutskiy 			 * later be found to be obsolete. So we put off the full
2641e0da3cbSArtem B. Bityutskiy 			 * data CRC checking until we have read all the inode
2651e0da3cbSArtem B. Bityutskiy 			 * nodes and have started building the fragtree.
2661e0da3cbSArtem B. Bityutskiy 			 *
2671e0da3cbSArtem B. Bityutskiy 			 * The fragtree is being built starting with nodes
2681e0da3cbSArtem B. Bityutskiy 			 * having the highest version number, so we'll be able
2691e0da3cbSArtem B. Bityutskiy 			 * to detect whether a node is valid (i.e., it is not
2701e0da3cbSArtem B. Bityutskiy 			 * overlapped by a node with higher version) or not.
2711e0da3cbSArtem B. Bityutskiy 			 * And we'll be able to check only those nodes, which
2721e0da3cbSArtem B. Bityutskiy 			 * are not obsolete.
2731e0da3cbSArtem B. Bityutskiy 			 *
2741e0da3cbSArtem B. Bityutskiy 			 * Of course, this optimization only makes sense in case
2751e0da3cbSArtem B. Bityutskiy 			 * of NAND flashes (or other flashes whith
2761e0da3cbSArtem B. Bityutskiy 			 * !jffs2_can_mark_obsolete()), since on NOR flashes
2771e0da3cbSArtem B. Bityutskiy 			 * nodes are marked obsolete physically.
2781e0da3cbSArtem B. Bityutskiy 			 *
2791e0da3cbSArtem B. Bityutskiy 			 * Since NAND flashes (or other flashes with
2801e0da3cbSArtem B. Bityutskiy 			 * jffs2_is_writebuffered(c)) are anyway read by
2811e0da3cbSArtem B. Bityutskiy 			 * fractions of c->wbuf_pagesize, and we have just read
2821e0da3cbSArtem B. Bityutskiy 			 * the node header, it is likely that the starting part
2831e0da3cbSArtem B. Bityutskiy 			 * of the node data is also read when we read the
2841e0da3cbSArtem B. Bityutskiy 			 * header. So we don't mind to check the CRC of the
2851e0da3cbSArtem B. Bityutskiy 			 * starting part of the data of the node now, and check
2861e0da3cbSArtem B. Bityutskiy 			 * the second part later (in jffs2_check_node_data()).
2871e0da3cbSArtem B. Bityutskiy 			 * Of course, we will not need to re-read and re-check
2881e0da3cbSArtem B. Bityutskiy 			 * the NAND page which we have just read. This is why we
2891e0da3cbSArtem B. Bityutskiy 			 * read the whole NAND page at jffs2_get_inode_nodes(),
2901e0da3cbSArtem B. Bityutskiy 			 * while we needed only the node header.
2911e0da3cbSArtem B. Bityutskiy 			 */
2921e0da3cbSArtem B. Bityutskiy 			unsigned char *buf;
293f97117d1SArtem B. Bityutskiy 
2941e0da3cbSArtem B. Bityutskiy 			/* 'buf' will point to the start of data */
2951e0da3cbSArtem B. Bityutskiy 			buf = (unsigned char *)rd + sizeof(*rd);
2961e0da3cbSArtem B. Bityutskiy 			/* len will be the read data length */
2971e0da3cbSArtem B. Bityutskiy 			len = min_t(uint32_t, rdlen - sizeof(*rd), csize);
298280562b2SArtem B. Bityutskiy 			tn->partial_crc = crc32(0, buf, len);
299f97117d1SArtem B. Bityutskiy 
300733802d9SArtem B. Bityutskiy 			dbg_readinode("Calculates CRC (%#08x) for %d bytes, csize %d\n", tn->partial_crc, len, csize);
301f97117d1SArtem B. Bityutskiy 
3021e0da3cbSArtem B. Bityutskiy 			/* If we actually calculated the whole data CRC
3031e0da3cbSArtem B. Bityutskiy 			 * and it is wrong, drop the node. */
3043c091337SArtem B. Bityutskiy 			if (len >= csize && unlikely(tn->partial_crc != je32_to_cpu(rd->data_crc))) {
30539243508SArtem B. Bityutskiy 				JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n",
30639243508SArtem B. Bityutskiy 					ref_offset(ref), tn->partial_crc, je32_to_cpu(rd->data_crc));
3071e0da3cbSArtem B. Bityutskiy 				goto free_out;
30839243508SArtem B. Bityutskiy 			}
309f97117d1SArtem B. Bityutskiy 
3101e0da3cbSArtem B. Bityutskiy 		} else if (csize == 0) {
3111e0da3cbSArtem B. Bityutskiy 			/*
3121e0da3cbSArtem B. Bityutskiy 			 * We checked the header CRC. If the node has no data, adjust
3131e0da3cbSArtem B. Bityutskiy 			 * the space accounting now. For other nodes this will be done
3141e0da3cbSArtem B. Bityutskiy 			 * later either when the node is marked obsolete or when its
3151e0da3cbSArtem B. Bityutskiy 			 * data is checked.
3161e0da3cbSArtem B. Bityutskiy 			 */
3171e0da3cbSArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb;
3181e0da3cbSArtem B. Bityutskiy 
319733802d9SArtem B. Bityutskiy 			dbg_readinode("the node has no data.\n");
320f97117d1SArtem B. Bityutskiy 			jeb = &c->blocks[ref->flash_offset / c->sector_size];
321f97117d1SArtem B. Bityutskiy 			len = ref_totlen(c, jeb, ref);
322f97117d1SArtem B. Bityutskiy 
323f97117d1SArtem B. Bityutskiy 			spin_lock(&c->erase_completion_lock);
324f97117d1SArtem B. Bityutskiy 			jeb->used_size += len;
325f97117d1SArtem B. Bityutskiy 			jeb->unchecked_size -= len;
326f97117d1SArtem B. Bityutskiy 			c->used_size += len;
327f97117d1SArtem B. Bityutskiy 			c->unchecked_size -= len;
328f97117d1SArtem B. Bityutskiy 			ref->flash_offset = ref_offset(ref) | REF_NORMAL;
329f97117d1SArtem B. Bityutskiy 			spin_unlock(&c->erase_completion_lock);
330f97117d1SArtem B. Bityutskiy 		}
331f97117d1SArtem B. Bityutskiy 	}
332f97117d1SArtem B. Bityutskiy 
333f97117d1SArtem B. Bityutskiy 	tn->fn = jffs2_alloc_full_dnode();
334f97117d1SArtem B. Bityutskiy 	if (!tn->fn) {
335e0d60137SArtem B. Bityutskiy 		JFFS2_ERROR("alloc fn failed\n");
3361e0da3cbSArtem B. Bityutskiy 		ret = -ENOMEM;
3371e0da3cbSArtem B. Bityutskiy 		goto free_out;
338f97117d1SArtem B. Bityutskiy 	}
339f97117d1SArtem B. Bityutskiy 
340f97117d1SArtem B. Bityutskiy 	tn->version = je32_to_cpu(rd->version);
341f97117d1SArtem B. Bityutskiy 	tn->fn->ofs = je32_to_cpu(rd->offset);
3421e0da3cbSArtem B. Bityutskiy 	tn->data_crc = je32_to_cpu(rd->data_crc);
3431e0da3cbSArtem B. Bityutskiy 	tn->csize = csize;
344f97117d1SArtem B. Bityutskiy 	tn->fn->raw = ref;
345f97117d1SArtem B. Bityutskiy 
346f97117d1SArtem B. Bityutskiy 	/* There was a bug where we wrote hole nodes out with
347f97117d1SArtem B. Bityutskiy 	   csize/dsize swapped. Deal with it */
3481e0da3cbSArtem B. Bityutskiy 	if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && csize)
3491e0da3cbSArtem B. Bityutskiy 		tn->fn->size = csize;
350f97117d1SArtem B. Bityutskiy 	else // normal case...
351f97117d1SArtem B. Bityutskiy 		tn->fn->size = je32_to_cpu(rd->dsize);
352f97117d1SArtem B. Bityutskiy 
353733802d9SArtem B. Bityutskiy 	dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n",
354280562b2SArtem B. Bityutskiy 		  ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize);
355f97117d1SArtem B. Bityutskiy 
356f97117d1SArtem B. Bityutskiy 	jffs2_add_tn_to_tree(tn, tnp);
357f97117d1SArtem B. Bityutskiy 
358f97117d1SArtem B. Bityutskiy 	return 0;
3591e0da3cbSArtem B. Bityutskiy 
3601e0da3cbSArtem B. Bityutskiy free_out:
3611e0da3cbSArtem B. Bityutskiy 	jffs2_free_tmp_dnode_info(tn);
3621e0da3cbSArtem B. Bityutskiy 	return ret;
363f97117d1SArtem B. Bityutskiy }
364f97117d1SArtem B. Bityutskiy 
365f97117d1SArtem B. Bityutskiy /*
366f97117d1SArtem B. Bityutskiy  * Helper function for jffs2_get_inode_nodes().
367f97117d1SArtem B. Bityutskiy  * It is called every time an unknown node is found.
368f97117d1SArtem B. Bityutskiy  *
3693877f0b6SDavid Woodhouse  * Returns: 0 on success;
370f97117d1SArtem B. Bityutskiy  * 	    1 if the node should be marked obsolete;
371f97117d1SArtem B. Bityutskiy  * 	    negative error code on failure.
372f97117d1SArtem B. Bityutskiy  */
3731e0da3cbSArtem B. Bityutskiy static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, struct jffs2_unknown_node *un)
374f97117d1SArtem B. Bityutskiy {
375f97117d1SArtem B. Bityutskiy 	/* We don't mark unknown nodes as REF_UNCHECKED */
376f97117d1SArtem B. Bityutskiy 	BUG_ON(ref_flags(ref) == REF_UNCHECKED);
377f97117d1SArtem B. Bityutskiy 
378f97117d1SArtem B. Bityutskiy 	un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
379f97117d1SArtem B. Bityutskiy 
380f97117d1SArtem B. Bityutskiy 	switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
381f97117d1SArtem B. Bityutskiy 
382f97117d1SArtem B. Bityutskiy 	case JFFS2_FEATURE_INCOMPAT:
383e0d60137SArtem B. Bityutskiy 		JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n",
384f97117d1SArtem B. Bityutskiy 			    je16_to_cpu(un->nodetype), ref_offset(ref));
385f97117d1SArtem B. Bityutskiy 		/* EEP */
386f97117d1SArtem B. Bityutskiy 		BUG();
387f97117d1SArtem B. Bityutskiy 		break;
388f97117d1SArtem B. Bityutskiy 
389f97117d1SArtem B. Bityutskiy 	case JFFS2_FEATURE_ROCOMPAT:
390e0d60137SArtem B. Bityutskiy 		JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n",
391f97117d1SArtem B. Bityutskiy 			    je16_to_cpu(un->nodetype), ref_offset(ref));
392f97117d1SArtem B. Bityutskiy 		BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
393f97117d1SArtem B. Bityutskiy 		break;
394f97117d1SArtem B. Bityutskiy 
395f97117d1SArtem B. Bityutskiy 	case JFFS2_FEATURE_RWCOMPAT_COPY:
396e0d60137SArtem B. Bityutskiy 		JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
397f97117d1SArtem B. Bityutskiy 			     je16_to_cpu(un->nodetype), ref_offset(ref));
398f97117d1SArtem B. Bityutskiy 		break;
399f97117d1SArtem B. Bityutskiy 
400f97117d1SArtem B. Bityutskiy 	case JFFS2_FEATURE_RWCOMPAT_DELETE:
401e0d60137SArtem B. Bityutskiy 		JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
402f97117d1SArtem B. Bityutskiy 			     je16_to_cpu(un->nodetype), ref_offset(ref));
403f97117d1SArtem B. Bityutskiy 		return 1;
404f97117d1SArtem B. Bityutskiy 	}
405f97117d1SArtem B. Bityutskiy 
406f97117d1SArtem B. Bityutskiy 	return 0;
407f97117d1SArtem B. Bityutskiy }
408f97117d1SArtem B. Bityutskiy 
4091e0da3cbSArtem B. Bityutskiy /*
4101e0da3cbSArtem B. Bityutskiy  * Helper function for jffs2_get_inode_nodes().
4111e0da3cbSArtem B. Bityutskiy  * The function detects whether more data should be read and reads it if yes.
4121e0da3cbSArtem B. Bityutskiy  *
4131e0da3cbSArtem B. Bityutskiy  * Returns: 0 on succes;
4141e0da3cbSArtem B. Bityutskiy  * 	    negative error code on failure.
4151e0da3cbSArtem B. Bityutskiy  */
4161e0da3cbSArtem B. Bityutskiy static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
4171e0da3cbSArtem B. Bityutskiy 		     int right_size, int *rdlen, unsigned char *buf, unsigned char *bufstart)
4181e0da3cbSArtem B. Bityutskiy {
4191e0da3cbSArtem B. Bityutskiy 	int right_len, err, len;
4201e0da3cbSArtem B. Bityutskiy 	size_t retlen;
4211e0da3cbSArtem B. Bityutskiy 	uint32_t offs;
4221e0da3cbSArtem B. Bityutskiy 
4231e0da3cbSArtem B. Bityutskiy 	if (jffs2_is_writebuffered(c)) {
4241e0da3cbSArtem B. Bityutskiy 		right_len = c->wbuf_pagesize - (bufstart - buf);
4251e0da3cbSArtem B. Bityutskiy 		if (right_size + (int)(bufstart - buf) > c->wbuf_pagesize)
4261e0da3cbSArtem B. Bityutskiy 			right_len += c->wbuf_pagesize;
4271e0da3cbSArtem B. Bityutskiy 	} else
4281e0da3cbSArtem B. Bityutskiy 		right_len = right_size;
4291e0da3cbSArtem B. Bityutskiy 
4301e0da3cbSArtem B. Bityutskiy 	if (*rdlen == right_len)
4311e0da3cbSArtem B. Bityutskiy 		return 0;
4321e0da3cbSArtem B. Bityutskiy 
4331e0da3cbSArtem B. Bityutskiy 	/* We need to read more data */
4341e0da3cbSArtem B. Bityutskiy 	offs = ref_offset(ref) + *rdlen;
4351e0da3cbSArtem B. Bityutskiy 	if (jffs2_is_writebuffered(c)) {
4361e0da3cbSArtem B. Bityutskiy 		bufstart = buf + c->wbuf_pagesize;
4371e0da3cbSArtem B. Bityutskiy 		len = c->wbuf_pagesize;
4381e0da3cbSArtem B. Bityutskiy 	} else {
4391e0da3cbSArtem B. Bityutskiy 		bufstart = buf + *rdlen;
4401e0da3cbSArtem B. Bityutskiy 		len = right_size - *rdlen;
4411e0da3cbSArtem B. Bityutskiy 	}
4421e0da3cbSArtem B. Bityutskiy 
443733802d9SArtem B. Bityutskiy 	dbg_readinode("read more %d bytes\n", len);
4441e0da3cbSArtem B. Bityutskiy 
4451e0da3cbSArtem B. Bityutskiy 	err = jffs2_flash_read(c, offs, len, &retlen, bufstart);
4461e0da3cbSArtem B. Bityutskiy 	if (err) {
4471e0da3cbSArtem B. Bityutskiy 		JFFS2_ERROR("can not read %d bytes from 0x%08x, "
4481e0da3cbSArtem B. Bityutskiy 			"error code: %d.\n", len, offs, err);
4491e0da3cbSArtem B. Bityutskiy 		return err;
4501e0da3cbSArtem B. Bityutskiy 	}
4511e0da3cbSArtem B. Bityutskiy 
4521e0da3cbSArtem B. Bityutskiy 	if (retlen < len) {
453fb6a82c9SRandy Dunlap 		JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n",
4541e0da3cbSArtem B. Bityutskiy 				offs, retlen, len);
4551e0da3cbSArtem B. Bityutskiy 		return -EIO;
4561e0da3cbSArtem B. Bityutskiy 	}
4571e0da3cbSArtem B. Bityutskiy 
4581e0da3cbSArtem B. Bityutskiy 	*rdlen = right_len;
4591e0da3cbSArtem B. Bityutskiy 
4601e0da3cbSArtem B. Bityutskiy 	return 0;
4611e0da3cbSArtem B. Bityutskiy }
4621e0da3cbSArtem B. Bityutskiy 
463f97117d1SArtem B. Bityutskiy /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated
464f97117d1SArtem B. Bityutskiy    with this ino, returning the former in order of version */
465f97117d1SArtem B. Bityutskiy static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
466f97117d1SArtem B. Bityutskiy 				 struct rb_root *tnp, struct jffs2_full_dirent **fdp,
467f97117d1SArtem B. Bityutskiy 				 uint32_t *highest_version, uint32_t *latest_mctime,
468f97117d1SArtem B. Bityutskiy 				 uint32_t *mctime_ver)
469f97117d1SArtem B. Bityutskiy {
470f97117d1SArtem B. Bityutskiy 	struct jffs2_raw_node_ref *ref, *valid_ref;
471f97117d1SArtem B. Bityutskiy 	struct rb_root ret_tn = RB_ROOT;
472f97117d1SArtem B. Bityutskiy 	struct jffs2_full_dirent *ret_fd = NULL;
4731e0da3cbSArtem B. Bityutskiy 	unsigned char *buf = NULL;
4741e0da3cbSArtem B. Bityutskiy 	union jffs2_node_union *node;
475f97117d1SArtem B. Bityutskiy 	size_t retlen;
4761e0da3cbSArtem B. Bityutskiy 	int len, err;
477f97117d1SArtem B. Bityutskiy 
478f97117d1SArtem B. Bityutskiy 	*mctime_ver = 0;
479f97117d1SArtem B. Bityutskiy 
480733802d9SArtem B. Bityutskiy 	dbg_readinode("ino #%u\n", f->inocache->ino);
481f97117d1SArtem B. Bityutskiy 
4821e0da3cbSArtem B. Bityutskiy 	if (jffs2_is_writebuffered(c)) {
4831e0da3cbSArtem B. Bityutskiy 		/*
4841e0da3cbSArtem B. Bityutskiy 		 * If we have the write buffer, we assume the minimal I/O unit
4851e0da3cbSArtem B. Bityutskiy 		 * is c->wbuf_pagesize. We implement some optimizations which in
4861e0da3cbSArtem B. Bityutskiy 		 * this case and we need a temporary buffer of size =
4871e0da3cbSArtem B. Bityutskiy 		 * 2*c->wbuf_pagesize bytes (see comments in read_dnode()).
4881e0da3cbSArtem B. Bityutskiy 		 * Basically, we want to read not only the node header, but the
4891e0da3cbSArtem B. Bityutskiy 		 * whole wbuf (NAND page in case of NAND) or 2, if the node
4901e0da3cbSArtem B. Bityutskiy 		 * header overlaps the border between the 2 wbufs.
4911e0da3cbSArtem B. Bityutskiy 		 */
4921e0da3cbSArtem B. Bityutskiy 		len = 2*c->wbuf_pagesize;
4931e0da3cbSArtem B. Bityutskiy 	} else {
4941e0da3cbSArtem B. Bityutskiy 		/*
4951e0da3cbSArtem B. Bityutskiy 		 * When there is no write buffer, the size of the temporary
4961e0da3cbSArtem B. Bityutskiy 		 * buffer is the size of the larges node header.
4971e0da3cbSArtem B. Bityutskiy 		 */
4981e0da3cbSArtem B. Bityutskiy 		len = sizeof(union jffs2_node_union);
4991e0da3cbSArtem B. Bityutskiy 	}
5001e0da3cbSArtem B. Bityutskiy 
5011e0da3cbSArtem B. Bityutskiy 	/* FIXME: in case of NOR and available ->point() this
5021e0da3cbSArtem B. Bityutskiy 	 * needs to be fixed. */
5031e0da3cbSArtem B. Bityutskiy 	buf = kmalloc(len, GFP_KERNEL);
5041e0da3cbSArtem B. Bityutskiy 	if (!buf)
5051e0da3cbSArtem B. Bityutskiy 		return -ENOMEM;
5061e0da3cbSArtem B. Bityutskiy 
507f97117d1SArtem B. Bityutskiy 	spin_lock(&c->erase_completion_lock);
508f97117d1SArtem B. Bityutskiy 	valid_ref = jffs2_first_valid_node(f->inocache->nodes);
5091e0da3cbSArtem B. Bityutskiy 	if (!valid_ref && f->inocache->ino != 1)
5101e0da3cbSArtem B. Bityutskiy 		JFFS2_WARNING("Eep. No valid nodes for ino #%u.\n", f->inocache->ino);
511f97117d1SArtem B. Bityutskiy 	while (valid_ref) {
5121e0da3cbSArtem B. Bityutskiy 		unsigned char *bufstart;
5131e0da3cbSArtem B. Bityutskiy 
514f97117d1SArtem B. Bityutskiy 		/* We can hold a pointer to a non-obsolete node without the spinlock,
515f97117d1SArtem B. Bityutskiy 		   but _obsolete_ nodes may disappear at any time, if the block
516f97117d1SArtem B. Bityutskiy 		   they're in gets erased. So if we mark 'ref' obsolete while we're
517f97117d1SArtem B. Bityutskiy 		   not holding the lock, it can go away immediately. For that reason,
518f97117d1SArtem B. Bityutskiy 		   we find the next valid node first, before processing 'ref'.
519f97117d1SArtem B. Bityutskiy 		*/
520f97117d1SArtem B. Bityutskiy 		ref = valid_ref;
521f97117d1SArtem B. Bityutskiy 		valid_ref = jffs2_first_valid_node(ref->next_in_ino);
522f97117d1SArtem B. Bityutskiy 		spin_unlock(&c->erase_completion_lock);
523f97117d1SArtem B. Bityutskiy 
524f97117d1SArtem B. Bityutskiy 		cond_resched();
525f97117d1SArtem B. Bityutskiy 
5261e0da3cbSArtem B. Bityutskiy 		/*
5271e0da3cbSArtem B. Bityutskiy 		 * At this point we don't know the type of the node we're going
5281e0da3cbSArtem B. Bityutskiy 		 * to read, so we do not know the size of its header. In order
5291e0da3cbSArtem B. Bityutskiy 		 * to minimize the amount of flash IO we assume the node has
5301e0da3cbSArtem B. Bityutskiy 		 * size = JFFS2_MIN_NODE_HEADER.
5311e0da3cbSArtem B. Bityutskiy 		 */
5321e0da3cbSArtem B. Bityutskiy 		if (jffs2_is_writebuffered(c)) {
5331e0da3cbSArtem B. Bityutskiy 			/*
5341e0da3cbSArtem B. Bityutskiy 			 * We treat 'buf' as 2 adjacent wbufs. We want to
5351e0da3cbSArtem B. Bityutskiy 			 * adjust bufstart such as it points to the
5361e0da3cbSArtem B. Bityutskiy 			 * beginning of the node within this wbuf.
5371e0da3cbSArtem B. Bityutskiy 			 */
5381e0da3cbSArtem B. Bityutskiy 			bufstart = buf + (ref_offset(ref) % c->wbuf_pagesize);
5391e0da3cbSArtem B. Bityutskiy 			/* We will read either one wbuf or 2 wbufs. */
5401e0da3cbSArtem B. Bityutskiy 			len = c->wbuf_pagesize - (bufstart - buf);
54139243508SArtem B. Bityutskiy 			if (JFFS2_MIN_NODE_HEADER + (int)(bufstart - buf) > c->wbuf_pagesize) {
54239243508SArtem B. Bityutskiy 				/* The header spans the border of the first wbuf */
5431e0da3cbSArtem B. Bityutskiy 				len += c->wbuf_pagesize;
5441e0da3cbSArtem B. Bityutskiy 			}
5451e0da3cbSArtem B. Bityutskiy 		} else {
5461e0da3cbSArtem B. Bityutskiy 			bufstart = buf;
5471e0da3cbSArtem B. Bityutskiy 			len = JFFS2_MIN_NODE_HEADER;
5481e0da3cbSArtem B. Bityutskiy 		}
5491e0da3cbSArtem B. Bityutskiy 
550733802d9SArtem B. Bityutskiy 		dbg_readinode("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref));
5511e0da3cbSArtem B. Bityutskiy 
552f97117d1SArtem B. Bityutskiy 		/* FIXME: point() */
5531e0da3cbSArtem B. Bityutskiy 		err = jffs2_flash_read(c, ref_offset(ref), len,
5541e0da3cbSArtem B. Bityutskiy 				       &retlen, bufstart);
555f97117d1SArtem B. Bityutskiy 		if (err) {
5561e0da3cbSArtem B. Bityutskiy 			JFFS2_ERROR("can not read %d bytes from 0x%08x, " "error code: %d.\n", len, ref_offset(ref), err);
557f97117d1SArtem B. Bityutskiy 			goto free_out;
558f97117d1SArtem B. Bityutskiy 		}
559f97117d1SArtem B. Bityutskiy 
5601e0da3cbSArtem B. Bityutskiy 		if (retlen < len) {
561fb6a82c9SRandy Dunlap 			JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", ref_offset(ref), retlen, len);
562f97117d1SArtem B. Bityutskiy 			err = -EIO;
563f97117d1SArtem B. Bityutskiy 			goto free_out;
564f97117d1SArtem B. Bityutskiy 		}
565f97117d1SArtem B. Bityutskiy 
5661e0da3cbSArtem B. Bityutskiy 		node = (union jffs2_node_union *)bufstart;
5671e0da3cbSArtem B. Bityutskiy 
5683877f0b6SDavid Woodhouse 		/* No need to mask in the valid bit; it shouldn't be invalid */
5693877f0b6SDavid Woodhouse 		if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) {
5703877f0b6SDavid Woodhouse 			JFFS2_NOTICE("Node header CRC failed at %#08x. {%04x,%04x,%08x,%08x}\n",
5713877f0b6SDavid Woodhouse 				     ref_offset(ref), je16_to_cpu(node->u.magic),
5723877f0b6SDavid Woodhouse 				     je16_to_cpu(node->u.nodetype),
5733877f0b6SDavid Woodhouse 				     je32_to_cpu(node->u.totlen),
5743877f0b6SDavid Woodhouse 				     je32_to_cpu(node->u.hdr_crc));
5753877f0b6SDavid Woodhouse 			jffs2_dbg_dump_node(c, ref_offset(ref));
5763877f0b6SDavid Woodhouse 			jffs2_mark_node_obsolete(c, ref);
5773877f0b6SDavid Woodhouse 			goto cont;
5783877f0b6SDavid Woodhouse 		}
5793877f0b6SDavid Woodhouse 
5801e0da3cbSArtem B. Bityutskiy 		switch (je16_to_cpu(node->u.nodetype)) {
5811e0da3cbSArtem B. Bityutskiy 
5821e0da3cbSArtem B. Bityutskiy 		case JFFS2_NODETYPE_DIRENT:
5831e0da3cbSArtem B. Bityutskiy 
5841e0da3cbSArtem B. Bityutskiy 			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) {
5851e0da3cbSArtem B. Bityutskiy 				err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf, bufstart);
5861e0da3cbSArtem B. Bityutskiy 				if (unlikely(err))
5871e0da3cbSArtem B. Bityutskiy 					goto free_out;
5881e0da3cbSArtem B. Bityutskiy 			}
5891e0da3cbSArtem B. Bityutskiy 
5901e0da3cbSArtem B. Bityutskiy 			err = read_direntry(c, ref, &node->d, retlen, &ret_fd, latest_mctime, mctime_ver);
591f97117d1SArtem B. Bityutskiy 			if (err == 1) {
592f97117d1SArtem B. Bityutskiy 				jffs2_mark_node_obsolete(c, ref);
593f97117d1SArtem B. Bityutskiy 				break;
594f97117d1SArtem B. Bityutskiy 			} else if (unlikely(err))
595f97117d1SArtem B. Bityutskiy 				goto free_out;
596f97117d1SArtem B. Bityutskiy 
5971e0da3cbSArtem B. Bityutskiy 			if (je32_to_cpu(node->d.version) > *highest_version)
5981e0da3cbSArtem B. Bityutskiy 				*highest_version = je32_to_cpu(node->d.version);
599f97117d1SArtem B. Bityutskiy 
600f97117d1SArtem B. Bityutskiy 			break;
601f97117d1SArtem B. Bityutskiy 
602f97117d1SArtem B. Bityutskiy 		case JFFS2_NODETYPE_INODE:
603f97117d1SArtem B. Bityutskiy 
6041e0da3cbSArtem B. Bityutskiy 			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) {
6051e0da3cbSArtem B. Bityutskiy 				err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf, bufstart);
6061e0da3cbSArtem B. Bityutskiy 				if (unlikely(err))
607f97117d1SArtem B. Bityutskiy 					goto free_out;
608f97117d1SArtem B. Bityutskiy 			}
609f97117d1SArtem B. Bityutskiy 
6101e0da3cbSArtem B. Bityutskiy 			err = read_dnode(c, ref, &node->i, &ret_tn, len, latest_mctime, mctime_ver);
611f97117d1SArtem B. Bityutskiy 			if (err == 1) {
612f97117d1SArtem B. Bityutskiy 				jffs2_mark_node_obsolete(c, ref);
613f97117d1SArtem B. Bityutskiy 				break;
614f97117d1SArtem B. Bityutskiy 			} else if (unlikely(err))
615f97117d1SArtem B. Bityutskiy 				goto free_out;
616f97117d1SArtem B. Bityutskiy 
6171e0da3cbSArtem B. Bityutskiy 			if (je32_to_cpu(node->i.version) > *highest_version)
6181e0da3cbSArtem B. Bityutskiy 				*highest_version = je32_to_cpu(node->i.version);
619f97117d1SArtem B. Bityutskiy 
6201da177e4SLinus Torvalds 			break;
6211da177e4SLinus Torvalds 
6221da177e4SLinus Torvalds 		default:
6231e0da3cbSArtem B. Bityutskiy 			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node)) {
6241e0da3cbSArtem B. Bityutskiy 				err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf, bufstart);
6251e0da3cbSArtem B. Bityutskiy 				if (unlikely(err))
6261e0da3cbSArtem B. Bityutskiy 					goto free_out;
6271da177e4SLinus Torvalds 			}
6281da177e4SLinus Torvalds 
6291e0da3cbSArtem B. Bityutskiy 			err = read_unknown(c, ref, &node->u);
630f97117d1SArtem B. Bityutskiy 			if (err == 1) {
631f97117d1SArtem B. Bityutskiy 				jffs2_mark_node_obsolete(c, ref);
632f97117d1SArtem B. Bityutskiy 				break;
633f97117d1SArtem B. Bityutskiy 			} else if (unlikely(err))
634f97117d1SArtem B. Bityutskiy 				goto free_out;
635f97117d1SArtem B. Bityutskiy 
6361da177e4SLinus Torvalds 		}
6373877f0b6SDavid Woodhouse 	cont:
638f97117d1SArtem B. Bityutskiy 		spin_lock(&c->erase_completion_lock);
6391da177e4SLinus Torvalds 	}
6401e0da3cbSArtem B. Bityutskiy 
641f97117d1SArtem B. Bityutskiy 	spin_unlock(&c->erase_completion_lock);
642f97117d1SArtem B. Bityutskiy 	*tnp = ret_tn;
643f97117d1SArtem B. Bityutskiy 	*fdp = ret_fd;
6441e0da3cbSArtem B. Bityutskiy 	kfree(buf);
645f97117d1SArtem B. Bityutskiy 
646733802d9SArtem B. Bityutskiy 	dbg_readinode("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n",
6471e0da3cbSArtem B. Bityutskiy 			f->inocache->ino, *highest_version, *latest_mctime, *mctime_ver);
648f97117d1SArtem B. Bityutskiy 	return 0;
649f97117d1SArtem B. Bityutskiy 
650f97117d1SArtem B. Bityutskiy  free_out:
651f97117d1SArtem B. Bityutskiy 	jffs2_free_tmp_dnode_info_list(&ret_tn);
652f97117d1SArtem B. Bityutskiy 	jffs2_free_full_dirent_list(ret_fd);
6531e0da3cbSArtem B. Bityutskiy 	kfree(buf);
654f97117d1SArtem B. Bityutskiy 	return err;
6551da177e4SLinus Torvalds }
6561da177e4SLinus Torvalds 
6571da177e4SLinus Torvalds static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
6581da177e4SLinus Torvalds 					struct jffs2_inode_info *f,
6591da177e4SLinus Torvalds 					struct jffs2_raw_inode *latest_node)
6601da177e4SLinus Torvalds {
6611e0da3cbSArtem B. Bityutskiy 	struct jffs2_tmp_dnode_info *tn;
6629dee7503SDavid Woodhouse 	struct rb_root tn_list;
6639dee7503SDavid Woodhouse 	struct rb_node *rb, *repl_rb;
6641da177e4SLinus Torvalds 	struct jffs2_full_dirent *fd_list;
6651e0da3cbSArtem B. Bityutskiy 	struct jffs2_full_dnode *fn, *first_fn = NULL;
6661da177e4SLinus Torvalds 	uint32_t crc;
6671da177e4SLinus Torvalds 	uint32_t latest_mctime, mctime_ver;
6681da177e4SLinus Torvalds 	size_t retlen;
6691da177e4SLinus Torvalds 	int ret;
6701da177e4SLinus Torvalds 
671733802d9SArtem B. Bityutskiy 	dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink);
6721da177e4SLinus Torvalds 
6731da177e4SLinus Torvalds 	/* Grab all nodes relevant to this ino */
6741da177e4SLinus Torvalds 	ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver);
6751da177e4SLinus Torvalds 
6761da177e4SLinus Torvalds 	if (ret) {
677e0d60137SArtem B. Bityutskiy 		JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret);
6781da177e4SLinus Torvalds 		if (f->inocache->state == INO_STATE_READING)
6791da177e4SLinus Torvalds 			jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
6801da177e4SLinus Torvalds 		return ret;
6811da177e4SLinus Torvalds 	}
6821da177e4SLinus Torvalds 	f->dents = fd_list;
6831da177e4SLinus Torvalds 
6849dee7503SDavid Woodhouse 	rb = rb_first(&tn_list);
6851da177e4SLinus Torvalds 
6869dee7503SDavid Woodhouse 	while (rb) {
6871e0da3cbSArtem B. Bityutskiy 		cond_resched();
6889dee7503SDavid Woodhouse 		tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb);
6891da177e4SLinus Torvalds 		fn = tn->fn;
6901e0da3cbSArtem B. Bityutskiy 		ret = 1;
691733802d9SArtem B. Bityutskiy 		dbg_readinode("consider node ver %u, phys offset "
6921e0da3cbSArtem B. Bityutskiy 			"%#08x(%d), range %u-%u.\n", tn->version,
6931e0da3cbSArtem B. Bityutskiy 			ref_offset(fn->raw), ref_flags(fn->raw),
6941e0da3cbSArtem B. Bityutskiy 			fn->ofs, fn->ofs + fn->size);
6951da177e4SLinus Torvalds 
6961da177e4SLinus Torvalds 		if (fn->size) {
6971e0da3cbSArtem B. Bityutskiy 			ret = jffs2_add_older_frag_to_fragtree(c, f, tn);
6981e0da3cbSArtem B. Bityutskiy 			/* TODO: the error code isn't checked, check it */
6991e0da3cbSArtem B. Bityutskiy 			jffs2_dbg_fragtree_paranoia_check_nolock(f);
7001e0da3cbSArtem B. Bityutskiy 			BUG_ON(ret < 0);
7011e0da3cbSArtem B. Bityutskiy 			if (!first_fn && ret == 0)
7021e0da3cbSArtem B. Bityutskiy 				first_fn = fn;
7031e0da3cbSArtem B. Bityutskiy 		} else if (!first_fn) {
7041e0da3cbSArtem B. Bityutskiy 			first_fn = fn;
7051da177e4SLinus Torvalds 			f->metadata = fn;
7061e0da3cbSArtem B. Bityutskiy 			ret = 0; /* Prevent freeing the metadata update node */
7071e0da3cbSArtem B. Bityutskiy 		} else
7081e0da3cbSArtem B. Bityutskiy 			jffs2_mark_node_obsolete(c, fn->raw);
7091e0da3cbSArtem B. Bityutskiy 
7109dee7503SDavid Woodhouse 		BUG_ON(rb->rb_left);
7119dee7503SDavid Woodhouse 		if (rb->rb_parent && rb->rb_parent->rb_left == rb) {
7129dee7503SDavid Woodhouse 			/* We were then left-hand child of our parent. We need
7131e0da3cbSArtem B. Bityutskiy 			 * to move our own right-hand child into our place. */
7149dee7503SDavid Woodhouse 			repl_rb = rb->rb_right;
7159dee7503SDavid Woodhouse 			if (repl_rb)
7169dee7503SDavid Woodhouse 				repl_rb->rb_parent = rb->rb_parent;
7179dee7503SDavid Woodhouse 		} else
7189dee7503SDavid Woodhouse 			repl_rb = NULL;
7199dee7503SDavid Woodhouse 
7209dee7503SDavid Woodhouse 		rb = rb_next(rb);
7219dee7503SDavid Woodhouse 
7229dee7503SDavid Woodhouse 		/* Remove the spent tn from the tree; don't bother rebalancing
7231e0da3cbSArtem B. Bityutskiy 		 * but put our right-hand child in our own place. */
7249dee7503SDavid Woodhouse 		if (tn->rb.rb_parent) {
7259dee7503SDavid Woodhouse 			if (tn->rb.rb_parent->rb_left == &tn->rb)
7269dee7503SDavid Woodhouse 				tn->rb.rb_parent->rb_left = repl_rb;
7279dee7503SDavid Woodhouse 			else if (tn->rb.rb_parent->rb_right == &tn->rb)
7289dee7503SDavid Woodhouse 				tn->rb.rb_parent->rb_right = repl_rb;
7299dee7503SDavid Woodhouse 			else BUG();
7309dee7503SDavid Woodhouse 		} else if (tn->rb.rb_right)
7319dee7503SDavid Woodhouse 			tn->rb.rb_right->rb_parent = NULL;
7329dee7503SDavid Woodhouse 
7331da177e4SLinus Torvalds 		jffs2_free_tmp_dnode_info(tn);
7341e0da3cbSArtem B. Bityutskiy 		if (ret) {
735733802d9SArtem B. Bityutskiy 			dbg_readinode("delete dnode %u-%u.\n",
7361e0da3cbSArtem B. Bityutskiy 				fn->ofs, fn->ofs + fn->size);
7371e0da3cbSArtem B. Bityutskiy 			jffs2_free_full_dnode(fn);
7381e0da3cbSArtem B. Bityutskiy 		}
7391da177e4SLinus Torvalds 	}
740e0c8e42fSArtem B. Bityutskiy 	jffs2_dbg_fragtree_paranoia_check_nolock(f);
7411da177e4SLinus Torvalds 
7421e0da3cbSArtem B. Bityutskiy 	BUG_ON(first_fn && ref_obsolete(first_fn->raw));
7431e0da3cbSArtem B. Bityutskiy 
7441e0da3cbSArtem B. Bityutskiy 	fn = first_fn;
7451e0da3cbSArtem B. Bityutskiy 	if (unlikely(!first_fn)) {
7461da177e4SLinus Torvalds 		/* No data nodes for this inode. */
7471da177e4SLinus Torvalds 		if (f->inocache->ino != 1) {
748e0d60137SArtem B. Bityutskiy 			JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino);
7491da177e4SLinus Torvalds 			if (!fd_list) {
7501da177e4SLinus Torvalds 				if (f->inocache->state == INO_STATE_READING)
7511da177e4SLinus Torvalds 					jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
7521da177e4SLinus Torvalds 				return -EIO;
7531da177e4SLinus Torvalds 			}
754e0d60137SArtem B. Bityutskiy 			JFFS2_NOTICE("but it has children so we fake some modes for it\n");
7551da177e4SLinus Torvalds 		}
7561da177e4SLinus Torvalds 		latest_node->mode = cpu_to_jemode(S_IFDIR|S_IRUGO|S_IWUSR|S_IXUGO);
7571da177e4SLinus Torvalds 		latest_node->version = cpu_to_je32(0);
7581da177e4SLinus Torvalds 		latest_node->atime = latest_node->ctime = latest_node->mtime = cpu_to_je32(0);
7591da177e4SLinus Torvalds 		latest_node->isize = cpu_to_je32(0);
7601da177e4SLinus Torvalds 		latest_node->gid = cpu_to_je16(0);
7611da177e4SLinus Torvalds 		latest_node->uid = cpu_to_je16(0);
7621da177e4SLinus Torvalds 		if (f->inocache->state == INO_STATE_READING)
7631da177e4SLinus Torvalds 			jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
7641da177e4SLinus Torvalds 		return 0;
7651da177e4SLinus Torvalds 	}
7661da177e4SLinus Torvalds 
7671da177e4SLinus Torvalds 	ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node);
7681da177e4SLinus Torvalds 	if (ret || retlen != sizeof(*latest_node)) {
769e0d60137SArtem B. Bityutskiy 		JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n",
7701da177e4SLinus Torvalds 			ret, retlen, sizeof(*latest_node));
7711da177e4SLinus Torvalds 		/* FIXME: If this fails, there seems to be a memory leak. Find it. */
7721da177e4SLinus Torvalds 		up(&f->sem);
7731da177e4SLinus Torvalds 		jffs2_do_clear_inode(c, f);
7741da177e4SLinus Torvalds 		return ret?ret:-EIO;
7751da177e4SLinus Torvalds 	}
7761da177e4SLinus Torvalds 
7771da177e4SLinus Torvalds 	crc = crc32(0, latest_node, sizeof(*latest_node)-8);
7781da177e4SLinus Torvalds 	if (crc != je32_to_cpu(latest_node->node_crc)) {
779e0d60137SArtem B. Bityutskiy 		JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n",
780e0d60137SArtem B. Bityutskiy 			f->inocache->ino, ref_offset(fn->raw));
7811da177e4SLinus Torvalds 		up(&f->sem);
7821da177e4SLinus Torvalds 		jffs2_do_clear_inode(c, f);
7831da177e4SLinus Torvalds 		return -EIO;
7841da177e4SLinus Torvalds 	}
7851da177e4SLinus Torvalds 
7861da177e4SLinus Torvalds 	switch(jemode_to_cpu(latest_node->mode) & S_IFMT) {
7871da177e4SLinus Torvalds 	case S_IFDIR:
7881da177e4SLinus Torvalds 		if (mctime_ver > je32_to_cpu(latest_node->version)) {
7891da177e4SLinus Torvalds 			/* The times in the latest_node are actually older than
7901da177e4SLinus Torvalds 			   mctime in the latest dirent. Cheat. */
7911da177e4SLinus Torvalds 			latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime);
7921da177e4SLinus Torvalds 		}
7931da177e4SLinus Torvalds 		break;
7941da177e4SLinus Torvalds 
7951da177e4SLinus Torvalds 
7961da177e4SLinus Torvalds 	case S_IFREG:
7971da177e4SLinus Torvalds 		/* If it was a regular file, truncate it to the latest node's isize */
798f302cd02SArtem B. Bityutskiy 		jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize));
7991da177e4SLinus Torvalds 		break;
8001da177e4SLinus Torvalds 
8011da177e4SLinus Torvalds 	case S_IFLNK:
8021da177e4SLinus Torvalds 		/* Hack to work around broken isize in old symlink code.
8031da177e4SLinus Torvalds 		   Remove this when dwmw2 comes to his senses and stops
8041da177e4SLinus Torvalds 		   symlinks from being an entirely gratuitous special
8051da177e4SLinus Torvalds 		   case. */
8061da177e4SLinus Torvalds 		if (!je32_to_cpu(latest_node->isize))
8071da177e4SLinus Torvalds 			latest_node->isize = latest_node->dsize;
80832f1a95dSArtem B. Bityuckiy 
80932f1a95dSArtem B. Bityuckiy 		if (f->inocache->state != INO_STATE_CHECKING) {
81032f1a95dSArtem B. Bityuckiy 			/* Symlink's inode data is the target path. Read it and
8112b79adccSArtem B. Bityutskiy 			 * keep in RAM to facilitate quick follow symlink
8122b79adccSArtem B. Bityutskiy 			 * operation. */
8132b79adccSArtem B. Bityutskiy 			f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL);
8142b79adccSArtem B. Bityutskiy 			if (!f->target) {
815e0d60137SArtem B. Bityutskiy 				JFFS2_ERROR("can't allocate %d bytes of memory for the symlink target path cache\n", je32_to_cpu(latest_node->csize));
81632f1a95dSArtem B. Bityuckiy 				up(&f->sem);
81732f1a95dSArtem B. Bityuckiy 				jffs2_do_clear_inode(c, f);
81832f1a95dSArtem B. Bityuckiy 				return -ENOMEM;
81932f1a95dSArtem B. Bityuckiy 			}
82032f1a95dSArtem B. Bityuckiy 
82132f1a95dSArtem B. Bityuckiy 			ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node),
8222b79adccSArtem B. Bityutskiy 						je32_to_cpu(latest_node->csize), &retlen, (char *)f->target);
82332f1a95dSArtem B. Bityuckiy 
82432f1a95dSArtem B. Bityuckiy 			if (ret  || retlen != je32_to_cpu(latest_node->csize)) {
82532f1a95dSArtem B. Bityuckiy 				if (retlen != je32_to_cpu(latest_node->csize))
82632f1a95dSArtem B. Bityuckiy 					ret = -EIO;
8272b79adccSArtem B. Bityutskiy 				kfree(f->target);
8282b79adccSArtem B. Bityutskiy 				f->target = NULL;
82932f1a95dSArtem B. Bityuckiy 				up(&f->sem);
83032f1a95dSArtem B. Bityuckiy 				jffs2_do_clear_inode(c, f);
83132f1a95dSArtem B. Bityuckiy 				return -ret;
83232f1a95dSArtem B. Bityuckiy 			}
83332f1a95dSArtem B. Bityuckiy 
8342b79adccSArtem B. Bityutskiy 			f->target[je32_to_cpu(latest_node->csize)] = '\0';
835733802d9SArtem B. Bityutskiy 			dbg_readinode("symlink's target '%s' cached\n", f->target);
83632f1a95dSArtem B. Bityuckiy 		}
83732f1a95dSArtem B. Bityuckiy 
8381da177e4SLinus Torvalds 		/* fall through... */
8391da177e4SLinus Torvalds 
8401da177e4SLinus Torvalds 	case S_IFBLK:
8411da177e4SLinus Torvalds 	case S_IFCHR:
8421da177e4SLinus Torvalds 		/* Certain inode types should have only one data node, and it's
8431da177e4SLinus Torvalds 		   kept as the metadata node */
8441da177e4SLinus Torvalds 		if (f->metadata) {
845e0d60137SArtem B. Bityutskiy 			JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n",
8461da177e4SLinus Torvalds 			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
8471da177e4SLinus Torvalds 			up(&f->sem);
8481da177e4SLinus Torvalds 			jffs2_do_clear_inode(c, f);
8491da177e4SLinus Torvalds 			return -EIO;
8501da177e4SLinus Torvalds 		}
8511da177e4SLinus Torvalds 		if (!frag_first(&f->fragtree)) {
852e0d60137SArtem B. Bityutskiy 			JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n",
8531da177e4SLinus Torvalds 			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
8541da177e4SLinus Torvalds 			up(&f->sem);
8551da177e4SLinus Torvalds 			jffs2_do_clear_inode(c, f);
8561da177e4SLinus Torvalds 			return -EIO;
8571da177e4SLinus Torvalds 		}
8581da177e4SLinus Torvalds 		/* ASSERT: f->fraglist != NULL */
8591da177e4SLinus Torvalds 		if (frag_next(frag_first(&f->fragtree))) {
860e0d60137SArtem B. Bityutskiy 			JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n",
8611da177e4SLinus Torvalds 			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
8621da177e4SLinus Torvalds 			/* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
8631da177e4SLinus Torvalds 			up(&f->sem);
8641da177e4SLinus Torvalds 			jffs2_do_clear_inode(c, f);
8651da177e4SLinus Torvalds 			return -EIO;
8661da177e4SLinus Torvalds 		}
8671da177e4SLinus Torvalds 		/* OK. We're happy */
8681da177e4SLinus Torvalds 		f->metadata = frag_first(&f->fragtree)->node;
8691da177e4SLinus Torvalds 		jffs2_free_node_frag(frag_first(&f->fragtree));
8701da177e4SLinus Torvalds 		f->fragtree = RB_ROOT;
8711da177e4SLinus Torvalds 		break;
8721da177e4SLinus Torvalds 	}
8731da177e4SLinus Torvalds 	if (f->inocache->state == INO_STATE_READING)
8741da177e4SLinus Torvalds 		jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
8751da177e4SLinus Torvalds 
8761da177e4SLinus Torvalds 	return 0;
8771da177e4SLinus Torvalds }
8781da177e4SLinus Torvalds 
879f97117d1SArtem B. Bityutskiy /* Scan the list of all nodes present for this ino, build map of versions, etc. */
880f97117d1SArtem B. Bityutskiy int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
881f97117d1SArtem B. Bityutskiy 			uint32_t ino, struct jffs2_raw_inode *latest_node)
882f97117d1SArtem B. Bityutskiy {
883733802d9SArtem B. Bityutskiy 	dbg_readinode("read inode #%u\n", ino);
884f97117d1SArtem B. Bityutskiy 
885f97117d1SArtem B. Bityutskiy  retry_inocache:
886f97117d1SArtem B. Bityutskiy 	spin_lock(&c->inocache_lock);
887f97117d1SArtem B. Bityutskiy 	f->inocache = jffs2_get_ino_cache(c, ino);
888f97117d1SArtem B. Bityutskiy 
889f97117d1SArtem B. Bityutskiy 	if (f->inocache) {
890f97117d1SArtem B. Bityutskiy 		/* Check its state. We may need to wait before we can use it */
891f97117d1SArtem B. Bityutskiy 		switch(f->inocache->state) {
892f97117d1SArtem B. Bityutskiy 		case INO_STATE_UNCHECKED:
893f97117d1SArtem B. Bityutskiy 		case INO_STATE_CHECKEDABSENT:
894f97117d1SArtem B. Bityutskiy 			f->inocache->state = INO_STATE_READING;
895f97117d1SArtem B. Bityutskiy 			break;
896f97117d1SArtem B. Bityutskiy 
897f97117d1SArtem B. Bityutskiy 		case INO_STATE_CHECKING:
898f97117d1SArtem B. Bityutskiy 		case INO_STATE_GC:
899f97117d1SArtem B. Bityutskiy 			/* If it's in either of these states, we need
900f97117d1SArtem B. Bityutskiy 			   to wait for whoever's got it to finish and
901f97117d1SArtem B. Bityutskiy 			   put it back. */
902733802d9SArtem B. Bityutskiy 			dbg_readinode("waiting for ino #%u in state %d\n", ino, f->inocache->state);
903f97117d1SArtem B. Bityutskiy 			sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
904f97117d1SArtem B. Bityutskiy 			goto retry_inocache;
905f97117d1SArtem B. Bityutskiy 
906f97117d1SArtem B. Bityutskiy 		case INO_STATE_READING:
907f97117d1SArtem B. Bityutskiy 		case INO_STATE_PRESENT:
908f97117d1SArtem B. Bityutskiy 			/* Eep. This should never happen. It can
909f97117d1SArtem B. Bityutskiy 			happen if Linux calls read_inode() again
910f97117d1SArtem B. Bityutskiy 			before clear_inode() has finished though. */
911e0d60137SArtem B. Bityutskiy 			JFFS2_ERROR("Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state);
912f97117d1SArtem B. Bityutskiy 			/* Fail. That's probably better than allowing it to succeed */
913f97117d1SArtem B. Bityutskiy 			f->inocache = NULL;
914f97117d1SArtem B. Bityutskiy 			break;
915f97117d1SArtem B. Bityutskiy 
916f97117d1SArtem B. Bityutskiy 		default:
917f97117d1SArtem B. Bityutskiy 			BUG();
918f97117d1SArtem B. Bityutskiy 		}
919f97117d1SArtem B. Bityutskiy 	}
920f97117d1SArtem B. Bityutskiy 	spin_unlock(&c->inocache_lock);
921f97117d1SArtem B. Bityutskiy 
922f97117d1SArtem B. Bityutskiy 	if (!f->inocache && ino == 1) {
923f97117d1SArtem B. Bityutskiy 		/* Special case - no root inode on medium */
924f97117d1SArtem B. Bityutskiy 		f->inocache = jffs2_alloc_inode_cache();
925f97117d1SArtem B. Bityutskiy 		if (!f->inocache) {
926e0d60137SArtem B. Bityutskiy 			JFFS2_ERROR("cannot allocate inocache for root inode\n");
927f97117d1SArtem B. Bityutskiy 			return -ENOMEM;
928f97117d1SArtem B. Bityutskiy 		}
929733802d9SArtem B. Bityutskiy 		dbg_readinode("creating inocache for root inode\n");
930f97117d1SArtem B. Bityutskiy 		memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
931f97117d1SArtem B. Bityutskiy 		f->inocache->ino = f->inocache->nlink = 1;
932f97117d1SArtem B. Bityutskiy 		f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
933f97117d1SArtem B. Bityutskiy 		f->inocache->state = INO_STATE_READING;
934f97117d1SArtem B. Bityutskiy 		jffs2_add_ino_cache(c, f->inocache);
935f97117d1SArtem B. Bityutskiy 	}
936f97117d1SArtem B. Bityutskiy 	if (!f->inocache) {
937e0d60137SArtem B. Bityutskiy 		JFFS2_ERROR("requestied to read an nonexistent ino %u\n", ino);
938f97117d1SArtem B. Bityutskiy 		return -ENOENT;
939f97117d1SArtem B. Bityutskiy 	}
940f97117d1SArtem B. Bityutskiy 
941f97117d1SArtem B. Bityutskiy 	return jffs2_do_read_inode_internal(c, f, latest_node);
942f97117d1SArtem B. Bityutskiy }
943f97117d1SArtem B. Bityutskiy 
944f97117d1SArtem B. Bityutskiy int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
945f97117d1SArtem B. Bityutskiy {
946f97117d1SArtem B. Bityutskiy 	struct jffs2_raw_inode n;
947f97117d1SArtem B. Bityutskiy 	struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL);
948f97117d1SArtem B. Bityutskiy 	int ret;
949f97117d1SArtem B. Bityutskiy 
950f97117d1SArtem B. Bityutskiy 	if (!f)
951f97117d1SArtem B. Bityutskiy 		return -ENOMEM;
952f97117d1SArtem B. Bityutskiy 
953f97117d1SArtem B. Bityutskiy 	memset(f, 0, sizeof(*f));
954f97117d1SArtem B. Bityutskiy 	init_MUTEX_LOCKED(&f->sem);
955f97117d1SArtem B. Bityutskiy 	f->inocache = ic;
956f97117d1SArtem B. Bityutskiy 
957f97117d1SArtem B. Bityutskiy 	ret = jffs2_do_read_inode_internal(c, f, &n);
958f97117d1SArtem B. Bityutskiy 	if (!ret) {
959f97117d1SArtem B. Bityutskiy 		up(&f->sem);
960f97117d1SArtem B. Bityutskiy 		jffs2_do_clear_inode(c, f);
961f97117d1SArtem B. Bityutskiy 	}
962f97117d1SArtem B. Bityutskiy 	kfree (f);
963f97117d1SArtem B. Bityutskiy 	return ret;
964f97117d1SArtem B. Bityutskiy }
965f97117d1SArtem B. Bityutskiy 
9661da177e4SLinus Torvalds void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
9671da177e4SLinus Torvalds {
9681da177e4SLinus Torvalds 	struct jffs2_full_dirent *fd, *fds;
9691da177e4SLinus Torvalds 	int deleted;
9701da177e4SLinus Torvalds 
9711da177e4SLinus Torvalds 	down(&f->sem);
9721da177e4SLinus Torvalds 	deleted = f->inocache && !f->inocache->nlink;
9731da177e4SLinus Torvalds 
97467e345d1SDavid Woodhouse 	if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
97567e345d1SDavid Woodhouse 		jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);
97667e345d1SDavid Woodhouse 
9771da177e4SLinus Torvalds 	if (f->metadata) {
9781da177e4SLinus Torvalds 		if (deleted)
9791da177e4SLinus Torvalds 			jffs2_mark_node_obsolete(c, f->metadata->raw);
9801da177e4SLinus Torvalds 		jffs2_free_full_dnode(f->metadata);
9811da177e4SLinus Torvalds 	}
9821da177e4SLinus Torvalds 
9831da177e4SLinus Torvalds 	jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL);
9841da177e4SLinus Torvalds 
9852b79adccSArtem B. Bityutskiy 	if (f->target) {
9862b79adccSArtem B. Bityutskiy 		kfree(f->target);
9872b79adccSArtem B. Bityutskiy 		f->target = NULL;
98832f1a95dSArtem B. Bityuckiy 	}
9891da177e4SLinus Torvalds 
9902b79adccSArtem B. Bityutskiy 	fds = f->dents;
9911da177e4SLinus Torvalds 	while(fds) {
9921da177e4SLinus Torvalds 		fd = fds;
9931da177e4SLinus Torvalds 		fds = fd->next;
9941da177e4SLinus Torvalds 		jffs2_free_full_dirent(fd);
9951da177e4SLinus Torvalds 	}
9961da177e4SLinus Torvalds 
99767e345d1SDavid Woodhouse 	if (f->inocache && f->inocache->state != INO_STATE_CHECKING) {
9981da177e4SLinus Torvalds 		jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
99967e345d1SDavid Woodhouse 		if (f->inocache->nodes == (void *)f->inocache)
100067e345d1SDavid Woodhouse 			jffs2_del_ino_cache(c, f->inocache);
100167e345d1SDavid Woodhouse 	}
10021da177e4SLinus Torvalds 
10031da177e4SLinus Torvalds 	up(&f->sem);
10041da177e4SLinus Torvalds }
1005