Blame view

fs/jffs2/summary.c 22.7 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
5
6
7
8
   * Copyright © 2004  Ferenc Havasi <havasi@inf.u-szeged.hu>,
   *                   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)
  {
3d375d9e0   Yan Burman   [JFFS2] replace k...
26
  	c->summary = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
27
28
29
30
31
32
  
  	if (!c->summary) {
  		JFFS2_WARNING("Can't allocate memory for summary information!
  ");
  		return -ENOMEM;
  	}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
33
34
35
36
37
  	c->summary->sum_buf = vmalloc(c->sector_size);
  
  	if (!c->summary->sum_buf) {
  		JFFS2_WARNING("Can't allocate buffer for writing out summary information!
  ");
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
38
  		kfree(c->summary);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
39
40
  		return -ENOMEM;
  	}
d6e05edc5   Andreas Mohr   spelling fixes
41
42
  	dbg_summary("returned successfully
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
43
44
45
46
47
48
  
  	return 0;
  }
  
  void jffs2_sum_exit(struct jffs2_sb_info *c)
  {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
49
50
  	dbg_summary("called
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  
  	jffs2_sum_disable_collecting(c->summary);
  
  	vfree(c->summary->sum_buf);
  	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...
73
74
  			dbg_summary("inode (%u) added to summary
  ",
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
75
76
77
78
79
  						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...
80
81
  			dbg_summary("dirent (%u) added to summary
  ",
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
82
83
  						je32_to_cpu(item->d.ino));
  			break;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  #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...
99
  		default:
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
100
101
  			JFFS2_WARNING("UNKNOWN node type %u
  ",
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
102
103
104
105
106
107
108
109
110
111
112
  					    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...
113
114
  	dbg_summary("called with %u
  ", size);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
  	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;
  	temp->offset = cpu_to_je32(ofs); /* relative offset from the begining of the jeb */
  	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;
  	temp->offset = cpu_to_je32(ofs);	/* relative from the begining of the jeb */
  	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...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  #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...
194
195
196
197
198
199
200
  /* 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...
201
202
  		dbg_summary("already empty
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
203
204
205
206
207
208
209
210
211
212
213
214
215
  	}
  	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...
216
217
  	dbg_summary("called
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
218
219
220
221
222
223
  	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...
224
225
  	dbg_summary("called
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
226
227
228
  	jffs2_sum_clean_collected(s);
  	s->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
  }
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
229
  int jffs2_sum_is_disabled(struct jffs2_summary *s)
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
230
231
232
233
234
235
236
237
  {
  	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...
238
239
  	dbg_summary("oldsize=0x%x oldnum=%u => newsize=0x%x newnum=%u
  ",
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
  				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...
259
260
261
262
263
  	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...
264
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
  	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...
319
320
321
  #ifdef CONFIG_JFFS2_FS_XATTR
  		case JFFS2_NODETYPE_XATTR: {
  			struct jffs2_sum_xattr_mem *temp;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
322
323
324
  			temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
  			if (!temp)
  				goto no_mem;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
325

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
326
327
328
329
330
331
332
333
334
335
336
  			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...
337
338
339
340
341
342
343
344
345
346
  			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...
347
  		case JFFS2_NODETYPE_PADDING:
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
348
349
  			dbg_summary("node PADDING
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
350
351
352
353
  			c->summary->sum_padded += je32_to_cpu(node->u.totlen);
  			break;
  
  		case JFFS2_NODETYPE_CLEANMARKER:
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
354
355
  			dbg_summary("node CLEANMARKER
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
356
357
358
  			break;
  
  		case JFFS2_NODETYPE_SUMMARY:
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
359
360
  			dbg_summary("node SUMMARY
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
  			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...
377
378
379
380
  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...
381
  {
49f11d407   David Woodhouse   [JFFS2] Mark gaps...
382
  	/* If there was a gap, mark it dirty */
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
383
384
385
  	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...
386
  	}
49f11d407   David Woodhouse   [JFFS2] Mark gaps...
387

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

a2166b933   Artem Bityutskiy   [JFFS2] Reschedul...
408
  		cond_resched();
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
409
  		/* Make sure there's a spare ref for dirty space */
046b8b980   David Woodhouse   [JFFS2] Add 'jeb'...
410
  		err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
411
412
  		if (err)
  			return err;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
413
414
415
416
417
418
  		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...
419
420
421
  				dbg_summary("Inode at 0x%08x-0x%08x
  ",
  					    jeb->offset + je32_to_cpu(spi->offset),
8b9e9fe8c   David Woodhouse   [JFFS2] Fix and i...
422
  					    jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spi->totlen));
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
423

e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
424
425
426
427
  				ic = jffs2_scan_make_ino_cache(c, ino);
  				if (!ic) {
  					JFFS2_NOTICE("scan_make_ino_cache failed
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
428
429
  					return -ENOMEM;
  				}
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
430
431
  				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...
432
433
  
  				*pseudo_random += je32_to_cpu(spi->version);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
434
435
436
437
438
439
440
441
442
  
  				sp += JFFS2_SUMMARY_INODE_SIZE;
  
  				break;
  			}
  
  			case JFFS2_NODETYPE_DIRENT: {
  				struct jffs2_sum_dirent_flash *spd;
  				spd = sp;
8b9e9fe8c   David Woodhouse   [JFFS2] Fix and i...
443
444
  				dbg_summary("Dirent at 0x%08x-0x%08x
  ",
9167e0f81   David Woodhouse   [JFFS2] Remove st...
445
446
  					    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...
447
448
  
  				fd = jffs2_alloc_full_dirent(spd->nsize+1);
9641b784f   David Woodhouse   [JFFS2] Optimise ...
449
  				if (!fd)
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
450
  					return -ENOMEM;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
451
452
453
  
  				memcpy(&fd->name, spd->name, spd->nsize);
  				fd->name[spd->nsize] = 0;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
454
455
456
  				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...
457
458
  					return -ENOMEM;
  				}
1046d8800   David Woodhouse   [JFFS2] Check CRC...
459
  				fd->raw = sum_link_node_ref(c, jeb,  je32_to_cpu(spd->offset) | REF_UNCHECKED,
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
460
  							    PAD(je32_to_cpu(spd->totlen)), ic);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
461

e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
462
463
464
465
466
  				fd->next = NULL;
  				fd->version = je32_to_cpu(spd->version);
  				fd->ino = je32_to_cpu(spd->ino);
  				fd->nhash = full_name_hash(fd->name, spd->nsize);
  				fd->type = spd->type;
f1f9671bd   David Woodhouse   [JFFS2] Introduce...
467

e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
468
469
470
471
472
473
474
475
  				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...
476
477
478
479
  #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...
480
481
  
  				spx = (struct jffs2_sum_xattr_flash *)sp;
9167e0f81   David Woodhouse   [JFFS2] Remove st...
482
483
  				dbg_summary("xattr at %#08x-%#08x (xid=%u, version=%u)
  ", 
49f11d407   David Woodhouse   [JFFS2] Mark gaps...
484
  					    jeb->offset + je32_to_cpu(spx->offset),
9167e0f81   David Woodhouse   [JFFS2] Remove st...
485
  					    jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen),
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
486
  					    je32_to_cpu(spx->xid), je32_to_cpu(spx->version));
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
487

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
488
489
  				xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid),
  								je32_to_cpu(spx->version));
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
490
  				if (IS_ERR(xd))
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
491
  					return PTR_ERR(xd);
c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
492
493
494
495
496
497
498
499
500
501
502
  				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...
503
  				}
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
504
  				*pseudo_random += je32_to_cpu(spx->xid);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
505
506
507
508
509
510
511
  				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...
512
513
  
  				spr = (struct jffs2_sum_xref_flash *)sp;
9167e0f81   David Woodhouse   [JFFS2] Remove st...
514
515
  				dbg_summary("xref at %#08x-%#08x
  ",
49f11d407   David Woodhouse   [JFFS2] Mark gaps...
516
  					    jeb->offset + je32_to_cpu(spr->offset),
9bfeb691e   David Woodhouse   [JFFS2] Switch to...
517
518
  					    jeb->offset + je32_to_cpu(spr->offset) + 
  					    (uint32_t)PAD(sizeof(struct jffs2_raw_xref)));
9167e0f81   David Woodhouse   [JFFS2] Remove st...
519

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
520
521
522
523
  				ref = jffs2_alloc_xattr_ref();
  				if (!ref) {
  					JFFS2_NOTICE("allocation of xattr_datum failed
  ");
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
524
525
  					return -ENOMEM;
  				}
8f2b6f49c   KaiGai Kohei   [JFFS2][XATTR] Re...
526
527
  				ref->next = c->xref_temp;
  				c->xref_temp = ref;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
528

c9f700f84   KaiGai Kohei   [JFFS2][XATTR] us...
529
530
  				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...
531

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

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
535
536
537
  				break;
  			}
  #endif
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
538
  			default : {
7807ef7ba   David Woodhouse   [JFFS2] Fix summa...
539
540
541
542
543
544
545
546
547
548
549
550
551
  				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...
552
  				jffs2_free_jeb_node_refs(c, jeb);
7807ef7ba   David Woodhouse   [JFFS2] Fix summa...
553
  				return -ENOTRECOVERABLE;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
554
555
556
  			}
  		}
  	}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
557
558
559
560
  	return 0;
  }
  
  /* Process the summary node - called from jffs2_scan_eraseblock() */
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
561
  int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
9641b784f   David Woodhouse   [JFFS2] Optimise ...
562
563
  			   struct jffs2_raw_summary *summary, uint32_t sumsize,
  			   uint32_t *pseudo_random)
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
564
565
  {
  	struct jffs2_unknown_node crcnode;
9641b784f   David Woodhouse   [JFFS2] Optimise ...
566
  	int ret, ofs;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
567
  	uint32_t crc;
49f11d407   David Woodhouse   [JFFS2] Mark gaps...
568
  	ofs = c->sector_size - sumsize;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
569

733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
570
571
  	dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)
  ",
49f11d407   David Woodhouse   [JFFS2] Mark gaps...
572
  		    jeb->offset, jeb->offset + ofs, sumsize);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
573
574
575
576
577
578
579
580
  
  	/* 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...
581
  		dbg_summary("Summary node header is corrupt (bad CRC or "
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
582
583
584
585
586
587
  				"no summary at all)
  ");
  		goto crc_err;
  	}
  
  	if (je32_to_cpu(summary->totlen) != sumsize) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
588
589
  		dbg_summary("Summary node is corrupt (wrong erasesize?)
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
590
591
  		goto crc_err;
  	}
2bc9764c4   Ferenc Havasi   [JFFS2] Rename jf...
592
  	crc = crc32(0, summary, sizeof(struct jffs2_raw_summary)-8);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
593
594
  
  	if (je32_to_cpu(summary->node_crc) != crc) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
595
596
  		dbg_summary("Summary node is corrupt (bad CRC)
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
597
598
  		goto crc_err;
  	}
2bc9764c4   Ferenc Havasi   [JFFS2] Rename jf...
599
  	crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_raw_summary));
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
600
601
  
  	if (je32_to_cpu(summary->sum_crc) != crc) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
602
603
  		dbg_summary("Summary node data is corrupt (bad CRC)
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
604
605
606
607
  		goto crc_err;
  	}
  
  	if ( je32_to_cpu(summary->cln_mkr) ) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
608
609
  		dbg_summary("Summary : CLEANMARKER node 
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
610

098a19811   David Woodhouse   [JFFS2] Prealloca...
611
612
613
  		ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
  		if (ret)
  			return ret;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
614
  		if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
615
616
  			dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x
  ",
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
617
  				je32_to_cpu(summary->cln_mkr), c->cleanmarker_size);
098a19811   David Woodhouse   [JFFS2] Prealloca...
618
619
  			if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
  				return ret;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
620
  		} else if (jeb->first_node) {
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
621
  			dbg_summary("CLEANMARKER node not first node in block "
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
622
623
  					"(0x%08x)
  ", jeb->offset);
098a19811   David Woodhouse   [JFFS2] Prealloca...
624
625
  			if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
  				return ret;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
626
  		} else {
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
627
628
  			jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL,
  					    je32_to_cpu(summary->cln_mkr), NULL);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
629
630
  		}
  	}
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
631
  	ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random);
7807ef7ba   David Woodhouse   [JFFS2] Fix summa...
632
633
634
635
  	/* -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...
636
  	if (ret)
7807ef7ba   David Woodhouse   [JFFS2] Fix summa...
637
  		return ret;		/* real error */
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
638
639
  
  	/* for PARANOIA_CHECK */
046b8b980   David Woodhouse   [JFFS2] Add 'jeb'...
640
  	ret = jffs2_prealloc_raw_node_refs(c, jeb, 2);
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
641
642
  	if (ret)
  		return ret;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
643

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

49f11d407   David Woodhouse   [JFFS2] Mark gaps...
646
647
648
649
650
651
652
653
654
  	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...
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
  
  	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,
  					uint32_t infosize, uint32_t datasize, int padsize)
  {
2bc9764c4   Ferenc Havasi   [JFFS2] Rename jf...
670
  	struct jffs2_raw_summary isum;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
671
672
673
  	union jffs2_sum_mem *temp;
  	struct jffs2_sum_marker *sm;
  	struct kvec vecs[2];
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
674
  	uint32_t sum_ofs;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
  	void *wpage;
  	int ret;
  	size_t retlen;
  
  	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...
692
  		temp = c->summary->sum_list_head;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
693

20ffdcb00   Jesper Juhl   [JFFS2] Remove nu...
694
  		switch (je16_to_cpu(temp->u.nodetype)) {
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
695
696
  			case JFFS2_NODETYPE_INODE: {
  				struct jffs2_sum_inode_flash *sino_ptr = wpage;
20ffdcb00   Jesper Juhl   [JFFS2] Remove nu...
697
698
699
700
701
  				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...
702
703
704
705
706
707
708
709
  
  				wpage += JFFS2_SUMMARY_INODE_SIZE;
  
  				break;
  			}
  
  			case JFFS2_NODETYPE_DIRENT: {
  				struct jffs2_sum_dirent_flash *sdrnt_ptr = wpage;
20ffdcb00   Jesper Juhl   [JFFS2] Remove nu...
710
711
712
713
714
715
716
717
  				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...
718

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

20ffdcb00   Jesper Juhl   [JFFS2] Remove nu...
722
  				wpage += JFFS2_SUMMARY_DIRENT_SIZE(temp->d.nsize);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
723
724
725
  
  				break;
  			}
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
  #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...
746

aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
747
748
749
750
  				wpage += JFFS2_SUMMARY_XREF_SIZE;
  				break;
  			}
  #endif
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
751
  			default : {
6171586a7   David Woodhouse   [JFFS2] Correct h...
752
753
754
755
756
757
758
759
760
  				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...
761
762
  			}
  		}
20ffdcb00   Jesper Juhl   [JFFS2] Remove nu...
763
  		c->summary->sum_list_head = temp->u.next;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
  		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...
784
  	sum_ofs = jeb->offset + c->sector_size - jeb->free_size;
733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
785
786
  	dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x
  ",
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
787
  		    sum_ofs);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
788

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

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

9bfeb691e   David Woodhouse   [JFFS2] Switch to...
797
798
799
800
801
802
  		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...
803

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

2f785402f   David Woodhouse   [JFFS2] Reduce vi...
806
  		return 0;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
807
  	}
010b06d6d   David Woodhouse   [JFFS2] Locking i...
808
  	spin_lock(&c->erase_completion_lock);
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
809
810
  	jffs2_link_node_ref(c, jeb, sum_ofs | REF_NORMAL, infosize, NULL);
  	spin_unlock(&c->erase_completion_lock);
010b06d6d   David Woodhouse   [JFFS2] Locking i...
811

e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
812
813
814
815
816
817
818
  	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...
819
  	int datasize, infosize, padsize;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
820
  	struct jffs2_eraseblock *jeb;
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
821
  	int ret;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
822

733802d97   Artem B. Bityutskiy   [JFFS2] Debug cod...
823
824
  	dbg_summary("called
  ");
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
825

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

e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
828
  	jeb = c->nextblock;
046b8b980   David Woodhouse   [JFFS2] Add 'jeb'...
829
  	jffs2_prealloc_raw_node_refs(c, jeb, 1);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
830
831
832
833
834
835
836
837
  
  	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...
838
  	infosize = sizeof(struct jffs2_raw_summary) + datasize;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
839
  	padsize = jeb->free_size - infosize;
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
840
  	infosize += padsize;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
841
842
843
844
845
846
847
848
849
  	datasize += padsize;
  
  	/* 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);
9bfeb691e   David Woodhouse   [JFFS2] Switch to...
850
  		spin_lock(&c->erase_completion_lock);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
851
852
853
854
  		return 0;
  	}
  
  	ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize);
010b06d6d   David Woodhouse   [JFFS2] Locking i...
855
  	spin_lock(&c->erase_completion_lock);
2f785402f   David Woodhouse   [JFFS2] Reduce vi...
856
  	return ret;
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
857
  }