Blame view

fs/jffs2/readinode.c 42.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   * JFFS2 -- Journalling Flash File System, Version 2.
   *
c00c310ea   David Woodhouse   [JFFS2] Tidy up l...
4
   * Copyright © 2001-2007 Red Hat, Inc.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
9
   *
   * Created by David Woodhouse <dwmw2@infradead.org>
   *
   * For licensing information, see the file 'LICENCE' in this directory.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
   */
5a528957e   Joe Perches   jffs2: Use pr_fmt...
11
12
  
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
  
  #include <linux/kernel.h>
737b7661e   Andrew Lunn   [JFFS2] Fix up ne...
15
  #include <linux/sched.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
19
20
21
22
  #include <linux/slab.h>
  #include <linux/fs.h>
  #include <linux/crc32.h>
  #include <linux/pagemap.h>
  #include <linux/mtd/mtd.h>
  #include <linux/compiler.h>
  #include "nodelist.h"
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
23
  /*
df8e96f39   David Woodhouse   [JFFS2] Improve r...
24
25
26
27
   * Check the data CRC of the node.
   *
   * Returns: 0 if the data CRC is correct;
   * 	    1 - if incorrect;
25985edce   Lucas De Marchi   Fix common misspe...
28
   *	    error code if an error occurred.
df8e96f39   David Woodhouse   [JFFS2] Improve r...
29
30
31
32
33
34
35
36
37
38
39
   */
  static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
  {
  	struct jffs2_raw_node_ref *ref = tn->fn->raw;
  	int err = 0, pointed = 0;
  	struct jffs2_eraseblock *jeb;
  	unsigned char *buffer;
  	uint32_t crc, ofs, len;
  	size_t retlen;
  
  	BUG_ON(tn->csize == 0);
df8e96f39   David Woodhouse   [JFFS2] Improve r...
40
41
  	/* Calculate how many bytes were already checked */
  	ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode);
92525726d   David Woodhouse   [JFFS2] Fix data ...
42
  	len = tn->csize;
df8e96f39   David Woodhouse   [JFFS2] Improve r...
43

92525726d   David Woodhouse   [JFFS2] Fix data ...
44
45
46
47
  	if (jffs2_is_writebuffered(c)) {
  		int adj = ofs % c->wbuf_pagesize;
  		if (likely(adj))
  			adj = c->wbuf_pagesize - adj;
df8e96f39   David Woodhouse   [JFFS2] Improve r...
48

92525726d   David Woodhouse   [JFFS2] Fix data ...
49
50
51
52
53
54
55
56
57
58
  		if (adj >= tn->csize) {
  			dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.
  ",
  				      ref_offset(ref), tn->csize, ofs);
  			goto adj_acc;
  		}
  
  		ofs += adj;
  		len -= adj;
  	}
df8e96f39   David Woodhouse   [JFFS2] Improve r...
59
60
61
62
63
64
65
66
  
  	dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.
  ",
  		ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len);
  
  #ifndef __ECOS
  	/* TODO: instead, incapsulate point() stuff to jffs2_flash_read(),
  	 * adding and jffs2_flash_read_end() interface. */
10934478e   Artem Bityutskiy   mtd: do use mtd->...
67
68
69
70
71
72
73
  	err = mtd_point(c->mtd, ofs, len, &retlen, (void **)&buffer, NULL);
  	if (!err && retlen < len) {
  		JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.
  ", retlen, tn->csize);
  		mtd_unpoint(c->mtd, ofs, retlen);
  	} else if (err) {
  		if (err != -EOPNOTSUPP)
df8e96f39   David Woodhouse   [JFFS2] Improve r...
74
75
  			JFFS2_WARNING("MTD point failed: error code %d.
  ", err);
10934478e   Artem Bityutskiy   mtd: do use mtd->...
76
77
  	} else
  		pointed = 1; /* succefully pointed to device */
df8e96f39   David Woodhouse   [JFFS2] Improve r...
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
  #endif
  
  	if (!pointed) {
  		buffer = kmalloc(len, GFP_KERNEL);
  		if (unlikely(!buffer))
  			return -ENOMEM;
  
  		/* TODO: this is very frequent pattern, make it a separate
  		 * routine */
  		err = jffs2_flash_read(c, ofs, len, &retlen, buffer);
  		if (err) {
  			JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.
  ", len, ofs, err);
  			goto free_out;
  		}
  
  		if (retlen != len) {
  			JFFS2_ERROR("short read at %#08x: %zd instead of %d.
  ", ofs, retlen, len);
  			err = -EIO;
  			goto free_out;
  		}
  	}
  
  	/* Continue calculating CRC */
  	crc = crc32(tn->partial_crc, buffer, len);
  	if(!pointed)
  		kfree(buffer);
  #ifndef __ECOS
  	else
7219778ad   Artem Bityutskiy   mtd: introduce mt...
108
  		mtd_unpoint(c->mtd, ofs, len);
df8e96f39   David Woodhouse   [JFFS2] Improve r...
109
110
111
112
113
  #endif
  
  	if (crc != tn->data_crc) {
  		JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.
  ",
b2e25235f   David Woodhouse   [JFFS2] Print cor...
114
  			     ref_offset(ref), tn->data_crc, crc);
df8e96f39   David Woodhouse   [JFFS2] Improve r...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  		return 1;
  	}
  
  adj_acc:
  	jeb = &c->blocks[ref->flash_offset / c->sector_size];
  	len = ref_totlen(c, jeb, ref);
  	/* If it should be REF_NORMAL, it'll get marked as such when
  	   we build the fragtree, shortly. No need to worry about GC
  	   moving it while it's marked REF_PRISTINE -- GC won't happen
  	   till we've finished checking every inode anyway. */
  	ref->flash_offset |= REF_PRISTINE;
  	/*
  	 * Mark the node as having been checked and fix the
  	 * accounting accordingly.
  	 */
  	spin_lock(&c->erase_completion_lock);
  	jeb->used_size += len;
  	jeb->unchecked_size -= len;
  	c->used_size += len;
  	c->unchecked_size -= len;
  	jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
  	spin_unlock(&c->erase_completion_lock);
  
  	return 0;
  
  free_out:
  	if(!pointed)
  		kfree(buffer);
  #ifndef __ECOS
  	else
7219778ad   Artem Bityutskiy   mtd: introduce mt...
145
  		mtd_unpoint(c->mtd, ofs, len);
df8e96f39   David Woodhouse   [JFFS2] Improve r...
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  #endif
  	return err;
  }
  
  /*
   * Helper function for jffs2_add_older_frag_to_fragtree().
   *
   * Checks the node if we are in the checking stage.
   */
  static int check_tn_node(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
  {
  	int ret;
  
  	BUG_ON(ref_obsolete(tn->fn->raw));
  
  	/* We only check the data CRC of unchecked nodes */
  	if (ref_flags(tn->fn->raw) != REF_UNCHECKED)
  		return 0;
  
  	dbg_readinode("check node %#04x-%#04x, phys offs %#08x
  ",
  		      tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw));
  
  	ret = check_node_data(c, tn);
  	if (unlikely(ret < 0)) {
  		JFFS2_ERROR("check_node_data() returned error: %d.
  ",
  			ret);
  	} else if (unlikely(ret > 0)) {
  		dbg_readinode("CRC error, mark it obsolete.
  ");
  		jffs2_mark_node_obsolete(c, tn->fn->raw);
  	}
  
  	return ret;
  }
  
  static struct jffs2_tmp_dnode_info *jffs2_lookup_tn(struct rb_root *tn_root, uint32_t offset)
  {
  	struct rb_node *next;
  	struct jffs2_tmp_dnode_info *tn = NULL;
  
  	dbg_readinode("root %p, offset %d
  ", tn_root, offset);
  
  	next = tn_root->rb_node;
  
  	while (next) {
  		tn = rb_entry(next, struct jffs2_tmp_dnode_info, rb);
  
  		if (tn->fn->ofs < offset)
  			next = tn->rb.rb_right;
  		else if (tn->fn->ofs >= offset)
  			next = tn->rb.rb_left;
  		else
  			break;
  	}
  
  	return tn;
  }
  
  
  static void jffs2_kill_tn(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
  {
  	jffs2_mark_node_obsolete(c, tn->fn->raw);
  	jffs2_free_full_dnode(tn->fn);
  	jffs2_free_tmp_dnode_info(tn);
  }
  /*
   * This function is used when we read an inode. Data nodes arrive in
   * arbitrary order -- they may be older or newer than the nodes which
   * are already in the tree. Where overlaps occur, the older node can
   * be discarded as long as the newer passes the CRC check. We don't
   * bother to keep track of holes in this rbtree, and neither do we deal
   * with frags -- we can have multiple entries starting at the same
   * offset, and the one with the smallest length will come first in the
   * ordering.
   *
14c6381ee   David Woodhouse   [JFFS2] Fix readi...
224
   * Returns 0 if the node was handled (including marking it obsolete)
ef53cb02f   David Woodhouse   [JFFS2] Whitespac...
225
   *	 < 0 an if error occurred
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
   */
df8e96f39   David Woodhouse   [JFFS2] Improve r...
227
228
229
230
231
  static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
  				struct jffs2_readinode_info *rii,
  				struct jffs2_tmp_dnode_info *tn)
  {
  	uint32_t fn_end = tn->fn->ofs + tn->fn->size;
4c41bd0ec   Thomas Gleixner   [JFFS2] fix mount...
232
  	struct jffs2_tmp_dnode_info *this, *ptn;
df8e96f39   David Woodhouse   [JFFS2] Improve r...
233

fcf3cafb3   David Woodhouse   [JFFS2] Remove an...
234
235
  	dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x
  ", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw));
df8e96f39   David Woodhouse   [JFFS2] Improve r...
236

4740f4965   Geert Uytterhoeven   jffs2: Drop bogus...
237
  	/* If a node has zero dsize, we only have to keep it if it might be the
df8e96f39   David Woodhouse   [JFFS2] Improve r...
238
239
240
241
242
  	   node with highest version -- i.e. the one which will end up as f->metadata.
  	   Note that such nodes won't be REF_UNCHECKED since there are no data to
  	   check anyway. */
  	if (!tn->fn->size) {
  		if (rii->mdata_tn) {
0477d24e2   David Woodhouse   [JFFS2] Fix obsol...
243
244
245
246
247
248
249
250
251
252
253
254
  			if (rii->mdata_tn->version < tn->version) {
  				/* We had a candidate mdata node already */
  				dbg_readinode("kill old mdata with ver %d
  ", rii->mdata_tn->version);
  				jffs2_kill_tn(c, rii->mdata_tn);
  			} else {
  				dbg_readinode("kill new mdata with ver %d (older than existing %d
  ",
  					      tn->version, rii->mdata_tn->version);
  				jffs2_kill_tn(c, tn);
  				return 0;
  			}
df8e96f39   David Woodhouse   [JFFS2] Improve r...
255
256
257
258
259
260
261
262
263
  		}
  		rii->mdata_tn = tn;
  		dbg_readinode("keep new mdata with ver %d
  ", tn->version);
  		return 0;
  	}
  
  	/* Find the earliest node which _may_ be relevant to this one */
  	this = jffs2_lookup_tn(&rii->tn_root, tn->fn->ofs);
1c9796452   David Woodhouse   [JFFS2] Simplify ...
264
265
266
  	if (this) {
  		/* If the node is coincident with another at a lower address,
  		   back up until the other node is found. It may be relevant */
4c41bd0ec   Thomas Gleixner   [JFFS2] fix mount...
267
268
269
270
271
272
273
274
275
276
277
278
  		while (this->overlapped) {
  			ptn = tn_prev(this);
  			if (!ptn) {
  				/*
  				 * We killed a node which set the overlapped
  				 * flags during the scan. Fix it up.
  				 */
  				this->overlapped = 0;
  				break;
  			}
  			this = ptn;
  		}
1c9796452   David Woodhouse   [JFFS2] Simplify ...
279
280
281
  		dbg_readinode("'this' found %#04x-%#04x (%s)
  ", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole");
  	}
df8e96f39   David Woodhouse   [JFFS2] Improve r...
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
  
  	while (this) {
  		if (this->fn->ofs > fn_end)
  			break;
  		dbg_readinode("Ponder this ver %d, 0x%x-0x%x
  ",
  			      this->version, this->fn->ofs, this->fn->size);
  
  		if (this->version == tn->version) {
  			/* Version number collision means REF_PRISTINE GC. Accept either of them
  			   as long as the CRC is correct. Check the one we have already...  */
  			if (!check_tn_node(c, this)) {
  				/* The one we already had was OK. Keep it and throw away the new one */
  				dbg_readinode("Like old node. Throw away new
  ");
  				jffs2_kill_tn(c, tn);
  				return 0;
  			} else {
  				/* Who cares if the new one is good; keep it for now anyway. */
fcf3cafb3   David Woodhouse   [JFFS2] Remove an...
301
302
  				dbg_readinode("Like new node. Throw away old
  ");
df8e96f39   David Woodhouse   [JFFS2] Improve r...
303
  				rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
df8e96f39   David Woodhouse   [JFFS2] Improve r...
304
  				jffs2_kill_tn(c, this);
fcf3cafb3   David Woodhouse   [JFFS2] Remove an...
305
306
  				/* Same overlapping from in front and behind */
  				return 0;
df8e96f39   David Woodhouse   [JFFS2] Improve r...
307
308
309
310
311
312
313
314
315
316
317
318
  			}
  		}
  		if (this->version < tn->version &&
  		    this->fn->ofs >= tn->fn->ofs &&
  		    this->fn->ofs + this->fn->size <= fn_end) {
  			/* New node entirely overlaps 'this' */
  			if (check_tn_node(c, tn)) {
  				dbg_readinode("new node bad CRC
  ");
  				jffs2_kill_tn(c, tn);
  				return 0;
  			}
fcf3cafb3   David Woodhouse   [JFFS2] Remove an...
319
  			/* ... and is good. Kill 'this' and any subsequent nodes which are also overlapped */
1c9796452   David Woodhouse   [JFFS2] Simplify ...
320
  			while (this && this->fn->ofs + this->fn->size <= fn_end) {
df8e96f39   David Woodhouse   [JFFS2] Improve r...
321
322
323
324
325
326
327
328
329
330
331
  				struct jffs2_tmp_dnode_info *next = tn_next(this);
  				if (this->version < tn->version) {
  					tn_erase(this, &rii->tn_root);
  					dbg_readinode("Kill overlapped ver %d, 0x%x-0x%x
  ",
  						      this->version, this->fn->ofs,
  						      this->fn->ofs+this->fn->size);
  					jffs2_kill_tn(c, this);
  				}
  				this = next;
  			}
fcf3cafb3   David Woodhouse   [JFFS2] Remove an...
332
333
  			dbg_readinode("Done killing overlapped nodes
  ");
1c9796452   David Woodhouse   [JFFS2] Simplify ...
334
  			continue;
df8e96f39   David Woodhouse   [JFFS2] Improve r...
335
336
337
338
339
340
341
342
343
344
345
346
  		}
  		if (this->version > tn->version &&
  		    this->fn->ofs <= tn->fn->ofs &&
  		    this->fn->ofs+this->fn->size >= fn_end) {
  			/* New node entirely overlapped by 'this' */
  			if (!check_tn_node(c, this)) {
  				dbg_readinode("Good CRC on old node. Kill new
  ");
  				jffs2_kill_tn(c, tn);
  				return 0;
  			}
  			/* ... but 'this' was bad. Replace it... */
df8e96f39   David Woodhouse   [JFFS2] Improve r...
347
348
  			dbg_readinode("Bad CRC on old overlapping node. Kill it
  ");
fcf3cafb3   David Woodhouse   [JFFS2] Remove an...
349
  			tn_erase(this, &rii->tn_root);
df8e96f39   David Woodhouse   [JFFS2] Improve r...
350
  			jffs2_kill_tn(c, this);
fcf3cafb3   David Woodhouse   [JFFS2] Remove an...
351
  			break;
df8e96f39   David Woodhouse   [JFFS2] Improve r...
352
  		}
df8e96f39   David Woodhouse   [JFFS2] Improve r...
353
354
355
  
  		this = tn_next(this);
  	}
96dd8d25d   David Woodhouse   [JFFS2] Remove br...
356

df8e96f39   David Woodhouse   [JFFS2] Improve r...
357
  	/* We neither completely obsoleted nor were completely
96dd8d25d   David Woodhouse   [JFFS2] Remove br...
358
  	   obsoleted by an earlier node. Insert into the tree */
df8e96f39   David Woodhouse   [JFFS2] Improve r...
359
  	{
96dd8d25d   David Woodhouse   [JFFS2] Remove br...
360
361
  		struct rb_node *parent;
  		struct rb_node **link = &rii->tn_root.rb_node;
1c9796452   David Woodhouse   [JFFS2] Simplify ...
362
  		struct jffs2_tmp_dnode_info *insert_point = NULL;
df8e96f39   David Woodhouse   [JFFS2] Improve r...
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
  
  		while (*link) {
  			parent = *link;
  			insert_point = rb_entry(parent, struct jffs2_tmp_dnode_info, rb);
  			if (tn->fn->ofs > insert_point->fn->ofs)
  				link = &insert_point->rb.rb_right;
  			else if (tn->fn->ofs < insert_point->fn->ofs ||
  				 tn->fn->size < insert_point->fn->size)
  				link = &insert_point->rb.rb_left;
  			else
  				link = &insert_point->rb.rb_right;
  		}
  		rb_link_node(&tn->rb, &insert_point->rb, link);
  		rb_insert_color(&tn->rb, &rii->tn_root);
  	}
1123e2a85   David Woodhouse   [JFFS2] Remember ...
378

df8e96f39   David Woodhouse   [JFFS2] Improve r...
379
380
381
382
383
384
385
386
387
388
389
390
391
392
  	/* If there's anything behind that overlaps us, note it */
  	this = tn_prev(tn);
  	if (this) {
  		while (1) {
  			if (this->fn->ofs + this->fn->size > tn->fn->ofs) {
  				dbg_readinode("Node is overlapped by %p (v %d, 0x%x-0x%x)
  ",
  					      this, this->version, this->fn->ofs,
  					      this->fn->ofs+this->fn->size);
  				tn->overlapped = 1;
  				break;
  			}
  			if (!this->overlapped)
  				break;
4c41bd0ec   Thomas Gleixner   [JFFS2] fix mount...
393
394
395
396
397
398
399
400
401
402
403
  
  			ptn = tn_prev(this);
  			if (!ptn) {
  				/*
  				 * We killed a node which set the overlapped
  				 * flags during the scan. Fix it up.
  				 */
  				this->overlapped = 0;
  				break;
  			}
  			this = ptn;
df8e96f39   David Woodhouse   [JFFS2] Improve r...
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
  		}
  	}
  
  	/* If the new node overlaps anything ahead, note it */
  	this = tn_next(tn);
  	while (this && this->fn->ofs < fn_end) {
  		this->overlapped = 1;
  		dbg_readinode("Node ver %d, 0x%x-0x%x is overlapped
  ",
  			      this->version, this->fn->ofs,
  			      this->fn->ofs+this->fn->size);
  		this = tn_next(this);
  	}
  	return 0;
  }
  
  /* Trivial function to remove the last node in the tree. Which by definition
bf7ad8eea   Michel Lespinasse   rbtree: move some...
421
422
423
424
425
     has no right-hand child — so can be removed just by making its left-hand
     child (if any) take its place under its parent. Since this is only done
     when we're consuming the whole tree, there's no need to use rb_erase()
     and let it worry about adjusting colours and balancing the tree. That
     would just be a waste of time. */
df8e96f39   David Woodhouse   [JFFS2] Improve r...
426
  static void eat_last(struct rb_root *root, struct rb_node *node)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
  {
df8e96f39   David Woodhouse   [JFFS2] Improve r...
428
429
430
431
432
433
434
435
436
437
438
439
440
441
  	struct rb_node *parent = rb_parent(node);
  	struct rb_node **link;
  
  	/* LAST! */
  	BUG_ON(node->rb_right);
  
  	if (!parent)
  		link = &root->rb_node;
  	else if (node == parent->rb_left)
  		link = &parent->rb_left;
  	else
  		link = &parent->rb_right;
  
  	*link = node->rb_left;
df8e96f39   David Woodhouse   [JFFS2] Improve r...
442
  	if (node->rb_left)
bf7ad8eea   Michel Lespinasse   rbtree: move some...
443
  		node->rb_left->__rb_parent_color = node->__rb_parent_color;
df8e96f39   David Woodhouse   [JFFS2] Improve r...
444
  }
bf7ad8eea   Michel Lespinasse   rbtree: move some...
445
446
  /* We put the version tree in reverse order, so we can use the same eat_last()
     function that we use to consume the tmpnode tree (tn_root). */
df8e96f39   David Woodhouse   [JFFS2] Improve r...
447
448
449
450
451
452
453
454
455
456
457
458
  static void ver_insert(struct rb_root *ver_root, struct jffs2_tmp_dnode_info *tn)
  {
  	struct rb_node **link = &ver_root->rb_node;
  	struct rb_node *parent = NULL;
  	struct jffs2_tmp_dnode_info *this_tn;
  
  	while (*link) {
  		parent = *link;
  		this_tn = rb_entry(parent, struct jffs2_tmp_dnode_info, rb);
  
  		if (tn->version > this_tn->version)
  			link = &parent->rb_left;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
459
  		else
df8e96f39   David Woodhouse   [JFFS2] Improve r...
460
  			link = &parent->rb_right;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
461
  	}
df8e96f39   David Woodhouse   [JFFS2] Improve r...
462
463
464
465
466
  	dbg_readinode("Link new node at %p (root is %p)
  ", link, ver_root);
  	rb_link_node(&tn->rb, parent, link);
  	rb_insert_color(&tn->rb, ver_root);
  }
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
467

df8e96f39   David Woodhouse   [JFFS2] Improve r...
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
  /* Build final, normal fragtree from tn tree. It doesn't matter which order
     we add nodes to the real fragtree, as long as they don't overlap. And
     having thrown away the majority of overlapped nodes as we went, there
     really shouldn't be many sets of nodes which do overlap. If we start at
     the end, we can use the overlap markers -- we can just eat nodes which
     aren't overlapped, and when we encounter nodes which _do_ overlap we
     sort them all into a temporary tree in version order before replaying them. */
  static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c,
  				      struct jffs2_inode_info *f,
  				      struct jffs2_readinode_info *rii)
  {
  	struct jffs2_tmp_dnode_info *pen, *last, *this;
  	struct rb_root ver_root = RB_ROOT;
  	uint32_t high_ver = 0;
  
  	if (rii->mdata_tn) {
  		dbg_readinode("potential mdata is ver %d at %p
  ", rii->mdata_tn->version, rii->mdata_tn);
  		high_ver = rii->mdata_tn->version;
  		rii->latest_ref = rii->mdata_tn->fn->raw;
  	}
  #ifdef JFFS2_DBG_READINODE_MESSAGES
  	this = tn_last(&rii->tn_root);
  	while (this) {
  		dbg_readinode("tn %p ver %d range 0x%x-0x%x ov %d
  ", this, this->version, this->fn->ofs,
96dd8d25d   David Woodhouse   [JFFS2] Remove br...
494
  			      this->fn->ofs+this->fn->size, this->overlapped);
df8e96f39   David Woodhouse   [JFFS2] Improve r...
495
496
497
498
499
500
501
502
503
  		this = tn_prev(this);
  	}
  #endif
  	pen = tn_last(&rii->tn_root);
  	while ((last = pen)) {
  		pen = tn_prev(last);
  
  		eat_last(&rii->tn_root, &last->rb);
  		ver_insert(&ver_root, last);
4c41bd0ec   Thomas Gleixner   [JFFS2] fix mount...
504
505
506
507
508
509
510
511
512
  		if (unlikely(last->overlapped)) {
  			if (pen)
  				continue;
  			/*
  			 * We killed a node which set the overlapped
  			 * flags during the scan. Fix it up.
  			 */
  			last->overlapped = 0;
  		}
df8e96f39   David Woodhouse   [JFFS2] Improve r...
513
514
515
516
517
518
519
520
521
522
523
524
525
  
  		/* Now we have a bunch of nodes in reverse version
  		   order, in the tree at ver_root. Most of the time,
  		   there'll actually be only one node in the 'tree',
  		   in fact. */
  		this = tn_last(&ver_root);
  
  		while (this) {
  			struct jffs2_tmp_dnode_info *vers_next;
  			int ret;
  			vers_next = tn_prev(this);
  			eat_last(&ver_root, &this->rb);
  			if (check_tn_node(c, this)) {
1123e2a85   David Woodhouse   [JFFS2] Remember ...
526
527
  				dbg_readinode("node ver %d, 0x%x-0x%x failed CRC
  ",
df8e96f39   David Woodhouse   [JFFS2] Improve r...
528
529
530
531
532
533
534
535
536
537
538
539
  					     this->version, this->fn->ofs,
  					     this->fn->ofs+this->fn->size);
  				jffs2_kill_tn(c, this);
  			} else {
  				if (this->version > high_ver) {
  					/* Note that this is different from the other
  					   highest_version, because this one is only
  					   counting _valid_ nodes which could give the
  					   latest inode metadata */
  					high_ver = this->version;
  					rii->latest_ref = this->fn->raw;
  				}
1123e2a85   David Woodhouse   [JFFS2] Remember ...
540
541
  				dbg_readinode("Add %p (v %d, 0x%x-0x%x, ov %d) to fragtree
  ",
df8e96f39   David Woodhouse   [JFFS2] Improve r...
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
  					     this, this->version, this->fn->ofs,
  					     this->fn->ofs+this->fn->size, this->overlapped);
  
  				ret = jffs2_add_full_dnode_to_inode(c, f, this->fn);
  				if (ret) {
  					/* Free the nodes in vers_root; let the caller
  					   deal with the rest */
  					JFFS2_ERROR("Add node to tree failed %d
  ", ret);
  					while (1) {
  						vers_next = tn_prev(this);
  						if (check_tn_node(c, this))
  							jffs2_mark_node_obsolete(c, this->fn->raw);
  						jffs2_free_full_dnode(this->fn);
  						jffs2_free_tmp_dnode_info(this);
  						this = vers_next;
  						if (!this)
  							break;
  						eat_last(&ver_root, &vers_next->rb);
  					}
  					return ret;
  				}
  				jffs2_free_tmp_dnode_info(this);
  			}
  			this = vers_next;
  		}
  	}
  	return 0;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
570
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
572
573
  static void jffs2_free_tmp_dnode_info_list(struct rb_root *list)
  {
e8bbeeb75   Cody P Schafer   fs/jffs2: use rbt...
574
  	struct jffs2_tmp_dnode_info *tn, *next;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
575

e8bbeeb75   Cody P Schafer   fs/jffs2: use rbt...
576
  	rbtree_postorder_for_each_entry_safe(tn, next, list, rb) {
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
577
578
  			jffs2_free_full_dnode(tn->fn);
  			jffs2_free_tmp_dnode_info(tn);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
579
  	}
e8bbeeb75   Cody P Schafer   fs/jffs2: use rbt...
580

bcc54e2a6   Venkatesh Pallipadi   jffs2: fix up rb_...
581
  	*list = RB_ROOT;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
582
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
584
585
586
  static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd)
  {
  	struct jffs2_full_dirent *next;
336d2ff71   Artem B. Bityuckiy   [JFFS2] Avoid all...
587

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
588
589
590
591
592
593
  	while (fd) {
  		next = fd->next;
  		jffs2_free_full_dirent(fd);
  		fd = next;
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
595
596
597
598
599
600
  /* Returns first valid node after 'ref'. May return 'ref' */
  static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_ref *ref)
  {
  	while (ref && ref->next_in_ino) {
  		if (!ref_obsolete(ref))
  			return ref;
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
601
602
  		dbg_noderef("node at 0x%08x is obsoleted. Ignoring.
  ", ref_offset(ref));
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
603
604
605
606
  		ref = ref->next_in_ino;
  	}
  	return NULL;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
607

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
608
609
610
611
  /*
   * Helper function for jffs2_get_inode_nodes().
   * It is called every time an directory entry node is found.
   *
14c6381ee   David Woodhouse   [JFFS2] Fix readi...
612
   * Returns: 0 on success;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
613
614
   * 	    negative error code on failure.
   */
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
615
  static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
df8e96f39   David Woodhouse   [JFFS2] Improve r...
616
617
  				struct jffs2_raw_dirent *rd, size_t read,
  				struct jffs2_readinode_info *rii)
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
618
619
  {
  	struct jffs2_full_dirent *fd;
1046d8800   David Woodhouse   [JFFS2] Check CRC...
620
  	uint32_t crc;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
621

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
622
623
  	/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
  	BUG_ON(ref_obsolete(ref));
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
624

1046d8800   David Woodhouse   [JFFS2] Check CRC...
625
626
627
628
629
  	crc = crc32(0, rd, sizeof(*rd) - 8);
  	if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
  		JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x
  ",
  			     ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
df8e96f39   David Woodhouse   [JFFS2] Improve r...
630
631
  		jffs2_mark_node_obsolete(c, ref);
  		return 0;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
632
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
633

1046d8800   David Woodhouse   [JFFS2] Check CRC...
634
635
636
637
638
639
640
641
642
643
  	/* If we've never checked the CRCs on this node, check them now */
  	if (ref_flags(ref) == REF_UNCHECKED) {
  		struct jffs2_eraseblock *jeb;
  		int len;
  
  		/* Sanity check */
  		if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
  			JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x
  ",
  				    ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
df8e96f39   David Woodhouse   [JFFS2] Improve r...
644
645
  			jffs2_mark_node_obsolete(c, ref);
  			return 0;
1046d8800   David Woodhouse   [JFFS2] Check CRC...
646
647
648
649
650
651
652
653
654
655
  		}
  
  		jeb = &c->blocks[ref->flash_offset / c->sector_size];
  		len = ref_totlen(c, jeb, ref);
  
  		spin_lock(&c->erase_completion_lock);
  		jeb->used_size += len;
  		jeb->unchecked_size -= len;
  		c->used_size += len;
  		c->unchecked_size -= len;
43dfa07fb   David Woodhouse   [JFFS2] Deletion ...
656
  		ref->flash_offset = ref_offset(ref) | dirent_node_state(rd);
1046d8800   David Woodhouse   [JFFS2] Check CRC...
657
658
  		spin_unlock(&c->erase_completion_lock);
  	}
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
659
660
661
  	fd = jffs2_alloc_full_dirent(rd->nsize + 1);
  	if (unlikely(!fd))
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
663
664
665
666
  	fd->raw = ref;
  	fd->version = je32_to_cpu(rd->version);
  	fd->ino = je32_to_cpu(rd->ino);
  	fd->type = rd->type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667

df8e96f39   David Woodhouse   [JFFS2] Improve r...
668
669
  	if (fd->version > rii->highest_version)
  		rii->highest_version = fd->version;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
670
  	/* Pick out the mctime of the latest dirent */
df8e96f39   David Woodhouse   [JFFS2] Improve r...
671
672
673
  	if(fd->version > rii->mctime_ver && je32_to_cpu(rd->mctime)) {
  		rii->mctime_ver = fd->version;
  		rii->latest_mctime = je32_to_cpu(rd->mctime);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
674
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
675
  	/*
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
676
677
678
679
680
681
  	 * Copy as much of the name as possible from the raw
  	 * dirent we've already read from the flash.
  	 */
  	if (read > sizeof(*rd))
  		memcpy(&fd->name[0], &rd->name[0],
  		       min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) ));
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
682

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
683
684
685
686
687
  	/* Do we need to copy any more of the name directly from the flash? */
  	if (rd->nsize + sizeof(*rd) > read) {
  		/* FIXME: point() */
  		int err;
  		int already = read - sizeof(*rd);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
688
689
  
  		err = jffs2_flash_read(c, (ref_offset(ref)) + read,
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
690
  				rd->nsize - already, &read, &fd->name[already]);
eb042ec35   Wei Fang   jffs2: fix a meml...
691
692
693
694
695
  		if (unlikely(read != rd->nsize - already) && likely(!err)) {
  			jffs2_free_full_dirent(fd);
  			JFFS2_ERROR("short read: wanted %d bytes, got %zd
  ",
  				    rd->nsize - already, read);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
696
  			return -EIO;
eb042ec35   Wei Fang   jffs2: fix a meml...
697
  		}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
698

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
699
  		if (unlikely(err)) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
700
701
  			JFFS2_ERROR("read remainder of name: error %d
  ", err);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
702
703
  			jffs2_free_full_dirent(fd);
  			return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
705
  		}
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
706

8387ff257   Linus Torvalds   vfs: make the str...
707
  	fd->nhash = full_name_hash(NULL, fd->name, rd->nsize);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
708
709
  	fd->next = NULL;
  	fd->name[rd->nsize] = '\0';
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
710

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
711
712
  	/*
  	 * Wheee. We now have a complete jffs2_full_dirent structure, with
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
713
  	 * the name in it and everything. Link it into the list
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
714
  	 */
df8e96f39   David Woodhouse   [JFFS2] Improve r...
715
  	jffs2_add_fd_to_list(c, fd, &rii->fds);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
716

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717
718
  	return 0;
  }
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
719
720
721
722
  /*
   * Helper function for jffs2_get_inode_nodes().
   * It is called every time an inode node is found.
   *
14c6381ee   David Woodhouse   [JFFS2] Fix readi...
723
   * Returns: 0 on success (possibly after marking a bad node obsolete);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
724
725
   * 	    negative error code on failure.
   */
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
726
  static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
df8e96f39   David Woodhouse   [JFFS2] Improve r...
727
728
  			     struct jffs2_raw_inode *rd, int rdlen,
  			     struct jffs2_readinode_info *rii)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
729
  {
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
730
  	struct jffs2_tmp_dnode_info *tn;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
731
  	uint32_t len, csize;
14c6381ee   David Woodhouse   [JFFS2] Fix readi...
732
  	int ret = 0;
1046d8800   David Woodhouse   [JFFS2] Check CRC...
733
  	uint32_t crc;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
734

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
735
736
  	/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
  	BUG_ON(ref_obsolete(ref));
1046d8800   David Woodhouse   [JFFS2] Check CRC...
737
738
739
740
741
  	crc = crc32(0, rd, sizeof(*rd) - 8);
  	if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
  		JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x
  ",
  			     ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
df8e96f39   David Woodhouse   [JFFS2] Improve r...
742
743
  		jffs2_mark_node_obsolete(c, ref);
  		return 0;
1046d8800   David Woodhouse   [JFFS2] Check CRC...
744
  	}
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
745
746
  	tn = jffs2_alloc_tmp_dnode_info();
  	if (!tn) {
fb6a82c94   Randy Dunlap   [PATCH] jffs2: fi...
747
748
  		JFFS2_ERROR("failed to allocate tn (%zu bytes).
  ", sizeof(*tn));
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
749
750
751
752
753
  		return -ENOMEM;
  	}
  
  	tn->partial_crc = 0;
  	csize = je32_to_cpu(rd->csize);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
754

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
755
756
  	/* If we've never checked the CRCs on this node, check them now */
  	if (ref_flags(ref) == REF_UNCHECKED) {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
757

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
758
759
760
  		/* Sanity checks */
  		if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) ||
  		    unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) {
14c6381ee   David Woodhouse   [JFFS2] Fix readi...
761
762
763
764
  			JFFS2_WARNING("inode node header CRC is corrupted at %#08x
  ", ref_offset(ref));
  			jffs2_dbg_dump_node(c, ref_offset(ref));
  			jffs2_mark_node_obsolete(c, ref);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
765
  			goto free_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
766
  		}
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
  		if (jffs2_is_writebuffered(c) && csize != 0) {
  			/* At this point we are supposed to check the data CRC
  			 * of our unchecked node. But thus far, we do not
  			 * know whether the node is valid or obsolete. To
  			 * figure this out, we need to walk all the nodes of
  			 * the inode and build the inode fragtree. We don't
  			 * want to spend time checking data of nodes which may
  			 * later be found to be obsolete. So we put off the full
  			 * data CRC checking until we have read all the inode
  			 * nodes and have started building the fragtree.
  			 *
  			 * The fragtree is being built starting with nodes
  			 * having the highest version number, so we'll be able
  			 * to detect whether a node is valid (i.e., it is not
  			 * overlapped by a node with higher version) or not.
  			 * And we'll be able to check only those nodes, which
  			 * are not obsolete.
  			 *
  			 * Of course, this optimization only makes sense in case
e1b8513d2   Robert P. J. Day   Typoes: "whith" ...
786
  			 * of NAND flashes (or other flashes with
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
  			 * !jffs2_can_mark_obsolete()), since on NOR flashes
  			 * nodes are marked obsolete physically.
  			 *
  			 * Since NAND flashes (or other flashes with
  			 * jffs2_is_writebuffered(c)) are anyway read by
  			 * fractions of c->wbuf_pagesize, and we have just read
  			 * the node header, it is likely that the starting part
  			 * of the node data is also read when we read the
  			 * header. So we don't mind to check the CRC of the
  			 * starting part of the data of the node now, and check
  			 * the second part later (in jffs2_check_node_data()).
  			 * Of course, we will not need to re-read and re-check
  			 * the NAND page which we have just read. This is why we
  			 * read the whole NAND page at jffs2_get_inode_nodes(),
  			 * while we needed only the node header.
  			 */
  			unsigned char *buf;
  
  			/* 'buf' will point to the start of data */
  			buf = (unsigned char *)rd + sizeof(*rd);
  			/* len will be the read data length */
  			len = min_t(uint32_t, rdlen - sizeof(*rd), csize);
280562b21   Artem B. Bityutskiy   [JFFS2] Calculate...
809
  			tn->partial_crc = crc32(0, buf, len);
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
810
811
  			dbg_readinode("Calculates CRC (%#08x) for %d bytes, csize %d
  ", tn->partial_crc, len, csize);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
812
813
814
  
  			/* If we actually calculated the whole data CRC
  			 * and it is wrong, drop the node. */
3c0913373   Artem B. Bityutskiy   [JFFS2] Correct b...
815
  			if (len >= csize && unlikely(tn->partial_crc != je32_to_cpu(rd->data_crc))) {
392435081   Artem B. Bityutskiy   [JFFS2] Debug cod...
816
817
818
  				JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.
  ",
  					ref_offset(ref), tn->partial_crc, je32_to_cpu(rd->data_crc));
14c6381ee   David Woodhouse   [JFFS2] Fix readi...
819
  				jffs2_mark_node_obsolete(c, ref);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
820
  				goto free_out;
392435081   Artem B. Bityutskiy   [JFFS2] Debug cod...
821
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822

1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
823
824
825
826
827
828
829
830
  		} else if (csize == 0) {
  			/*
  			 * We checked the header CRC. If the node has no data, adjust
  			 * the space accounting now. For other nodes this will be done
  			 * later either when the node is marked obsolete or when its
  			 * data is checked.
  			 */
  			struct jffs2_eraseblock *jeb;
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
831
832
  			dbg_readinode("the node has no data.
  ");
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
833
834
835
836
837
838
839
840
  			jeb = &c->blocks[ref->flash_offset / c->sector_size];
  			len = ref_totlen(c, jeb, ref);
  
  			spin_lock(&c->erase_completion_lock);
  			jeb->used_size += len;
  			jeb->unchecked_size -= len;
  			c->used_size += len;
  			c->unchecked_size -= len;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
841
  			ref->flash_offset = ref_offset(ref) | REF_NORMAL;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
842
  			spin_unlock(&c->erase_completion_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
844
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
846
847
  	tn->fn = jffs2_alloc_full_dnode();
  	if (!tn->fn) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
848
849
  		JFFS2_ERROR("alloc fn failed
  ");
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
850
851
  		ret = -ENOMEM;
  		goto free_out;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
852
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
853

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
854
855
  	tn->version = je32_to_cpu(rd->version);
  	tn->fn->ofs = je32_to_cpu(rd->offset);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
856
857
  	tn->data_crc = je32_to_cpu(rd->data_crc);
  	tn->csize = csize;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
858
  	tn->fn->raw = ref;
df8e96f39   David Woodhouse   [JFFS2] Improve r...
859
860
861
862
  	tn->overlapped = 0;
  
  	if (tn->version > rii->highest_version)
  		rii->highest_version = tn->version;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
863

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
864
865
  	/* There was a bug where we wrote hole nodes out with
  	   csize/dsize swapped. Deal with it */
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
866
867
  	if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && csize)
  		tn->fn->size = csize;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
868
869
  	else // normal case...
  		tn->fn->size = je32_to_cpu(rd->dsize);
2c61cb250   David Woodhouse   [JFFS2] Introduce...
870
871
872
873
  	dbg_readinode2("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x
  ",
  		       ref_offset(ref), je32_to_cpu(rd->version),
  		       je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
874

df8e96f39   David Woodhouse   [JFFS2] Improve r...
875
  	ret = jffs2_add_tn_to_tree(c, rii, tn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
876

df8e96f39   David Woodhouse   [JFFS2] Improve r...
877
878
879
880
881
882
  	if (ret) {
  		jffs2_free_full_dnode(tn->fn);
  	free_out:
  		jffs2_free_tmp_dnode_info(tn);
  		return ret;
  	}
2c61cb250   David Woodhouse   [JFFS2] Introduce...
883
884
885
  #ifdef JFFS2_DBG_READINODE2_MESSAGES
  	dbg_readinode2("After adding ver %d:
  ", je32_to_cpu(rd->version));
df8e96f39   David Woodhouse   [JFFS2] Improve r...
886
887
  	tn = tn_first(&rii->tn_root);
  	while (tn) {
2c61cb250   David Woodhouse   [JFFS2] Introduce...
888
889
890
891
  		dbg_readinode2("%p: v %d r 0x%x-0x%x ov %d
  ",
  			       tn, tn->version, tn->fn->ofs,
  			       tn->fn->ofs+tn->fn->size, tn->overlapped);
df8e96f39   David Woodhouse   [JFFS2] Improve r...
892
893
894
  		tn = tn_next(tn);
  	}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
895
896
  	return 0;
  }
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
897
898
899
900
  /*
   * Helper function for jffs2_get_inode_nodes().
   * It is called every time an unknown node is found.
   *
3877f0b6c   David Woodhouse   [JFFS2] Don't tru...
901
   * Returns: 0 on success;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
902
903
   * 	    negative error code on failure.
   */
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
904
  static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, struct jffs2_unknown_node *un)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
  {
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
906
  	/* We don't mark unknown nodes as REF_UNCHECKED */
c7258a447   David Woodhouse   [JFFS2] Check for...
907
908
909
910
911
912
  	if (ref_flags(ref) == REF_UNCHECKED) {
  		JFFS2_ERROR("REF_UNCHECKED but unknown node at %#08x
  ",
  			    ref_offset(ref));
  		JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.
  ",
ef53cb02f   David Woodhouse   [JFFS2] Whitespac...
913
914
  			    je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
  			    je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc));
df8e96f39   David Woodhouse   [JFFS2] Improve r...
915
916
  		jffs2_mark_node_obsolete(c, ref);
  		return 0;
c7258a447   David Woodhouse   [JFFS2] Check for...
917
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
918

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
919
  	un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
920

3877f0b6c   David Woodhouse   [JFFS2] Don't tru...
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
  	switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
  
  	case JFFS2_FEATURE_INCOMPAT:
  		JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x
  ",
  			    je16_to_cpu(un->nodetype), ref_offset(ref));
  		/* EEP */
  		BUG();
  		break;
  
  	case JFFS2_FEATURE_ROCOMPAT:
  		JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x
  ",
  			    je16_to_cpu(un->nodetype), ref_offset(ref));
  		BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
  		break;
  
  	case JFFS2_FEATURE_RWCOMPAT_COPY:
  		JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x
  ",
  			     je16_to_cpu(un->nodetype), ref_offset(ref));
  		break;
  
  	case JFFS2_FEATURE_RWCOMPAT_DELETE:
  		JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x
  ",
  			     je16_to_cpu(un->nodetype), ref_offset(ref));
df8e96f39   David Woodhouse   [JFFS2] Improve r...
948
949
  		jffs2_mark_node_obsolete(c, ref);
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
950
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
951

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
952
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
953
  }
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
954
955
956
957
  /*
   * Helper function for jffs2_get_inode_nodes().
   * The function detects whether more data should be read and reads it if yes.
   *
af901ca18   André Goddard Rosa   tree-wide: fix as...
958
   * Returns: 0 on success;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
959
960
961
   * 	    negative error code on failure.
   */
  static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
962
  		     int needed_len, int *rdlen, unsigned char *buf)
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
963
  {
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
964
  	int err, to_read = needed_len - *rdlen;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
965
966
967
968
  	size_t retlen;
  	uint32_t offs;
  
  	if (jffs2_is_writebuffered(c)) {
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
969
  		int rem = to_read % c->wbuf_pagesize;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
970

10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
971
972
973
  		if (rem)
  			to_read += c->wbuf_pagesize - rem;
  	}
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
974
975
976
  
  	/* We need to read more data */
  	offs = ref_offset(ref) + *rdlen;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
977

10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
978
979
  	dbg_readinode("read more %d bytes
  ", to_read);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
980

10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
981
  	err = jffs2_flash_read(c, offs, to_read, &retlen, buf + *rdlen);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
982
983
  	if (err) {
  		JFFS2_ERROR("can not read %d bytes from 0x%08x, "
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
984
985
  			"error code: %d.
  ", to_read, offs, err);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
986
987
  		return err;
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
988

10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
989
  	if (retlen < to_read) {
fb6a82c94   Randy Dunlap   [PATCH] jffs2: fi...
990
991
  		JFFS2_ERROR("short read at %#08x: %zu instead of %d.
  ",
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
992
  				offs, retlen, to_read);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
993
994
  		return -EIO;
  	}
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
995
  	*rdlen += to_read;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
996
997
  	return 0;
  }
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
998
  /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated
df8e96f39   David Woodhouse   [JFFS2] Improve r...
999
1000
1001
1002
     with this ino. Perform a preliminary ordering on data nodes, throwing away
     those which are completely obsoleted by newer ones. The naïve approach we
     use to take of just returning them _all_ in version order will cause us to
     run out of memory in certain degenerate cases. */
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1003
  static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1004
  				 struct jffs2_readinode_info *rii)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1005
  {
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1006
  	struct jffs2_raw_node_ref *ref, *valid_ref;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1007
1008
  	unsigned char *buf = NULL;
  	union jffs2_node_union *node;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1009
  	size_t retlen;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1010
  	int len, err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1011

df8e96f39   David Woodhouse   [JFFS2] Improve r...
1012
  	rii->mctime_ver = 0;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1013

733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
1014
1015
  	dbg_readinode("ino #%u
  ", f->inocache->ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1016

1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1017
1018
  	/* FIXME: in case of NOR and available ->point() this
  	 * needs to be fixed. */
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1019
  	len = sizeof(union jffs2_node_union) + c->wbuf_pagesize;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1020
1021
1022
  	buf = kmalloc(len, GFP_KERNEL);
  	if (!buf)
  		return -ENOMEM;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1023

1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1024
  	spin_lock(&c->erase_completion_lock);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1025
  	valid_ref = jffs2_first_valid_node(f->inocache->nodes);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1026
1027
1028
  	if (!valid_ref && f->inocache->ino != 1)
  		JFFS2_WARNING("Eep. No valid nodes for ino #%u.
  ", f->inocache->ino);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
  	while (valid_ref) {
  		/* We can hold a pointer to a non-obsolete node without the spinlock,
  		   but _obsolete_ nodes may disappear at any time, if the block
  		   they're in gets erased. So if we mark 'ref' obsolete while we're
  		   not holding the lock, it can go away immediately. For that reason,
  		   we find the next valid node first, before processing 'ref'.
  		*/
  		ref = valid_ref;
  		valid_ref = jffs2_first_valid_node(ref->next_in_ino);
  		spin_unlock(&c->erase_completion_lock);
  
  		cond_resched();
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1041
1042
1043
  		/*
  		 * At this point we don't know the type of the node we're going
  		 * to read, so we do not know the size of its header. In order
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1044
1045
  		 * to minimize the amount of flash IO we assume the header is
  		 * of size = JFFS2_MIN_NODE_HEADER.
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1046
  		 */
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1047
  		len = JFFS2_MIN_NODE_HEADER;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1048
  		if (jffs2_is_writebuffered(c)) {
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1049
  			int end, rem;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1050
  			/*
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1051
1052
1053
1054
1055
  			 * We are about to read JFFS2_MIN_NODE_HEADER bytes,
  			 * but this flash has some minimal I/O unit. It is
  			 * possible that we'll need to read more soon, so read
  			 * up to the next min. I/O unit, in order not to
  			 * re-read the same min. I/O unit twice.
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1056
  			 */
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1057
1058
1059
1060
1061
  			end = ref_offset(ref) + len;
  			rem = end % c->wbuf_pagesize;
  			if (rem)
  				end += c->wbuf_pagesize - rem;
  			len = end - ref_offset(ref);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1062
  		}
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
1063
1064
  		dbg_readinode("read %d bytes at %#08x(%d).
  ", len, ref_offset(ref), ref_flags(ref));
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1065

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1066
  		/* FIXME: point() */
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1067
  		err = jffs2_flash_read(c, ref_offset(ref), len, &retlen, buf);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1068
  		if (err) {
df2e301fe   Jean Delvare   fs: Merge split s...
1069
1070
  			JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.
  ", len, ref_offset(ref), err);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1071
1072
  			goto free_out;
  		}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1073

1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1074
  		if (retlen < len) {
fb6a82c94   Randy Dunlap   [PATCH] jffs2: fi...
1075
1076
  			JFFS2_ERROR("short read at %#08x: %zu instead of %d.
  ", ref_offset(ref), retlen, len);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1077
  			err = -EIO;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1078
1079
  			goto free_out;
  		}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1080

10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1081
  		node = (union jffs2_node_union *)buf;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1082

3877f0b6c   David Woodhouse   [JFFS2] Don't tru...
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
  		/* No need to mask in the valid bit; it shouldn't be invalid */
  		if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) {
  			JFFS2_NOTICE("Node header CRC failed at %#08x. {%04x,%04x,%08x,%08x}
  ",
  				     ref_offset(ref), je16_to_cpu(node->u.magic),
  				     je16_to_cpu(node->u.nodetype),
  				     je32_to_cpu(node->u.totlen),
  				     je32_to_cpu(node->u.hdr_crc));
  			jffs2_dbg_dump_node(c, ref_offset(ref));
  			jffs2_mark_node_obsolete(c, ref);
  			goto cont;
  		}
0dec4c8bc   Joakim Tjernlund   [JFFS2] Better fi...
1095
1096
1097
1098
1099
  		if (je16_to_cpu(node->u.magic) != JFFS2_MAGIC_BITMASK) {
  			/* Not a JFFS2 node, whinge and move on */
  			JFFS2_NOTICE("Wrong magic bitmask 0x%04x in node header at %#08x.
  ",
  				     je16_to_cpu(node->u.magic), ref_offset(ref));
c7258a447   David Woodhouse   [JFFS2] Check for...
1100
1101
1102
  			jffs2_mark_node_obsolete(c, ref);
  			goto cont;
  		}
3877f0b6c   David Woodhouse   [JFFS2] Don't tru...
1103

1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1104
  		switch (je16_to_cpu(node->u.nodetype)) {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1105

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1106
  		case JFFS2_NODETYPE_DIRENT:
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1107

ea55d3079   Artem Bityutskiy   [JFFS2] Fix buffe...
1108
1109
  			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent) &&
  			    len < sizeof(struct jffs2_raw_dirent)) {
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1110
  				err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1111
1112
1113
  				if (unlikely(err))
  					goto free_out;
  			}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1114

df8e96f39   David Woodhouse   [JFFS2] Improve r...
1115
1116
  			err = read_direntry(c, ref, &node->d, retlen, rii);
  			if (unlikely(err))
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1117
  				goto free_out;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1118

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1119
  			break;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1120
  		case JFFS2_NODETYPE_INODE:
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1121

ea55d3079   Artem Bityutskiy   [JFFS2] Fix buffe...
1122
1123
  			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode) &&
  			    len < sizeof(struct jffs2_raw_inode)) {
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1124
  				err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1125
1126
  				if (unlikely(err))
  					goto free_out;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1127
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1128

df8e96f39   David Woodhouse   [JFFS2] Improve r...
1129
1130
  			err = read_dnode(c, ref, &node->i, len, rii);
  			if (unlikely(err))
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1131
  				goto free_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1132

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1133
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1134

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1135
  		default:
ea55d3079   Artem Bityutskiy   [JFFS2] Fix buffe...
1136
1137
  			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node) &&
  			    len < sizeof(struct jffs2_unknown_node)) {
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1138
  				err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1139
1140
  				if (unlikely(err))
  					goto free_out;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1141
  			}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1142

1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1143
  			err = read_unknown(c, ref, &node->u);
14c6381ee   David Woodhouse   [JFFS2] Fix readi...
1144
  			if (unlikely(err))
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1145
1146
1147
  				goto free_out;
  
  		}
3877f0b6c   David Woodhouse   [JFFS2] Don't tru...
1148
  	cont:
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1149
  		spin_lock(&c->erase_completion_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1150
  	}
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1151

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1152
  	spin_unlock(&c->erase_completion_lock);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1153
  	kfree(buf);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1154

df8e96f39   David Woodhouse   [JFFS2] Improve r...
1155
  	f->highest_version = rii->highest_version;
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
1156
1157
  	dbg_readinode("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.
  ",
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1158
1159
  		      f->inocache->ino, rii->highest_version, rii->latest_mctime,
  		      rii->mctime_ver);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1160
1161
1162
  	return 0;
  
   free_out:
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1163
1164
1165
  	jffs2_free_tmp_dnode_info_list(&rii->tn_root);
  	jffs2_free_full_dirent_list(rii->fds);
  	rii->fds = NULL;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1166
  	kfree(buf);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1167
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1168
  }
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1169
  static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1170
1171
1172
  					struct jffs2_inode_info *f,
  					struct jffs2_raw_inode *latest_node)
  {
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1173
  	struct jffs2_readinode_info rii;
61c4b2377   David Woodhouse   [JFFS2] Handle in...
1174
  	uint32_t crc, new_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1175
1176
  	size_t retlen;
  	int ret;
27c72b040   David Woodhouse   [JFFS2] Track par...
1177
1178
1179
  	dbg_readinode("ino #%u pino/nlink is %d
  ", f->inocache->ino,
  		      f->inocache->pino_nlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180

df8e96f39   David Woodhouse   [JFFS2] Improve r...
1181
  	memset(&rii, 0, sizeof(rii));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1182
  	/* Grab all nodes relevant to this ino */
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1183
  	ret = jffs2_get_inode_nodes(c, f, &rii);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1184
1185
  
  	if (ret) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
1186
1187
  		JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d
  ", f->inocache->ino, ret);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1188
1189
1190
1191
  		if (f->inocache->state == INO_STATE_READING)
  			jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
  		return ret;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1192

df8e96f39   David Woodhouse   [JFFS2] Improve r...
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
  	ret = jffs2_build_inode_fragtree(c, f, &rii);
  	if (ret) {
  		JFFS2_ERROR("Failed to build final fragtree for inode #%u: error %d
  ",
  			    f->inocache->ino, ret);
  		if (f->inocache->state == INO_STATE_READING)
  			jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
  		jffs2_free_tmp_dnode_info_list(&rii.tn_root);
  		/* FIXME: We could at least crc-check them all */
  		if (rii.mdata_tn) {
  			jffs2_free_full_dnode(rii.mdata_tn->fn);
  			jffs2_free_tmp_dnode_info(rii.mdata_tn);
  			rii.mdata_tn = NULL;
  		}
  		return ret;
  	}
9dee7503c   David Woodhouse   [JFFS2] Optimise ...
1209

df8e96f39   David Woodhouse   [JFFS2] Improve r...
1210
1211
1212
1213
1214
1215
  	if (rii.mdata_tn) {
  		if (rii.mdata_tn->fn->raw == rii.latest_ref) {
  			f->metadata = rii.mdata_tn->fn;
  			jffs2_free_tmp_dnode_info(rii.mdata_tn);
  		} else {
  			jffs2_kill_tn(c, rii.mdata_tn);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1216
  		}
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1217
  		rii.mdata_tn = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1218
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1219

df8e96f39   David Woodhouse   [JFFS2] Improve r...
1220
1221
1222
  	f->dents = rii.fds;
  
  	jffs2_dbg_fragtree_paranoia_check_nolock(f);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1223

df8e96f39   David Woodhouse   [JFFS2] Improve r...
1224
  	if (unlikely(!rii.latest_ref)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1225
1226
  		/* No data nodes for this inode. */
  		if (f->inocache->ino != 1) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
1227
1228
  			JFFS2_WARNING("no data nodes found for ino #%u
  ", f->inocache->ino);
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1229
  			if (!rii.fds) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1230
1231
1232
1233
  				if (f->inocache->state == INO_STATE_READING)
  					jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
  				return -EIO;
  			}
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
1234
1235
  			JFFS2_NOTICE("but it has children so we fake some modes for it
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
  		}
  		latest_node->mode = cpu_to_jemode(S_IFDIR|S_IRUGO|S_IWUSR|S_IXUGO);
  		latest_node->version = cpu_to_je32(0);
  		latest_node->atime = latest_node->ctime = latest_node->mtime = cpu_to_je32(0);
  		latest_node->isize = cpu_to_je32(0);
  		latest_node->gid = cpu_to_je16(0);
  		latest_node->uid = cpu_to_je16(0);
  		if (f->inocache->state == INO_STATE_READING)
  			jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
  		return 0;
  	}
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1247
  	ret = jffs2_flash_read(c, ref_offset(rii.latest_ref), sizeof(*latest_node), &retlen, (void *)latest_node);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1248
  	if (ret || retlen != sizeof(*latest_node)) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
1249
1250
1251
  		JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read
  ",
  			ret, retlen, sizeof(*latest_node));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1252
  		/* FIXME: If this fails, there seems to be a memory leak. Find it. */
7aaea7605   Brian Norris   jffs2: fix unbala...
1253
  		return ret ? ret : -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1254
1255
1256
1257
  	}
  
  	crc = crc32(0, latest_node, sizeof(*latest_node)-8);
  	if (crc != je32_to_cpu(latest_node->node_crc)) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
1258
1259
  		JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x
  ",
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1260
  			f->inocache->ino, ref_offset(rii.latest_ref));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1261
1262
1263
1264
1265
  		return -EIO;
  	}
  
  	switch(jemode_to_cpu(latest_node->mode) & S_IFMT) {
  	case S_IFDIR:
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1266
  		if (rii.mctime_ver > je32_to_cpu(latest_node->version)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1267
1268
  			/* The times in the latest_node are actually older than
  			   mctime in the latest dirent. Cheat. */
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1269
  			latest_node->ctime = latest_node->mtime = cpu_to_je32(rii.latest_mctime);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1270
1271
  		}
  		break;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1272

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1273
1274
  	case S_IFREG:
  		/* If it was a regular file, truncate it to the latest node's isize */
61c4b2377   David Woodhouse   [JFFS2] Handle in...
1275
1276
1277
1278
1279
1280
1281
  		new_size = jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize));
  		if (new_size != je32_to_cpu(latest_node->isize)) {
  			JFFS2_WARNING("Truncating ino #%u to %d bytes failed because it only had %d bytes to start with!
  ",
  				      f->inocache->ino, je32_to_cpu(latest_node->isize), new_size);
  			latest_node->isize = cpu_to_je32(new_size);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1282
1283
1284
1285
1286
1287
1288
1289
1290
  		break;
  
  	case S_IFLNK:
  		/* Hack to work around broken isize in old symlink code.
  		   Remove this when dwmw2 comes to his senses and stops
  		   symlinks from being an entirely gratuitous special
  		   case. */
  		if (!je32_to_cpu(latest_node->isize))
  			latest_node->isize = latest_node->dsize;
32f1a95d5   Artem B. Bityuckiy   [JFFS2] Add symli...
1291
1292
1293
  
  		if (f->inocache->state != INO_STATE_CHECKING) {
  			/* Symlink's inode data is the target path. Read it and
2b79adcca   Artem B. Bityutskiy   [JFFS2] Use f->ta...
1294
1295
  			 * keep in RAM to facilitate quick follow symlink
  			 * operation. */
7c80c3523   Xi Wang   jffs2: validate s...
1296
  			uint32_t csize = je32_to_cpu(latest_node->csize);
7aaea7605   Brian Norris   jffs2: fix unbala...
1297
  			if (csize > JFFS2_MAX_NAME_LEN)
7c80c3523   Xi Wang   jffs2: validate s...
1298
  				return -ENAMETOOLONG;
b6778fd78   Xi Wang   jffs2: refactor c...
1299
  			f->target = kmalloc(csize + 1, GFP_KERNEL);
2b79adcca   Artem B. Bityutskiy   [JFFS2] Use f->ta...
1300
  			if (!f->target) {
b6778fd78   Xi Wang   jffs2: refactor c...
1301
1302
  				JFFS2_ERROR("can't allocate %u bytes of memory for the symlink target path cache
  ", csize);
32f1a95d5   Artem B. Bityuckiy   [JFFS2] Add symli...
1303
1304
  				return -ENOMEM;
  			}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1305

df8e96f39   David Woodhouse   [JFFS2] Improve r...
1306
  			ret = jffs2_flash_read(c, ref_offset(rii.latest_ref) + sizeof(*latest_node),
b6778fd78   Xi Wang   jffs2: refactor c...
1307
  					       csize, &retlen, (char *)f->target);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1308

b6778fd78   Xi Wang   jffs2: refactor c...
1309
1310
  			if (ret || retlen != csize) {
  				if (retlen != csize)
32f1a95d5   Artem B. Bityuckiy   [JFFS2] Add symli...
1311
  					ret = -EIO;
2b79adcca   Artem B. Bityutskiy   [JFFS2] Use f->ta...
1312
1313
  				kfree(f->target);
  				f->target = NULL;
e670e41ae   Roel Kluin   jffs2: Fix error ...
1314
  				return ret;
32f1a95d5   Artem B. Bityuckiy   [JFFS2] Add symli...
1315
  			}
b6778fd78   Xi Wang   jffs2: refactor c...
1316
  			f->target[csize] = '\0';
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
1317
1318
  			dbg_readinode("symlink's target '%s' cached
  ", f->target);
32f1a95d5   Artem B. Bityuckiy   [JFFS2] Add symli...
1319
  		}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1320

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1321
1322
1323
1324
1325
1326
1327
  		/* fall through... */
  
  	case S_IFBLK:
  	case S_IFCHR:
  		/* Certain inode types should have only one data node, and it's
  		   kept as the metadata node */
  		if (f->metadata) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
1328
1329
  			JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1330
  			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1331
1332
1333
  			return -EIO;
  		}
  		if (!frag_first(&f->fragtree)) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
1334
1335
  			JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1336
  			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1337
1338
1339
1340
  			return -EIO;
  		}
  		/* ASSERT: f->fraglist != NULL */
  		if (frag_next(frag_first(&f->fragtree))) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
1341
1342
  			JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1343
1344
  			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
  			/* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
  			return -EIO;
  		}
  		/* OK. We're happy */
  		f->metadata = frag_first(&f->fragtree)->node;
  		jffs2_free_node_frag(frag_first(&f->fragtree));
  		f->fragtree = RB_ROOT;
  		break;
  	}
  	if (f->inocache->state == INO_STATE_READING)
  		jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
  
  	return 0;
  }
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1358
  /* Scan the list of all nodes present for this ino, build map of versions, etc. */
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1359
  int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1360
1361
  			uint32_t ino, struct jffs2_raw_inode *latest_node)
  {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
1362
1363
  	dbg_readinode("read inode #%u
  ", ino);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1364
1365
1366
1367
  
   retry_inocache:
  	spin_lock(&c->inocache_lock);
  	f->inocache = jffs2_get_ino_cache(c, ino);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1368
1369
1370
1371
1372
1373
1374
  	if (f->inocache) {
  		/* Check its state. We may need to wait before we can use it */
  		switch(f->inocache->state) {
  		case INO_STATE_UNCHECKED:
  		case INO_STATE_CHECKEDABSENT:
  			f->inocache->state = INO_STATE_READING;
  			break;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1375

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1376
1377
1378
1379
1380
  		case INO_STATE_CHECKING:
  		case INO_STATE_GC:
  			/* If it's in either of these states, we need
  			   to wait for whoever's got it to finish and
  			   put it back. */
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
1381
1382
  			dbg_readinode("waiting for ino #%u in state %d
  ", ino, f->inocache->state);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1383
1384
1385
1386
1387
1388
1389
1390
  			sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
  			goto retry_inocache;
  
  		case INO_STATE_READING:
  		case INO_STATE_PRESENT:
  			/* Eep. This should never happen. It can
  			happen if Linux calls read_inode() again
  			before clear_inode() has finished though. */
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
1391
1392
  			JFFS2_ERROR("Eep. Trying to read_inode #%u when it's already in state %d!
  ", ino, f->inocache->state);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
  			/* Fail. That's probably better than allowing it to succeed */
  			f->inocache = NULL;
  			break;
  
  		default:
  			BUG();
  		}
  	}
  	spin_unlock(&c->inocache_lock);
  
  	if (!f->inocache && ino == 1) {
  		/* Special case - no root inode on medium */
  		f->inocache = jffs2_alloc_inode_cache();
  		if (!f->inocache) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
1407
1408
  			JFFS2_ERROR("cannot allocate inocache for root inode
  ");
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1409
1410
  			return -ENOMEM;
  		}
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
1411
1412
  		dbg_readinode("creating inocache for root inode
  ");
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1413
  		memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
27c72b040   David Woodhouse   [JFFS2] Track par...
1414
  		f->inocache->ino = f->inocache->pino_nlink = 1;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1415
1416
1417
1418
1419
  		f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
  		f->inocache->state = INO_STATE_READING;
  		jffs2_add_ino_cache(c, f->inocache);
  	}
  	if (!f->inocache) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
1420
1421
  		JFFS2_ERROR("requestied to read an nonexistent ino %u
  ", ino);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1422
1423
1424
1425
1426
1427
1428
1429
1430
  		return -ENOENT;
  	}
  
  	return jffs2_do_read_inode_internal(c, f, latest_node);
  }
  
  int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
  {
  	struct jffs2_raw_inode n;
3d375d9e0   Yan Burman   [JFFS2] replace k...
1431
  	struct jffs2_inode_info *f = kzalloc(sizeof(*f), GFP_KERNEL);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1432
1433
1434
1435
  	int ret;
  
  	if (!f)
  		return -ENOMEM;
ced220703   David Woodhouse   [JFFS2] semaphore...
1436
1437
  	mutex_init(&f->sem);
  	mutex_lock(&f->sem);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1438
1439
1440
  	f->inocache = ic;
  
  	ret = jffs2_do_read_inode_internal(c, f, &n);
7aaea7605   Brian Norris   jffs2: fix unbala...
1441
1442
  	mutex_unlock(&f->sem);
  	jffs2_do_clear_inode(c, f);
8c5a03664   Jean-Christophe DUBOIS   jffs2: allow to c...
1443
  	jffs2_xattr_do_crccheck_inode(c, ic);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1444
1445
1446
  	kfree (f);
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1447
1448
1449
1450
  void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
  {
  	struct jffs2_full_dirent *fd, *fds;
  	int deleted;
355ed4e14   KaiGai Kohei   [JFFS2][XATTR] Fi...
1451
  	jffs2_xattr_delete_inode(c, f->inocache);
ced220703   David Woodhouse   [JFFS2] semaphore...
1452
  	mutex_lock(&f->sem);
27c72b040   David Woodhouse   [JFFS2] Track par...
1453
  	deleted = f->inocache && !f->inocache->pino_nlink;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1454

67e345d17   David Woodhouse   [JFFS2] Prevent i...
1455
1456
  	if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
  		jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1457
1458
1459
1460
1461
1462
1463
  	if (f->metadata) {
  		if (deleted)
  			jffs2_mark_node_obsolete(c, f->metadata->raw);
  		jffs2_free_full_dnode(f->metadata);
  	}
  
  	jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL);
2b79adcca   Artem B. Bityutskiy   [JFFS2] Use f->ta...
1464
1465
1466
1467
  	if (f->target) {
  		kfree(f->target);
  		f->target = NULL;
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1468

2b79adcca   Artem B. Bityutskiy   [JFFS2] Use f->ta...
1469
1470
1471
1472
1473
  	fds = f->dents;
  	while(fds) {
  		fd = fds;
  		fds = fd->next;
  		jffs2_free_full_dirent(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1474
  	}
67e345d17   David Woodhouse   [JFFS2] Prevent i...
1475
  	if (f->inocache && f->inocache->state != INO_STATE_CHECKING) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1476
  		jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
67e345d17   David Woodhouse   [JFFS2] Prevent i...
1477
1478
1479
  		if (f->inocache->nodes == (void *)f->inocache)
  			jffs2_del_ino_cache(c, f->inocache);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1480

ced220703   David Woodhouse   [JFFS2] semaphore...
1481
  	mutex_unlock(&f->sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1482
  }