Blame view

fs/jffs2/scan.c 35.6 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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
17
18
19
  #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...
20
21
  #include "summary.h"
  #include "debug.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  #define noisy_printk(noise, args...) do { \
  	if (*(noise)) { \
  		printk(KERN_NOTICE args); \
  		 (*(noise))--; \
  		 if (!(*(noise))) { \
  			 printk(KERN_NOTICE "Further such events for this erase block will not be printed
  "); \
  		 } \
  	} \
  } while(0)
  
  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...
39
  				  unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40

182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
41
  /* These helper functions _must_ increase ofs and also do the dirty/used space accounting.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
   * Returning an error will abort the mount - bad checksums etc. should just mark the space
   * as dirty.
   */
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
45
  static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
46
  				 struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
  static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
48
  				 struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
52
  
  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...
53
  #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
57
58
59
  	if (!jffs2_can_mark_obsolete(c) && min < c->wbuf_pagesize)
  		return c->wbuf_pagesize;
  #endif
  	return min;
  
  }
3be36675d   Andrew Victor   [JFFS2] Core chan...
60
61
62
63
64
65
66
  
  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...
67
68
  static int file_dirty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
  {
a6a8bef72   David Woodhouse   [JFFS2] Prealloca...
69
70
71
72
73
  	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...
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  		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
88
89
90
91
92
93
  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...
94
  	struct jffs2_summary *s = NULL; /* summary info collected by the scan process */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
  #ifndef __ECOS
1ddd0d9a3   Grant Erickson   JFFS2: retry larg...
96
  	size_t pointlen, try_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
  
  	if (c->mtd->point) {
d35ea200c   Artem Bityutskiy   mtd: introduce mt...
99
100
  		ret = mtd_point(c->mtd, 0, c->mtd->size, &pointlen,
  				(void **)&flashbuf, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
102
103
104
  		if (!ret && pointlen < c->mtd->size) {
  			/* Don't muck about if it won't let us point to the whole flash */
  			D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx
  ", pointlen));
7219778ad   Artem Bityutskiy   mtd: introduce mt...
105
  			mtd_unpoint(c->mtd, 0, pointlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
  			flashbuf = NULL;
  		}
10934478e   Artem Bityutskiy   mtd: do use mtd->...
108
  		if (ret && ret != -EOPNOTSUPP)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
112
113
114
115
116
  			D1(printk(KERN_DEBUG "MTD point failed %d
  ", ret));
  	}
  #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

1ddd0d9a3   Grant Erickson   JFFS2: retry larg...
121
122
123
  		D1(printk(KERN_DEBUG "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
129
130
131
132
133
  
  		D1(printk(KERN_DEBUG "Allocated readbuf of %zu bytes
  ",
  			try_size));
  
  		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
180
181
182
183
184
185
186
187
  			 * 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 */
  				D1(printk(KERN_DEBUG "Adding all-dirty block at 0x%08x to erase_pending_list
  ", jeb->offset));
  				list_add(&jeb->list, &c->erase_pending_list);
  				c->nr_erasing_blocks++;
  			}
  			break;
  
  		case BLK_STATE_CLEAN:
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
188
189
  			/* Full (or almost full) of clean data. Clean list */
  			list_add(&jeb->list, &c->clean_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
191
192
  			break;
  
  		case BLK_STATE_PARTDIRTY:
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
193
194
195
196
197
198
199
  			/* 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...
200
201
  					ret = file_dirty(c, c->nextblock);
  					if (ret)
a2ab0ce09   Christian Engelmayer   jffs2: leaking jf...
202
  						goto out;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
203
204
  					/* deleting summary information of the old nextblock */
  					jffs2_sum_reset_collected(c->summary);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
  				}
25090a6b2   David Woodhouse   [JFFS2] Discard r...
206
  				/* update collected summary information for the current nextblock */
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
207
208
209
210
211
  				jffs2_sum_move_collected(c, s);
  				D1(printk(KERN_DEBUG "jffs2_scan_medium(): new nextblock = 0x%08x
  ", jeb->offset));
  				c->nextblock = jeb;
  			} else {
25090a6b2   David Woodhouse   [JFFS2] Discard r...
212
213
  				ret = file_dirty(c, jeb);
  				if (ret)
a2ab0ce09   Christian Engelmayer   jffs2: leaking jf...
214
  					goto out;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
215
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
219
  			break;
  
  		case BLK_STATE_ALLDIRTY:
  			/* Nothing valid - not even a clean marker. Needs erasing. */
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
220
  			/* For now we just put it on the erasing list. We'll start the erases later */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
  			D1(printk(KERN_NOTICE "JFFS2: Erase block at 0x%08x is not formatted. It will be erased
  ", jeb->offset));
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
223
  			list_add(&jeb->list, &c->erase_pending_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
  			c->nr_erasing_blocks++;
  			break;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
226

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
229
  		case BLK_STATE_BADBLOCK:
  			D1(printk(KERN_NOTICE "JFFS2: Block at 0x%08x is bad
  ", jeb->offset));
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
230
  			list_add(&jeb->list, &c->bad_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
232
233
234
235
236
237
  			c->bad_size += c->sector_size;
  			c->free_size -= c->sector_size;
  			bad_blocks++;
  			break;
  		default:
  			printk(KERN_WARNING "jffs2_scan_medium(): unknown block state
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
238
  			BUG();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
  		}
  	}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
241

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
244
245
246
247
248
  	/* 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...
249
  #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
e96fb230c   David Woodhouse   [PATCH] jffs2: av...
250
  	if (!jffs2_can_mark_obsolete(c) && c->wbuf_pagesize && c->nextblock && (c->nextblock->free_size % c->wbuf_pagesize)) {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
251
  		/* If we're going to start writing into a block which already
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
253
  		   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...
254
  		uint32_t skip = c->nextblock->free_size % c->wbuf_pagesize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
257
258
  
  		D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment
  ",
  			  skip));
046b8b980   David Woodhouse   [JFFS2] Add 'jeb'...
259
  		jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
f560928ba   David Woodhouse   [JFFS2] Allocate ...
260
  		jffs2_scan_dirty_space(c, c->nextblock, skip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
263
  	}
  #endif
  	if (c->nr_erasing_blocks) {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
264
  		if ( !c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
268
269
270
271
  			printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes
  ");
  			printk(KERN_NOTICE "empty_blocks %d, bad_blocks %d, c->nr_blocks %d
  ",empty_blocks,bad_blocks,c->nr_blocks);
  			ret = -EIO;
  			goto out;
  		}
ae3b6ba06   David Woodhouse   jffs2: Use jffs2_...
272
273
274
  		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
275
276
277
278
279
280
  	}
  	ret = 0;
   out:
  	if (buf_size)
  		kfree(flashbuf);
  #ifndef __ECOS
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
281
  	else
7219778ad   Artem Bityutskiy   mtd: introduce mt...
282
  		mtd_unpoint(c->mtd, 0, c->mtd->size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
  #endif
e8a0e4126   Jesper Juhl   jffs2: Avoid unne...
284
  	kfree(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
286
  	return ret;
  }
c05d52c74   Adrian Bunk   fs/jffs2/: make 2...
287
288
  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
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
  {
  	int ret;
  	size_t retlen;
  
  	ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
  	if (ret) {
  		D1(printk(KERN_WARNING "mtd->read(0x%x bytes from 0x%x) returned %d
  ", len, ofs, ret));
  		return ret;
  	}
  	if (retlen < len) {
  		D1(printk(KERN_WARNING "Read at 0x%x gave only 0x%zx bytes
  ", ofs, retlen));
  		return -EIO;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
  	return 0;
  }
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
306
307
308
  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...
309
  	    && (!jeb->first_node || !ref_next(jeb->first_node)) )
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
310
311
312
313
314
315
316
317
318
319
320
321
322
323
  		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...
324
325
326
327
328
329
  #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...
330
  	uint32_t xid, version, totlen, crc;
68270995f   David Woodhouse   [JFFS2] Introduce...
331
  	int err;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
332
333
334
  
  	crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4);
  	if (crc != je32_to_cpu(rx->node_crc)) {
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
335
336
337
  		JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x
  ",
  			      ofs, je32_to_cpu(rx->node_crc), crc);
68270995f   David Woodhouse   [JFFS2] Introduce...
338
339
  		if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
  			return err;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
340
341
  		return 0;
  	}
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
342
343
  	xid = je32_to_cpu(rx->xid);
  	version = je32_to_cpu(rx->version);
8a13695cb   KaiGai Kohei   [JFFS2][XATTR] ri...
344
345
  	totlen = PAD(sizeof(struct jffs2_raw_xattr)
  			+ rx->name_len + 1 + je16_to_cpu(rx->value_len));
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
346
347
348
349
  	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...
350
351
  		if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
  			return err;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
352
353
  		return 0;
  	}
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
354
355
  	xd = jffs2_setup_xattr_datum(c, xid, version);
  	if (IS_ERR(xd))
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
356
  		return PTR_ERR(xd);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
357

c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
358
359
360
361
362
363
364
365
366
367
368
369
370
371
  	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...
372

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
373
374
375
376
377
378
379
380
381
382
383
384
385
  	if (jffs2_sum_active())
  		jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset);
  	dbg_xattr("scaning xdatum at %#08x (xid=%u, version=%u)
  ",
  		  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...
386
  	uint32_t crc;
68270995f   David Woodhouse   [JFFS2] Introduce...
387
  	int err;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
388
389
390
  
  	crc = crc32(0, rr, sizeof(*rr) - 4);
  	if (crc != je32_to_cpu(rr->node_crc)) {
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
391
392
393
  		JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x
  ",
  			      ofs, je32_to_cpu(rr->node_crc), crc);
68270995f   David Woodhouse   [JFFS2] Introduce...
394
395
  		if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen)))))
  			return err;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
396
397
398
399
  		return 0;
  	}
  
  	if (PAD(sizeof(struct jffs2_raw_xref)) != je32_to_cpu(rr->totlen)) {
89291a9d5   David Woodhouse   [JFFS2] Fix 64-bi...
400
401
  		JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%zd
  ",
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
402
403
  			      ofs, je32_to_cpu(rr->totlen),
  			      PAD(sizeof(struct jffs2_raw_xref)));
68270995f   David Woodhouse   [JFFS2] Introduce...
404
405
  		if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rr->totlen))))
  			return err;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
406
407
408
409
410
411
  		return 0;
  	}
  
  	ref = jffs2_alloc_xattr_ref();
  	if (!ref)
  		return -ENOMEM;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
412
  	/* BEFORE jffs2_build_xattr_subsystem() called, 
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
413
  	 * and AFTER xattr_ref is marked as a dead xref,
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
414
415
416
  	 * 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...
417
  	 * are exclusive. In a similar way, ref->next is temporarily
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
418
419
420
  	 * 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...
421
422
  	ref->ino = je32_to_cpu(rr->ino);
  	ref->xid = je32_to_cpu(rr->xid);
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
423
424
425
  	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...
426
427
  	ref->next = c->xref_temp;
  	c->xref_temp = ref;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
428

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

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
431
432
433
434
435
436
437
438
  	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 ...
439
440
  /* 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
441
  static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
9641b784f   David Woodhouse   [JFFS2] Optimise ...
442
  				  unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
444
  	struct jffs2_unknown_node *node;
  	struct jffs2_unknown_node crcnode;
41bdc602e   Joakim Tjernlund   jffs2: Reduce exc...
445
  	uint32_t ofs, prevofs, max_ofs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
447
448
  	uint32_t hdr_crc, buf_ofs, buf_len;
  	int err;
  	int noise = 0;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
449

2f82ce1eb   Andrew Victor   [JFFS2] Use a sin...
450
  #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
452
453
454
455
456
457
458
  	int cleanmarkerfound = 0;
  #endif
  
  	ofs = jeb->offset;
  	prevofs = jeb->offset - 1;
  
  	D1(printk(KERN_DEBUG "jffs2_scan_eraseblock(): Scanning block at 0x%x
  ", ofs));
2f82ce1eb   Andrew Victor   [JFFS2] Use a sin...
459
  #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
  	if (jffs2_cleanmarker_oob(c)) {
a7a6ace14   Artem Bityutskiy   [JFFS2] Use MTD_O...
461
  		int ret;
7086c19d0   Artem Bityutskiy   mtd: introduce mt...
462
  		if (mtd_block_isbad(c->mtd, jeb->offset))
a7a6ace14   Artem Bityutskiy   [JFFS2] Use MTD_O...
463
464
465
  			return BLK_STATE_BADBLOCK;
  
  		ret = jffs2_check_nand_cleanmarker(c, jeb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466
467
  		D2(printk(KERN_NOTICE "jffs_check_nand_cleanmarker returned %d
  ",ret));
a7a6ace14   Artem Bityutskiy   [JFFS2] Use MTD_O...
468

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
470
471
472
473
474
  		/* 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
475
476
477
478
  		default: 	return ret;
  		}
  	}
  #endif
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
479
480
  
  	if (jffs2_sum_active()) {
9641b784f   David Woodhouse   [JFFS2] Optimise ...
481
482
483
484
485
486
  		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...
487
  			sm = (void *)buf + c->sector_size - sizeof(*sm);
9641b784f   David Woodhouse   [JFFS2] Optimise ...
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
  			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;
  
  				/* 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...
528

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

9641b784f   David Woodhouse   [JFFS2] Optimise ...
533
534
  			if (buf_size && sumlen > buf_size)
  				kfree(sumptr);
3560160aa   David Woodhouse   [JFFS2] Fix memor...
535
536
537
538
539
540
  			/* 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...
541
  		}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
542
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543
544
545
  	buf_ofs = jeb->offset;
  
  	if (!buf_size) {
9641b784f   David Woodhouse   [JFFS2] Optimise ...
546
  		/* This is the XIP case -- we're reading _directly_ from the flash chip */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
  		buf_len = c->sector_size;
  	} else {
3be36675d   Andrew Victor   [JFFS2] Core chan...
549
  		buf_len = EMPTY_SCAN_SIZE(c->sector_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
551
552
553
  		err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);
  		if (err)
  			return err;
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
554

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
556
  	/* We temporarily use 'ofs' as a pointer into the buffer/jeb */
  	ofs = 0;
41bdc602e   Joakim Tjernlund   jffs2: Reduce exc...
557
558
559
  	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
560
  		ofs += 4;
41bdc602e   Joakim Tjernlund   jffs2: Reduce exc...
561
  	if (ofs == max_ofs) {
2f82ce1eb   Andrew Victor   [JFFS2] Use a sin...
562
  #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563
564
565
566
567
568
569
570
571
572
573
574
575
576
  		if (jffs2_cleanmarker_oob(c)) {
  			/* scan oob, take care of cleanmarker */
  			int ret = jffs2_check_oob_empty(c, jeb, cleanmarkerfound);
  			D2(printk(KERN_NOTICE "jffs2_check_oob_empty returned %d
  ",ret));
  			switch (ret) {
  			case 0:		return cleanmarkerfound ? BLK_STATE_CLEANMARKER : BLK_STATE_ALLFF;
  			case 1: 	return BLK_STATE_ALLDIRTY;
  			default: 	return ret;
  			}
  		}
  #endif
  		D1(printk(KERN_DEBUG "Block at 0x%08x is empty (erased)
  ", jeb->offset));
8f15fd55f   Andrew Victor   [JFFS2] Add suppo...
577
578
579
580
  		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
581
582
583
584
585
  	}
  	if (ofs) {
  		D1(printk(KERN_DEBUG "Free space at %08x ends at %08x
  ", jeb->offset,
  			  jeb->offset + ofs));
a6a8bef72   David Woodhouse   [JFFS2] Prealloca...
586
587
  		if ((err = jffs2_prealloc_raw_node_refs(c, jeb, 1)))
  			return err;
68270995f   David Woodhouse   [JFFS2] Introduce...
588
589
  		if ((err = jffs2_scan_dirty_space(c, jeb, ofs)))
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590
591
592
593
594
595
  	}
  
  	/* Now ofs is a complete physical flash offset as it always was... */
  	ofs += jeb->offset;
  
  	noise = 10;
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
596
597
  	dbg_summary("no summary found in jeb 0x%08x. Apply original scan.
  ",jeb->offset);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
598

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

2f785402f   David Woodhouse   [JFFS2] Reduce vi...
603
  		/* Make sure there are node refs available for use */
046b8b980   David Woodhouse   [JFFS2] Add 'jeb'...
604
  		err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
605
606
  		if (err)
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
607
608
609
610
611
612
613
614
615
616
617
  		cond_resched();
  
  		if (ofs & 3) {
  			printk(KERN_WARNING "Eep. ofs 0x%08x not word-aligned!
  ", ofs);
  			ofs = PAD(ofs);
  			continue;
  		}
  		if (ofs == prevofs) {
  			printk(KERN_WARNING "ofs 0x%08x has already been seen. Skipping
  ", ofs);
68270995f   David Woodhouse   [JFFS2] Introduce...
618
619
  			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
620
621
622
623
624
625
626
627
628
  			ofs += 4;
  			continue;
  		}
  		prevofs = ofs;
  
  		if (jeb->offset + c->sector_size < ofs + sizeof(*node)) {
  			D1(printk(KERN_DEBUG "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...
629
630
  			if ((err = jffs2_scan_dirty_space(c, jeb, (jeb->offset + c->sector_size)-ofs)))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
  			break;
  		}
  
  		if (buf_ofs + buf_len < ofs + sizeof(*node)) {
  			buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
  			D1(printk(KERN_DEBUG "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));
  			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 ...
649
  			uint32_t empty_start, scan_end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
651
652
  
  			empty_start = ofs;
  			ofs += 4;
c2aecda79   Joakim Tjernlund   [JFFS2] Speed up ...
653
  			scan_end = min_t(uint32_t, EMPTY_SCAN_SIZE(c->sector_size)/8, buf_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
655
656
657
658
  
  			D1(printk(KERN_DEBUG "Found empty flash at 0x%08x
  ", ofs));
  		more_empty:
  			inbuf_ofs = ofs - buf_ofs;
c2aecda79   Joakim Tjernlund   [JFFS2] Speed up ...
659
660
  			while (inbuf_ofs < scan_end) {
  				if (unlikely(*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
662
663
  					printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x
  ",
  					       empty_start, ofs);
68270995f   David Woodhouse   [JFFS2] Introduce...
664
665
  					if ((err = jffs2_scan_dirty_space(c, jeb, ofs-empty_start)))
  						return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
668
669
670
671
672
673
674
675
676
677
  					goto scan_more;
  				}
  
  				inbuf_ofs+=4;
  				ofs += 4;
  			}
  			/* Ran off end. */
  			D1(printk(KERN_DEBUG "Empty flash to end of buffer at 0x%08x
  ", ofs));
  
  			/* If we're only checking the beginning of a block with a cleanmarker,
  			   bail now */
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
678
  			if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) &&
99988f7bb   David Woodhouse   [JFFS2] Introduce...
679
  			    c->cleanmarker_size && !jeb->dirty_size && !ref_next(jeb->first_node)) {
3be36675d   Andrew Victor   [JFFS2] Core chan...
680
681
  				D1(printk(KERN_DEBUG "%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
682
683
  				return BLK_STATE_CLEANMARKER;
  			}
c2aecda79   Joakim Tjernlund   [JFFS2] Speed up ...
684
685
686
687
688
  			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
689
690
691
  			/* 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 ...
692
  				/* No more to read. Break out of main loop without marking
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
694
695
696
697
698
  				   this range of empty space as dirty (because it's not) */
  				D1(printk(KERN_DEBUG "Empty flash at %08x runs to end of block. Treating as free_space
  ",
  					  empty_start));
  				break;
  			}
c2aecda79   Joakim Tjernlund   [JFFS2] Speed up ...
699
700
  			/* point never reaches here */
  			scan_end = buf_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
702
703
704
705
706
707
708
709
710
711
712
  			D1(printk(KERN_DEBUG "Reading another 0x%x at 0x%08x
  ", buf_len, ofs));
  			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) {
  			printk(KERN_WARNING "Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?
  ", ofs);
68270995f   David Woodhouse   [JFFS2] Introduce...
713
714
  			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
716
717
718
719
720
  			ofs += 4;
  			continue;
  		}
  		if (je16_to_cpu(node->magic) == JFFS2_DIRTY_BITMASK) {
  			D1(printk(KERN_DEBUG "Dirty bitmask at 0x%08x
  ", ofs));
68270995f   David Woodhouse   [JFFS2] Introduce...
721
722
  			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723
724
725
726
727
728
729
730
  			ofs += 4;
  			continue;
  		}
  		if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) {
  			printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x
  ", ofs);
  			printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels
  ");
68270995f   David Woodhouse   [JFFS2] Introduce...
731
732
  			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
734
735
736
737
  			ofs += 4;
  			continue;
  		}
  		if (je16_to_cpu(node->magic) != JFFS2_MAGIC_BITMASK) {
  			/* OK. We're out of possibilities. Whinge and move on */
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
738
739
740
  			noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead
  ",
  				     JFFS2_MAGIC_BITMASK, ofs,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
  				     je16_to_cpu(node->magic));
68270995f   David Woodhouse   [JFFS2] Introduce...
742
743
  			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
745
746
747
748
749
750
751
752
753
754
755
756
  			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)) {
  			noisy_printk(&noise, "jffs2_scan_eraseblock(): Node at 0x%08x {0x%04x, 0x%04x, 0x%08x) has invalid CRC 0x%08x (calculated 0x%08x)
  ",
  				     ofs, je16_to_cpu(node->magic),
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
757
  				     je16_to_cpu(node->nodetype),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
758
759
760
  				     je32_to_cpu(node->totlen),
  				     je32_to_cpu(node->hdr_crc),
  				     hdr_crc);
68270995f   David Woodhouse   [JFFS2] Introduce...
761
762
  			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
764
765
  			ofs += 4;
  			continue;
  		}
0dec4c8bc   Joakim Tjernlund   [JFFS2] Better fi...
766
  		if (ofs + je32_to_cpu(node->totlen) > jeb->offset + c->sector_size) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
768
769
770
771
772
  			/* Eep. Node goes over the end of the erase block. */
  			printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block
  ",
  			       ofs, je32_to_cpu(node->totlen));
  			printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?
  ");
68270995f   David Woodhouse   [JFFS2] Introduce...
773
774
  			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
775
776
777
778
779
780
781
782
  			ofs += 4;
  			continue;
  		}
  
  		if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) {
  			/* Wheee. This is an obsoleted node */
  			D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping
  ", ofs));
68270995f   David Woodhouse   [JFFS2] Introduce...
783
784
  			if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
  			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);
  				D1(printk(KERN_DEBUG "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));
  				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...
802
  			err = jffs2_scan_inode_node(c, jeb, (void *)node, ofs, s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803
804
805
  			if (err) return err;
  			ofs += PAD(je32_to_cpu(node->totlen));
  			break;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
806

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
808
809
810
811
812
813
814
815
816
817
818
  		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);
  				D1(printk(KERN_DEBUG "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));
  				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...
819
  			err = jffs2_scan_dirent_node(c, jeb, (void *)node, ofs, s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
821
822
  			if (err) return err;
  			ofs += PAD(je32_to_cpu(node->totlen));
  			break;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
  #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);
  				D1(printk(KERN_DEBUG "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));
  				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);
  				D1(printk(KERN_DEBUG "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));
  				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
861
862
863
864
  		case JFFS2_NODETYPE_CLEANMARKER:
  			D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x
  ", ofs));
  			if (je32_to_cpu(node->totlen) != c->cleanmarker_size) {
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
865
866
  				printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867
  				       ofs, je32_to_cpu(node->totlen), c->cleanmarker_size);
68270995f   David Woodhouse   [JFFS2] Introduce...
868
869
  				if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))
  					return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
870
871
872
873
  				ofs += PAD(sizeof(struct jffs2_unknown_node));
  			} else if (jeb->first_node) {
  				printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)
  ", ofs, jeb->offset);
68270995f   David Woodhouse   [JFFS2] Introduce...
874
875
  				if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))
  					return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
876
877
  				ofs += PAD(sizeof(struct jffs2_unknown_node));
  			} else {
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
878
  				jffs2_link_node_ref(c, jeb, ofs | REF_NORMAL, c->cleanmarker_size, NULL);
f1f9671bd   David Woodhouse   [JFFS2] Introduce...
879

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880
881
882
883
884
  				ofs += PAD(c->cleanmarker_size);
  			}
  			break;
  
  		case JFFS2_NODETYPE_PADDING:
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
885
886
  			if (jffs2_sum_active())
  				jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen));
68270995f   David Woodhouse   [JFFS2] Introduce...
887
888
  			if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
  				return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
889
890
891
892
893
894
895
896
  			ofs += PAD(je32_to_cpu(node->totlen));
  			break;
  
  		default:
  			switch (je16_to_cpu(node->nodetype) & JFFS2_COMPAT_MASK) {
  			case JFFS2_FEATURE_ROCOMPAT:
  				printk(KERN_NOTICE "Read-only compatible feature node (0x%04x) found at offset 0x%08x
  ", je16_to_cpu(node->nodetype), ofs);
ef53cb02f   David Woodhouse   [JFFS2] Whitespac...
897
  				c->flags |= JFFS2_SB_FLAG_RO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
898
899
  				if (!(jffs2_is_readonly(c)))
  					return -EROFS;
68270995f   David Woodhouse   [JFFS2] Introduce...
900
901
  				if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
  					return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
902
903
904
905
906
907
908
909
910
911
912
  				ofs += PAD(je32_to_cpu(node->totlen));
  				break;
  
  			case JFFS2_FEATURE_INCOMPAT:
  				printk(KERN_NOTICE "Incompatible feature node (0x%04x) found at offset 0x%08x
  ", je16_to_cpu(node->nodetype), ofs);
  				return -EINVAL;
  
  			case JFFS2_FEATURE_RWCOMPAT_DELETE:
  				D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x
  ", je16_to_cpu(node->nodetype), ofs));
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
  				ofs += PAD(je32_to_cpu(node->totlen));
  				break;
6171586a7   David Woodhouse   [JFFS2] Correct h...
917
  			case JFFS2_FEATURE_RWCOMPAT_COPY: {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918
919
  				D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x
  ", je16_to_cpu(node->nodetype), ofs));
6171586a7   David Woodhouse   [JFFS2] Correct h...
920

2f785402f   David Woodhouse   [JFFS2] Reduce vi...
921
  				jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(node->totlen)), NULL);
6171586a7   David Woodhouse   [JFFS2] Correct h...
922
923
924
  
  				/* We can't summarise nodes we don't grok */
  				jffs2_sum_disable_collecting(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
925
926
  				ofs += PAD(je32_to_cpu(node->totlen));
  				break;
6171586a7   David Woodhouse   [JFFS2] Correct h...
927
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
928
929
930
  			}
  		}
  	}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
931
932
  	if (jffs2_sum_active()) {
  		if (PAD(s->sum_size + JFFS2_SUMMARY_FRAME_SIZE) > jeb->free_size) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
933
  			dbg_summary("There is not enough space for "
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
934
935
936
937
938
  				"summary information, disabling for this jeb!
  ");
  			jffs2_sum_disable_collecting(s);
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939

8b9e9fe8c   David Woodhouse   [JFFS2] Fix and i...
940
941
942
943
  	D1(printk(KERN_DEBUG "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));
  	
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
944
945
946
947
948
949
950
  	/* 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...
951
  	return jffs2_scan_classify_jeb(c, jeb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
952
  }
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
953
  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
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
  {
  	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) {
  		printk(KERN_NOTICE "jffs2_scan_make_inode_cache(): allocation of inode cache failed
  ");
  		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...
976
  		ic->pino_nlink = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
977
978
  	return ic;
  }
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
979
  static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
980
  				 struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
981
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
982
  	struct jffs2_inode_cache *ic;
53043002e   Thomas Gleixner   [JFFS2] check nod...
983
  	uint32_t crc, ino = je32_to_cpu(ri->ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
984
985
986
987
988
  
  	D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x
  ", ofs));
  
  	/* We do very little here now. Just check the ino# to which we should attribute
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
989
  	   this node; we can do all the CRC checking etc. later. There's a tradeoff here --
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
991
992
  	   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 ...
993
  	   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
994
995
  	   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...
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
  	/* Check the node CRC in any case. */
  	crc = crc32(0, ri, sizeof(*ri)-8);
  	if (crc != je32_to_cpu(ri->node_crc)) {
  		printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on "
  		       "node at 0x%08x: Read 0x%08x, calculated 0x%08x
  ",
  		       ofs, je32_to_cpu(ri->node_crc), crc);
  		/*
  		 * 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
1010
1011
  	ic = jffs2_get_ino_cache(c, ino);
  	if (!ic) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1012
  		ic = jffs2_scan_make_ino_cache(c, ino);
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
1013
  		if (!ic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1014
  			return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
1016
1017
  	}
  
  	/* Wheee. It worked */
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
1018
  	jffs2_link_node_ref(c, jeb, ofs | REF_UNCHECKED, PAD(je32_to_cpu(ri->totlen)), ic);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019

182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1020
1021
  	D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
1023
1024
1025
1026
  		  je32_to_cpu(ri->ino), je32_to_cpu(ri->version),
  		  je32_to_cpu(ri->offset),
  		  je32_to_cpu(ri->offset)+je32_to_cpu(ri->dsize)));
  
  	pseudo_random += je32_to_cpu(ri->version);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
1027
1028
1029
  	if (jffs2_sum_active()) {
  		jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1030
1031
  	return 0;
  }
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1032
  static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
1033
  				  struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1035
1036
  	struct jffs2_full_dirent *fd;
  	struct jffs2_inode_cache *ic;
b534e70cf   David Woodhouse   [JFFS2] Handle di...
1037
  	uint32_t checkedlen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1038
  	uint32_t crc;
68270995f   David Woodhouse   [JFFS2] Introduce...
1039
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
  
  	D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x
  ", ofs));
  
  	/* 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)) {
  		printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x
  ",
  		       ofs, je32_to_cpu(rd->node_crc), crc);
  		/* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
68270995f   David Woodhouse   [JFFS2] Introduce...
1053
1054
  		if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
  			return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1055
1056
1057
1058
  		return 0;
  	}
  
  	pseudo_random += je32_to_cpu(rd->version);
b534e70cf   David Woodhouse   [JFFS2] Handle di...
1059
1060
1061
1062
1063
1064
1065
1066
  	/* Should never happen. Did. (OLPC trac #4184)*/
  	checkedlen = strnlen(rd->name, rd->nsize);
  	if (checkedlen < rd->nsize) {
  		printk(KERN_ERR "Dirent at %08x has zeroes in name. Truncating to %d chars
  ",
  		       ofs, checkedlen);
  	}
  	fd = jffs2_alloc_full_dirent(checkedlen+1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1067
1068
1069
  	if (!fd) {
  		return -ENOMEM;
  	}
b534e70cf   David Woodhouse   [JFFS2] Handle di...
1070
1071
  	memcpy(&fd->name, rd->name, checkedlen);
  	fd->name[checkedlen] = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1072
1073
1074
1075
1076
  
  	crc = crc32(0, fd->name, rd->nsize);
  	if (crc != je32_to_cpu(rd->name_crc)) {
  		printk(KERN_NOTICE "jffs2_scan_dirent_node(): Name CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x
  ",
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1077
  		       ofs, je32_to_cpu(rd->name_crc), crc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1078
1079
1080
1081
1082
  		D1(printk(KERN_NOTICE "Name for which CRC failed is (now) '%s', ino #%d
  ", fd->name, je32_to_cpu(rd->ino)));
  		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...
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
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1087
1088
1089
  	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
1090
1091
  		return -ENOMEM;
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
1092

43dfa07fb   David Woodhouse   [JFFS2] Deletion ...
1093
1094
  	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
1095

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1096
1097
1098
  	fd->next = NULL;
  	fd->version = je32_to_cpu(rd->version);
  	fd->ino = je32_to_cpu(rd->ino);
b534e70cf   David Woodhouse   [JFFS2] Handle di...
1099
  	fd->nhash = full_name_hash(fd->name, checkedlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1100
  	fd->type = rd->type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1101
  	jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
1102
1103
1104
  	if (jffs2_sum_active()) {
  		jffs2_sum_add_dirent_mem(s, rd, ofs - jeb->offset);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
  	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
1140
  		rotate_list((&c->clean_list), rotateby);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1141
1142
1143
1144
1145
  	}
  
  	x = count_list(&c->very_dirty_list);
  	if (x) {
  		rotateby = pseudo_random % x;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1146
  		rotate_list((&c->very_dirty_list), rotateby);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1147
1148
1149
1150
1151
  	}
  
  	x = count_list(&c->dirty_list);
  	if (x) {
  		rotateby = pseudo_random % x;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1152
  		rotate_list((&c->dirty_list), rotateby);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1153
1154
1155
1156
1157
  	}
  
  	x = count_list(&c->erasable_list);
  	if (x) {
  		rotateby = pseudo_random % x;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1158
  		rotate_list((&c->erasable_list), rotateby);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1159
1160
1161
1162
  	}
  
  	if (c->nr_erasing_blocks) {
  		rotateby = pseudo_random % c->nr_erasing_blocks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1163
  		rotate_list((&c->erase_pending_list), rotateby);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1164
1165
1166
1167
  	}
  
  	if (c->nr_free_blocks) {
  		rotateby = pseudo_random % c->nr_free_blocks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1168
  		rotate_list((&c->free_list), rotateby);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1169
1170
  	}
  }