xref: /openbmc/linux/fs/jffs2/readinode.c (revision f97117d1)
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  *
10f97117d1SArtem B. Bityutskiy  * $Id: readinode.c,v 1.131 2005/07/27 14:46:11 dedekind Exp $
111da177e4SLinus Torvalds  *
121da177e4SLinus Torvalds  */
131da177e4SLinus Torvalds 
141da177e4SLinus Torvalds #include <linux/kernel.h>
151da177e4SLinus Torvalds #include <linux/slab.h>
161da177e4SLinus Torvalds #include <linux/fs.h>
171da177e4SLinus Torvalds #include <linux/crc32.h>
181da177e4SLinus Torvalds #include <linux/pagemap.h>
191da177e4SLinus Torvalds #include <linux/mtd/mtd.h>
201da177e4SLinus Torvalds #include <linux/compiler.h>
211da177e4SLinus Torvalds #include "nodelist.h"
221da177e4SLinus Torvalds 
23f302cd02SArtem B. Bityutskiy void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size)
241da177e4SLinus Torvalds {
251da177e4SLinus Torvalds 	struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size);
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds 	D1(printk(KERN_DEBUG "Truncating fraglist to 0x%08x bytes\n", size));
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds 	/* We know frag->ofs <= size. That's what lookup does for us */
301da177e4SLinus Torvalds 	if (frag && frag->ofs != size) {
311da177e4SLinus Torvalds 		if (frag->ofs+frag->size >= size) {
321da177e4SLinus Torvalds 			D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size));
331da177e4SLinus Torvalds 			frag->size = size - frag->ofs;
341da177e4SLinus Torvalds 		}
351da177e4SLinus Torvalds 		frag = frag_next(frag);
361da177e4SLinus Torvalds 	}
371da177e4SLinus Torvalds 	while (frag && frag->ofs >= size) {
381da177e4SLinus Torvalds 		struct jffs2_node_frag *next = frag_next(frag);
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds 		D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size));
411da177e4SLinus Torvalds 		frag_erase(frag, list);
421da177e4SLinus Torvalds 		jffs2_obsolete_node_frag(c, frag);
431da177e4SLinus Torvalds 		frag = next;
441da177e4SLinus Torvalds 	}
451da177e4SLinus Torvalds }
461da177e4SLinus Torvalds 
47f97117d1SArtem B. Bityutskiy /*
48f97117d1SArtem B. Bityutskiy  * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in
49f97117d1SArtem B. Bityutskiy  * order of increasing version.
50f97117d1SArtem B. Bityutskiy  */
51f97117d1SArtem B. Bityutskiy static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list)
521da177e4SLinus Torvalds {
53f97117d1SArtem B. Bityutskiy 	struct rb_node **p = &list->rb_node;
54f97117d1SArtem B. Bityutskiy 	struct rb_node * parent = NULL;
55f97117d1SArtem B. Bityutskiy 	struct jffs2_tmp_dnode_info *this;
561da177e4SLinus Torvalds 
57f97117d1SArtem B. Bityutskiy 	while (*p) {
58f97117d1SArtem B. Bityutskiy 		parent = *p;
59f97117d1SArtem B. Bityutskiy 		this = rb_entry(parent, struct jffs2_tmp_dnode_info, rb);
601da177e4SLinus Torvalds 
61f97117d1SArtem B. Bityutskiy 		/* There may actually be a collision here, but it doesn't
62f97117d1SArtem B. Bityutskiy 		   actually matter. As long as the two nodes with the same
63f97117d1SArtem B. Bityutskiy 		   version are together, it's all fine. */
64f97117d1SArtem B. Bityutskiy 		if (tn->version < this->version)
65f97117d1SArtem B. Bityutskiy 			p = &(*p)->rb_left;
66f97117d1SArtem B. Bityutskiy 		else
67f97117d1SArtem B. Bityutskiy 			p = &(*p)->rb_right;
68f97117d1SArtem B. Bityutskiy         }
691da177e4SLinus Torvalds 
70f97117d1SArtem B. Bityutskiy 	rb_link_node(&tn->rb, parent, p);
71f97117d1SArtem B. Bityutskiy 	rb_insert_color(&tn->rb, list);
72f97117d1SArtem B. Bityutskiy }
73f97117d1SArtem B. Bityutskiy 
74f97117d1SArtem B. Bityutskiy static void jffs2_free_tmp_dnode_info_list(struct rb_root *list)
75f97117d1SArtem B. Bityutskiy {
76f97117d1SArtem B. Bityutskiy 	struct rb_node *this;
77f97117d1SArtem B. Bityutskiy 	struct jffs2_tmp_dnode_info *tn;
78f97117d1SArtem B. Bityutskiy 
79f97117d1SArtem B. Bityutskiy 	this = list->rb_node;
80f97117d1SArtem B. Bityutskiy 
81f97117d1SArtem B. Bityutskiy 	/* Now at bottom of tree */
82f97117d1SArtem B. Bityutskiy 	while (this) {
83f97117d1SArtem B. Bityutskiy 		if (this->rb_left)
84f97117d1SArtem B. Bityutskiy 			this = this->rb_left;
85f97117d1SArtem B. Bityutskiy 		else if (this->rb_right)
86f97117d1SArtem B. Bityutskiy 			this = this->rb_right;
87f97117d1SArtem B. Bityutskiy 		else {
88f97117d1SArtem B. Bityutskiy 			tn = rb_entry(this, struct jffs2_tmp_dnode_info, rb);
89f97117d1SArtem B. Bityutskiy 			jffs2_free_full_dnode(tn->fn);
90f97117d1SArtem B. Bityutskiy 			jffs2_free_tmp_dnode_info(tn);
91f97117d1SArtem B. Bityutskiy 
92f97117d1SArtem B. Bityutskiy 			this = this->rb_parent;
93f97117d1SArtem B. Bityutskiy 			if (!this)
941da177e4SLinus Torvalds 				break;
951da177e4SLinus Torvalds 
96f97117d1SArtem B. Bityutskiy 			if (this->rb_left == &tn->rb)
97f97117d1SArtem B. Bityutskiy 				this->rb_left = NULL;
98f97117d1SArtem B. Bityutskiy 			else if (this->rb_right == &tn->rb)
99f97117d1SArtem B. Bityutskiy 				this->rb_right = NULL;
100f97117d1SArtem B. Bityutskiy 			else BUG();
101f97117d1SArtem B. Bityutskiy 		}
102f97117d1SArtem B. Bityutskiy 	}
103f97117d1SArtem B. Bityutskiy 	list->rb_node = NULL;
104f97117d1SArtem B. Bityutskiy }
1051da177e4SLinus Torvalds 
106f97117d1SArtem B. Bityutskiy static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd)
107f97117d1SArtem B. Bityutskiy {
108f97117d1SArtem B. Bityutskiy 	struct jffs2_full_dirent *next;
109f97117d1SArtem B. Bityutskiy 
110f97117d1SArtem B. Bityutskiy 	while (fd) {
111f97117d1SArtem B. Bityutskiy 		next = fd->next;
112f97117d1SArtem B. Bityutskiy 		jffs2_free_full_dirent(fd);
113f97117d1SArtem B. Bityutskiy 		fd = next;
114f97117d1SArtem B. Bityutskiy 	}
115f97117d1SArtem B. Bityutskiy }
116f97117d1SArtem B. Bityutskiy 
117f97117d1SArtem B. Bityutskiy /* Returns first valid node after 'ref'. May return 'ref' */
118f97117d1SArtem B. Bityutskiy static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_ref *ref)
119f97117d1SArtem B. Bityutskiy {
120f97117d1SArtem B. Bityutskiy 	while (ref && ref->next_in_ino) {
121f97117d1SArtem B. Bityutskiy 		if (!ref_obsolete(ref))
122f97117d1SArtem B. Bityutskiy 			return ref;
123f97117d1SArtem B. Bityutskiy 		D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref)));
124f97117d1SArtem B. Bityutskiy 		ref = ref->next_in_ino;
125f97117d1SArtem B. Bityutskiy 	}
126f97117d1SArtem B. Bityutskiy 	return NULL;
127f97117d1SArtem B. Bityutskiy }
128f97117d1SArtem B. Bityutskiy 
129f97117d1SArtem B. Bityutskiy /*
130f97117d1SArtem B. Bityutskiy  * Helper function for jffs2_get_inode_nodes().
131f97117d1SArtem B. Bityutskiy  * It is called every time an directory entry node is found.
132f97117d1SArtem B. Bityutskiy  *
133f97117d1SArtem B. Bityutskiy  * Returns: 0 on succes;
134f97117d1SArtem B. Bityutskiy  * 	    1 if the node should be marked obsolete;
135f97117d1SArtem B. Bityutskiy  * 	    negative error code on failure.
136f97117d1SArtem B. Bityutskiy  */
137f97117d1SArtem B. Bityutskiy static inline int
138f97117d1SArtem B. Bityutskiy read_direntry(struct jffs2_sb_info *c,
139f97117d1SArtem B. Bityutskiy 	      struct jffs2_raw_node_ref *ref,
140f97117d1SArtem B. Bityutskiy 	      struct jffs2_raw_dirent *rd,
141f97117d1SArtem B. Bityutskiy 	      uint32_t read,
142f97117d1SArtem B. Bityutskiy 	      struct jffs2_full_dirent **fdp,
143f97117d1SArtem B. Bityutskiy 	      int32_t *latest_mctime,
144f97117d1SArtem B. Bityutskiy 	      uint32_t *mctime_ver)
145f97117d1SArtem B. Bityutskiy {
146f97117d1SArtem B. Bityutskiy 	struct jffs2_full_dirent *fd;
147f97117d1SArtem B. Bityutskiy 
148f97117d1SArtem B. Bityutskiy 	/* The direntry nodes are checked during the flash scanning */
149f97117d1SArtem B. Bityutskiy 	BUG_ON(ref_flags(ref) == REF_UNCHECKED);
150f97117d1SArtem B. Bityutskiy 	/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
151f97117d1SArtem B. Bityutskiy 	BUG_ON(ref_obsolete(ref));
152f97117d1SArtem B. Bityutskiy 
153f97117d1SArtem B. Bityutskiy 	/* Sanity check */
154f97117d1SArtem B. Bityutskiy 	if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
155f97117d1SArtem B. Bityutskiy 		printk(KERN_ERR "Error! Illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
156f97117d1SArtem B. Bityutskiy 		       ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
157f97117d1SArtem B. Bityutskiy 		return 1;
158f97117d1SArtem B. Bityutskiy 	}
159f97117d1SArtem B. Bityutskiy 
160f97117d1SArtem B. Bityutskiy 	fd = jffs2_alloc_full_dirent(rd->nsize + 1);
161f97117d1SArtem B. Bityutskiy 	if (unlikely(!fd))
162f97117d1SArtem B. Bityutskiy 		return -ENOMEM;
163f97117d1SArtem B. Bityutskiy 
164f97117d1SArtem B. Bityutskiy 	fd->raw = ref;
165f97117d1SArtem B. Bityutskiy 	fd->version = je32_to_cpu(rd->version);
166f97117d1SArtem B. Bityutskiy 	fd->ino = je32_to_cpu(rd->ino);
167f97117d1SArtem B. Bityutskiy 	fd->type = rd->type;
168f97117d1SArtem B. Bityutskiy 
169f97117d1SArtem B. Bityutskiy 	/* Pick out the mctime of the latest dirent */
170f97117d1SArtem B. Bityutskiy 	if(fd->version > *mctime_ver) {
171f97117d1SArtem B. Bityutskiy 		*mctime_ver = fd->version;
172f97117d1SArtem B. Bityutskiy 		*latest_mctime = je32_to_cpu(rd->mctime);
173f97117d1SArtem B. Bityutskiy 	}
174f97117d1SArtem B. Bityutskiy 
175f97117d1SArtem B. Bityutskiy 	/*
176f97117d1SArtem B. Bityutskiy 	 * Copy as much of the name as possible from the raw
177f97117d1SArtem B. Bityutskiy 	 * dirent we've already read from the flash.
178f97117d1SArtem B. Bityutskiy 	 */
179f97117d1SArtem B. Bityutskiy 	if (read > sizeof(*rd))
180f97117d1SArtem B. Bityutskiy 		memcpy(&fd->name[0], &rd->name[0],
181f97117d1SArtem B. Bityutskiy 		       min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) ));
182f97117d1SArtem B. Bityutskiy 
183f97117d1SArtem B. Bityutskiy 	/* Do we need to copy any more of the name directly from the flash? */
184f97117d1SArtem B. Bityutskiy 	if (rd->nsize + sizeof(*rd) > read) {
185f97117d1SArtem B. Bityutskiy 		/* FIXME: point() */
186f97117d1SArtem B. Bityutskiy 		int err;
187f97117d1SArtem B. Bityutskiy 		int already = read - sizeof(*rd);
188f97117d1SArtem B. Bityutskiy 
189f97117d1SArtem B. Bityutskiy 		err = jffs2_flash_read(c, (ref_offset(ref)) + read,
190f97117d1SArtem B. Bityutskiy 				rd->nsize - already, &read, &fd->name[already]);
191f97117d1SArtem B. Bityutskiy 		if (unlikely(read != rd->nsize - already) && likely(!err))
192f97117d1SArtem B. Bityutskiy 			return -EIO;
193f97117d1SArtem B. Bityutskiy 
194f97117d1SArtem B. Bityutskiy 		if (unlikely(err)) {
195f97117d1SArtem B. Bityutskiy 			printk(KERN_WARNING "Read remainder of name: error %d\n", err);
196f97117d1SArtem B. Bityutskiy 			jffs2_free_full_dirent(fd);
197f97117d1SArtem B. Bityutskiy 			return -EIO;
198f97117d1SArtem B. Bityutskiy 		}
199f97117d1SArtem B. Bityutskiy 	}
200f97117d1SArtem B. Bityutskiy 
201f97117d1SArtem B. Bityutskiy 	fd->nhash = full_name_hash(fd->name, rd->nsize);
202f97117d1SArtem B. Bityutskiy 	fd->next = NULL;
203f97117d1SArtem B. Bityutskiy 	fd->name[rd->nsize] = '\0';
204f97117d1SArtem B. Bityutskiy 
205f97117d1SArtem B. Bityutskiy 	/*
206f97117d1SArtem B. Bityutskiy 	 * Wheee. We now have a complete jffs2_full_dirent structure, with
207f97117d1SArtem B. Bityutskiy 	 * the name in it and everything. Link it into the list
208f97117d1SArtem B. Bityutskiy 	 */
209f97117d1SArtem B. Bityutskiy 	D1(printk(KERN_DEBUG "Adding fd \"%s\", ino #%u\n", fd->name, fd->ino));
210f97117d1SArtem B. Bityutskiy 
211f97117d1SArtem B. Bityutskiy 	jffs2_add_fd_to_list(c, fd, fdp);
212f97117d1SArtem B. Bityutskiy 
213f97117d1SArtem B. Bityutskiy 	return 0;
214f97117d1SArtem B. Bityutskiy }
215f97117d1SArtem B. Bityutskiy 
216f97117d1SArtem B. Bityutskiy /*
217f97117d1SArtem B. Bityutskiy  * Helper function for jffs2_get_inode_nodes().
218f97117d1SArtem B. Bityutskiy  * It is called every time an inode node is found.
219f97117d1SArtem B. Bityutskiy  *
220f97117d1SArtem B. Bityutskiy  * Returns: 0 on succes;
221f97117d1SArtem B. Bityutskiy  * 	    1 if the node should be marked obsolete;
222f97117d1SArtem B. Bityutskiy  * 	    negative error code on failure.
223f97117d1SArtem B. Bityutskiy  */
224f97117d1SArtem B. Bityutskiy static inline int
225f97117d1SArtem B. Bityutskiy read_dnode(struct jffs2_sb_info *c,
226f97117d1SArtem B. Bityutskiy 	   struct jffs2_raw_node_ref *ref,
227f97117d1SArtem B. Bityutskiy 	   struct jffs2_raw_inode *rd,
228f97117d1SArtem B. Bityutskiy 	   uint32_t read,
229f97117d1SArtem B. Bityutskiy 	   struct rb_root *tnp,
230f97117d1SArtem B. Bityutskiy 	   int32_t *latest_mctime,
231f97117d1SArtem B. Bityutskiy 	   uint32_t *mctime_ver)
232f97117d1SArtem B. Bityutskiy {
233f97117d1SArtem B. Bityutskiy 	struct jffs2_eraseblock *jeb;
234f97117d1SArtem B. Bityutskiy 	struct jffs2_tmp_dnode_info *tn;
235f97117d1SArtem B. Bityutskiy 
236f97117d1SArtem B. Bityutskiy 	/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
237f97117d1SArtem B. Bityutskiy 	BUG_ON(ref_obsolete(ref));
238f97117d1SArtem B. Bityutskiy 
239f97117d1SArtem B. Bityutskiy 	/* If we've never checked the CRCs on this node, check them now */
240f97117d1SArtem B. Bityutskiy 	if (ref_flags(ref) == REF_UNCHECKED) {
241f97117d1SArtem B. Bityutskiy 		uint32_t crc, len;
242f97117d1SArtem B. Bityutskiy 
243f97117d1SArtem B. Bityutskiy 		crc = crc32(0, rd, sizeof(*rd) - 8);
244f97117d1SArtem B. Bityutskiy 		if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
245f97117d1SArtem B. Bityutskiy 			printk(KERN_WARNING "Header CRC failed on node at %#08x: read %#08x, calculated %#08x\n",
246f97117d1SArtem B. Bityutskiy 					ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
247f97117d1SArtem B. Bityutskiy 			return 1;
248f97117d1SArtem B. Bityutskiy 		}
249f97117d1SArtem B. Bityutskiy 
250f97117d1SArtem B. Bityutskiy 		/* Sanity checks */
251f97117d1SArtem B. Bityutskiy 		if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) ||
252f97117d1SArtem B. Bityutskiy 		    unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) {
253f97117d1SArtem B. Bityutskiy 			printk(KERN_WARNING "Inode corrupted at %#08x, totlen %d, #ino  %d, version %d, "
254f97117d1SArtem B. Bityutskiy 				"isize %d, csize %d, dsize %d \n",
255f97117d1SArtem B. Bityutskiy 				ref_offset(ref),  je32_to_cpu(rd->totlen),  je32_to_cpu(rd->ino),
256f97117d1SArtem B. Bityutskiy 				je32_to_cpu(rd->version),  je32_to_cpu(rd->isize),
257f97117d1SArtem B. Bityutskiy 				je32_to_cpu(rd->csize), je32_to_cpu(rd->dsize));
258f97117d1SArtem B. Bityutskiy 			return 1;
259f97117d1SArtem B. Bityutskiy 		}
260f97117d1SArtem B. Bityutskiy 
261f97117d1SArtem B. Bityutskiy 		if (rd->compr != JFFS2_COMPR_ZERO && je32_to_cpu(rd->csize)) {
262f97117d1SArtem B. Bityutskiy 			unsigned char *buf = NULL;
263f97117d1SArtem B. Bityutskiy 			uint32_t pointed = 0;
264f97117d1SArtem B. Bityutskiy 			int err;
265f97117d1SArtem B. Bityutskiy #ifndef __ECOS
266f97117d1SArtem B. Bityutskiy 			if (c->mtd->point) {
267f97117d1SArtem B. Bityutskiy 				err = c->mtd->point (c->mtd, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize),
268f97117d1SArtem B. Bityutskiy 						     &read, &buf);
269f97117d1SArtem B. Bityutskiy 				if (unlikely(read < je32_to_cpu(rd->csize)) && likely(!err)) {
270f97117d1SArtem B. Bityutskiy 					D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", read));
271f97117d1SArtem B. Bityutskiy 					c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd),
272f97117d1SArtem B. Bityutskiy 							je32_to_cpu(rd->csize));
273f97117d1SArtem B. Bityutskiy 				} else if (unlikely(err)){
274f97117d1SArtem B. Bityutskiy 					D1(printk(KERN_DEBUG "MTD point failed %d\n", err));
275f97117d1SArtem B. Bityutskiy 				} else
276f97117d1SArtem B. Bityutskiy 					pointed = 1; /* succefully pointed to device */
277f97117d1SArtem B. Bityutskiy 			}
278f97117d1SArtem B. Bityutskiy #endif
279f97117d1SArtem B. Bityutskiy 			if(!pointed){
280f97117d1SArtem B. Bityutskiy 				buf = kmalloc(je32_to_cpu(rd->csize), GFP_KERNEL);
281f97117d1SArtem B. Bityutskiy 				if (!buf)
282f97117d1SArtem B. Bityutskiy 					return -ENOMEM;
283f97117d1SArtem B. Bityutskiy 
284f97117d1SArtem B. Bityutskiy 				err = jffs2_flash_read(c, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize),
285f97117d1SArtem B. Bityutskiy 							&read, buf);
286f97117d1SArtem B. Bityutskiy 				if (unlikely(read != je32_to_cpu(rd->csize)) && likely(!err))
287f97117d1SArtem B. Bityutskiy 					err = -EIO;
288f97117d1SArtem B. Bityutskiy 				if (err) {
289f97117d1SArtem B. Bityutskiy 					kfree(buf);
290f97117d1SArtem B. Bityutskiy 					return err;
291f97117d1SArtem B. Bityutskiy 				}
292f97117d1SArtem B. Bityutskiy 			}
293f97117d1SArtem B. Bityutskiy 			crc = crc32(0, buf, je32_to_cpu(rd->csize));
294f97117d1SArtem B. Bityutskiy 			if(!pointed)
295f97117d1SArtem B. Bityutskiy 				kfree(buf);
296f97117d1SArtem B. Bityutskiy #ifndef __ECOS
297f97117d1SArtem B. Bityutskiy 			else
298f97117d1SArtem B. Bityutskiy 				c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize));
299f97117d1SArtem B. Bityutskiy #endif
300f97117d1SArtem B. Bityutskiy 
301f97117d1SArtem B. Bityutskiy 			if (crc != je32_to_cpu(rd->data_crc)) {
302f97117d1SArtem B. Bityutskiy 				printk(KERN_NOTICE "Data CRC failed on node at %#08x: read %#08x, calculated %#08x\n",
303f97117d1SArtem B. Bityutskiy 				       ref_offset(ref), je32_to_cpu(rd->data_crc), crc);
304f97117d1SArtem B. Bityutskiy 				return 1;
305f97117d1SArtem B. Bityutskiy 			}
306f97117d1SArtem B. Bityutskiy 
307f97117d1SArtem B. Bityutskiy 		}
308f97117d1SArtem B. Bityutskiy 
309f97117d1SArtem B. Bityutskiy 		/* Mark the node as having been checked and fix the accounting accordingly */
310f97117d1SArtem B. Bityutskiy 		jeb = &c->blocks[ref->flash_offset / c->sector_size];
311f97117d1SArtem B. Bityutskiy 		len = ref_totlen(c, jeb, ref);
312f97117d1SArtem B. Bityutskiy 
313f97117d1SArtem B. Bityutskiy 		spin_lock(&c->erase_completion_lock);
314f97117d1SArtem B. Bityutskiy 		jeb->used_size += len;
315f97117d1SArtem B. Bityutskiy 		jeb->unchecked_size -= len;
316f97117d1SArtem B. Bityutskiy 		c->used_size += len;
317f97117d1SArtem B. Bityutskiy 		c->unchecked_size -= len;
318f97117d1SArtem B. Bityutskiy 
319f97117d1SArtem B. Bityutskiy 		/* If node covers at least a whole page, or if it starts at the
320f97117d1SArtem B. Bityutskiy 		   beginning of a page and runs to the end of the file, or if
321f97117d1SArtem B. Bityutskiy 		   it's a hole node, mark it REF_PRISTINE, else REF_NORMAL.
322f97117d1SArtem B. Bityutskiy 
323f97117d1SArtem B. Bityutskiy 		   If it's actually overlapped, it'll get made NORMAL (or OBSOLETE)
324f97117d1SArtem B. Bityutskiy 		   when the overlapping node(s) get added to the tree anyway.
325f97117d1SArtem B. Bityutskiy 		*/
326f97117d1SArtem B. Bityutskiy 		if ((je32_to_cpu(rd->dsize) >= PAGE_CACHE_SIZE) ||
327f97117d1SArtem B. Bityutskiy 		    ( ((je32_to_cpu(rd->offset) & (PAGE_CACHE_SIZE-1))==0) &&
328f97117d1SArtem B. Bityutskiy 		      (je32_to_cpu(rd->dsize) + je32_to_cpu(rd->offset) == je32_to_cpu(rd->isize)))) {
329f97117d1SArtem B. Bityutskiy 			D1(printk(KERN_DEBUG "Marking node at %#08x REF_PRISTINE\n", ref_offset(ref)));
330f97117d1SArtem B. Bityutskiy 			ref->flash_offset = ref_offset(ref) | REF_PRISTINE;
331f97117d1SArtem B. Bityutskiy 		} else {
332f97117d1SArtem B. Bityutskiy 			D1(printk(KERN_DEBUG "Marking node at %#08x REF_NORMAL\n", ref_offset(ref)));
333f97117d1SArtem B. Bityutskiy 			ref->flash_offset = ref_offset(ref) | REF_NORMAL;
334f97117d1SArtem B. Bityutskiy 		}
335f97117d1SArtem B. Bityutskiy 		spin_unlock(&c->erase_completion_lock);
336f97117d1SArtem B. Bityutskiy 	}
337f97117d1SArtem B. Bityutskiy 
338f97117d1SArtem B. Bityutskiy 	tn = jffs2_alloc_tmp_dnode_info();
339f97117d1SArtem B. Bityutskiy 	if (!tn) {
340f97117d1SArtem B. Bityutskiy 		D1(printk(KERN_DEBUG "alloc tn failed\n"));
341f97117d1SArtem B. Bityutskiy 		return -ENOMEM;
342f97117d1SArtem B. Bityutskiy 	}
343f97117d1SArtem B. Bityutskiy 
344f97117d1SArtem B. Bityutskiy 	tn->fn = jffs2_alloc_full_dnode();
345f97117d1SArtem B. Bityutskiy 	if (!tn->fn) {
346f97117d1SArtem B. Bityutskiy 		D1(printk(KERN_DEBUG "alloc fn failed\n"));
347f97117d1SArtem B. Bityutskiy 		jffs2_free_tmp_dnode_info(tn);
348f97117d1SArtem B. Bityutskiy 		return -ENOMEM;
349f97117d1SArtem B. Bityutskiy 	}
350f97117d1SArtem B. Bityutskiy 
351f97117d1SArtem B. Bityutskiy 	tn->version = je32_to_cpu(rd->version);
352f97117d1SArtem B. Bityutskiy 	tn->fn->ofs = je32_to_cpu(rd->offset);
353f97117d1SArtem B. Bityutskiy 	tn->fn->raw = ref;
354f97117d1SArtem B. Bityutskiy 
355f97117d1SArtem B. Bityutskiy 	/* There was a bug where we wrote hole nodes out with
356f97117d1SArtem B. Bityutskiy 	   csize/dsize swapped. Deal with it */
357f97117d1SArtem B. Bityutskiy 	if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && je32_to_cpu(rd->csize))
358f97117d1SArtem B. Bityutskiy 		tn->fn->size = je32_to_cpu(rd->csize);
359f97117d1SArtem B. Bityutskiy 	else // normal case...
360f97117d1SArtem B. Bityutskiy 		tn->fn->size = je32_to_cpu(rd->dsize);
361f97117d1SArtem B. Bityutskiy 
362f97117d1SArtem B. Bityutskiy 	D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %#04x, dsize %#04x\n",
363f97117d1SArtem B. Bityutskiy 		  ref_offset(ref), je32_to_cpu(rd->version),
364f97117d1SArtem B. Bityutskiy 		  je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize)));
365f97117d1SArtem B. Bityutskiy 
366f97117d1SArtem B. Bityutskiy 	jffs2_add_tn_to_tree(tn, tnp);
367f97117d1SArtem B. Bityutskiy 
368f97117d1SArtem B. Bityutskiy 	return 0;
369f97117d1SArtem B. Bityutskiy }
370f97117d1SArtem B. Bityutskiy 
371f97117d1SArtem B. Bityutskiy /*
372f97117d1SArtem B. Bityutskiy  * Helper function for jffs2_get_inode_nodes().
373f97117d1SArtem B. Bityutskiy  * It is called every time an unknown node is found.
374f97117d1SArtem B. Bityutskiy  *
375f97117d1SArtem B. Bityutskiy  * Returns: 0 on succes;
376f97117d1SArtem B. Bityutskiy  * 	    1 if the node should be marked obsolete;
377f97117d1SArtem B. Bityutskiy  * 	    negative error code on failure.
378f97117d1SArtem B. Bityutskiy  */
379f97117d1SArtem B. Bityutskiy static inline int
380f97117d1SArtem B. Bityutskiy read_unknown(struct jffs2_sb_info *c,
381f97117d1SArtem B. Bityutskiy 	     struct jffs2_raw_node_ref *ref,
382f97117d1SArtem B. Bityutskiy 	     struct jffs2_unknown_node *un,
383f97117d1SArtem B. Bityutskiy 	     uint32_t read)
384f97117d1SArtem B. Bityutskiy {
385f97117d1SArtem B. Bityutskiy 	/* We don't mark unknown nodes as REF_UNCHECKED */
386f97117d1SArtem B. Bityutskiy 	BUG_ON(ref_flags(ref) == REF_UNCHECKED);
387f97117d1SArtem B. Bityutskiy 
388f97117d1SArtem B. Bityutskiy 	un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
389f97117d1SArtem B. Bityutskiy 
390f97117d1SArtem B. Bityutskiy 	if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) {
391f97117d1SArtem B. Bityutskiy 
392f97117d1SArtem B. Bityutskiy 		/* Hmmm. This should have been caught at scan time. */
393f97117d1SArtem B. Bityutskiy 		printk(KERN_WARNING "Warning! Node header CRC failed at %#08x. "
394f97117d1SArtem B. Bityutskiy 				"But it must have been OK earlier.\n", ref_offset(ref));
395f97117d1SArtem B. Bityutskiy 		D1(printk(KERN_DEBUG "Node was: { %#04x, %#04x, %#08x, %#08x }\n",
396f97117d1SArtem B. Bityutskiy 			je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
397f97117d1SArtem B. Bityutskiy 			je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc)));
398f97117d1SArtem B. Bityutskiy 		return 1;
399f97117d1SArtem B. Bityutskiy 	} else {
400f97117d1SArtem B. Bityutskiy 		switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
401f97117d1SArtem B. Bityutskiy 
402f97117d1SArtem B. Bityutskiy 		case JFFS2_FEATURE_INCOMPAT:
403f97117d1SArtem B. Bityutskiy 			printk(KERN_NOTICE "Unknown INCOMPAT nodetype %#04X at %#08x\n",
404f97117d1SArtem B. Bityutskiy 					je16_to_cpu(un->nodetype), ref_offset(ref));
405f97117d1SArtem B. Bityutskiy 			/* EEP */
406f97117d1SArtem B. Bityutskiy 			BUG();
407f97117d1SArtem B. Bityutskiy 			break;
408f97117d1SArtem B. Bityutskiy 
409f97117d1SArtem B. Bityutskiy 		case JFFS2_FEATURE_ROCOMPAT:
410f97117d1SArtem B. Bityutskiy 			printk(KERN_NOTICE "Unknown ROCOMPAT nodetype %#04X at %#08x\n",
411f97117d1SArtem B. Bityutskiy 					je16_to_cpu(un->nodetype), ref_offset(ref));
412f97117d1SArtem B. Bityutskiy 			BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
413f97117d1SArtem B. Bityutskiy 			break;
414f97117d1SArtem B. Bityutskiy 
415f97117d1SArtem B. Bityutskiy 		case JFFS2_FEATURE_RWCOMPAT_COPY:
416f97117d1SArtem B. Bityutskiy 			printk(KERN_NOTICE "Unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
417f97117d1SArtem B. Bityutskiy 					je16_to_cpu(un->nodetype), ref_offset(ref));
418f97117d1SArtem B. Bityutskiy 			break;
419f97117d1SArtem B. Bityutskiy 
420f97117d1SArtem B. Bityutskiy 		case JFFS2_FEATURE_RWCOMPAT_DELETE:
421f97117d1SArtem B. Bityutskiy 			printk(KERN_NOTICE "Unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
422f97117d1SArtem B. Bityutskiy 					je16_to_cpu(un->nodetype), ref_offset(ref));
423f97117d1SArtem B. Bityutskiy 			return 1;
424f97117d1SArtem B. Bityutskiy 		}
425f97117d1SArtem B. Bityutskiy 	}
426f97117d1SArtem B. Bityutskiy 
427f97117d1SArtem B. Bityutskiy 	return 0;
428f97117d1SArtem B. Bityutskiy }
429f97117d1SArtem B. Bityutskiy 
430f97117d1SArtem B. Bityutskiy /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated
431f97117d1SArtem B. Bityutskiy    with this ino, returning the former in order of version */
432f97117d1SArtem B. Bityutskiy 
433f97117d1SArtem B. Bityutskiy static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
434f97117d1SArtem B. Bityutskiy 				 struct rb_root *tnp, struct jffs2_full_dirent **fdp,
435f97117d1SArtem B. Bityutskiy 				 uint32_t *highest_version, uint32_t *latest_mctime,
436f97117d1SArtem B. Bityutskiy 				 uint32_t *mctime_ver)
437f97117d1SArtem B. Bityutskiy {
438f97117d1SArtem B. Bityutskiy 	struct jffs2_raw_node_ref *ref, *valid_ref;
439f97117d1SArtem B. Bityutskiy 	struct rb_root ret_tn = RB_ROOT;
440f97117d1SArtem B. Bityutskiy 	struct jffs2_full_dirent *ret_fd = NULL;
441f97117d1SArtem B. Bityutskiy 	union jffs2_node_union node;
442f97117d1SArtem B. Bityutskiy 	size_t retlen;
443f97117d1SArtem B. Bityutskiy 	int err;
444f97117d1SArtem B. Bityutskiy 
445f97117d1SArtem B. Bityutskiy 	*mctime_ver = 0;
446f97117d1SArtem B. Bityutskiy 
447f97117d1SArtem B. Bityutskiy 	D1(printk(KERN_DEBUG "jffs2_get_inode_nodes(): ino #%u\n", f->inocache->ino));
448f97117d1SArtem B. Bityutskiy 
449f97117d1SArtem B. Bityutskiy 	spin_lock(&c->erase_completion_lock);
450f97117d1SArtem B. Bityutskiy 
451f97117d1SArtem B. Bityutskiy 	valid_ref = jffs2_first_valid_node(f->inocache->nodes);
452f97117d1SArtem B. Bityutskiy 
453f97117d1SArtem B. Bityutskiy 	if (!valid_ref && (f->inocache->ino != 1))
454f97117d1SArtem B. Bityutskiy 		printk(KERN_WARNING "Eep. No valid nodes for ino #%u\n", f->inocache->ino);
455f97117d1SArtem B. Bityutskiy 
456f97117d1SArtem B. Bityutskiy 	while (valid_ref) {
457f97117d1SArtem B. Bityutskiy 		/* We can hold a pointer to a non-obsolete node without the spinlock,
458f97117d1SArtem B. Bityutskiy 		   but _obsolete_ nodes may disappear at any time, if the block
459f97117d1SArtem B. Bityutskiy 		   they're in gets erased. So if we mark 'ref' obsolete while we're
460f97117d1SArtem B. Bityutskiy 		   not holding the lock, it can go away immediately. For that reason,
461f97117d1SArtem B. Bityutskiy 		   we find the next valid node first, before processing 'ref'.
462f97117d1SArtem B. Bityutskiy 		*/
463f97117d1SArtem B. Bityutskiy 		ref = valid_ref;
464f97117d1SArtem B. Bityutskiy 		valid_ref = jffs2_first_valid_node(ref->next_in_ino);
465f97117d1SArtem B. Bityutskiy 		spin_unlock(&c->erase_completion_lock);
466f97117d1SArtem B. Bityutskiy 
467f97117d1SArtem B. Bityutskiy 		cond_resched();
468f97117d1SArtem B. Bityutskiy 
469f97117d1SArtem B. Bityutskiy 		/* FIXME: point() */
470f97117d1SArtem B. Bityutskiy 		err = jffs2_flash_read(c, (ref_offset(ref)),
471f97117d1SArtem B. Bityutskiy 				       min_t(uint32_t, ref_totlen(c, NULL, ref), sizeof(node)),
472f97117d1SArtem B. Bityutskiy 				       &retlen, (void *)&node);
473f97117d1SArtem B. Bityutskiy 		if (err) {
474f97117d1SArtem B. Bityutskiy 			printk(KERN_WARNING "error %d reading node at 0x%08x in get_inode_nodes()\n", err, ref_offset(ref));
475f97117d1SArtem B. Bityutskiy 			goto free_out;
476f97117d1SArtem B. Bityutskiy 		}
477f97117d1SArtem B. Bityutskiy 
478f97117d1SArtem B. Bityutskiy 		switch (je16_to_cpu(node.u.nodetype)) {
479f97117d1SArtem B. Bityutskiy 
480f97117d1SArtem B. Bityutskiy 		case JFFS2_NODETYPE_DIRENT:
481f97117d1SArtem B. Bityutskiy 			D1(printk(KERN_DEBUG "Node at %08x (%d) is a dirent node\n", ref_offset(ref), ref_flags(ref)));
482f97117d1SArtem B. Bityutskiy 
483f97117d1SArtem B. Bityutskiy 			if (retlen < sizeof(node.d)) {
484f97117d1SArtem B. Bityutskiy 				printk(KERN_WARNING "Warning! Short read dirent at %#08x\n", ref_offset(ref));
485f97117d1SArtem B. Bityutskiy 				err = -EIO;
486f97117d1SArtem B. Bityutskiy 				goto free_out;
487f97117d1SArtem B. Bityutskiy 			}
488f97117d1SArtem B. Bityutskiy 
489f97117d1SArtem B. Bityutskiy 			err = read_direntry(c, ref, &node.d, retlen, &ret_fd, latest_mctime, mctime_ver);
490f97117d1SArtem B. Bityutskiy 			if (err == 1) {
491f97117d1SArtem B. Bityutskiy 				jffs2_mark_node_obsolete(c, ref);
492f97117d1SArtem B. Bityutskiy 				break;
493f97117d1SArtem B. Bityutskiy 			} else if (unlikely(err))
494f97117d1SArtem B. Bityutskiy 				goto free_out;
495f97117d1SArtem B. Bityutskiy 
496f97117d1SArtem B. Bityutskiy 			if (je32_to_cpu(node.d.version) > *highest_version)
497f97117d1SArtem B. Bityutskiy 				*highest_version = je32_to_cpu(node.d.version);
498f97117d1SArtem B. Bityutskiy 
499f97117d1SArtem B. Bityutskiy 			break;
500f97117d1SArtem B. Bityutskiy 
501f97117d1SArtem B. Bityutskiy 		case JFFS2_NODETYPE_INODE:
502f97117d1SArtem B. Bityutskiy 			D1(printk(KERN_DEBUG "Node at %08x (%d) is a data node\n", ref_offset(ref), ref_flags(ref)));
503f97117d1SArtem B. Bityutskiy 
504f97117d1SArtem B. Bityutskiy 			if (retlen < sizeof(node.i)) {
505f97117d1SArtem B. Bityutskiy 				printk(KERN_WARNING "Warning! Short read dnode at %#08x\n", ref_offset(ref));
506f97117d1SArtem B. Bityutskiy 				err = -EIO;
507f97117d1SArtem B. Bityutskiy 				goto free_out;
508f97117d1SArtem B. Bityutskiy 			}
509f97117d1SArtem B. Bityutskiy 
510f97117d1SArtem B. Bityutskiy 			err = read_dnode(c, ref, &node.i, retlen, &ret_tn, latest_mctime, mctime_ver);
511f97117d1SArtem B. Bityutskiy 			if (err == 1) {
512f97117d1SArtem B. Bityutskiy 				jffs2_mark_node_obsolete(c, ref);
513f97117d1SArtem B. Bityutskiy 				break;
514f97117d1SArtem B. Bityutskiy 			} else if (unlikely(err))
515f97117d1SArtem B. Bityutskiy 				goto free_out;
516f97117d1SArtem B. Bityutskiy 
517f97117d1SArtem B. Bityutskiy 			if (je32_to_cpu(node.i.version) > *highest_version)
518f97117d1SArtem B. Bityutskiy 				*highest_version = je32_to_cpu(node.i.version);
519f97117d1SArtem B. Bityutskiy 
520f97117d1SArtem B. Bityutskiy 			D1(printk(KERN_DEBUG "version %d, highest_version now %d\n",
521f97117d1SArtem B. Bityutskiy 					je32_to_cpu(node.i.version), *highest_version));
522f97117d1SArtem B. Bityutskiy 
5231da177e4SLinus Torvalds 			break;
5241da177e4SLinus Torvalds 
5251da177e4SLinus Torvalds 		default:
526f97117d1SArtem B. Bityutskiy 			/* Check we've managed to read at least the common node header */
527f97117d1SArtem B. Bityutskiy 			if (retlen < sizeof(struct jffs2_unknown_node)) {
528f97117d1SArtem B. Bityutskiy 				printk(KERN_WARNING "Warning! Short read unknown node at %#08x\n",
529f97117d1SArtem B. Bityutskiy 						ref_offset(ref));
530f97117d1SArtem B. Bityutskiy 				return -EIO;
5311da177e4SLinus Torvalds 			}
5321da177e4SLinus Torvalds 
533f97117d1SArtem B. Bityutskiy 			err = read_unknown(c, ref, &node.u, retlen);
534f97117d1SArtem B. Bityutskiy 			if (err == 1) {
535f97117d1SArtem B. Bityutskiy 				jffs2_mark_node_obsolete(c, ref);
536f97117d1SArtem B. Bityutskiy 				break;
537f97117d1SArtem B. Bityutskiy 			} else if (unlikely(err))
538f97117d1SArtem B. Bityutskiy 				goto free_out;
539f97117d1SArtem B. Bityutskiy 
5401da177e4SLinus Torvalds 		}
541f97117d1SArtem B. Bityutskiy 		spin_lock(&c->erase_completion_lock);
5421da177e4SLinus Torvalds 
5431da177e4SLinus Torvalds 	}
544f97117d1SArtem B. Bityutskiy 	spin_unlock(&c->erase_completion_lock);
545f97117d1SArtem B. Bityutskiy 	*tnp = ret_tn;
546f97117d1SArtem B. Bityutskiy 	*fdp = ret_fd;
547f97117d1SArtem B. Bityutskiy 
548f97117d1SArtem B. Bityutskiy 	return 0;
549f97117d1SArtem B. Bityutskiy 
550f97117d1SArtem B. Bityutskiy  free_out:
551f97117d1SArtem B. Bityutskiy 	jffs2_free_tmp_dnode_info_list(&ret_tn);
552f97117d1SArtem B. Bityutskiy 	jffs2_free_full_dirent_list(ret_fd);
553f97117d1SArtem B. Bityutskiy 	return err;
5541da177e4SLinus Torvalds }
5551da177e4SLinus Torvalds 
5561da177e4SLinus Torvalds static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
5571da177e4SLinus Torvalds 					struct jffs2_inode_info *f,
5581da177e4SLinus Torvalds 					struct jffs2_raw_inode *latest_node)
5591da177e4SLinus Torvalds {
5609dee7503SDavid Woodhouse 	struct jffs2_tmp_dnode_info *tn = NULL;
5619dee7503SDavid Woodhouse 	struct rb_root tn_list;
5629dee7503SDavid Woodhouse 	struct rb_node *rb, *repl_rb;
5631da177e4SLinus Torvalds 	struct jffs2_full_dirent *fd_list;
5641da177e4SLinus Torvalds 	struct jffs2_full_dnode *fn = NULL;
5651da177e4SLinus Torvalds 	uint32_t crc;
5661da177e4SLinus Torvalds 	uint32_t latest_mctime, mctime_ver;
5671da177e4SLinus Torvalds 	uint32_t mdata_ver = 0;
5681da177e4SLinus Torvalds 	size_t retlen;
5691da177e4SLinus Torvalds 	int ret;
5701da177e4SLinus Torvalds 
5711da177e4SLinus Torvalds 	D1(printk(KERN_DEBUG "jffs2_do_read_inode_internal(): ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink));
5721da177e4SLinus Torvalds 
5731da177e4SLinus Torvalds 	/* Grab all nodes relevant to this ino */
5741da177e4SLinus Torvalds 	ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver);
5751da177e4SLinus Torvalds 
5761da177e4SLinus Torvalds 	if (ret) {
5771da177e4SLinus Torvalds 		printk(KERN_CRIT "jffs2_get_inode_nodes() for ino %u returned %d\n", f->inocache->ino, ret);
5781da177e4SLinus Torvalds 		if (f->inocache->state == INO_STATE_READING)
5791da177e4SLinus Torvalds 			jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
5801da177e4SLinus Torvalds 		return ret;
5811da177e4SLinus Torvalds 	}
5821da177e4SLinus Torvalds 	f->dents = fd_list;
5831da177e4SLinus Torvalds 
5849dee7503SDavid Woodhouse 	rb = rb_first(&tn_list);
5851da177e4SLinus Torvalds 
5869dee7503SDavid Woodhouse 	while (rb) {
5879dee7503SDavid Woodhouse 		tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb);
5881da177e4SLinus Torvalds 		fn = tn->fn;
5891da177e4SLinus Torvalds 
5901da177e4SLinus Torvalds 		if (f->metadata) {
5911da177e4SLinus Torvalds 			if (likely(tn->version >= mdata_ver)) {
5921da177e4SLinus Torvalds 				D1(printk(KERN_DEBUG "Obsoleting old metadata at 0x%08x\n", ref_offset(f->metadata->raw)));
5931da177e4SLinus Torvalds 				jffs2_mark_node_obsolete(c, f->metadata->raw);
5941da177e4SLinus Torvalds 				jffs2_free_full_dnode(f->metadata);
5951da177e4SLinus Torvalds 				f->metadata = NULL;
5961da177e4SLinus Torvalds 
5971da177e4SLinus Torvalds 				mdata_ver = 0;
5981da177e4SLinus Torvalds 			} else {
5991da177e4SLinus Torvalds 				/* This should never happen. */
6001da177e4SLinus Torvalds 				printk(KERN_WARNING "Er. New metadata at 0x%08x with ver %d is actually older than previous ver %d at 0x%08x\n",
6011da177e4SLinus Torvalds 					  ref_offset(fn->raw), tn->version, mdata_ver, ref_offset(f->metadata->raw));
6021da177e4SLinus Torvalds 				jffs2_mark_node_obsolete(c, fn->raw);
6031da177e4SLinus Torvalds 				jffs2_free_full_dnode(fn);
6041da177e4SLinus Torvalds 				/* Fill in latest_node from the metadata, not this one we're about to free... */
6051da177e4SLinus Torvalds 				fn = f->metadata;
6061da177e4SLinus Torvalds 				goto next_tn;
6071da177e4SLinus Torvalds 			}
6081da177e4SLinus Torvalds 		}
6091da177e4SLinus Torvalds 
6101da177e4SLinus Torvalds 		if (fn->size) {
6111da177e4SLinus Torvalds 			jffs2_add_full_dnode_to_inode(c, f, fn);
6121da177e4SLinus Torvalds 		} else {
6131da177e4SLinus Torvalds 			/* Zero-sized node at end of version list. Just a metadata update */
6141da177e4SLinus Torvalds 			D1(printk(KERN_DEBUG "metadata @%08x: ver %d\n", ref_offset(fn->raw), tn->version));
6151da177e4SLinus Torvalds 			f->metadata = fn;
6161da177e4SLinus Torvalds 			mdata_ver = tn->version;
6171da177e4SLinus Torvalds 		}
6181da177e4SLinus Torvalds 	next_tn:
6199dee7503SDavid Woodhouse 		BUG_ON(rb->rb_left);
6209dee7503SDavid Woodhouse 		if (rb->rb_parent && rb->rb_parent->rb_left == rb) {
6219dee7503SDavid Woodhouse 			/* We were then left-hand child of our parent. We need
6229dee7503SDavid Woodhouse 			   to move our own right-hand child into our place. */
6239dee7503SDavid Woodhouse 			repl_rb = rb->rb_right;
6249dee7503SDavid Woodhouse 			if (repl_rb)
6259dee7503SDavid Woodhouse 				repl_rb->rb_parent = rb->rb_parent;
6269dee7503SDavid Woodhouse 		} else
6279dee7503SDavid Woodhouse 			repl_rb = NULL;
6289dee7503SDavid Woodhouse 
6299dee7503SDavid Woodhouse 		rb = rb_next(rb);
6309dee7503SDavid Woodhouse 
6319dee7503SDavid Woodhouse 		/* Remove the spent tn from the tree; don't bother rebalancing
6329dee7503SDavid Woodhouse 		   but put our right-hand child in our own place. */
6339dee7503SDavid Woodhouse 		if (tn->rb.rb_parent) {
6349dee7503SDavid Woodhouse 			if (tn->rb.rb_parent->rb_left == &tn->rb)
6359dee7503SDavid Woodhouse 				tn->rb.rb_parent->rb_left = repl_rb;
6369dee7503SDavid Woodhouse 			else if (tn->rb.rb_parent->rb_right == &tn->rb)
6379dee7503SDavid Woodhouse 				tn->rb.rb_parent->rb_right = repl_rb;
6389dee7503SDavid Woodhouse 			else BUG();
6399dee7503SDavid Woodhouse 		} else if (tn->rb.rb_right)
6409dee7503SDavid Woodhouse 			tn->rb.rb_right->rb_parent = NULL;
6419dee7503SDavid Woodhouse 
6421da177e4SLinus Torvalds 		jffs2_free_tmp_dnode_info(tn);
6431da177e4SLinus Torvalds 	}
644e0c8e42fSArtem B. Bityutskiy 	jffs2_dbg_fragtree_paranoia_check_nolock(f);
6451da177e4SLinus Torvalds 
6461da177e4SLinus Torvalds 	if (!fn) {
6471da177e4SLinus Torvalds 		/* No data nodes for this inode. */
6481da177e4SLinus Torvalds 		if (f->inocache->ino != 1) {
6491da177e4SLinus Torvalds 			printk(KERN_WARNING "jffs2_do_read_inode(): No data nodes found for ino #%u\n", f->inocache->ino);
6501da177e4SLinus Torvalds 			if (!fd_list) {
6511da177e4SLinus Torvalds 				if (f->inocache->state == INO_STATE_READING)
6521da177e4SLinus Torvalds 					jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
6531da177e4SLinus Torvalds 				return -EIO;
6541da177e4SLinus Torvalds 			}
6551da177e4SLinus Torvalds 			printk(KERN_WARNING "jffs2_do_read_inode(): But it has children so we fake some modes for it\n");
6561da177e4SLinus Torvalds 		}
6571da177e4SLinus Torvalds 		latest_node->mode = cpu_to_jemode(S_IFDIR|S_IRUGO|S_IWUSR|S_IXUGO);
6581da177e4SLinus Torvalds 		latest_node->version = cpu_to_je32(0);
6591da177e4SLinus Torvalds 		latest_node->atime = latest_node->ctime = latest_node->mtime = cpu_to_je32(0);
6601da177e4SLinus Torvalds 		latest_node->isize = cpu_to_je32(0);
6611da177e4SLinus Torvalds 		latest_node->gid = cpu_to_je16(0);
6621da177e4SLinus Torvalds 		latest_node->uid = cpu_to_je16(0);
6631da177e4SLinus Torvalds 		if (f->inocache->state == INO_STATE_READING)
6641da177e4SLinus Torvalds 			jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
6651da177e4SLinus Torvalds 		return 0;
6661da177e4SLinus Torvalds 	}
6671da177e4SLinus Torvalds 
6681da177e4SLinus Torvalds 	ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node);
6691da177e4SLinus Torvalds 	if (ret || retlen != sizeof(*latest_node)) {
6701da177e4SLinus Torvalds 		printk(KERN_NOTICE "MTD read in jffs2_do_read_inode() failed: Returned %d, %zd of %zd bytes read\n",
6711da177e4SLinus Torvalds 		       ret, retlen, sizeof(*latest_node));
6721da177e4SLinus Torvalds 		/* FIXME: If this fails, there seems to be a memory leak. Find it. */
6731da177e4SLinus Torvalds 		up(&f->sem);
6741da177e4SLinus Torvalds 		jffs2_do_clear_inode(c, f);
6751da177e4SLinus Torvalds 		return ret?ret:-EIO;
6761da177e4SLinus Torvalds 	}
6771da177e4SLinus Torvalds 
6781da177e4SLinus Torvalds 	crc = crc32(0, latest_node, sizeof(*latest_node)-8);
6791da177e4SLinus Torvalds 	if (crc != je32_to_cpu(latest_node->node_crc)) {
6801da177e4SLinus Torvalds 		printk(KERN_NOTICE "CRC failed for read_inode of inode %u at physical location 0x%x\n", f->inocache->ino, ref_offset(fn->raw));
6811da177e4SLinus Torvalds 		up(&f->sem);
6821da177e4SLinus Torvalds 		jffs2_do_clear_inode(c, f);
6831da177e4SLinus Torvalds 		return -EIO;
6841da177e4SLinus Torvalds 	}
6851da177e4SLinus Torvalds 
6861da177e4SLinus Torvalds 	switch(jemode_to_cpu(latest_node->mode) & S_IFMT) {
6871da177e4SLinus Torvalds 	case S_IFDIR:
6881da177e4SLinus Torvalds 		if (mctime_ver > je32_to_cpu(latest_node->version)) {
6891da177e4SLinus Torvalds 			/* The times in the latest_node are actually older than
6901da177e4SLinus Torvalds 			   mctime in the latest dirent. Cheat. */
6911da177e4SLinus Torvalds 			latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime);
6921da177e4SLinus Torvalds 		}
6931da177e4SLinus Torvalds 		break;
6941da177e4SLinus Torvalds 
6951da177e4SLinus Torvalds 
6961da177e4SLinus Torvalds 	case S_IFREG:
6971da177e4SLinus Torvalds 		/* If it was a regular file, truncate it to the latest node's isize */
698f302cd02SArtem B. Bityutskiy 		jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize));
6991da177e4SLinus Torvalds 		break;
7001da177e4SLinus Torvalds 
7011da177e4SLinus Torvalds 	case S_IFLNK:
7021da177e4SLinus Torvalds 		/* Hack to work around broken isize in old symlink code.
7031da177e4SLinus Torvalds 		   Remove this when dwmw2 comes to his senses and stops
7041da177e4SLinus Torvalds 		   symlinks from being an entirely gratuitous special
7051da177e4SLinus Torvalds 		   case. */
7061da177e4SLinus Torvalds 		if (!je32_to_cpu(latest_node->isize))
7071da177e4SLinus Torvalds 			latest_node->isize = latest_node->dsize;
70832f1a95dSArtem B. Bityuckiy 
70932f1a95dSArtem B. Bityuckiy 		if (f->inocache->state != INO_STATE_CHECKING) {
71032f1a95dSArtem B. Bityuckiy 			/* Symlink's inode data is the target path. Read it and
7112b79adccSArtem B. Bityutskiy 			 * keep in RAM to facilitate quick follow symlink
7122b79adccSArtem B. Bityutskiy 			 * operation. */
7132b79adccSArtem B. Bityutskiy 			f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL);
7142b79adccSArtem B. Bityutskiy 			if (!f->target) {
71532f1a95dSArtem B. Bityuckiy 				printk(KERN_WARNING "Can't allocate %d bytes of memory "
71632f1a95dSArtem B. Bityuckiy 						"for the symlink target path cache\n",
71732f1a95dSArtem B. Bityuckiy 						je32_to_cpu(latest_node->csize));
71832f1a95dSArtem B. Bityuckiy 				up(&f->sem);
71932f1a95dSArtem B. Bityuckiy 				jffs2_do_clear_inode(c, f);
72032f1a95dSArtem B. Bityuckiy 				return -ENOMEM;
72132f1a95dSArtem B. Bityuckiy 			}
72232f1a95dSArtem B. Bityuckiy 
72332f1a95dSArtem B. Bityuckiy 			ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node),
7242b79adccSArtem B. Bityutskiy 						je32_to_cpu(latest_node->csize), &retlen, (char *)f->target);
72532f1a95dSArtem B. Bityuckiy 
72632f1a95dSArtem B. Bityuckiy 			if (ret  || retlen != je32_to_cpu(latest_node->csize)) {
72732f1a95dSArtem B. Bityuckiy 				if (retlen != je32_to_cpu(latest_node->csize))
72832f1a95dSArtem B. Bityuckiy 					ret = -EIO;
7292b79adccSArtem B. Bityutskiy 				kfree(f->target);
7302b79adccSArtem B. Bityutskiy 				f->target = NULL;
73132f1a95dSArtem B. Bityuckiy 				up(&f->sem);
73232f1a95dSArtem B. Bityuckiy 				jffs2_do_clear_inode(c, f);
73332f1a95dSArtem B. Bityuckiy 				return -ret;
73432f1a95dSArtem B. Bityuckiy 			}
73532f1a95dSArtem B. Bityuckiy 
7362b79adccSArtem B. Bityutskiy 			f->target[je32_to_cpu(latest_node->csize)] = '\0';
73732f1a95dSArtem B. Bityuckiy 			D1(printk(KERN_DEBUG "jffs2_do_read_inode(): symlink's target '%s' cached\n",
7382b79adccSArtem B. Bityutskiy 						f->target));
73932f1a95dSArtem B. Bityuckiy 		}
74032f1a95dSArtem B. Bityuckiy 
7411da177e4SLinus Torvalds 		/* fall through... */
7421da177e4SLinus Torvalds 
7431da177e4SLinus Torvalds 	case S_IFBLK:
7441da177e4SLinus Torvalds 	case S_IFCHR:
7451da177e4SLinus Torvalds 		/* Certain inode types should have only one data node, and it's
7461da177e4SLinus Torvalds 		   kept as the metadata node */
7471da177e4SLinus Torvalds 		if (f->metadata) {
7481da177e4SLinus Torvalds 			printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had metadata node\n",
7491da177e4SLinus Torvalds 			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
7501da177e4SLinus Torvalds 			up(&f->sem);
7511da177e4SLinus Torvalds 			jffs2_do_clear_inode(c, f);
7521da177e4SLinus Torvalds 			return -EIO;
7531da177e4SLinus Torvalds 		}
7541da177e4SLinus Torvalds 		if (!frag_first(&f->fragtree)) {
7551da177e4SLinus Torvalds 			printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o has no fragments\n",
7561da177e4SLinus Torvalds 			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
7571da177e4SLinus Torvalds 			up(&f->sem);
7581da177e4SLinus Torvalds 			jffs2_do_clear_inode(c, f);
7591da177e4SLinus Torvalds 			return -EIO;
7601da177e4SLinus Torvalds 		}
7611da177e4SLinus Torvalds 		/* ASSERT: f->fraglist != NULL */
7621da177e4SLinus Torvalds 		if (frag_next(frag_first(&f->fragtree))) {
7631da177e4SLinus Torvalds 			printk(KERN_WARNING "Argh. Special inode #%u with mode 0x%x had more than one node\n",
7641da177e4SLinus Torvalds 			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
7651da177e4SLinus Torvalds 			/* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
7661da177e4SLinus Torvalds 			up(&f->sem);
7671da177e4SLinus Torvalds 			jffs2_do_clear_inode(c, f);
7681da177e4SLinus Torvalds 			return -EIO;
7691da177e4SLinus Torvalds 		}
7701da177e4SLinus Torvalds 		/* OK. We're happy */
7711da177e4SLinus Torvalds 		f->metadata = frag_first(&f->fragtree)->node;
7721da177e4SLinus Torvalds 		jffs2_free_node_frag(frag_first(&f->fragtree));
7731da177e4SLinus Torvalds 		f->fragtree = RB_ROOT;
7741da177e4SLinus Torvalds 		break;
7751da177e4SLinus Torvalds 	}
7761da177e4SLinus Torvalds 	if (f->inocache->state == INO_STATE_READING)
7771da177e4SLinus Torvalds 		jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
7781da177e4SLinus Torvalds 
7791da177e4SLinus Torvalds 	return 0;
7801da177e4SLinus Torvalds }
7811da177e4SLinus Torvalds 
782f97117d1SArtem B. Bityutskiy /* Scan the list of all nodes present for this ino, build map of versions, etc. */
783f97117d1SArtem B. Bityutskiy int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
784f97117d1SArtem B. Bityutskiy 			uint32_t ino, struct jffs2_raw_inode *latest_node)
785f97117d1SArtem B. Bityutskiy {
786f97117d1SArtem B. Bityutskiy 	D2(printk(KERN_DEBUG "jffs2_do_read_inode(): getting inocache\n"));
787f97117d1SArtem B. Bityutskiy 
788f97117d1SArtem B. Bityutskiy  retry_inocache:
789f97117d1SArtem B. Bityutskiy 	spin_lock(&c->inocache_lock);
790f97117d1SArtem B. Bityutskiy 	f->inocache = jffs2_get_ino_cache(c, ino);
791f97117d1SArtem B. Bityutskiy 
792f97117d1SArtem B. Bityutskiy 	D2(printk(KERN_DEBUG "jffs2_do_read_inode(): Got inocache at %p\n", f->inocache));
793f97117d1SArtem B. Bityutskiy 
794f97117d1SArtem B. Bityutskiy 	if (f->inocache) {
795f97117d1SArtem B. Bityutskiy 		/* Check its state. We may need to wait before we can use it */
796f97117d1SArtem B. Bityutskiy 		switch(f->inocache->state) {
797f97117d1SArtem B. Bityutskiy 		case INO_STATE_UNCHECKED:
798f97117d1SArtem B. Bityutskiy 		case INO_STATE_CHECKEDABSENT:
799f97117d1SArtem B. Bityutskiy 			f->inocache->state = INO_STATE_READING;
800f97117d1SArtem B. Bityutskiy 			break;
801f97117d1SArtem B. Bityutskiy 
802f97117d1SArtem B. Bityutskiy 		case INO_STATE_CHECKING:
803f97117d1SArtem B. Bityutskiy 		case INO_STATE_GC:
804f97117d1SArtem B. Bityutskiy 			/* If it's in either of these states, we need
805f97117d1SArtem B. Bityutskiy 			   to wait for whoever's got it to finish and
806f97117d1SArtem B. Bityutskiy 			   put it back. */
807f97117d1SArtem B. Bityutskiy 			D1(printk(KERN_DEBUG "jffs2_get_ino_cache_read waiting for ino #%u in state %d\n",
808f97117d1SArtem B. Bityutskiy 				  ino, f->inocache->state));
809f97117d1SArtem B. Bityutskiy 			sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
810f97117d1SArtem B. Bityutskiy 			goto retry_inocache;
811f97117d1SArtem B. Bityutskiy 
812f97117d1SArtem B. Bityutskiy 		case INO_STATE_READING:
813f97117d1SArtem B. Bityutskiy 		case INO_STATE_PRESENT:
814f97117d1SArtem B. Bityutskiy 			/* Eep. This should never happen. It can
815f97117d1SArtem B. Bityutskiy 			happen if Linux calls read_inode() again
816f97117d1SArtem B. Bityutskiy 			before clear_inode() has finished though. */
817f97117d1SArtem B. Bityutskiy 			printk(KERN_WARNING "Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state);
818f97117d1SArtem B. Bityutskiy 			/* Fail. That's probably better than allowing it to succeed */
819f97117d1SArtem B. Bityutskiy 			f->inocache = NULL;
820f97117d1SArtem B. Bityutskiy 			break;
821f97117d1SArtem B. Bityutskiy 
822f97117d1SArtem B. Bityutskiy 		default:
823f97117d1SArtem B. Bityutskiy 			BUG();
824f97117d1SArtem B. Bityutskiy 		}
825f97117d1SArtem B. Bityutskiy 	}
826f97117d1SArtem B. Bityutskiy 	spin_unlock(&c->inocache_lock);
827f97117d1SArtem B. Bityutskiy 
828f97117d1SArtem B. Bityutskiy 	if (!f->inocache && ino == 1) {
829f97117d1SArtem B. Bityutskiy 		/* Special case - no root inode on medium */
830f97117d1SArtem B. Bityutskiy 		f->inocache = jffs2_alloc_inode_cache();
831f97117d1SArtem B. Bityutskiy 		if (!f->inocache) {
832f97117d1SArtem B. Bityutskiy 			printk(KERN_CRIT "jffs2_do_read_inode(): Cannot allocate inocache for root inode\n");
833f97117d1SArtem B. Bityutskiy 			return -ENOMEM;
834f97117d1SArtem B. Bityutskiy 		}
835f97117d1SArtem B. Bityutskiy 		D1(printk(KERN_DEBUG "jffs2_do_read_inode(): Creating inocache for root inode\n"));
836f97117d1SArtem B. Bityutskiy 		memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
837f97117d1SArtem B. Bityutskiy 		f->inocache->ino = f->inocache->nlink = 1;
838f97117d1SArtem B. Bityutskiy 		f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
839f97117d1SArtem B. Bityutskiy 		f->inocache->state = INO_STATE_READING;
840f97117d1SArtem B. Bityutskiy 		jffs2_add_ino_cache(c, f->inocache);
841f97117d1SArtem B. Bityutskiy 	}
842f97117d1SArtem B. Bityutskiy 	if (!f->inocache) {
843f97117d1SArtem B. Bityutskiy 		printk(KERN_WARNING "jffs2_do_read_inode() on nonexistent ino %u\n", ino);
844f97117d1SArtem B. Bityutskiy 		return -ENOENT;
845f97117d1SArtem B. Bityutskiy 	}
846f97117d1SArtem B. Bityutskiy 
847f97117d1SArtem B. Bityutskiy 	return jffs2_do_read_inode_internal(c, f, latest_node);
848f97117d1SArtem B. Bityutskiy }
849f97117d1SArtem B. Bityutskiy 
850f97117d1SArtem B. Bityutskiy int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
851f97117d1SArtem B. Bityutskiy {
852f97117d1SArtem B. Bityutskiy 	struct jffs2_raw_inode n;
853f97117d1SArtem B. Bityutskiy 	struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL);
854f97117d1SArtem B. Bityutskiy 	int ret;
855f97117d1SArtem B. Bityutskiy 
856f97117d1SArtem B. Bityutskiy 	if (!f)
857f97117d1SArtem B. Bityutskiy 		return -ENOMEM;
858f97117d1SArtem B. Bityutskiy 
859f97117d1SArtem B. Bityutskiy 	memset(f, 0, sizeof(*f));
860f97117d1SArtem B. Bityutskiy 	init_MUTEX_LOCKED(&f->sem);
861f97117d1SArtem B. Bityutskiy 	f->inocache = ic;
862f97117d1SArtem B. Bityutskiy 
863f97117d1SArtem B. Bityutskiy 	ret = jffs2_do_read_inode_internal(c, f, &n);
864f97117d1SArtem B. Bityutskiy 	if (!ret) {
865f97117d1SArtem B. Bityutskiy 		up(&f->sem);
866f97117d1SArtem B. Bityutskiy 		jffs2_do_clear_inode(c, f);
867f97117d1SArtem B. Bityutskiy 	}
868f97117d1SArtem B. Bityutskiy 	kfree (f);
869f97117d1SArtem B. Bityutskiy 	return ret;
870f97117d1SArtem B. Bityutskiy }
871f97117d1SArtem B. Bityutskiy 
8721da177e4SLinus Torvalds void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
8731da177e4SLinus Torvalds {
8741da177e4SLinus Torvalds 	struct jffs2_full_dirent *fd, *fds;
8751da177e4SLinus Torvalds 	int deleted;
8761da177e4SLinus Torvalds 
8771da177e4SLinus Torvalds 	down(&f->sem);
8781da177e4SLinus Torvalds 	deleted = f->inocache && !f->inocache->nlink;
8791da177e4SLinus Torvalds 
88067e345d1SDavid Woodhouse 	if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
88167e345d1SDavid Woodhouse 		jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);
88267e345d1SDavid Woodhouse 
8831da177e4SLinus Torvalds 	if (f->metadata) {
8841da177e4SLinus Torvalds 		if (deleted)
8851da177e4SLinus Torvalds 			jffs2_mark_node_obsolete(c, f->metadata->raw);
8861da177e4SLinus Torvalds 		jffs2_free_full_dnode(f->metadata);
8871da177e4SLinus Torvalds 	}
8881da177e4SLinus Torvalds 
8891da177e4SLinus Torvalds 	jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL);
8901da177e4SLinus Torvalds 
8912b79adccSArtem B. Bityutskiy 	if (f->target) {
8922b79adccSArtem B. Bityutskiy 		kfree(f->target);
8932b79adccSArtem B. Bityutskiy 		f->target = NULL;
89432f1a95dSArtem B. Bityuckiy 	}
8951da177e4SLinus Torvalds 
8962b79adccSArtem B. Bityutskiy 	fds = f->dents;
8971da177e4SLinus Torvalds 	while(fds) {
8981da177e4SLinus Torvalds 		fd = fds;
8991da177e4SLinus Torvalds 		fds = fd->next;
9001da177e4SLinus Torvalds 		jffs2_free_full_dirent(fd);
9011da177e4SLinus Torvalds 	}
9021da177e4SLinus Torvalds 
90367e345d1SDavid Woodhouse 	if (f->inocache && f->inocache->state != INO_STATE_CHECKING) {
9041da177e4SLinus Torvalds 		jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
90567e345d1SDavid Woodhouse 		if (f->inocache->nodes == (void *)f->inocache)
90667e345d1SDavid Woodhouse 			jffs2_del_ino_cache(c, f->inocache);
90767e345d1SDavid Woodhouse 	}
9081da177e4SLinus Torvalds 
9091da177e4SLinus Torvalds 	up(&f->sem);
9101da177e4SLinus Torvalds }
911