Blame view

fs/jffs2/readinode.c 43.2 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
  		}
ecdb868ac   Zhe Li   jffs2: Fix GC exi...
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
  
  #ifdef CONFIG_JFFS2_SUMMARY
  		/*
  		 * we use CONFIG_JFFS2_SUMMARY because without it, we
  		 * have checked it while mounting
  		 */
  		crc = crc32(0, fd->name, rd->nsize);
  		if (unlikely(crc != je32_to_cpu(rd->name_crc))) {
  			JFFS2_NOTICE("name CRC failed on dirent node at"
  			   "%#08x: read %#08x,calculated %#08x
  ",
  			   ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
  			jffs2_mark_node_obsolete(c, ref);
  			jffs2_free_full_dirent(fd);
  			return 0;
  		}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
723

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
  	return 0;
  }
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
736
737
738
739
  /*
   * Helper function for jffs2_get_inode_nodes().
   * It is called every time an inode node is found.
   *
14c6381ee   David Woodhouse   [JFFS2] Fix readi...
740
   * Returns: 0 on success (possibly after marking a bad node obsolete);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
741
742
   * 	    negative error code on failure.
   */
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
743
  static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
df8e96f39   David Woodhouse   [JFFS2] Improve r...
744
745
  			     struct jffs2_raw_inode *rd, int rdlen,
  			     struct jffs2_readinode_info *rii)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
  {
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
747
  	struct jffs2_tmp_dnode_info *tn;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
748
  	uint32_t len, csize;
14c6381ee   David Woodhouse   [JFFS2] Fix readi...
749
  	int ret = 0;
1046d8800   David Woodhouse   [JFFS2] Check CRC...
750
  	uint32_t crc;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
751

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
752
753
  	/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
  	BUG_ON(ref_obsolete(ref));
1046d8800   David Woodhouse   [JFFS2] Check CRC...
754
755
756
757
758
  	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...
759
760
  		jffs2_mark_node_obsolete(c, ref);
  		return 0;
1046d8800   David Woodhouse   [JFFS2] Check CRC...
761
  	}
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
762
763
  	tn = jffs2_alloc_tmp_dnode_info();
  	if (!tn) {
fb6a82c94   Randy Dunlap   [PATCH] jffs2: fi...
764
765
  		JFFS2_ERROR("failed to allocate tn (%zu bytes).
  ", sizeof(*tn));
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
766
767
768
769
770
  		return -ENOMEM;
  	}
  
  	tn->partial_crc = 0;
  	csize = je32_to_cpu(rd->csize);
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
771

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
772
773
  	/* 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 ...
774

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
775
776
777
  		/* 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...
778
779
780
781
  			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...
782
  			goto free_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
783
  		}
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
  		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" ...
803
  			 * of NAND flashes (or other flashes with
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
  			 * !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...
826
  			tn->partial_crc = crc32(0, buf, len);
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
827
828
  			dbg_readinode("Calculates CRC (%#08x) for %d bytes, csize %d
  ", tn->partial_crc, len, csize);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
829
830
831
  
  			/* If we actually calculated the whole data CRC
  			 * and it is wrong, drop the node. */
3c0913373   Artem B. Bityutskiy   [JFFS2] Correct b...
832
  			if (len >= csize && unlikely(tn->partial_crc != je32_to_cpu(rd->data_crc))) {
392435081   Artem B. Bityutskiy   [JFFS2] Debug cod...
833
834
835
  				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...
836
  				jffs2_mark_node_obsolete(c, ref);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
837
  				goto free_out;
392435081   Artem B. Bityutskiy   [JFFS2] Debug cod...
838
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839

1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
840
841
842
843
844
845
846
847
  		} 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...
848
849
  			dbg_readinode("the node has no data.
  ");
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
850
851
852
853
854
855
856
857
  			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...
858
  			ref->flash_offset = ref_offset(ref) | REF_NORMAL;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
859
  			spin_unlock(&c->erase_completion_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
862

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
863
864
  	tn->fn = jffs2_alloc_full_dnode();
  	if (!tn->fn) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
865
866
  		JFFS2_ERROR("alloc fn failed
  ");
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
867
868
  		ret = -ENOMEM;
  		goto free_out;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
869
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
870

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
871
872
  	tn->version = je32_to_cpu(rd->version);
  	tn->fn->ofs = je32_to_cpu(rd->offset);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
873
874
  	tn->data_crc = je32_to_cpu(rd->data_crc);
  	tn->csize = csize;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
875
  	tn->fn->raw = ref;
df8e96f39   David Woodhouse   [JFFS2] Improve r...
876
877
878
879
  	tn->overlapped = 0;
  
  	if (tn->version > rii->highest_version)
  		rii->highest_version = tn->version;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
880

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
881
882
  	/* There was a bug where we wrote hole nodes out with
  	   csize/dsize swapped. Deal with it */
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
883
884
  	if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && csize)
  		tn->fn->size = csize;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
885
886
  	else // normal case...
  		tn->fn->size = je32_to_cpu(rd->dsize);
2c61cb250   David Woodhouse   [JFFS2] Introduce...
887
888
889
890
  	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 ...
891

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

df8e96f39   David Woodhouse   [JFFS2] Improve r...
894
895
896
897
898
899
  	if (ret) {
  		jffs2_free_full_dnode(tn->fn);
  	free_out:
  		jffs2_free_tmp_dnode_info(tn);
  		return ret;
  	}
2c61cb250   David Woodhouse   [JFFS2] Introduce...
900
901
902
  #ifdef JFFS2_DBG_READINODE2_MESSAGES
  	dbg_readinode2("After adding ver %d:
  ", je32_to_cpu(rd->version));
df8e96f39   David Woodhouse   [JFFS2] Improve r...
903
904
  	tn = tn_first(&rii->tn_root);
  	while (tn) {
2c61cb250   David Woodhouse   [JFFS2] Introduce...
905
906
907
908
  		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...
909
910
911
  		tn = tn_next(tn);
  	}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912
913
  	return 0;
  }
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
914
915
916
917
  /*
   * Helper function for jffs2_get_inode_nodes().
   * It is called every time an unknown node is found.
   *
3877f0b6c   David Woodhouse   [JFFS2] Don't tru...
918
   * Returns: 0 on success;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
919
920
   * 	    negative error code on failure.
   */
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
921
  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
922
  {
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
923
  	/* We don't mark unknown nodes as REF_UNCHECKED */
c7258a447   David Woodhouse   [JFFS2] Check for...
924
925
926
927
928
929
  	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...
930
931
  			    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...
932
933
  		jffs2_mark_node_obsolete(c, ref);
  		return 0;
c7258a447   David Woodhouse   [JFFS2] Check for...
934
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
935

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

3877f0b6c   David Woodhouse   [JFFS2] Don't tru...
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
  	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...
965
966
  		jffs2_mark_node_obsolete(c, ref);
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
968

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
969
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
970
  }
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
971
972
973
974
  /*
   * 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...
975
   * Returns: 0 on success;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
976
977
978
   * 	    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...
979
  		     int needed_len, int *rdlen, unsigned char *buf)
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
980
  {
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
981
  	int err, to_read = needed_len - *rdlen;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
982
983
984
985
  	size_t retlen;
  	uint32_t offs;
  
  	if (jffs2_is_writebuffered(c)) {
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
986
  		int rem = to_read % c->wbuf_pagesize;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
987

10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
988
989
990
  		if (rem)
  			to_read += c->wbuf_pagesize - rem;
  	}
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
991
992
993
  
  	/* We need to read more data */
  	offs = ref_offset(ref) + *rdlen;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
994

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

10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
998
  	err = jffs2_flash_read(c, offs, to_read, &retlen, buf + *rdlen);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
999
1000
  	if (err) {
  		JFFS2_ERROR("can not read %d bytes from 0x%08x, "
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1001
1002
  			"error code: %d.
  ", to_read, offs, err);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1003
1004
  		return err;
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1005

10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1006
  	if (retlen < to_read) {
fb6a82c94   Randy Dunlap   [PATCH] jffs2: fi...
1007
1008
  		JFFS2_ERROR("short read at %#08x: %zu instead of %d.
  ",
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1009
  				offs, retlen, to_read);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1010
1011
  		return -EIO;
  	}
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1012
  	*rdlen += to_read;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1013
1014
  	return 0;
  }
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1015
  /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1016
1017
1018
1019
     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...
1020
  static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1021
  				 struct jffs2_readinode_info *rii)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
  {
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1023
  	struct jffs2_raw_node_ref *ref, *valid_ref;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1024
1025
  	unsigned char *buf = NULL;
  	union jffs2_node_union *node;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1026
  	size_t retlen;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1027
  	int len, err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028

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

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

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

1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1041
  	spin_lock(&c->erase_completion_lock);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1042
  	valid_ref = jffs2_first_valid_node(f->inocache->nodes);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1043
1044
1045
  	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...
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
  	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...
1058
1059
1060
  		/*
  		 * 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...
1061
1062
  		 * 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...
1063
  		 */
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1064
  		len = JFFS2_MIN_NODE_HEADER;
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1065
  		if (jffs2_is_writebuffered(c)) {
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1066
  			int end, rem;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1067
  			/*
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1068
1069
1070
1071
1072
  			 * 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...
1073
  			 */
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1074
1075
1076
1077
1078
  			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...
1079
  		}
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
1080
1081
  		dbg_readinode("read %d bytes at %#08x(%d).
  ", len, ref_offset(ref), ref_flags(ref));
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1082

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1083
  		/* FIXME: point() */
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1084
  		err = jffs2_flash_read(c, ref_offset(ref), len, &retlen, buf);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1085
  		if (err) {
df2e301fe   Jean Delvare   fs: Merge split s...
1086
1087
  			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...
1088
1089
  			goto free_out;
  		}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1090

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

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

3877f0b6c   David Woodhouse   [JFFS2] Don't tru...
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
  		/* 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...
1112
1113
1114
1115
1116
  		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...
1117
1118
1119
  			jffs2_mark_node_obsolete(c, ref);
  			goto cont;
  		}
3877f0b6c   David Woodhouse   [JFFS2] Don't tru...
1120

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

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1123
  		case JFFS2_NODETYPE_DIRENT:
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1124

ea55d3079   Artem Bityutskiy   [JFFS2] Fix buffe...
1125
1126
  			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent) &&
  			    len < sizeof(struct jffs2_raw_dirent)) {
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1127
  				err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1128
1129
1130
  				if (unlikely(err))
  					goto free_out;
  			}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1131

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

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

ea55d3079   Artem Bityutskiy   [JFFS2] Fix buffe...
1139
1140
  			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode) &&
  			    len < sizeof(struct jffs2_raw_inode)) {
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1141
  				err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1142
1143
  				if (unlikely(err))
  					goto free_out;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1144
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1145

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

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

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1152
  		default:
ea55d3079   Artem Bityutskiy   [JFFS2] Fix buffe...
1153
1154
  			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node) &&
  			    len < sizeof(struct jffs2_unknown_node)) {
10731f830   Artem Bityutskiy   [JFFS2] fix buffe...
1155
  				err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1156
1157
  				if (unlikely(err))
  					goto free_out;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1158
  			}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1159

1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1160
  			err = read_unknown(c, ref, &node->u);
14c6381ee   David Woodhouse   [JFFS2] Fix readi...
1161
  			if (unlikely(err))
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1162
1163
1164
  				goto free_out;
  
  		}
3877f0b6c   David Woodhouse   [JFFS2] Don't tru...
1165
  	cont:
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1166
  		spin_lock(&c->erase_completion_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1167
  	}
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1168

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

df8e96f39   David Woodhouse   [JFFS2] Improve r...
1172
  	f->highest_version = rii->highest_version;
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
1173
1174
  	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...
1175
1176
  		      f->inocache->ino, rii->highest_version, rii->latest_mctime,
  		      rii->mctime_ver);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1177
1178
1179
  	return 0;
  
   free_out:
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1180
1181
1182
  	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...
1183
  	kfree(buf);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1184
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1185
  }
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1186
  static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1187
1188
1189
  					struct jffs2_inode_info *f,
  					struct jffs2_raw_inode *latest_node)
  {
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1190
  	struct jffs2_readinode_info rii;
61c4b2377   David Woodhouse   [JFFS2] Handle in...
1191
  	uint32_t crc, new_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1192
1193
  	size_t retlen;
  	int ret;
27c72b040   David Woodhouse   [JFFS2] Track par...
1194
1195
1196
  	dbg_readinode("ino #%u pino/nlink is %d
  ", f->inocache->ino,
  		      f->inocache->pino_nlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1197

df8e96f39   David Woodhouse   [JFFS2] Improve r...
1198
  	memset(&rii, 0, sizeof(rii));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1199
  	/* Grab all nodes relevant to this ino */
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1200
  	ret = jffs2_get_inode_nodes(c, f, &rii);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1201
1202
  
  	if (ret) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
1203
1204
  		JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d
  ", f->inocache->ino, ret);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1205
1206
1207
1208
  		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
1209

df8e96f39   David Woodhouse   [JFFS2] Improve r...
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
  	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 ...
1226

df8e96f39   David Woodhouse   [JFFS2] Improve r...
1227
1228
1229
1230
1231
1232
  	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...
1233
  		}
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1234
  		rii.mdata_tn = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1235
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236

df8e96f39   David Woodhouse   [JFFS2] Improve r...
1237
1238
1239
  	f->dents = rii.fds;
  
  	jffs2_dbg_fragtree_paranoia_check_nolock(f);
1e0da3cb6   Artem B. Bityutskiy   [JFFS2] Build fra...
1240

df8e96f39   David Woodhouse   [JFFS2] Improve r...
1241
  	if (unlikely(!rii.latest_ref)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1242
1243
  		/* No data nodes for this inode. */
  		if (f->inocache->ino != 1) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
1244
1245
  			JFFS2_WARNING("no data nodes found for ino #%u
  ", f->inocache->ino);
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1246
  			if (!rii.fds) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1247
1248
1249
1250
  				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...
1251
1252
  			JFFS2_NOTICE("but it has children so we fake some modes for it
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
  		}
  		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...
1264
  	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
1265
  	if (ret || retlen != sizeof(*latest_node)) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
1266
1267
1268
  		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
1269
  		/* FIXME: If this fails, there seems to be a memory leak. Find it. */
7aaea7605   Brian Norris   jffs2: fix unbala...
1270
  		return ret ? ret : -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1271
1272
1273
1274
  	}
  
  	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...
1275
1276
  		JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x
  ",
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1277
  			f->inocache->ino, ref_offset(rii.latest_ref));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1278
1279
1280
1281
1282
  		return -EIO;
  	}
  
  	switch(jemode_to_cpu(latest_node->mode) & S_IFMT) {
  	case S_IFDIR:
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1283
  		if (rii.mctime_ver > je32_to_cpu(latest_node->version)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1284
1285
  			/* The times in the latest_node are actually older than
  			   mctime in the latest dirent. Cheat. */
df8e96f39   David Woodhouse   [JFFS2] Improve r...
1286
  			latest_node->ctime = latest_node->mtime = cpu_to_je32(rii.latest_mctime);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1287
1288
  		}
  		break;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1289

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1290
1291
  	case S_IFREG:
  		/* If it was a regular file, truncate it to the latest node's isize */
61c4b2377   David Woodhouse   [JFFS2] Handle in...
1292
1293
1294
1295
1296
1297
1298
  		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
1299
1300
1301
1302
1303
1304
1305
1306
1307
  		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...
1308
1309
1310
  
  		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...
1311
1312
  			 * keep in RAM to facilitate quick follow symlink
  			 * operation. */
7c80c3523   Xi Wang   jffs2: validate s...
1313
  			uint32_t csize = je32_to_cpu(latest_node->csize);
7aaea7605   Brian Norris   jffs2: fix unbala...
1314
  			if (csize > JFFS2_MAX_NAME_LEN)
7c80c3523   Xi Wang   jffs2: validate s...
1315
  				return -ENAMETOOLONG;
b6778fd78   Xi Wang   jffs2: refactor c...
1316
  			f->target = kmalloc(csize + 1, GFP_KERNEL);
2b79adcca   Artem B. Bityutskiy   [JFFS2] Use f->ta...
1317
  			if (!f->target) {
b6778fd78   Xi Wang   jffs2: refactor c...
1318
1319
  				JFFS2_ERROR("can't allocate %u bytes of memory for the symlink target path cache
  ", csize);
32f1a95d5   Artem B. Bityuckiy   [JFFS2] Add symli...
1320
1321
  				return -ENOMEM;
  			}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1322

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

b6778fd78   Xi Wang   jffs2: refactor c...
1326
1327
  			if (ret || retlen != csize) {
  				if (retlen != csize)
32f1a95d5   Artem B. Bityuckiy   [JFFS2] Add symli...
1328
  					ret = -EIO;
2b79adcca   Artem B. Bityutskiy   [JFFS2] Use f->ta...
1329
1330
  				kfree(f->target);
  				f->target = NULL;
e670e41ae   Roel Kluin   jffs2: Fix error ...
1331
  				return ret;
32f1a95d5   Artem B. Bityuckiy   [JFFS2] Add symli...
1332
  			}
b6778fd78   Xi Wang   jffs2: refactor c...
1333
  			f->target[csize] = '\0';
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
1334
1335
  			dbg_readinode("symlink's target '%s' cached
  ", f->target);
32f1a95d5   Artem B. Bityuckiy   [JFFS2] Add symli...
1336
  		}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1337

df561f668   Gustavo A. R. Silva   treewide: Use fal...
1338
  		fallthrough;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1339
1340
1341
1342
1343
1344
  
  	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...
1345
1346
  			JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1347
  			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1348
1349
1350
  			return -EIO;
  		}
  		if (!frag_first(&f->fragtree)) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
1351
1352
  			JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353
  			       f->inocache->ino, jemode_to_cpu(latest_node->mode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1354
1355
1356
1357
  			return -EIO;
  		}
  		/* ASSERT: f->fraglist != NULL */
  		if (frag_next(frag_first(&f->fragtree))) {
e0d601373   Artem B. Bityutskiy   [JFFS2] Debug cod...
1358
1359
  			JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1360
1361
  			       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
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
  			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...
1375
  /* Scan the list of all nodes present for this ino, build map of versions, etc. */
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1376
  int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1377
1378
  			uint32_t ino, struct jffs2_raw_inode *latest_node)
  {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
1379
1380
  	dbg_readinode("read inode #%u
  ", ino);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1381
1382
1383
1384
  
   retry_inocache:
  	spin_lock(&c->inocache_lock);
  	f->inocache = jffs2_get_ino_cache(c, ino);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1385
1386
1387
1388
1389
1390
1391
  	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 ...
1392

f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1393
1394
1395
1396
1397
  		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...
1398
1399
  			dbg_readinode("waiting for ino #%u in state %d
  ", ino, f->inocache->state);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1400
1401
1402
1403
1404
1405
1406
1407
  			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...
1408
1409
  			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...
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
  			/* 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...
1424
1425
  			JFFS2_ERROR("cannot allocate inocache for root inode
  ");
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1426
1427
  			return -ENOMEM;
  		}
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
1428
1429
  		dbg_readinode("creating inocache for root inode
  ");
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1430
  		memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
27c72b040   David Woodhouse   [JFFS2] Track par...
1431
  		f->inocache->ino = f->inocache->pino_nlink = 1;
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1432
1433
1434
1435
1436
  		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) {
8918821f3   Colin Ian King   jffs2: fix spelli...
1437
1438
  		JFFS2_ERROR("requested to read a nonexistent ino %u
  ", ino);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1439
1440
1441
1442
1443
1444
1445
1446
1447
  		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...
1448
  	struct jffs2_inode_info *f = kzalloc(sizeof(*f), GFP_KERNEL);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1449
1450
1451
1452
  	int ret;
  
  	if (!f)
  		return -ENOMEM;
ced220703   David Woodhouse   [JFFS2] semaphore...
1453
1454
  	mutex_init(&f->sem);
  	mutex_lock(&f->sem);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1455
1456
1457
  	f->inocache = ic;
  
  	ret = jffs2_do_read_inode_internal(c, f, &n);
7aaea7605   Brian Norris   jffs2: fix unbala...
1458
1459
  	mutex_unlock(&f->sem);
  	jffs2_do_clear_inode(c, f);
8c5a03664   Jean-Christophe DUBOIS   jffs2: allow to c...
1460
  	jffs2_xattr_do_crccheck_inode(c, ic);
f97117d15   Artem B. Bityutskiy   [JFFS2] Move scat...
1461
1462
1463
  	kfree (f);
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1464
1465
1466
1467
  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...
1468
  	jffs2_xattr_delete_inode(c, f->inocache);
ced220703   David Woodhouse   [JFFS2] semaphore...
1469
  	mutex_lock(&f->sem);
27c72b040   David Woodhouse   [JFFS2] Track par...
1470
  	deleted = f->inocache && !f->inocache->pino_nlink;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1471

67e345d17   David Woodhouse   [JFFS2] Prevent i...
1472
1473
  	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
1474
1475
1476
1477
1478
1479
1480
  	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...
1481
1482
1483
1484
1485
  	fds = f->dents;
  	while(fds) {
  		fd = fds;
  		fds = fd->next;
  		jffs2_free_full_dirent(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1486
  	}
67e345d17   David Woodhouse   [JFFS2] Prevent i...
1487
  	if (f->inocache && f->inocache->state != INO_STATE_CHECKING) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1488
  		jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
67e345d17   David Woodhouse   [JFFS2] Prevent i...
1489
1490
1491
  		if (f->inocache->nodes == (void *)f->inocache)
  			jffs2_del_ino_cache(c, f->inocache);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1492

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