Blame view

fs/jffs2/summary.c 23.5 KB
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
1
2
3
  /*
   * JFFS2 -- Journalling Flash File System, Version 2.
   *
c00c310ea   David Woodhouse   [JFFS2] Tidy up l...
4
   * Copyright © 2004  Ferenc Havasi <havasi@inf.u-szeged.hu>,
ef53cb02f   David Woodhouse   [JFFS2] Whitespac...
5
6
7
8
   *		     Zoltan Sogor <weth@inf.u-szeged.hu>,
   *		     Patrik Kluba <pajko@halom.u-szeged.hu>,
   *		     University of Szeged, Hungary
   *	       2006  KaiGai Kohei <kaigai@ak.jp.nec.com>
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
9
10
11
   *
   * For licensing information, see the file 'LICENCE' in this directory.
   *
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
12
13
14
   */
  
  #include <linux/kernel.h>
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
15
16
17
18
19
20
21
22
23
24
25
  #include <linux/slab.h>
  #include <linux/mtd/mtd.h>
  #include <linux/pagemap.h>
  #include <linux/crc32.h>
  #include <linux/compiler.h>
  #include <linux/vmalloc.h>
  #include "nodelist.h"
  #include "debug.h"
  
  int jffs2_sum_init(struct jffs2_sb_info *c)
  {
0fed784b0   Roel Kluin   JFFS2: fix min/ma...
26
  	uint32_t sum_size = min_t(uint32_t, c->sector_size, MAX_SUMMARY_SIZE);
b7600dba6   David Woodhouse   [JFFS2] Fix alloc...
27

3d375d9e0   Yan Burman   [JFFS2] replace k...
28
  	c->summary = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
29
30
31
32
33
34
  
  	if (!c->summary) {
  		JFFS2_WARNING("Can't allocate memory for summary information!
  ");
  		return -ENOMEM;
  	}
b7600dba6   David Woodhouse   [JFFS2] Fix alloc...
35
  	c->summary->sum_buf = kmalloc(sum_size, GFP_KERNEL);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
36
37
38
39
  
  	if (!c->summary->sum_buf) {
  		JFFS2_WARNING("Can't allocate buffer for writing out summary information!
  ");
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
40
  		kfree(c->summary);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
41
42
  		return -ENOMEM;
  	}
d6e05edc5   Andreas Mohr   spelling fixes
43
44
  	dbg_summary("returned successfully
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
45
46
47
48
49
50
  
  	return 0;
  }
  
  void jffs2_sum_exit(struct jffs2_sb_info *c)
  {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
51
52
  	dbg_summary("called
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
53
54
  
  	jffs2_sum_disable_collecting(c->summary);
b7600dba6   David Woodhouse   [JFFS2] Fix alloc...
55
  	kfree(c->summary->sum_buf);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  	c->summary->sum_buf = NULL;
  
  	kfree(c->summary);
  	c->summary = NULL;
  }
  
  static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item)
  {
  	if (!s->sum_list_head)
  		s->sum_list_head = (union jffs2_sum_mem *) item;
  	if (s->sum_list_tail)
  		s->sum_list_tail->u.next = (union jffs2_sum_mem *) item;
  	s->sum_list_tail = (union jffs2_sum_mem *) item;
  
  	switch (je16_to_cpu(item->u.nodetype)) {
  		case JFFS2_NODETYPE_INODE:
  			s->sum_size += JFFS2_SUMMARY_INODE_SIZE;
  			s->sum_num++;
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
74
75
  			dbg_summary("inode (%u) added to summary
  ",
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
76
77
78
79
80
  						je32_to_cpu(item->i.inode));
  			break;
  		case JFFS2_NODETYPE_DIRENT:
  			s->sum_size += JFFS2_SUMMARY_DIRENT_SIZE(item->d.nsize);
  			s->sum_num++;
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
81
82
  			dbg_summary("dirent (%u) added to summary
  ",
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
83
84
  						je32_to_cpu(item->d.ino));
  			break;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  #ifdef CONFIG_JFFS2_FS_XATTR
  		case JFFS2_NODETYPE_XATTR:
  			s->sum_size += JFFS2_SUMMARY_XATTR_SIZE;
  			s->sum_num++;
  			dbg_summary("xattr (xid=%u, version=%u) added to summary
  ",
  				    je32_to_cpu(item->x.xid), je32_to_cpu(item->x.version));
  			break;
  		case JFFS2_NODETYPE_XREF:
  			s->sum_size += JFFS2_SUMMARY_XREF_SIZE;
  			s->sum_num++;
  			dbg_summary("xref added to summary
  ");
  			break;
  #endif
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
100
  		default:
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
101
102
  			JFFS2_WARNING("UNKNOWN node type %u
  ",
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
103
104
105
106
107
108
109
110
111
112
113
  					    je16_to_cpu(item->u.nodetype));
  			return 1;
  	}
  	return 0;
  }
  
  
  /* The following 3 functions are called from scan.c to collect summary info for not closed jeb */
  
  int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size)
  {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
114
115
  	dbg_summary("called with %u
  ", size);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
  	s->sum_padded += size;
  	return 0;
  }
  
  int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri,
  				uint32_t ofs)
  {
  	struct jffs2_sum_inode_mem *temp = kmalloc(sizeof(struct jffs2_sum_inode_mem), GFP_KERNEL);
  
  	if (!temp)
  		return -ENOMEM;
  
  	temp->nodetype = ri->nodetype;
  	temp->inode = ri->ino;
  	temp->version = ri->version;
25985edce   Lucas De Marchi   Fix common misspe...
131
  	temp->offset = cpu_to_je32(ofs); /* relative offset from the beginning of the jeb */
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  	temp->totlen = ri->totlen;
  	temp->next = NULL;
  
  	return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
  }
  
  int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd,
  				uint32_t ofs)
  {
  	struct jffs2_sum_dirent_mem *temp =
  		kmalloc(sizeof(struct jffs2_sum_dirent_mem) + rd->nsize, GFP_KERNEL);
  
  	if (!temp)
  		return -ENOMEM;
  
  	temp->nodetype = rd->nodetype;
  	temp->totlen = rd->totlen;
25985edce   Lucas De Marchi   Fix common misspe...
149
  	temp->offset = cpu_to_je32(ofs);	/* relative from the beginning of the jeb */
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
150
151
152
153
154
155
156
157
158
159
160
  	temp->pino = rd->pino;
  	temp->version = rd->version;
  	temp->ino = rd->ino;
  	temp->nsize = rd->nsize;
  	temp->type = rd->type;
  	temp->next = NULL;
  
  	memcpy(temp->name, rd->name, rd->nsize);
  
  	return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
  }
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
  #ifdef CONFIG_JFFS2_FS_XATTR
  int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs)
  {
  	struct jffs2_sum_xattr_mem *temp;
  
  	temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
  	if (!temp)
  		return -ENOMEM;
  
  	temp->nodetype = rx->nodetype;
  	temp->xid = rx->xid;
  	temp->version = rx->version;
  	temp->offset = cpu_to_je32(ofs);
  	temp->totlen = rx->totlen;
  	temp->next = NULL;
  
  	return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
  }
  
  int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs)
  {
  	struct jffs2_sum_xref_mem *temp;
  
  	temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
  	if (!temp)
  		return -ENOMEM;
  
  	temp->nodetype = rr->nodetype;
  	temp->offset = cpu_to_je32(ofs);
  	temp->next = NULL;
  
  	return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
  }
  #endif
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
195
196
197
198
199
200
201
  /* Cleanup every collected summary information */
  
  static void jffs2_sum_clean_collected(struct jffs2_summary *s)
  {
  	union jffs2_sum_mem *temp;
  
  	if (!s->sum_list_head) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
202
203
  		dbg_summary("already empty
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
204
205
206
207
208
209
210
211
212
213
214
215
216
  	}
  	while (s->sum_list_head) {
  		temp = s->sum_list_head;
  		s->sum_list_head = s->sum_list_head->u.next;
  		kfree(temp);
  	}
  	s->sum_list_tail = NULL;
  	s->sum_padded = 0;
  	s->sum_num = 0;
  }
  
  void jffs2_sum_reset_collected(struct jffs2_summary *s)
  {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
217
218
  	dbg_summary("called
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
219
220
221
222
223
224
  	jffs2_sum_clean_collected(s);
  	s->sum_size = 0;
  }
  
  void jffs2_sum_disable_collecting(struct jffs2_summary *s)
  {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
225
226
  	dbg_summary("called
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
227
228
229
  	jffs2_sum_clean_collected(s);
  	s->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
  }
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
230
  int jffs2_sum_is_disabled(struct jffs2_summary *s)
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
231
232
233
234
235
236
237
238
  {
  	return (s->sum_size == JFFS2_SUMMARY_NOSUM_SIZE);
  }
  
  /* Move the collected summary information into sb (called from scan.c) */
  
  void jffs2_sum_move_collected(struct jffs2_sb_info *c, struct jffs2_summary *s)
  {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
239
240
  	dbg_summary("oldsize=0x%x oldnum=%u => newsize=0x%x newnum=%u
  ",
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  				c->summary->sum_size, c->summary->sum_num,
  				s->sum_size, s->sum_num);
  
  	c->summary->sum_size = s->sum_size;
  	c->summary->sum_num = s->sum_num;
  	c->summary->sum_padded = s->sum_padded;
  	c->summary->sum_list_head = s->sum_list_head;
  	c->summary->sum_list_tail = s->sum_list_tail;
  
  	s->sum_list_head = s->sum_list_tail = NULL;
  }
  
  /* Called from wbuf.c to collect writed node info */
  
  int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
  				unsigned long count, uint32_t ofs)
  {
  	union jffs2_node_union *node;
  	struct jffs2_eraseblock *jeb;
27bea3275   Zoltan Sogor   [PATCH] JFFS2: SU...
260
261
262
263
264
  	if (c->summary->sum_size == JFFS2_SUMMARY_NOSUM_SIZE) {
  		dbg_summary("Summary is disabled for this jeb! Skipping summary info!
  ");
  		return 0;
  	}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
  	node = invecs[0].iov_base;
  	jeb = &c->blocks[ofs / c->sector_size];
  	ofs -= jeb->offset;
  
  	switch (je16_to_cpu(node->u.nodetype)) {
  		case JFFS2_NODETYPE_INODE: {
  			struct jffs2_sum_inode_mem *temp =
  				kmalloc(sizeof(struct jffs2_sum_inode_mem), GFP_KERNEL);
  
  			if (!temp)
  				goto no_mem;
  
  			temp->nodetype = node->i.nodetype;
  			temp->inode = node->i.ino;
  			temp->version = node->i.version;
  			temp->offset = cpu_to_je32(ofs);
  			temp->totlen = node->i.totlen;
  			temp->next = NULL;
  
  			return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
  		}
  
  		case JFFS2_NODETYPE_DIRENT: {
  			struct jffs2_sum_dirent_mem *temp =
  				kmalloc(sizeof(struct jffs2_sum_dirent_mem) + node->d.nsize, GFP_KERNEL);
  
  			if (!temp)
  				goto no_mem;
  
  			temp->nodetype = node->d.nodetype;
  			temp->totlen = node->d.totlen;
  			temp->offset = cpu_to_je32(ofs);
  			temp->pino = node->d.pino;
  			temp->version = node->d.version;
  			temp->ino = node->d.ino;
  			temp->nsize = node->d.nsize;
  			temp->type = node->d.type;
  			temp->next = NULL;
  
  			switch (count) {
  				case 1:
  					memcpy(temp->name,node->d.name,node->d.nsize);
  					break;
  
  				case 2:
  					memcpy(temp->name,invecs[1].iov_base,node->d.nsize);
  					break;
  
  				default:
  					BUG();	/* impossible count value */
  					break;
  			}
  
  			return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
  		}
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
320
321
322
  #ifdef CONFIG_JFFS2_FS_XATTR
  		case JFFS2_NODETYPE_XATTR: {
  			struct jffs2_sum_xattr_mem *temp;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
323
324
325
  			temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
  			if (!temp)
  				goto no_mem;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
326

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
327
328
329
330
331
332
333
334
335
336
337
  			temp->nodetype = node->x.nodetype;
  			temp->xid = node->x.xid;
  			temp->version = node->x.version;
  			temp->totlen = node->x.totlen;
  			temp->offset = cpu_to_je32(ofs);
  			temp->next = NULL;
  
  			return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
  		}
  		case JFFS2_NODETYPE_XREF: {
  			struct jffs2_sum_xref_mem *temp;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
338
339
340
341
342
343
344
345
346
347
  			temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
  			if (!temp)
  				goto no_mem;
  			temp->nodetype = node->r.nodetype;
  			temp->offset = cpu_to_je32(ofs);
  			temp->next = NULL;
  
  			return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
  		}
  #endif
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
348
  		case JFFS2_NODETYPE_PADDING:
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
349
350
  			dbg_summary("node PADDING
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
351
352
353
354
  			c->summary->sum_padded += je32_to_cpu(node->u.totlen);
  			break;
  
  		case JFFS2_NODETYPE_CLEANMARKER:
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
355
356
  			dbg_summary("node CLEANMARKER
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
357
358
359
  			break;
  
  		case JFFS2_NODETYPE_SUMMARY:
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
360
361
  			dbg_summary("node SUMMARY
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
  			break;
  
  		default:
  			/* If you implement a new node type you should also implement
  			   summary support for it or disable summary.
  			*/
  			BUG();
  			break;
  	}
  
  	return 0;
  
  no_mem:
  	JFFS2_WARNING("MEMORY ALLOCATION ERROR!");
  	return -ENOMEM;
  }
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
378
379
380
381
  static struct jffs2_raw_node_ref *sum_link_node_ref(struct jffs2_sb_info *c,
  						    struct jffs2_eraseblock *jeb,
  						    uint32_t ofs, uint32_t len,
  						    struct jffs2_inode_cache *ic)
49f11d407   David Woodhouse   [JFFS2] Mark gaps...
382
  {
49f11d407   David Woodhouse   [JFFS2] Mark gaps...
383
  	/* If there was a gap, mark it dirty */
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
384
385
386
  	if ((ofs & ~3) > c->sector_size - jeb->free_size) {
  		/* Ew. Summary doesn't actually tell us explicitly about dirty space */
  		jffs2_scan_dirty_space(c, jeb, (ofs & ~3) - (c->sector_size - jeb->free_size));
49f11d407   David Woodhouse   [JFFS2] Mark gaps...
387
  	}
49f11d407   David Woodhouse   [JFFS2] Mark gaps...
388

2f785402f   David Woodhouse   [JFFS2] Reduce vi...
389
  	return jffs2_link_node_ref(c, jeb, jeb->offset + ofs, len, ic);
49f11d407   David Woodhouse   [JFFS2] Mark gaps...
390
  }
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
391
392
393
394
  
  /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */
  
  static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
2bc9764c4   Ferenc Havasi   [JFFS2] Rename jf...
395
  				struct jffs2_raw_summary *summary, uint32_t *pseudo_random)
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
396
  {
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
397
398
399
400
  	struct jffs2_inode_cache *ic;
  	struct jffs2_full_dirent *fd;
  	void *sp;
  	int i, ino;
68270995f   David Woodhouse   [JFFS2] Introduce...
401
  	int err;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
402
403
404
405
  
  	sp = summary->sum;
  
  	for (i=0; i<je32_to_cpu(summary->sum_num); i++) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
406
407
  		dbg_summary("processing summary index %d
  ", i);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
408

a2166b933   Artem Bityutskiy   [JFFS2] Reschedul...
409
  		cond_resched();
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
410
  		/* Make sure there's a spare ref for dirty space */
046b8b980   David Woodhouse   [JFFS2] Add 'jeb'...
411
  		err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
412
413
  		if (err)
  			return err;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
414
415
416
417
418
419
  		switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) {
  			case JFFS2_NODETYPE_INODE: {
  				struct jffs2_sum_inode_flash *spi;
  				spi = sp;
  
  				ino = je32_to_cpu(spi->inode);
9167e0f81   David Woodhouse   [JFFS2] Remove st...
420
421
422
  				dbg_summary("Inode at 0x%08x-0x%08x
  ",
  					    jeb->offset + je32_to_cpu(spi->offset),
8b9e9fe8c   David Woodhouse   [JFFS2] Fix and i...
423
  					    jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spi->totlen));
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
424

e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
425
426
427
428
  				ic = jffs2_scan_make_ino_cache(c, ino);
  				if (!ic) {
  					JFFS2_NOTICE("scan_make_ino_cache failed
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
429
430
  					return -ENOMEM;
  				}
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
431
432
  				sum_link_node_ref(c, jeb, je32_to_cpu(spi->offset) | REF_UNCHECKED,
  						  PAD(je32_to_cpu(spi->totlen)), ic);
f1f9671bd   David Woodhouse   [JFFS2] Introduce...
433
434
  
  				*pseudo_random += je32_to_cpu(spi->version);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
435
436
437
438
439
440
441
442
  
  				sp += JFFS2_SUMMARY_INODE_SIZE;
  
  				break;
  			}
  
  			case JFFS2_NODETYPE_DIRENT: {
  				struct jffs2_sum_dirent_flash *spd;
b534e70cf   David Woodhouse   [JFFS2] Handle di...
443
  				int checkedlen;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
444
  				spd = sp;
8b9e9fe8c   David Woodhouse   [JFFS2] Fix and i...
445
446
  				dbg_summary("Dirent at 0x%08x-0x%08x
  ",
9167e0f81   David Woodhouse   [JFFS2] Remove st...
447
448
  					    jeb->offset + je32_to_cpu(spd->offset),
  					    jeb->offset + je32_to_cpu(spd->offset) + je32_to_cpu(spd->totlen));
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
449

b534e70cf   David Woodhouse   [JFFS2] Handle di...
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
  				/* This should never happen, but https://dev.laptop.org/ticket/4184 */
  				checkedlen = strnlen(spd->name, spd->nsize);
  				if (!checkedlen) {
  					printk(KERN_ERR "Dirent at %08x has zero at start of name. Aborting mount.
  ",
  					       jeb->offset + je32_to_cpu(spd->offset));
  					return -EIO;
  				}
  				if (checkedlen < spd->nsize) {
  					printk(KERN_ERR "Dirent at %08x has zeroes in name. Truncating to %d chars
  ",
  					       jeb->offset + je32_to_cpu(spd->offset), checkedlen);
  				}
  
  
  				fd = jffs2_alloc_full_dirent(checkedlen+1);
9641b784f   David Woodhouse   [JFFS2] Optimise ...
466
  				if (!fd)
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
467
  					return -ENOMEM;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
468

b534e70cf   David Woodhouse   [JFFS2] Handle di...
469
470
  				memcpy(&fd->name, spd->name, checkedlen);
  				fd->name[checkedlen] = 0;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
471

e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
472
473
474
  				ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino));
  				if (!ic) {
  					jffs2_free_full_dirent(fd);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
475
476
  					return -ENOMEM;
  				}
1046d8800   David Woodhouse   [JFFS2] Check CRC...
477
  				fd->raw = sum_link_node_ref(c, jeb,  je32_to_cpu(spd->offset) | REF_UNCHECKED,
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
478
  							    PAD(je32_to_cpu(spd->totlen)), ic);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
479

e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
480
481
482
  				fd->next = NULL;
  				fd->version = je32_to_cpu(spd->version);
  				fd->ino = je32_to_cpu(spd->ino);
b534e70cf   David Woodhouse   [JFFS2] Handle di...
483
  				fd->nhash = full_name_hash(fd->name, checkedlen);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
484
  				fd->type = spd->type;
f1f9671bd   David Woodhouse   [JFFS2] Introduce...
485

e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
486
487
488
489
490
491
492
493
  				jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
  
  				*pseudo_random += je32_to_cpu(spd->version);
  
  				sp += JFFS2_SUMMARY_DIRENT_SIZE(spd->nsize);
  
  				break;
  			}
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
494
495
496
497
  #ifdef CONFIG_JFFS2_FS_XATTR
  			case JFFS2_NODETYPE_XATTR: {
  				struct jffs2_xattr_datum *xd;
  				struct jffs2_sum_xattr_flash *spx;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
498
499
  
  				spx = (struct jffs2_sum_xattr_flash *)sp;
9167e0f81   David Woodhouse   [JFFS2] Remove st...
500
501
  				dbg_summary("xattr at %#08x-%#08x (xid=%u, version=%u)
  ", 
49f11d407   David Woodhouse   [JFFS2] Mark gaps...
502
  					    jeb->offset + je32_to_cpu(spx->offset),
9167e0f81   David Woodhouse   [JFFS2] Remove st...
503
  					    jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen),
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
504
  					    je32_to_cpu(spx->xid), je32_to_cpu(spx->version));
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
505

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
506
507
  				xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid),
  								je32_to_cpu(spx->version));
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
508
  				if (IS_ERR(xd))
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
509
  					return PTR_ERR(xd);
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
510
511
512
513
514
515
516
517
518
519
520
  				if (xd->version > je32_to_cpu(spx->version)) {
  					/* node is not the newest one */
  					struct jffs2_raw_node_ref *raw
  						= sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
  								    PAD(je32_to_cpu(spx->totlen)), NULL);
  					raw->next_in_ino = xd->node->next_in_ino;
  					xd->node->next_in_ino = raw;
  				} else {
  					xd->version = je32_to_cpu(spx->version);
  					sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
  							  PAD(je32_to_cpu(spx->totlen)), (void *)xd);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
521
  				}
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
522
  				*pseudo_random += je32_to_cpu(spx->xid);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
523
524
525
526
527
528
529
  				sp += JFFS2_SUMMARY_XATTR_SIZE;
  
  				break;
  			}
  			case JFFS2_NODETYPE_XREF: {
  				struct jffs2_xattr_ref *ref;
  				struct jffs2_sum_xref_flash *spr;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
530
531
  
  				spr = (struct jffs2_sum_xref_flash *)sp;
9167e0f81   David Woodhouse   [JFFS2] Remove st...
532
533
  				dbg_summary("xref at %#08x-%#08x
  ",
49f11d407   David Woodhouse   [JFFS2] Mark gaps...
534
  					    jeb->offset + je32_to_cpu(spr->offset),
9bfeb691e   David Woodhouse   [JFFS2] Switch to...
535
536
  					    jeb->offset + je32_to_cpu(spr->offset) + 
  					    (uint32_t)PAD(sizeof(struct jffs2_raw_xref)));
9167e0f81   David Woodhouse   [JFFS2] Remove st...
537

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
538
539
540
541
  				ref = jffs2_alloc_xattr_ref();
  				if (!ref) {
  					JFFS2_NOTICE("allocation of xattr_datum failed
  ");
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
542
543
  					return -ENOMEM;
  				}
8f2b6f49c   KaiGai Kohei   [JFFS2][XATTR] Re...
544
545
  				ref->next = c->xref_temp;
  				c->xref_temp = ref;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
546

c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
547
548
  				sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED,
  						  PAD(sizeof(struct jffs2_raw_xref)), (void *)ref);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
549

2f785402f   David Woodhouse   [JFFS2] Reduce vi...
550
  				*pseudo_random += ref->node->flash_offset;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
551
  				sp += JFFS2_SUMMARY_XREF_SIZE;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
552

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
553
554
555
  				break;
  			}
  #endif
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
556
  			default : {
7807ef7ba   David Woodhouse   [JFFS2] Fix summa...
557
558
559
560
561
562
563
564
565
566
567
568
569
  				uint16_t nodetype = je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype);
  				JFFS2_WARNING("Unsupported node type %x found in summary! Exiting...
  ", nodetype);
  				if ((nodetype & JFFS2_COMPAT_MASK) == JFFS2_FEATURE_INCOMPAT)
  					return -EIO;
  
  				/* For compatible node types, just fall back to the full scan */
  				c->wasted_size -= jeb->wasted_size;
  				c->free_size += c->sector_size - jeb->free_size;
  				c->used_size -= jeb->used_size;
  				c->dirty_size -= jeb->dirty_size;
  				jeb->wasted_size = jeb->used_size = jeb->dirty_size = 0;
  				jeb->free_size = c->sector_size;
c38c1b613   David Woodhouse   [JFFS2] jffs2_fre...
570
  				jffs2_free_jeb_node_refs(c, jeb);
7807ef7ba   David Woodhouse   [JFFS2] Fix summa...
571
  				return -ENOTRECOVERABLE;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
572
573
574
  			}
  		}
  	}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
575
576
577
578
  	return 0;
  }
  
  /* Process the summary node - called from jffs2_scan_eraseblock() */
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
579
  int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
9641b784f   David Woodhouse   [JFFS2] Optimise ...
580
581
  			   struct jffs2_raw_summary *summary, uint32_t sumsize,
  			   uint32_t *pseudo_random)
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
582
583
  {
  	struct jffs2_unknown_node crcnode;
9641b784f   David Woodhouse   [JFFS2] Optimise ...
584
  	int ret, ofs;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
585
  	uint32_t crc;
49f11d407   David Woodhouse   [JFFS2] Mark gaps...
586
  	ofs = c->sector_size - sumsize;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
587

733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
588
589
  	dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)
  ",
49f11d407   David Woodhouse   [JFFS2] Mark gaps...
590
  		    jeb->offset, jeb->offset + ofs, sumsize);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
591
592
593
594
595
596
597
598
  
  	/* OK, now check for node validity and CRC */
  	crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
  	crcnode.nodetype = cpu_to_je16(JFFS2_NODETYPE_SUMMARY);
  	crcnode.totlen = summary->totlen;
  	crc = crc32(0, &crcnode, sizeof(crcnode)-4);
  
  	if (je32_to_cpu(summary->hdr_crc) != crc) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
599
  		dbg_summary("Summary node header is corrupt (bad CRC or "
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
600
601
602
603
604
605
  				"no summary at all)
  ");
  		goto crc_err;
  	}
  
  	if (je32_to_cpu(summary->totlen) != sumsize) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
606
607
  		dbg_summary("Summary node is corrupt (wrong erasesize?)
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
608
609
  		goto crc_err;
  	}
2bc9764c4   Ferenc Havasi   [JFFS2] Rename jf...
610
  	crc = crc32(0, summary, sizeof(struct jffs2_raw_summary)-8);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
611
612
  
  	if (je32_to_cpu(summary->node_crc) != crc) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
613
614
  		dbg_summary("Summary node is corrupt (bad CRC)
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
615
616
  		goto crc_err;
  	}
2bc9764c4   Ferenc Havasi   [JFFS2] Rename jf...
617
  	crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_raw_summary));
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
618
619
  
  	if (je32_to_cpu(summary->sum_crc) != crc) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
620
621
  		dbg_summary("Summary node data is corrupt (bad CRC)
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
622
623
624
625
  		goto crc_err;
  	}
  
  	if ( je32_to_cpu(summary->cln_mkr) ) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
626
627
  		dbg_summary("Summary : CLEANMARKER node 
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
628

098a19811   David Woodhouse   [JFFS2] Prealloca...
629
630
631
  		ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
  		if (ret)
  			return ret;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
632
  		if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
633
634
  			dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x
  ",
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
635
  				je32_to_cpu(summary->cln_mkr), c->cleanmarker_size);
098a19811   David Woodhouse   [JFFS2] Prealloca...
636
637
  			if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
  				return ret;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
638
  		} else if (jeb->first_node) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
639
  			dbg_summary("CLEANMARKER node not first node in block "
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
640
641
  					"(0x%08x)
  ", jeb->offset);
098a19811   David Woodhouse   [JFFS2] Prealloca...
642
643
  			if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
  				return ret;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
644
  		} else {
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
645
646
  			jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL,
  					    je32_to_cpu(summary->cln_mkr), NULL);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
647
648
  		}
  	}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
649
  	ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random);
7807ef7ba   David Woodhouse   [JFFS2] Fix summa...
650
651
652
653
  	/* -ENOTRECOVERABLE isn't a fatal error -- it means we should do a full
  	   scan of this eraseblock. So return zero */
  	if (ret == -ENOTRECOVERABLE)
  		return 0;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
654
  	if (ret)
7807ef7ba   David Woodhouse   [JFFS2] Fix summa...
655
  		return ret;		/* real error */
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
656
657
  
  	/* for PARANOIA_CHECK */
046b8b980   David Woodhouse   [JFFS2] Add 'jeb'...
658
  	ret = jffs2_prealloc_raw_node_refs(c, jeb, 2);
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
659
660
  	if (ret)
  		return ret;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
661

f61579c33   David Woodhouse   [JFFS2] Correctly...
662
  	sum_link_node_ref(c, jeb, ofs | REF_NORMAL, sumsize, NULL);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
663

49f11d407   David Woodhouse   [JFFS2] Mark gaps...
664
665
666
667
668
669
670
671
672
  	if (unlikely(jeb->free_size)) {
  		JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?
  ",
  			      jeb->free_size, jeb->offset);
  		jeb->wasted_size += jeb->free_size;
  		c->wasted_size += jeb->free_size;
  		c->free_size -= jeb->free_size;
  		jeb->free_size = 0;
  	}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
673
674
675
676
677
678
679
680
681
682
683
684
685
  
  	return jffs2_scan_classify_jeb(c, jeb);
  
  crc_err:
  	JFFS2_WARNING("Summary node crc error, skipping summary information.
  ");
  
  	return 0;
  }
  
  /* Write summary data to flash - helper function for jffs2_sum_write_sumnode() */
  
  static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
b7600dba6   David Woodhouse   [JFFS2] Fix alloc...
686
  				uint32_t infosize, uint32_t datasize, int padsize)
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
687
  {
2bc9764c4   Ferenc Havasi   [JFFS2] Rename jf...
688
  	struct jffs2_raw_summary isum;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
689
690
691
  	union jffs2_sum_mem *temp;
  	struct jffs2_sum_marker *sm;
  	struct kvec vecs[2];
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
692
  	uint32_t sum_ofs;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
693
694
695
  	void *wpage;
  	int ret;
  	size_t retlen;
b7600dba6   David Woodhouse   [JFFS2] Fix alloc...
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
  	if (padsize + datasize > MAX_SUMMARY_SIZE) {
  		/* It won't fit in the buffer. Abort summary for this jeb */
  		jffs2_sum_disable_collecting(c->summary);
  
  		JFFS2_WARNING("Summary too big (%d data, %d pad) in eraseblock at %08x
  ",
  			      datasize, padsize, jeb->offset);
  		/* Non-fatal */
  		return 0;
  	}
  	/* Is there enough space for summary? */
  	if (padsize < 0) {
  		/* don't try to write out summary for this jeb */
  		jffs2_sum_disable_collecting(c->summary);
  
  		JFFS2_WARNING("Not enough space for summary, padsize = %d
  ",
  			      padsize);
  		/* Non-fatal */
  		return 0;
  	}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
717
718
719
720
721
722
723
724
725
726
727
728
729
  	memset(c->summary->sum_buf, 0xff, datasize);
  	memset(&isum, 0, sizeof(isum));
  
  	isum.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
  	isum.nodetype = cpu_to_je16(JFFS2_NODETYPE_SUMMARY);
  	isum.totlen = cpu_to_je32(infosize);
  	isum.hdr_crc = cpu_to_je32(crc32(0, &isum, sizeof(struct jffs2_unknown_node) - 4));
  	isum.padded = cpu_to_je32(c->summary->sum_padded);
  	isum.cln_mkr = cpu_to_je32(c->cleanmarker_size);
  	isum.sum_num = cpu_to_je32(c->summary->sum_num);
  	wpage = c->summary->sum_buf;
  
  	while (c->summary->sum_num) {
20ffdcb00   Jesper Juhl   [JFFS2] Remove nu...
730
  		temp = c->summary->sum_list_head;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
731

20ffdcb00   Jesper Juhl   [JFFS2] Remove nu...
732
  		switch (je16_to_cpu(temp->u.nodetype)) {
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
733
734
  			case JFFS2_NODETYPE_INODE: {
  				struct jffs2_sum_inode_flash *sino_ptr = wpage;
20ffdcb00   Jesper Juhl   [JFFS2] Remove nu...
735
736
737
738
739
  				sino_ptr->nodetype = temp->i.nodetype;
  				sino_ptr->inode = temp->i.inode;
  				sino_ptr->version = temp->i.version;
  				sino_ptr->offset = temp->i.offset;
  				sino_ptr->totlen = temp->i.totlen;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
740
741
742
743
744
745
746
747
  
  				wpage += JFFS2_SUMMARY_INODE_SIZE;
  
  				break;
  			}
  
  			case JFFS2_NODETYPE_DIRENT: {
  				struct jffs2_sum_dirent_flash *sdrnt_ptr = wpage;
20ffdcb00   Jesper Juhl   [JFFS2] Remove nu...
748
749
750
751
752
753
754
755
  				sdrnt_ptr->nodetype = temp->d.nodetype;
  				sdrnt_ptr->totlen = temp->d.totlen;
  				sdrnt_ptr->offset = temp->d.offset;
  				sdrnt_ptr->pino = temp->d.pino;
  				sdrnt_ptr->version = temp->d.version;
  				sdrnt_ptr->ino = temp->d.ino;
  				sdrnt_ptr->nsize = temp->d.nsize;
  				sdrnt_ptr->type = temp->d.type;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
756

20ffdcb00   Jesper Juhl   [JFFS2] Remove nu...
757
758
  				memcpy(sdrnt_ptr->name, temp->d.name,
  							temp->d.nsize);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
759

20ffdcb00   Jesper Juhl   [JFFS2] Remove nu...
760
  				wpage += JFFS2_SUMMARY_DIRENT_SIZE(temp->d.nsize);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
761
762
763
  
  				break;
  			}
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
  #ifdef CONFIG_JFFS2_FS_XATTR
  			case JFFS2_NODETYPE_XATTR: {
  				struct jffs2_sum_xattr_flash *sxattr_ptr = wpage;
  
  				temp = c->summary->sum_list_head;
  				sxattr_ptr->nodetype = temp->x.nodetype;
  				sxattr_ptr->xid = temp->x.xid;
  				sxattr_ptr->version = temp->x.version;
  				sxattr_ptr->offset = temp->x.offset;
  				sxattr_ptr->totlen = temp->x.totlen;
  
  				wpage += JFFS2_SUMMARY_XATTR_SIZE;
  				break;
  			}
  			case JFFS2_NODETYPE_XREF: {
  				struct jffs2_sum_xref_flash *sxref_ptr = wpage;
  
  				temp = c->summary->sum_list_head;
  				sxref_ptr->nodetype = temp->r.nodetype;
  				sxref_ptr->offset = temp->r.offset;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
784

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
785
786
787
788
  				wpage += JFFS2_SUMMARY_XREF_SIZE;
  				break;
  			}
  #endif
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
789
  			default : {
6171586a7   David Woodhouse   [JFFS2] Correct h...
790
791
792
793
794
795
796
797
798
  				if ((je16_to_cpu(temp->u.nodetype) & JFFS2_COMPAT_MASK)
  				    == JFFS2_FEATURE_RWCOMPAT_COPY) {
  					dbg_summary("Writing unknown RWCOMPAT_COPY node type %x
  ",
  						    je16_to_cpu(temp->u.nodetype));
  					jffs2_sum_disable_collecting(c->summary);
  				} else {
  					BUG();	/* unknown node in summary information */
  				}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
799
800
  			}
  		}
20ffdcb00   Jesper Juhl   [JFFS2] Remove nu...
801
  		c->summary->sum_list_head = temp->u.next;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
  		kfree(temp);
  
  		c->summary->sum_num--;
  	}
  
  	jffs2_sum_reset_collected(c->summary);
  
  	wpage += padsize;
  
  	sm = wpage;
  	sm->offset = cpu_to_je32(c->sector_size - jeb->free_size);
  	sm->magic = cpu_to_je32(JFFS2_SUM_MAGIC);
  
  	isum.sum_crc = cpu_to_je32(crc32(0, c->summary->sum_buf, datasize));
  	isum.node_crc = cpu_to_je32(crc32(0, &isum, sizeof(isum) - 8));
  
  	vecs[0].iov_base = &isum;
  	vecs[0].iov_len = sizeof(isum);
  	vecs[1].iov_base = c->summary->sum_buf;
  	vecs[1].iov_len = datasize;
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
822
  	sum_ofs = jeb->offset + c->sector_size - jeb->free_size;
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
823
824
  	dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x
  ",
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
825
  		    sum_ofs);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
826

2f785402f   David Woodhouse   [JFFS2] Reduce vi...
827
  	ret = jffs2_flash_writev(c, vecs, 2, sum_ofs, &retlen, 0);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
828
829
  
  	if (ret || (retlen != infosize)) {
010b06d6d   David Woodhouse   [JFFS2] Locking i...
830

c41ff6e5f   David Woodhouse   [JFFS2] Fix print...
831
832
  		JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd
  ",
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
833
  			      infosize, sum_ofs, ret, retlen);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
834

9bfeb691e   David Woodhouse   [JFFS2] Switch to...
835
836
837
838
839
840
  		if (retlen) {
  			/* Waste remaining space */
  			spin_lock(&c->erase_completion_lock);
  			jffs2_link_node_ref(c, jeb, sum_ofs | REF_OBSOLETE, infosize, NULL);
  			spin_unlock(&c->erase_completion_lock);
  		}
010b06d6d   David Woodhouse   [JFFS2] Locking i...
841

e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
842
  		c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
843

2f785402f   David Woodhouse   [JFFS2] Reduce vi...
844
  		return 0;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
845
  	}
010b06d6d   David Woodhouse   [JFFS2] Locking i...
846
  	spin_lock(&c->erase_completion_lock);
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
847
848
  	jffs2_link_node_ref(c, jeb, sum_ofs | REF_NORMAL, infosize, NULL);
  	spin_unlock(&c->erase_completion_lock);
010b06d6d   David Woodhouse   [JFFS2] Locking i...
849

e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
850
851
852
853
854
855
856
  	return 0;
  }
  
  /* Write out summary information - called from jffs2_do_reserve_space */
  
  int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
  {
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
857
  	int datasize, infosize, padsize;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
858
  	struct jffs2_eraseblock *jeb;
b7600dba6   David Woodhouse   [JFFS2] Fix alloc...
859
  	int ret = 0;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
860

733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
861
862
  	dbg_summary("called
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
863

2f785402f   David Woodhouse   [JFFS2] Reduce vi...
864
  	spin_unlock(&c->erase_completion_lock);
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
865

e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
866
  	jeb = c->nextblock;
046b8b980   David Woodhouse   [JFFS2] Add 'jeb'...
867
  	jffs2_prealloc_raw_node_refs(c, jeb, 1);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
868
869
870
871
872
873
874
875
  
  	if (!c->summary->sum_num || !c->summary->sum_list_head) {
  		JFFS2_WARNING("Empty summary info!!!
  ");
  		BUG();
  	}
  
  	datasize = c->summary->sum_size + sizeof(struct jffs2_sum_marker);
2bc9764c4   Ferenc Havasi   [JFFS2] Rename jf...
876
  	infosize = sizeof(struct jffs2_raw_summary) + datasize;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
877
  	padsize = jeb->free_size - infosize;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
878
  	infosize += padsize;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
879
  	datasize += padsize;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
880
  	ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize);
010b06d6d   David Woodhouse   [JFFS2] Locking i...
881
  	spin_lock(&c->erase_completion_lock);
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
882
  	return ret;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
883
  }