Blame view

fs/jffs2/scan.c 35.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
   */
c00c310ea   David Woodhouse   [JFFS2] Tidy up l...
11

5a528957e   Joe Perches   jffs2: Use pr_fmt...
12
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
15
16
17
18
19
20
  #include <linux/kernel.h>
  #include <linux/sched.h>
  #include <linux/slab.h>
  #include <linux/mtd/mtd.h>
  #include <linux/pagemap.h>
  #include <linux/crc32.h>
  #include <linux/compiler.h>
  #include "nodelist.h"
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
21
22
  #include "summary.h"
  #include "debug.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23

41bdc602e   Joakim Tjernlund   jffs2: Reduce exc...
24
  #define DEFAULT_EMPTY_SCAN_SIZE 256
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25

da320f055   Joe Perches   jffs2: Convert pr...
26
27
28
29
30
31
32
33
34
35
  #define noisy_printk(noise, fmt, ...)					\
  do {									\
  	if (*(noise)) {							\
  		pr_notice(fmt, ##__VA_ARGS__);				\
  		(*(noise))--;						\
  		if (!(*(noise)))					\
  			pr_notice("Further such events for this erase block will not be printed
  "); \
  	}								\
  } while (0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
39
  
  static uint32_t pseudo_random;
  
  static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
40
  				  unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41

182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
42
  /* These helper functions _must_ increase ofs and also do the dirty/used space accounting.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
45
   * Returning an error will abort the mount - bad checksums etc. should just mark the space
   * as dirty.
   */
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
46
  static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
47
  				 struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
  static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
49
  				 struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
  
  static inline int min_free(struct jffs2_sb_info *c)
  {
  	uint32_t min = 2 * sizeof(struct jffs2_raw_inode);
2f82ce1eb   Andrew Victor   [JFFS2] Use a sin...
54
  #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
57
58
59
60
  	if (!jffs2_can_mark_obsolete(c) && min < c->wbuf_pagesize)
  		return c->wbuf_pagesize;
  #endif
  	return min;
  
  }
3be36675d   Andrew Victor   [JFFS2] Core chan...
61
62
63
64
65
66
67
  
  static inline uint32_t EMPTY_SCAN_SIZE(uint32_t sector_size) {
  	if (sector_size < DEFAULT_EMPTY_SCAN_SIZE)
  		return sector_size;
  	else
  		return DEFAULT_EMPTY_SCAN_SIZE;
  }
25090a6b2   David Woodhouse   [JFFS2] Discard r...
68
69
  static int file_dirty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
  {
a6a8bef72   David Woodhouse   [JFFS2] Prealloca...
70
71
72
73
74
  	int ret;
  
  	if ((ret = jffs2_prealloc_raw_node_refs(c, jeb, 1)))
  		return ret;
  	if ((ret = jffs2_scan_dirty_space(c, jeb, jeb->free_size)))
25090a6b2   David Woodhouse   [JFFS2] Discard r...
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  		return ret;
  	/* Turned wasted size into dirty, since we apparently 
  	   think it's recoverable now. */
  	jeb->dirty_size += jeb->wasted_size;
  	c->dirty_size += jeb->wasted_size;
  	c->wasted_size -= jeb->wasted_size;
  	jeb->wasted_size = 0;
  	if (VERYDIRTY(c, jeb->dirty_size)) {
  		list_add(&jeb->list, &c->very_dirty_list);
  	} else {
  		list_add(&jeb->list, &c->dirty_list);
  	}
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
90
91
92
93
94
  int jffs2_scan_medium(struct jffs2_sb_info *c)
  {
  	int i, ret;
  	uint32_t empty_blocks = 0, bad_blocks = 0;
  	unsigned char *flashbuf = NULL;
  	uint32_t buf_size = 0;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
95
  	struct jffs2_summary *s = NULL; /* summary info collected by the scan process */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
  #ifndef __ECOS
1ddd0d9a3   Grant Erickson   JFFS2: retry larg...
97
  	size_t pointlen, try_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98

f02654504   Artem Bityutskiy   jffs2: remove dir...
99
100
101
102
  	ret = mtd_point(c->mtd, 0, c->mtd->size, &pointlen,
  			(void **)&flashbuf, NULL);
  	if (!ret && pointlen < c->mtd->size) {
  		/* Don't muck about if it won't let us point to the whole flash */
9c261b33a   Joe Perches   jffs2: Convert mo...
103
104
105
  		jffs2_dbg(1, "MTD point returned len too short: 0x%zx
  ",
  			  pointlen);
f02654504   Artem Bityutskiy   jffs2: remove dir...
106
107
  		mtd_unpoint(c->mtd, 0, pointlen);
  		flashbuf = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
  	}
f02654504   Artem Bityutskiy   jffs2: remove dir...
109
  	if (ret && ret != -EOPNOTSUPP)
9c261b33a   Joe Perches   jffs2: Convert mo...
110
111
  		jffs2_dbg(1, "MTD point failed %d
  ", ret);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
113
114
115
116
  #endif
  	if (!flashbuf) {
  		/* For NAND it's quicker to read a whole eraseblock at a time,
  		   apparently */
  		if (jffs2_cleanmarker_oob(c))
1ddd0d9a3   Grant Erickson   JFFS2: retry larg...
117
  			try_size = c->sector_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
  		else
1ddd0d9a3   Grant Erickson   JFFS2: retry larg...
119
  			try_size = PAGE_SIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120

9c261b33a   Joe Perches   jffs2: Convert mo...
121
122
123
  		jffs2_dbg(1, "Trying to allocate readbuf of %zu "
  			  "bytes
  ", try_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124

1ddd0d9a3   Grant Erickson   JFFS2: retry larg...
125
  		flashbuf = mtd_kmalloc_up_to(c->mtd, &try_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
  		if (!flashbuf)
  			return -ENOMEM;
1ddd0d9a3   Grant Erickson   JFFS2: retry larg...
128

9c261b33a   Joe Perches   jffs2: Convert mo...
129
130
131
  		jffs2_dbg(1, "Allocated readbuf of %zu bytes
  ",
  			  try_size);
1ddd0d9a3   Grant Erickson   JFFS2: retry larg...
132
133
  
  		buf_size = (uint32_t)try_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
  	}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
135
  	if (jffs2_sum_active()) {
3d375d9e0   Yan Burman   [JFFS2] replace k...
136
  		s = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
137
138
139
  		if (!s) {
  			JFFS2_WARNING("Can't allocate memory for summary
  ");
483964133   David Woodhouse   jffs2: fix anothe...
140
141
  			ret = -ENOMEM;
  			goto out;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
142
  		}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
143
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
  	for (i=0; i<c->nr_blocks; i++) {
  		struct jffs2_eraseblock *jeb = &c->blocks[i];
a2166b933   Artem Bityutskiy   [JFFS2] Reschedul...
146
  		cond_resched();
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
147
148
149
150
151
  		/* reset summary info for next eraseblock scan */
  		jffs2_sum_reset_collected(s);
  
  		ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
  						buf_size, s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
  
  		if (ret < 0)
  			goto out;
e0c8e42f8   Artem B. Bityutskiy   [JFFS2] Debug cod...
155
  		jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
157
158
159
  
  		/* Now decide which list to put it on */
  		switch(ret) {
  		case BLK_STATE_ALLFF:
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
160
161
  			/*
  			 * Empty block.   Since we can't be sure it
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  			 * was entirely erased, we just queue it for erase
  			 * again.  It will be marked as such when the erase
  			 * is complete.  Meanwhile we still count it as empty
  			 * for later checks.
  			 */
  			empty_blocks++;
  			list_add(&jeb->list, &c->erase_pending_list);
  			c->nr_erasing_blocks++;
  			break;
  
  		case BLK_STATE_CLEANMARKER:
  			/* Only a CLEANMARKER node is valid */
  			if (!jeb->dirty_size) {
  				/* It's actually free */
  				list_add(&jeb->list, &c->free_list);
  				c->nr_free_blocks++;
  			} else {
  				/* Dirt */
9c261b33a   Joe Perches   jffs2: Convert mo...
180
181
182
  				jffs2_dbg(1, "Adding all-dirty block at 0x%08x to erase_pending_list
  ",
  					  jeb->offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
185
186
187
188
  				list_add(&jeb->list, &c->erase_pending_list);
  				c->nr_erasing_blocks++;
  			}
  			break;
  
  		case BLK_STATE_CLEAN:
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
189
190
  			/* Full (or almost full) of clean data. Clean list */
  			list_add(&jeb->list, &c->clean_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
192
193
  			break;
  
  		case BLK_STATE_PARTDIRTY:
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
194
195
196
197
198
199
200
  			/* Some data, but not full. Dirty list. */
  			/* We want to remember the block with most free space
  			and stick it in the 'nextblock' position to start writing to it. */
  			if (jeb->free_size > min_free(c) &&
  					(!c->nextblock || c->nextblock->free_size < jeb->free_size)) {
  				/* Better candidate for the next writes to go to */
  				if (c->nextblock) {
25090a6b2   David Woodhouse   [JFFS2] Discard r...
201
202
  					ret = file_dirty(c, c->nextblock);
  					if (ret)
a2ab0ce09   Christian Engelmayer   jffs2: leaking jf...
203
  						goto out;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
204
205
  					/* deleting summary information of the old nextblock */
  					jffs2_sum_reset_collected(c->summary);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
  				}
25090a6b2   David Woodhouse   [JFFS2] Discard r...
207
  				/* update collected summary information for the current nextblock */
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
208
  				jffs2_sum_move_collected(c, s);
9c261b33a   Joe Perches   jffs2: Convert mo...
209
210
211
  				jffs2_dbg(1, "%s(): new nextblock = 0x%08x
  ",
  					  __func__, jeb->offset);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
212
213
  				c->nextblock = jeb;
  			} else {
25090a6b2   David Woodhouse   [JFFS2] Discard r...
214
215
  				ret = file_dirty(c, jeb);
  				if (ret)
a2ab0ce09   Christian Engelmayer   jffs2: leaking jf...
216
  					goto out;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
217
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
219
220
221
  			break;
  
  		case BLK_STATE_ALLDIRTY:
  			/* Nothing valid - not even a clean marker. Needs erasing. */
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
222
  			/* For now we just put it on the erasing list. We'll start the erases later */
5a528957e   Joe Perches   jffs2: Use pr_fmt...
223
224
  			jffs2_dbg(1, "Erase block at 0x%08x is not formatted. It will be erased
  ",
9c261b33a   Joe Perches   jffs2: Convert mo...
225
  				  jeb->offset);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
226
  			list_add(&jeb->list, &c->erase_pending_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
  			c->nr_erasing_blocks++;
  			break;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
229

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
  		case BLK_STATE_BADBLOCK:
5a528957e   Joe Perches   jffs2: Use pr_fmt...
231
232
  			jffs2_dbg(1, "Block at 0x%08x is bad
  ", jeb->offset);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
233
  			list_add(&jeb->list, &c->bad_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
235
236
237
238
  			c->bad_size += c->sector_size;
  			c->free_size -= c->sector_size;
  			bad_blocks++;
  			break;
  		default:
da320f055   Joe Perches   jffs2: Convert pr...
239
240
  			pr_warn("%s(): unknown block state
  ", __func__);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
241
  			BUG();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
  		}
  	}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
244

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
247
248
249
250
251
  	/* Nextblock dirty is always seen as wasted, because we cannot recycle it now */
  	if (c->nextblock && (c->nextblock->dirty_size)) {
  		c->nextblock->wasted_size += c->nextblock->dirty_size;
  		c->wasted_size += c->nextblock->dirty_size;
  		c->dirty_size -= c->nextblock->dirty_size;
  		c->nextblock->dirty_size = 0;
  	}
2f82ce1eb   Andrew Victor   [JFFS2] Use a sin...
252
  #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
e96fb230c   David Woodhouse   [PATCH] jffs2: av...
253
  	if (!jffs2_can_mark_obsolete(c) && c->wbuf_pagesize && c->nextblock && (c->nextblock->free_size % c->wbuf_pagesize)) {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
254
  		/* If we're going to start writing into a block which already
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
  		   contains data, and the end of the data isn't page-aligned,
  		   skip a little and align it. */
daba5cc4b   Artem B. Bityutskiy   [JFFS2] Fix dataf...
257
  		uint32_t skip = c->nextblock->free_size % c->wbuf_pagesize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258

9c261b33a   Joe Perches   jffs2: Convert mo...
259
260
261
  		jffs2_dbg(1, "%s(): Skipping %d bytes in nextblock to ensure page alignment
  ",
  			  __func__, skip);
046b8b980   David Woodhouse   [JFFS2] Add 'jeb'...
262
  		jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
f560928ba   David Woodhouse   [JFFS2] Allocate ...
263
  		jffs2_scan_dirty_space(c, c->nextblock, skip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
265
266
  	}
  #endif
  	if (c->nr_erasing_blocks) {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
267
  		if ( !c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) {
da320f055   Joe Perches   jffs2: Convert pr...
268
269
270
271
272
  			pr_notice("Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes
  ");
  			pr_notice("empty_blocks %d, bad_blocks %d, c->nr_blocks %d
  ",
  				  empty_blocks, bad_blocks, c->nr_blocks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
274
275
  			ret = -EIO;
  			goto out;
  		}
ae3b6ba06   David Woodhouse   jffs2: Use jffs2_...
276
277
278
  		spin_lock(&c->erase_completion_lock);
  		jffs2_garbage_collect_trigger(c);
  		spin_unlock(&c->erase_completion_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
281
282
283
284
  	}
  	ret = 0;
   out:
  	if (buf_size)
  		kfree(flashbuf);
  #ifndef __ECOS
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
285
  	else
7219778ad   Artem Bityutskiy   mtd: introduce mt...
286
  		mtd_unpoint(c->mtd, 0, c->mtd->size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  #endif
e8a0e4126   Jesper Juhl   jffs2: Avoid unne...
288
  	kfree(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
290
  	return ret;
  }
c05d52c74   Adrian Bunk   fs/jffs2/: make 2...
291
292
  static int jffs2_fill_scan_buf(struct jffs2_sb_info *c, void *buf,
  			       uint32_t ofs, uint32_t len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
295
296
297
298
  {
  	int ret;
  	size_t retlen;
  
  	ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
  	if (ret) {
9c261b33a   Joe Perches   jffs2: Convert mo...
299
300
301
  		jffs2_dbg(1, "mtd->read(0x%x bytes from 0x%x) returned %d
  ",
  			  len, ofs, ret);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
304
  		return ret;
  	}
  	if (retlen < len) {
9c261b33a   Joe Perches   jffs2: Convert mo...
305
306
307
  		jffs2_dbg(1, "Read at 0x%x gave only 0x%zx bytes
  ",
  			  ofs, retlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
309
  		return -EIO;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
311
  	return 0;
  }
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
312
313
314
  int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
  {
  	if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size
99988f7bb   David Woodhouse   [JFFS2] Introduce...
315
  	    && (!jeb->first_node || !ref_next(jeb->first_node)) )
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
  		return BLK_STATE_CLEANMARKER;
  
  	/* move blocks with max 4 byte dirty space to cleanlist */
  	else if (!ISDIRTY(c->sector_size - (jeb->used_size + jeb->unchecked_size))) {
  		c->dirty_size -= jeb->dirty_size;
  		c->wasted_size += jeb->dirty_size;
  		jeb->wasted_size += jeb->dirty_size;
  		jeb->dirty_size = 0;
  		return BLK_STATE_CLEAN;
  	} else if (jeb->used_size || jeb->unchecked_size)
  		return BLK_STATE_PARTDIRTY;
  	else
  		return BLK_STATE_ALLDIRTY;
  }
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
330
331
332
333
334
335
  #ifdef CONFIG_JFFS2_FS_XATTR
  static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
  				 struct jffs2_raw_xattr *rx, uint32_t ofs,
  				 struct jffs2_summary *s)
  {
  	struct jffs2_xattr_datum *xd;
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
336
  	uint32_t xid, version, totlen, crc;
68270995f   David Woodhouse   [JFFS2] Introduce...
337
  	int err;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
338
339
340
  
  	crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4);
  	if (crc != je32_to_cpu(rx->node_crc)) {
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
341
342
343
  		JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x
  ",
  			      ofs, je32_to_cpu(rx->node_crc), crc);
68270995f   David Woodhouse   [JFFS2] Introduce...
344
345
  		if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
  			return err;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
346
347
  		return 0;
  	}
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
348
349
  	xid = je32_to_cpu(rx->xid);
  	version = je32_to_cpu(rx->version);
8a13695cb   KaiGai Kohei   [JFFS2][XATTR] ri...
350
351
  	totlen = PAD(sizeof(struct jffs2_raw_xattr)
  			+ rx->name_len + 1 + je16_to_cpu(rx->value_len));
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
352
353
354
355
  	if (totlen != je32_to_cpu(rx->totlen)) {
  		JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u
  ",
  			      ofs, je32_to_cpu(rx->totlen), totlen);
68270995f   David Woodhouse   [JFFS2] Introduce...
356
357
  		if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
  			return err;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
358
359
  		return 0;
  	}
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
360
361
  	xd = jffs2_setup_xattr_datum(c, xid, version);
  	if (IS_ERR(xd))
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
362
  		return PTR_ERR(xd);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
363

c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
  	if (xd->version > version) {
  		struct jffs2_raw_node_ref *raw
  			= jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL);
  		raw->next_in_ino = xd->node->next_in_ino;
  		xd->node->next_in_ino = raw;
  	} else {
  		xd->version = version;
  		xd->xprefix = rx->xprefix;
  		xd->name_len = rx->name_len;
  		xd->value_len = je16_to_cpu(rx->value_len);
  		xd->data_crc = je32_to_cpu(rx->data_crc);
  
  		jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, (void *)xd);
  	}
f1f9671bd   David Woodhouse   [JFFS2] Introduce...
378

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
379
380
  	if (jffs2_sum_active())
  		jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset);
3e3417402   Masanari Iida   jffs2: fix typo i...
381
382
  	dbg_xattr("scanning xdatum at %#08x (xid=%u, version=%u)
  ",
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
383
384
385
386
387
388
389
390
391
  		  ofs, xd->xid, xd->version);
  	return 0;
  }
  
  static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
  				struct jffs2_raw_xref *rr, uint32_t ofs,
  				struct jffs2_summary *s)
  {
  	struct jffs2_xattr_ref *ref;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
392
  	uint32_t crc;
68270995f   David Woodhouse   [JFFS2] Introduce...
393
  	int err;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
394
395
396
  
  	crc = crc32(0, rr, sizeof(*rr) - 4);
  	if (crc != je32_to_cpu(rr->node_crc)) {
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
397
398
399
  		JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x
  ",
  			      ofs, je32_to_cpu(rr->node_crc), crc);
68270995f   David Woodhouse   [JFFS2] Introduce...
400
401
  		if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen)))))
  			return err;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
402
403
404
405
  		return 0;
  	}
  
  	if (PAD(sizeof(struct jffs2_raw_xref)) != je32_to_cpu(rr->totlen)) {
89291a9d5   David Woodhouse   [JFFS2] Fix 64-bi...
406
407
  		JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%zd
  ",
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
408
409
  			      ofs, je32_to_cpu(rr->totlen),
  			      PAD(sizeof(struct jffs2_raw_xref)));
68270995f   David Woodhouse   [JFFS2] Introduce...
410
411
  		if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rr->totlen))))
  			return err;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
412
413
414
415
416
417
  		return 0;
  	}
  
  	ref = jffs2_alloc_xattr_ref();
  	if (!ref)
  		return -ENOMEM;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
418
  	/* BEFORE jffs2_build_xattr_subsystem() called, 
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
419
  	 * and AFTER xattr_ref is marked as a dead xref,
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
420
421
422
  	 * ref->xid is used to store 32bit xid, xd is not used
  	 * ref->ino is used to store 32bit inode-number, ic is not used
  	 * Thoes variables are declared as union, thus using those
8f2b6f49c   KaiGai Kohei   [JFFS2][XATTR] Re...
423
  	 * are exclusive. In a similar way, ref->next is temporarily
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
424
425
426
  	 * used to chain all xattr_ref object. It's re-chained to
  	 * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly.
  	 */
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
427
428
  	ref->ino = je32_to_cpu(rr->ino);
  	ref->xid = je32_to_cpu(rr->xid);
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
429
430
431
  	ref->xseqno = je32_to_cpu(rr->xseqno);
  	if (ref->xseqno > c->highest_xseqno)
  		c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
8f2b6f49c   KaiGai Kohei   [JFFS2][XATTR] Re...
432
433
  	ref->next = c->xref_temp;
  	c->xref_temp = ref;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
434

c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
435
  	jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), (void *)ref);
f1f9671bd   David Woodhouse   [JFFS2] Introduce...
436

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
437
438
439
440
441
442
443
444
  	if (jffs2_sum_active())
  		jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset);
  	dbg_xattr("scan xref at %#08x (xid=%u, ino=%u)
  ",
  		  ofs, ref->xid, ref->ino);
  	return 0;
  }
  #endif
9641b784f   David Woodhouse   [JFFS2] Optimise ...
445
446
  /* Called with 'buf_size == 0' if buf is in fact a pointer _directly_ into
     the flash, XIP-style */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
  static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
9641b784f   David Woodhouse   [JFFS2] Optimise ...
448
  				  unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
450
  	struct jffs2_unknown_node *node;
  	struct jffs2_unknown_node crcnode;
41bdc602e   Joakim Tjernlund   jffs2: Reduce exc...
451
  	uint32_t ofs, prevofs, max_ofs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
452
453
454
  	uint32_t hdr_crc, buf_ofs, buf_len;
  	int err;
  	int noise = 0;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
455

2f82ce1eb   Andrew Victor   [JFFS2] Use a sin...
456
  #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
458
459
460
461
  	int cleanmarkerfound = 0;
  #endif
  
  	ofs = jeb->offset;
  	prevofs = jeb->offset - 1;
9c261b33a   Joe Perches   jffs2: Convert mo...
462
463
  	jffs2_dbg(1, "%s(): Scanning block at 0x%x
  ", __func__, ofs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464

2f82ce1eb   Andrew Victor   [JFFS2] Use a sin...
465
  #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466
  	if (jffs2_cleanmarker_oob(c)) {
a7a6ace14   Artem Bityutskiy   [JFFS2] Use MTD_O...
467
  		int ret;
7086c19d0   Artem Bityutskiy   mtd: introduce mt...
468
  		if (mtd_block_isbad(c->mtd, jeb->offset))
a7a6ace14   Artem Bityutskiy   [JFFS2] Use MTD_O...
469
470
471
  			return BLK_STATE_BADBLOCK;
  
  		ret = jffs2_check_nand_cleanmarker(c, jeb);
9c261b33a   Joe Perches   jffs2: Convert mo...
472
473
  		jffs2_dbg(2, "jffs_check_nand_cleanmarker returned %d
  ", ret);
a7a6ace14   Artem Bityutskiy   [JFFS2] Use MTD_O...
474

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
476
477
478
479
480
  		/* Even if it's not found, we still scan to see
  		   if the block is empty. We use this information
  		   to decide whether to erase it or not. */
  		switch (ret) {
  		case 0:		cleanmarkerfound = 1; break;
  		case 1: 	break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
483
484
  		default: 	return ret;
  		}
  	}
  #endif
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
485
486
  
  	if (jffs2_sum_active()) {
9641b784f   David Woodhouse   [JFFS2] Optimise ...
487
488
489
490
491
492
  		struct jffs2_sum_marker *sm;
  		void *sumptr = NULL;
  		uint32_t sumlen;
  	      
  		if (!buf_size) {
  			/* XIP case. Just look, point at the summary if it's there */
13ba42df4   David Woodhouse   [JFFS2] Fix calcu...
493
  			sm = (void *)buf + c->sector_size - sizeof(*sm);
9641b784f   David Woodhouse   [JFFS2] Optimise ...
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
  			if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
  				sumptr = buf + je32_to_cpu(sm->offset);
  				sumlen = c->sector_size - je32_to_cpu(sm->offset);
  			}
  		} else {
  			/* If NAND flash, read a whole page of it. Else just the end */
  			if (c->wbuf_pagesize)
  				buf_len = c->wbuf_pagesize;
  			else
  				buf_len = sizeof(*sm);
  
  			/* Read as much as we want into the _end_ of the preallocated buffer */
  			err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len, 
  						  jeb->offset + c->sector_size - buf_len,
  						  buf_len);				
  			if (err)
  				return err;
  
  			sm = (void *)buf + buf_size - sizeof(*sm);
  			if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
  				sumlen = c->sector_size - je32_to_cpu(sm->offset);
  				sumptr = buf + buf_size - sumlen;
164c24063   Chen Jie   jffs2: fix handli...
516
517
518
  				/* sm->offset maybe wrong but MAGIC maybe right */
  				if (sumlen > c->sector_size)
  					goto full_scan;
9641b784f   David Woodhouse   [JFFS2] Optimise ...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
  				/* Now, make sure the summary itself is available */
  				if (sumlen > buf_size) {
  					/* Need to kmalloc for this. */
  					sumptr = kmalloc(sumlen, GFP_KERNEL);
  					if (!sumptr)
  						return -ENOMEM;
  					memcpy(sumptr + sumlen - buf_len, buf + buf_size - buf_len, buf_len);
  				}
  				if (buf_len < sumlen) {
  					/* Need to read more so that the entire summary node is present */
  					err = jffs2_fill_scan_buf(c, sumptr, 
  								  jeb->offset + c->sector_size - sumlen,
  								  sumlen - buf_len);				
  					if (err)
  						return err;
  				}
  			}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
536

e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
537
  		}
9641b784f   David Woodhouse   [JFFS2] Optimise ...
538
539
  		if (sumptr) {
  			err = jffs2_sum_scan_sumnode(c, jeb, sumptr, sumlen, &pseudo_random);
3560160aa   David Woodhouse   [JFFS2] Fix memor...
540

9641b784f   David Woodhouse   [JFFS2] Optimise ...
541
542
  			if (buf_size && sumlen > buf_size)
  				kfree(sumptr);
3560160aa   David Woodhouse   [JFFS2] Fix memor...
543
544
545
546
547
548
  			/* If it returns with a real error, bail. 
  			   If it returns positive, that's a block classification
  			   (i.e. BLK_STATE_xxx) so return that too.
  			   If it returns zero, fall through to full scan. */
  			if (err)
  				return err;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
549
  		}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
550
  	}
164c24063   Chen Jie   jffs2: fix handli...
551
  full_scan:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
553
554
  	buf_ofs = jeb->offset;
  
  	if (!buf_size) {
9641b784f   David Woodhouse   [JFFS2] Optimise ...
555
  		/* This is the XIP case -- we're reading _directly_ from the flash chip */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556
557
  		buf_len = c->sector_size;
  	} else {
3be36675d   Andrew Victor   [JFFS2] Core chan...
558
  		buf_len = EMPTY_SCAN_SIZE(c->sector_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559
560
561
562
  		err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);
  		if (err)
  			return err;
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
563

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
565
  	/* We temporarily use 'ofs' as a pointer into the buffer/jeb */
  	ofs = 0;
41bdc602e   Joakim Tjernlund   jffs2: Reduce exc...
566
567
568
  	max_ofs = EMPTY_SCAN_SIZE(c->sector_size);
  	/* Scan only EMPTY_SCAN_SIZE of 0xFF before declaring it's empty */
  	while(ofs < max_ofs && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569
  		ofs += 4;
41bdc602e   Joakim Tjernlund   jffs2: Reduce exc...
570
  	if (ofs == max_ofs) {
2f82ce1eb   Andrew Victor   [JFFS2] Use a sin...
571
  #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
572
573
574
  		if (jffs2_cleanmarker_oob(c)) {
  			/* scan oob, take care of cleanmarker */
  			int ret = jffs2_check_oob_empty(c, jeb, cleanmarkerfound);
9c261b33a   Joe Perches   jffs2: Convert mo...
575
576
577
  			jffs2_dbg(2, "jffs2_check_oob_empty returned %d
  ",
  				  ret);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
579
580
581
582
583
584
  			switch (ret) {
  			case 0:		return cleanmarkerfound ? BLK_STATE_CLEANMARKER : BLK_STATE_ALLFF;
  			case 1: 	return BLK_STATE_ALLDIRTY;
  			default: 	return ret;
  			}
  		}
  #endif
9c261b33a   Joe Perches   jffs2: Convert mo...
585
586
587
  		jffs2_dbg(1, "Block at 0x%08x is empty (erased)
  ",
  			  jeb->offset);
8f15fd55f   Andrew Victor   [JFFS2] Add suppo...
588
589
590
591
  		if (c->cleanmarker_size == 0)
  			return BLK_STATE_CLEANMARKER;	/* don't bother with re-erase */
  		else
  			return BLK_STATE_ALLFF;	/* OK to erase if all blocks are like this */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
593
  	}
  	if (ofs) {
9c261b33a   Joe Perches   jffs2: Convert mo...
594
595
596
  		jffs2_dbg(1, "Free space at %08x ends at %08x
  ", jeb->offset,
  			  jeb->offset + ofs);
a6a8bef72   David Woodhouse   [JFFS2] Prealloca...
597
598
  		if ((err = jffs2_prealloc_raw_node_refs(c, jeb, 1)))
  			return err;
68270995f   David Woodhouse   [JFFS2] Introduce...
599
600
  		if ((err = jffs2_scan_dirty_space(c, jeb, ofs)))
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
602
603
604
605
606
  	}
  
  	/* Now ofs is a complete physical flash offset as it always was... */
  	ofs += jeb->offset;
  
  	noise = 10;
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
607
608
  	dbg_summary("no summary found in jeb 0x%08x. Apply original scan.
  ",jeb->offset);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
609

182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
610
  scan_more:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
611
  	while(ofs < jeb->offset + c->sector_size) {
e0c8e42f8   Artem B. Bityutskiy   [JFFS2] Debug cod...
612
  		jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613

2f785402f   David Woodhouse   [JFFS2] Reduce vi...
614
  		/* Make sure there are node refs available for use */
046b8b980   David Woodhouse   [JFFS2] Add 'jeb'...
615
  		err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
616
617
  		if (err)
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
618
619
620
  		cond_resched();
  
  		if (ofs & 3) {
da320f055   Joe Perches   jffs2: Convert pr...
621
622
  			pr_warn("Eep. ofs 0x%08x not word-aligned!
  ", ofs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623
624
625
626
  			ofs = PAD(ofs);
  			continue;
  		}
  		if (ofs == prevofs) {
da320f055   Joe Perches   jffs2: Convert pr...
627
628
629
  			pr_warn("ofs 0x%08x has already been seen. Skipping
  ",
  				ofs);
68270995f   David Woodhouse   [JFFS2] Introduce...
630
631
  			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
633
634
635
636
637
  			ofs += 4;
  			continue;
  		}
  		prevofs = ofs;
  
  		if (jeb->offset + c->sector_size < ofs + sizeof(*node)) {
9c261b33a   Joe Perches   jffs2: Convert mo...
638
639
640
641
642
  			jffs2_dbg(1, "Fewer than %zd bytes left to end of block. (%x+%x<%x+%zx) Not reading
  ",
  				  sizeof(struct jffs2_unknown_node),
  				  jeb->offset, c->sector_size, ofs,
  				  sizeof(*node));
68270995f   David Woodhouse   [JFFS2] Introduce...
643
644
  			if ((err = jffs2_scan_dirty_space(c, jeb, (jeb->offset + c->sector_size)-ofs)))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645
646
647
648
649
  			break;
  		}
  
  		if (buf_ofs + buf_len < ofs + sizeof(*node)) {
  			buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
9c261b33a   Joe Perches   jffs2: Convert mo...
650
651
652
653
  			jffs2_dbg(1, "Fewer than %zd bytes (node header) left to end of buf. Reading 0x%x at 0x%08x
  ",
  				  sizeof(struct jffs2_unknown_node),
  				  buf_len, ofs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
655
656
657
658
659
660
661
662
663
  			err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
  			if (err)
  				return err;
  			buf_ofs = ofs;
  		}
  
  		node = (struct jffs2_unknown_node *)&buf[ofs-buf_ofs];
  
  		if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) {
  			uint32_t inbuf_ofs;
c2aecda79   Joakim Tjernlund   [JFFS2] Speed up ...
664
  			uint32_t empty_start, scan_end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
666
667
  
  			empty_start = ofs;
  			ofs += 4;
c2aecda79   Joakim Tjernlund   [JFFS2] Speed up ...
668
  			scan_end = min_t(uint32_t, EMPTY_SCAN_SIZE(c->sector_size)/8, buf_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669

9c261b33a   Joe Perches   jffs2: Convert mo...
670
671
  			jffs2_dbg(1, "Found empty flash at 0x%08x
  ", ofs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
673
  		more_empty:
  			inbuf_ofs = ofs - buf_ofs;
c2aecda79   Joakim Tjernlund   [JFFS2] Speed up ...
674
675
  			while (inbuf_ofs < scan_end) {
  				if (unlikely(*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff)) {
da320f055   Joe Perches   jffs2: Convert pr...
676
677
678
  					pr_warn("Empty flash at 0x%08x ends at 0x%08x
  ",
  						empty_start, ofs);
68270995f   David Woodhouse   [JFFS2] Introduce...
679
680
  					if ((err = jffs2_scan_dirty_space(c, jeb, ofs-empty_start)))
  						return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
682
683
684
685
686
687
  					goto scan_more;
  				}
  
  				inbuf_ofs+=4;
  				ofs += 4;
  			}
  			/* Ran off end. */
9c261b33a   Joe Perches   jffs2: Convert mo...
688
689
690
  			jffs2_dbg(1, "Empty flash to end of buffer at 0x%08x
  ",
  				  ofs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
692
693
  
  			/* If we're only checking the beginning of a block with a cleanmarker,
  			   bail now */
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
694
  			if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) &&
99988f7bb   David Woodhouse   [JFFS2] Introduce...
695
  			    c->cleanmarker_size && !jeb->dirty_size && !ref_next(jeb->first_node)) {
9c261b33a   Joe Perches   jffs2: Convert mo...
696
697
698
  				jffs2_dbg(1, "%d bytes at start of block seems clean... assuming all clean
  ",
  					  EMPTY_SCAN_SIZE(c->sector_size));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
700
  				return BLK_STATE_CLEANMARKER;
  			}
c2aecda79   Joakim Tjernlund   [JFFS2] Speed up ...
701
702
703
704
705
  			if (!buf_size && (scan_end != buf_len)) {/* XIP/point case */
  				scan_end = buf_len;
  				goto more_empty;
  			}
  			
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
707
708
  			/* See how much more there is to read in this eraseblock... */
  			buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
  			if (!buf_len) {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
709
  				/* No more to read. Break out of main loop without marking
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
  				   this range of empty space as dirty (because it's not) */
9c261b33a   Joe Perches   jffs2: Convert mo...
711
712
713
  				jffs2_dbg(1, "Empty flash at %08x runs to end of block. Treating as free_space
  ",
  					  empty_start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
715
  				break;
  			}
c2aecda79   Joakim Tjernlund   [JFFS2] Speed up ...
716
717
  			/* point never reaches here */
  			scan_end = buf_len;
9c261b33a   Joe Perches   jffs2: Convert mo...
718
719
720
  			jffs2_dbg(1, "Reading another 0x%x at 0x%08x
  ",
  				  buf_len, ofs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
721
722
723
724
725
726
727
728
  			err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
  			if (err)
  				return err;
  			buf_ofs = ofs;
  			goto more_empty;
  		}
  
  		if (ofs == jeb->offset && je16_to_cpu(node->magic) == KSAMTIB_CIGAM_2SFFJ) {
da320f055   Joe Perches   jffs2: Convert pr...
729
730
731
  			pr_warn("Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?
  ",
  				ofs);
68270995f   David Woodhouse   [JFFS2] Introduce...
732
733
  			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
736
737
  			ofs += 4;
  			continue;
  		}
  		if (je16_to_cpu(node->magic) == JFFS2_DIRTY_BITMASK) {
9c261b33a   Joe Perches   jffs2: Convert mo...
738
739
  			jffs2_dbg(1, "Dirty bitmask at 0x%08x
  ", ofs);
68270995f   David Woodhouse   [JFFS2] Introduce...
740
741
  			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
743
744
745
  			ofs += 4;
  			continue;
  		}
  		if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) {
da320f055   Joe Perches   jffs2: Convert pr...
746
747
748
749
  			pr_warn("Old JFFS2 bitmask found at 0x%08x
  ", ofs);
  			pr_warn("You cannot use older JFFS2 filesystems with newer kernels
  ");
68270995f   David Woodhouse   [JFFS2] Introduce...
750
751
  			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
753
754
755
756
  			ofs += 4;
  			continue;
  		}
  		if (je16_to_cpu(node->magic) != JFFS2_MAGIC_BITMASK) {
  			/* OK. We're out of possibilities. Whinge and move on */
da320f055   Joe Perches   jffs2: Convert pr...
757
758
759
  			noisy_printk(&noise, "%s(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead
  ",
  				     __func__,
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
760
  				     JFFS2_MAGIC_BITMASK, ofs,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
761
  				     je16_to_cpu(node->magic));
68270995f   David Woodhouse   [JFFS2] Introduce...
762
763
  			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
765
766
767
768
769
770
771
772
773
  			ofs += 4;
  			continue;
  		}
  		/* We seem to have a node of sorts. Check the CRC */
  		crcnode.magic = node->magic;
  		crcnode.nodetype = cpu_to_je16( je16_to_cpu(node->nodetype) | JFFS2_NODE_ACCURATE);
  		crcnode.totlen = node->totlen;
  		hdr_crc = crc32(0, &crcnode, sizeof(crcnode)-4);
  
  		if (hdr_crc != je32_to_cpu(node->hdr_crc)) {
da320f055   Joe Perches   jffs2: Convert pr...
774
775
776
  			noisy_printk(&noise, "%s(): Node at 0x%08x {0x%04x, 0x%04x, 0x%08x) has invalid CRC 0x%08x (calculated 0x%08x)
  ",
  				     __func__,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777
  				     ofs, je16_to_cpu(node->magic),
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
778
  				     je16_to_cpu(node->nodetype),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779
780
781
  				     je32_to_cpu(node->totlen),
  				     je32_to_cpu(node->hdr_crc),
  				     hdr_crc);
68270995f   David Woodhouse   [JFFS2] Introduce...
782
783
  			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784
785
786
  			ofs += 4;
  			continue;
  		}
0dec4c8bc   Joakim Tjernlund   [JFFS2] Better fi...
787
  		if (ofs + je32_to_cpu(node->totlen) > jeb->offset + c->sector_size) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
  			/* Eep. Node goes over the end of the erase block. */
da320f055   Joe Perches   jffs2: Convert pr...
789
790
791
792
793
  			pr_warn("Node at 0x%08x with length 0x%08x would run over the end of the erase block
  ",
  				ofs, je32_to_cpu(node->totlen));
  			pr_warn("Perhaps the file system was created with the wrong erase size?
  ");
68270995f   David Woodhouse   [JFFS2] Introduce...
794
795
  			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796
797
798
799
800
801
  			ofs += 4;
  			continue;
  		}
  
  		if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) {
  			/* Wheee. This is an obsoleted node */
9c261b33a   Joe Perches   jffs2: Convert mo...
802
803
804
  			jffs2_dbg(2, "Node at 0x%08x is obsolete. Skipping
  ",
  				  ofs);
68270995f   David Woodhouse   [JFFS2] Introduce...
805
806
  			if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
808
809
810
811
812
813
814
  			ofs += PAD(je32_to_cpu(node->totlen));
  			continue;
  		}
  
  		switch(je16_to_cpu(node->nodetype)) {
  		case JFFS2_NODETYPE_INODE:
  			if (buf_ofs + buf_len < ofs + sizeof(struct jffs2_raw_inode)) {
  				buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
9c261b33a   Joe Perches   jffs2: Convert mo...
815
816
817
818
  				jffs2_dbg(1, "Fewer than %zd bytes (inode node) left to end of buf. Reading 0x%x at 0x%08x
  ",
  					  sizeof(struct jffs2_raw_inode),
  					  buf_len, ofs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819
820
821
822
823
824
  				err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
  				if (err)
  					return err;
  				buf_ofs = ofs;
  				node = (void *)buf;
  			}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
825
  			err = jffs2_scan_inode_node(c, jeb, (void *)node, ofs, s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
826
827
828
  			if (err) return err;
  			ofs += PAD(je32_to_cpu(node->totlen));
  			break;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
829

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830
831
832
  		case JFFS2_NODETYPE_DIRENT:
  			if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
  				buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
9c261b33a   Joe Perches   jffs2: Convert mo...
833
834
835
836
  				jffs2_dbg(1, "Fewer than %d bytes (dirent node) left to end of buf. Reading 0x%x at 0x%08x
  ",
  					  je32_to_cpu(node->totlen), buf_len,
  					  ofs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
837
838
839
840
841
842
  				err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
  				if (err)
  					return err;
  				buf_ofs = ofs;
  				node = (void *)buf;
  			}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
843
  			err = jffs2_scan_dirent_node(c, jeb, (void *)node, ofs, s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
844
845
846
  			if (err) return err;
  			ofs += PAD(je32_to_cpu(node->totlen));
  			break;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
847
848
849
850
  #ifdef CONFIG_JFFS2_FS_XATTR
  		case JFFS2_NODETYPE_XATTR:
  			if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
  				buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
9c261b33a   Joe Perches   jffs2: Convert mo...
851
852
853
854
  				jffs2_dbg(1, "Fewer than %d bytes (xattr node) left to end of buf. Reading 0x%x at 0x%08x
  ",
  					  je32_to_cpu(node->totlen), buf_len,
  					  ofs);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
855
856
857
858
859
860
861
862
863
864
865
866
867
868
  				err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
  				if (err)
  					return err;
  				buf_ofs = ofs;
  				node = (void *)buf;
  			}
  			err = jffs2_scan_xattr_node(c, jeb, (void *)node, ofs, s);
  			if (err)
  				return err;
  			ofs += PAD(je32_to_cpu(node->totlen));
  			break;
  		case JFFS2_NODETYPE_XREF:
  			if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
  				buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
9c261b33a   Joe Perches   jffs2: Convert mo...
869
870
871
872
  				jffs2_dbg(1, "Fewer than %d bytes (xref node) left to end of buf. Reading 0x%x at 0x%08x
  ",
  					  je32_to_cpu(node->totlen), buf_len,
  					  ofs);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
873
874
875
876
877
878
879
880
881
882
883
884
  				err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
  				if (err)
  					return err;
  				buf_ofs = ofs;
  				node = (void *)buf;
  			}
  			err = jffs2_scan_xref_node(c, jeb, (void *)node, ofs, s);
  			if (err)
  				return err;
  			ofs += PAD(je32_to_cpu(node->totlen));
  			break;
  #endif	/* CONFIG_JFFS2_FS_XATTR */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
885
  		case JFFS2_NODETYPE_CLEANMARKER:
9c261b33a   Joe Perches   jffs2: Convert mo...
886
887
  			jffs2_dbg(1, "CLEANMARKER node found at 0x%08x
  ", ofs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
888
  			if (je32_to_cpu(node->totlen) != c->cleanmarker_size) {
da320f055   Joe Perches   jffs2: Convert pr...
889
890
891
892
  				pr_notice("CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x
  ",
  					  ofs, je32_to_cpu(node->totlen),
  					  c->cleanmarker_size);
68270995f   David Woodhouse   [JFFS2] Introduce...
893
894
  				if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))
  					return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
895
896
  				ofs += PAD(sizeof(struct jffs2_unknown_node));
  			} else if (jeb->first_node) {
da320f055   Joe Perches   jffs2: Convert pr...
897
898
899
  				pr_notice("CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)
  ",
  					  ofs, jeb->offset);
68270995f   David Woodhouse   [JFFS2] Introduce...
900
901
  				if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))
  					return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
902
903
  				ofs += PAD(sizeof(struct jffs2_unknown_node));
  			} else {
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
904
  				jffs2_link_node_ref(c, jeb, ofs | REF_NORMAL, c->cleanmarker_size, NULL);
f1f9671bd   David Woodhouse   [JFFS2] Introduce...
905

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
906
907
908
909
910
  				ofs += PAD(c->cleanmarker_size);
  			}
  			break;
  
  		case JFFS2_NODETYPE_PADDING:
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
911
912
  			if (jffs2_sum_active())
  				jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen));
68270995f   David Woodhouse   [JFFS2] Introduce...
913
914
  			if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
915
916
917
918
919
920
  			ofs += PAD(je32_to_cpu(node->totlen));
  			break;
  
  		default:
  			switch (je16_to_cpu(node->nodetype) & JFFS2_COMPAT_MASK) {
  			case JFFS2_FEATURE_ROCOMPAT:
da320f055   Joe Perches   jffs2: Convert pr...
921
922
923
  				pr_notice("Read-only compatible feature node (0x%04x) found at offset 0x%08x
  ",
  					  je16_to_cpu(node->nodetype), ofs);
ef53cb02f   David Woodhouse   [JFFS2] Whitespac...
924
  				c->flags |= JFFS2_SB_FLAG_RO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
925
926
  				if (!(jffs2_is_readonly(c)))
  					return -EROFS;
68270995f   David Woodhouse   [JFFS2] Introduce...
927
928
  				if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
  					return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929
930
931
932
  				ofs += PAD(je32_to_cpu(node->totlen));
  				break;
  
  			case JFFS2_FEATURE_INCOMPAT:
da320f055   Joe Perches   jffs2: Convert pr...
933
934
935
  				pr_notice("Incompatible feature node (0x%04x) found at offset 0x%08x
  ",
  					  je16_to_cpu(node->nodetype), ofs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
936
937
938
  				return -EINVAL;
  
  			case JFFS2_FEATURE_RWCOMPAT_DELETE:
9c261b33a   Joe Perches   jffs2: Convert mo...
939
940
941
  				jffs2_dbg(1, "Unknown but compatible feature node (0x%04x) found at offset 0x%08x
  ",
  					  je16_to_cpu(node->nodetype), ofs);
68270995f   David Woodhouse   [JFFS2] Introduce...
942
943
  				if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
  					return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
944
945
  				ofs += PAD(je32_to_cpu(node->totlen));
  				break;
6171586a7   David Woodhouse   [JFFS2] Correct h...
946
  			case JFFS2_FEATURE_RWCOMPAT_COPY: {
9c261b33a   Joe Perches   jffs2: Convert mo...
947
948
949
  				jffs2_dbg(1, "Unknown but compatible feature node (0x%04x) found at offset 0x%08x
  ",
  					  je16_to_cpu(node->nodetype), ofs);
6171586a7   David Woodhouse   [JFFS2] Correct h...
950

2f785402f   David Woodhouse   [JFFS2] Reduce vi...
951
  				jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(node->totlen)), NULL);
6171586a7   David Woodhouse   [JFFS2] Correct h...
952
953
954
  
  				/* We can't summarise nodes we don't grok */
  				jffs2_sum_disable_collecting(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
955
956
  				ofs += PAD(je32_to_cpu(node->totlen));
  				break;
6171586a7   David Woodhouse   [JFFS2] Correct h...
957
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
959
960
  			}
  		}
  	}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
961
962
  	if (jffs2_sum_active()) {
  		if (PAD(s->sum_size + JFFS2_SUMMARY_FRAME_SIZE) > jeb->free_size) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
963
  			dbg_summary("There is not enough space for "
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
964
965
966
967
968
  				"summary information, disabling for this jeb!
  ");
  			jffs2_sum_disable_collecting(s);
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969

9c261b33a   Joe Perches   jffs2: Convert mo...
970
971
972
973
  	jffs2_dbg(1, "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x, wasted 0x%08x
  ",
  		  jeb->offset, jeb->free_size, jeb->dirty_size,
  		  jeb->unchecked_size, jeb->used_size, jeb->wasted_size);
8b9e9fe8c   David Woodhouse   [JFFS2] Fix and i...
974
  	
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
975
976
977
978
979
980
981
  	/* mark_node_obsolete can add to wasted !! */
  	if (jeb->wasted_size) {
  		jeb->dirty_size += jeb->wasted_size;
  		c->dirty_size += jeb->wasted_size;
  		c->wasted_size -= jeb->wasted_size;
  		jeb->wasted_size = 0;
  	}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
982
  	return jffs2_scan_classify_jeb(c, jeb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
  }
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
984
  struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
985
986
987
988
989
990
991
992
993
994
995
996
  {
  	struct jffs2_inode_cache *ic;
  
  	ic = jffs2_get_ino_cache(c, ino);
  	if (ic)
  		return ic;
  
  	if (ino > c->highest_ino)
  		c->highest_ino = ino;
  
  	ic = jffs2_alloc_inode_cache();
  	if (!ic) {
da320f055   Joe Perches   jffs2: Convert pr...
997
998
  		pr_notice("%s(): allocation of inode cache failed
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
999
1000
1001
1002
1003
1004
1005
1006
  		return NULL;
  	}
  	memset(ic, 0, sizeof(*ic));
  
  	ic->ino = ino;
  	ic->nodes = (void *)ic;
  	jffs2_add_ino_cache(c, ic);
  	if (ino == 1)
27c72b040   David Woodhouse   [JFFS2] Track par...
1007
  		ic->pino_nlink = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1008
1009
  	return ic;
  }
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1010
  static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
1011
  				 struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1012
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1013
  	struct jffs2_inode_cache *ic;
53043002e   Thomas Gleixner   [JFFS2] check nod...
1014
  	uint32_t crc, ino = je32_to_cpu(ri->ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015

9c261b33a   Joe Perches   jffs2: Convert mo...
1016
1017
  	jffs2_dbg(1, "%s(): Node at 0x%08x
  ", __func__, ofs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1018
1019
  
  	/* We do very little here now. Just check the ino# to which we should attribute
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1020
  	   this node; we can do all the CRC checking etc. later. There's a tradeoff here --
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1021
1022
1023
  	   we used to scan the flash once only, reading everything we want from it into
  	   memory, then building all our in-core data structures and freeing the extra
  	   information. Now we allow the first part of the mount to complete a lot quicker,
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1024
  	   but we have to go _back_ to the flash in order to finish the CRC checking, etc.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1025
1026
  	   Which means that the _full_ amount of time to get to proper write mode with GC
  	   operational may actually be _longer_ than before. Sucks to be me. */
53043002e   Thomas Gleixner   [JFFS2] check nod...
1027
1028
1029
  	/* Check the node CRC in any case. */
  	crc = crc32(0, ri, sizeof(*ri)-8);
  	if (crc != je32_to_cpu(ri->node_crc)) {
da320f055   Joe Perches   jffs2: Convert pr...
1030
1031
1032
  		pr_notice("%s(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x
  ",
  			  __func__, ofs, je32_to_cpu(ri->node_crc), crc);
53043002e   Thomas Gleixner   [JFFS2] check nod...
1033
1034
1035
1036
1037
1038
1039
  		/*
  		 * We believe totlen because the CRC on the node
  		 * _header_ was OK, just the node itself failed.
  		 */
  		return jffs2_scan_dirty_space(c, jeb,
  					      PAD(je32_to_cpu(ri->totlen)));
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
1041
  	ic = jffs2_get_ino_cache(c, ino);
  	if (!ic) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1042
  		ic = jffs2_scan_make_ino_cache(c, ino);
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
1043
  		if (!ic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1044
  			return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1045
1046
1047
  	}
  
  	/* Wheee. It worked */
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
1048
  	jffs2_link_node_ref(c, jeb, ofs | REF_UNCHECKED, PAD(je32_to_cpu(ri->totlen)), ic);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1049

9c261b33a   Joe Perches   jffs2: Convert mo...
1050
1051
  	jffs2_dbg(1, "Node is ino #%u, version %d. Range 0x%x-0x%x
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1052
1053
  		  je32_to_cpu(ri->ino), je32_to_cpu(ri->version),
  		  je32_to_cpu(ri->offset),
9c261b33a   Joe Perches   jffs2: Convert mo...
1054
  		  je32_to_cpu(ri->offset)+je32_to_cpu(ri->dsize));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1055
1056
  
  	pseudo_random += je32_to_cpu(ri->version);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
1057
1058
1059
  	if (jffs2_sum_active()) {
  		jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1060
1061
  	return 0;
  }
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1062
  static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
1063
  				  struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1064
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1065
1066
  	struct jffs2_full_dirent *fd;
  	struct jffs2_inode_cache *ic;
b534e70cf   David Woodhouse   [JFFS2] Handle di...
1067
  	uint32_t checkedlen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1068
  	uint32_t crc;
68270995f   David Woodhouse   [JFFS2] Introduce...
1069
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1070

9c261b33a   Joe Perches   jffs2: Convert mo...
1071
1072
  	jffs2_dbg(1, "%s(): Node at 0x%08x
  ", __func__, ofs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1073
1074
1075
1076
1077
1078
  
  	/* We don't get here unless the node is still valid, so we don't have to
  	   mask in the ACCURATE bit any more. */
  	crc = crc32(0, rd, sizeof(*rd)-8);
  
  	if (crc != je32_to_cpu(rd->node_crc)) {
da320f055   Joe Perches   jffs2: Convert pr...
1079
1080
1081
  		pr_notice("%s(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x
  ",
  			  __func__, ofs, je32_to_cpu(rd->node_crc), crc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1082
  		/* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
68270995f   David Woodhouse   [JFFS2] Introduce...
1083
1084
  		if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1085
1086
1087
1088
  		return 0;
  	}
  
  	pseudo_random += je32_to_cpu(rd->version);
b534e70cf   David Woodhouse   [JFFS2] Handle di...
1089
1090
1091
  	/* Should never happen. Did. (OLPC trac #4184)*/
  	checkedlen = strnlen(rd->name, rd->nsize);
  	if (checkedlen < rd->nsize) {
da320f055   Joe Perches   jffs2: Convert pr...
1092
1093
  		pr_err("Dirent at %08x has zeroes in name. Truncating to %d chars
  ",
b534e70cf   David Woodhouse   [JFFS2] Handle di...
1094
1095
1096
  		       ofs, checkedlen);
  	}
  	fd = jffs2_alloc_full_dirent(checkedlen+1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1097
1098
1099
  	if (!fd) {
  		return -ENOMEM;
  	}
b534e70cf   David Woodhouse   [JFFS2] Handle di...
1100
1101
  	memcpy(&fd->name, rd->name, checkedlen);
  	fd->name[checkedlen] = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1102
1103
1104
  
  	crc = crc32(0, fd->name, rd->nsize);
  	if (crc != je32_to_cpu(rd->name_crc)) {
da320f055   Joe Perches   jffs2: Convert pr...
1105
1106
1107
  		pr_notice("%s(): Name CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x
  ",
  			  __func__, ofs, je32_to_cpu(rd->name_crc), crc);
9c261b33a   Joe Perches   jffs2: Convert mo...
1108
1109
1110
  		jffs2_dbg(1, "Name for which CRC failed is (now) '%s', ino #%d
  ",
  			  fd->name, je32_to_cpu(rd->ino));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1111
1112
1113
  		jffs2_free_full_dirent(fd);
  		/* FIXME: Why do we believe totlen? */
  		/* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */
68270995f   David Woodhouse   [JFFS2] Introduce...
1114
1115
  		if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1116
1117
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1118
1119
1120
  	ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino));
  	if (!ic) {
  		jffs2_free_full_dirent(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1121
1122
  		return -ENOMEM;
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1123

43dfa07fb   David Woodhouse   [JFFS2] Deletion ...
1124
1125
  	fd->raw = jffs2_link_node_ref(c, jeb, ofs | dirent_node_state(rd),
  				      PAD(je32_to_cpu(rd->totlen)), ic);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1126

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1127
1128
1129
  	fd->next = NULL;
  	fd->version = je32_to_cpu(rd->version);
  	fd->ino = je32_to_cpu(rd->ino);
8387ff257   Linus Torvalds   vfs: make the str...
1130
  	fd->nhash = full_name_hash(NULL, fd->name, checkedlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1131
  	fd->type = rd->type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1132
  	jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
1133
1134
1135
  	if (jffs2_sum_active()) {
  		jffs2_sum_add_dirent_mem(s, rd, ofs - jeb->offset);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
  	return 0;
  }
  
  static int count_list(struct list_head *l)
  {
  	uint32_t count = 0;
  	struct list_head *tmp;
  
  	list_for_each(tmp, l) {
  		count++;
  	}
  	return count;
  }
  
  /* Note: This breaks if list_empty(head). I don't care. You
     might, if you copy this code and use it elsewhere :) */
  static void rotate_list(struct list_head *head, uint32_t count)
  {
  	struct list_head *n = head->next;
  
  	list_del(head);
  	while(count--) {
  		n = n->next;
  	}
  	list_add(head, n);
  }
  
  void jffs2_rotate_lists(struct jffs2_sb_info *c)
  {
  	uint32_t x;
  	uint32_t rotateby;
  
  	x = count_list(&c->clean_list);
  	if (x) {
  		rotateby = pseudo_random % x;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1171
  		rotate_list((&c->clean_list), rotateby);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1172
1173
1174
1175
1176
  	}
  
  	x = count_list(&c->very_dirty_list);
  	if (x) {
  		rotateby = pseudo_random % x;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1177
  		rotate_list((&c->very_dirty_list), rotateby);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1178
1179
1180
1181
1182
  	}
  
  	x = count_list(&c->dirty_list);
  	if (x) {
  		rotateby = pseudo_random % x;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1183
  		rotate_list((&c->dirty_list), rotateby);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1184
1185
1186
1187
1188
  	}
  
  	x = count_list(&c->erasable_list);
  	if (x) {
  		rotateby = pseudo_random % x;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1189
  		rotate_list((&c->erasable_list), rotateby);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1190
1191
1192
1193
  	}
  
  	if (c->nr_erasing_blocks) {
  		rotateby = pseudo_random % c->nr_erasing_blocks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1194
  		rotate_list((&c->erase_pending_list), rotateby);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195
1196
1197
1198
  	}
  
  	if (c->nr_free_blocks) {
  		rotateby = pseudo_random % c->nr_free_blocks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1199
  		rotate_list((&c->free_list), rotateby);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1200
1201
  	}
  }