xref: /openbmc/linux/fs/jffs2/summary.c (revision 9641b784)
1 /*
2  * JFFS2 -- Journalling Flash File System, Version 2.
3  *
4  * Copyright (C) 2004  Ferenc Havasi <havasi@inf.u-szeged.hu>,
5  *                     Zoltan Sogor <weth@inf.u-szeged.hu>,
6  *                     Patrik Kluba <pajko@halom.u-szeged.hu>,
7  *                     University of Szeged, Hungary
8  *
9  * For licensing information, see the file 'LICENCE' in this directory.
10  *
11  * $Id: summary.c,v 1.4 2005/09/26 11:37:21 havasi Exp $
12  *
13  */
14 
15 #include <linux/kernel.h>
16 #include <linux/sched.h>
17 #include <linux/slab.h>
18 #include <linux/mtd/mtd.h>
19 #include <linux/pagemap.h>
20 #include <linux/crc32.h>
21 #include <linux/compiler.h>
22 #include <linux/vmalloc.h>
23 #include "nodelist.h"
24 #include "debug.h"
25 
26 int jffs2_sum_init(struct jffs2_sb_info *c)
27 {
28 	c->summary = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
29 
30 	if (!c->summary) {
31 		JFFS2_WARNING("Can't allocate memory for summary information!\n");
32 		return -ENOMEM;
33 	}
34 
35 	memset(c->summary, 0, sizeof(struct jffs2_summary));
36 
37 	c->summary->sum_buf = vmalloc(c->sector_size);
38 
39 	if (!c->summary->sum_buf) {
40 		JFFS2_WARNING("Can't allocate buffer for writing out summary information!\n");
41 		kfree(c->summary);
42 		return -ENOMEM;
43 	}
44 
45 	dbg_summary("returned succesfully\n");
46 
47 	return 0;
48 }
49 
50 void jffs2_sum_exit(struct jffs2_sb_info *c)
51 {
52 	dbg_summary("called\n");
53 
54 	jffs2_sum_disable_collecting(c->summary);
55 
56 	vfree(c->summary->sum_buf);
57 	c->summary->sum_buf = NULL;
58 
59 	kfree(c->summary);
60 	c->summary = NULL;
61 }
62 
63 static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item)
64 {
65 	if (!s->sum_list_head)
66 		s->sum_list_head = (union jffs2_sum_mem *) item;
67 	if (s->sum_list_tail)
68 		s->sum_list_tail->u.next = (union jffs2_sum_mem *) item;
69 	s->sum_list_tail = (union jffs2_sum_mem *) item;
70 
71 	switch (je16_to_cpu(item->u.nodetype)) {
72 		case JFFS2_NODETYPE_INODE:
73 			s->sum_size += JFFS2_SUMMARY_INODE_SIZE;
74 			s->sum_num++;
75 			dbg_summary("inode (%u) added to summary\n",
76 						je32_to_cpu(item->i.inode));
77 			break;
78 		case JFFS2_NODETYPE_DIRENT:
79 			s->sum_size += JFFS2_SUMMARY_DIRENT_SIZE(item->d.nsize);
80 			s->sum_num++;
81 			dbg_summary("dirent (%u) added to summary\n",
82 						je32_to_cpu(item->d.ino));
83 			break;
84 		default:
85 			JFFS2_WARNING("UNKNOWN node type %u\n",
86 					    je16_to_cpu(item->u.nodetype));
87 			return 1;
88 	}
89 	return 0;
90 }
91 
92 
93 /* The following 3 functions are called from scan.c to collect summary info for not closed jeb */
94 
95 int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size)
96 {
97 	dbg_summary("called with %u\n", size);
98 	s->sum_padded += size;
99 	return 0;
100 }
101 
102 int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri,
103 				uint32_t ofs)
104 {
105 	struct jffs2_sum_inode_mem *temp = kmalloc(sizeof(struct jffs2_sum_inode_mem), GFP_KERNEL);
106 
107 	if (!temp)
108 		return -ENOMEM;
109 
110 	temp->nodetype = ri->nodetype;
111 	temp->inode = ri->ino;
112 	temp->version = ri->version;
113 	temp->offset = cpu_to_je32(ofs); /* relative offset from the begining of the jeb */
114 	temp->totlen = ri->totlen;
115 	temp->next = NULL;
116 
117 	return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
118 }
119 
120 int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd,
121 				uint32_t ofs)
122 {
123 	struct jffs2_sum_dirent_mem *temp =
124 		kmalloc(sizeof(struct jffs2_sum_dirent_mem) + rd->nsize, GFP_KERNEL);
125 
126 	if (!temp)
127 		return -ENOMEM;
128 
129 	temp->nodetype = rd->nodetype;
130 	temp->totlen = rd->totlen;
131 	temp->offset = cpu_to_je32(ofs);	/* relative from the begining of the jeb */
132 	temp->pino = rd->pino;
133 	temp->version = rd->version;
134 	temp->ino = rd->ino;
135 	temp->nsize = rd->nsize;
136 	temp->type = rd->type;
137 	temp->next = NULL;
138 
139 	memcpy(temp->name, rd->name, rd->nsize);
140 
141 	return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
142 }
143 
144 /* Cleanup every collected summary information */
145 
146 static void jffs2_sum_clean_collected(struct jffs2_summary *s)
147 {
148 	union jffs2_sum_mem *temp;
149 
150 	if (!s->sum_list_head) {
151 		dbg_summary("already empty\n");
152 	}
153 	while (s->sum_list_head) {
154 		temp = s->sum_list_head;
155 		s->sum_list_head = s->sum_list_head->u.next;
156 		kfree(temp);
157 	}
158 	s->sum_list_tail = NULL;
159 	s->sum_padded = 0;
160 	s->sum_num = 0;
161 }
162 
163 void jffs2_sum_reset_collected(struct jffs2_summary *s)
164 {
165 	dbg_summary("called\n");
166 	jffs2_sum_clean_collected(s);
167 	s->sum_size = 0;
168 }
169 
170 void jffs2_sum_disable_collecting(struct jffs2_summary *s)
171 {
172 	dbg_summary("called\n");
173 	jffs2_sum_clean_collected(s);
174 	s->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
175 }
176 
177 int jffs2_sum_is_disabled(struct jffs2_summary *s)
178 {
179 	return (s->sum_size == JFFS2_SUMMARY_NOSUM_SIZE);
180 }
181 
182 /* Move the collected summary information into sb (called from scan.c) */
183 
184 void jffs2_sum_move_collected(struct jffs2_sb_info *c, struct jffs2_summary *s)
185 {
186 	dbg_summary("oldsize=0x%x oldnum=%u => newsize=0x%x newnum=%u\n",
187 				c->summary->sum_size, c->summary->sum_num,
188 				s->sum_size, s->sum_num);
189 
190 	c->summary->sum_size = s->sum_size;
191 	c->summary->sum_num = s->sum_num;
192 	c->summary->sum_padded = s->sum_padded;
193 	c->summary->sum_list_head = s->sum_list_head;
194 	c->summary->sum_list_tail = s->sum_list_tail;
195 
196 	s->sum_list_head = s->sum_list_tail = NULL;
197 }
198 
199 /* Called from wbuf.c to collect writed node info */
200 
201 int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
202 				unsigned long count, uint32_t ofs)
203 {
204 	union jffs2_node_union *node;
205 	struct jffs2_eraseblock *jeb;
206 
207 	node = invecs[0].iov_base;
208 	jeb = &c->blocks[ofs / c->sector_size];
209 	ofs -= jeb->offset;
210 
211 	switch (je16_to_cpu(node->u.nodetype)) {
212 		case JFFS2_NODETYPE_INODE: {
213 			struct jffs2_sum_inode_mem *temp =
214 				kmalloc(sizeof(struct jffs2_sum_inode_mem), GFP_KERNEL);
215 
216 			if (!temp)
217 				goto no_mem;
218 
219 			temp->nodetype = node->i.nodetype;
220 			temp->inode = node->i.ino;
221 			temp->version = node->i.version;
222 			temp->offset = cpu_to_je32(ofs);
223 			temp->totlen = node->i.totlen;
224 			temp->next = NULL;
225 
226 			return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
227 		}
228 
229 		case JFFS2_NODETYPE_DIRENT: {
230 			struct jffs2_sum_dirent_mem *temp =
231 				kmalloc(sizeof(struct jffs2_sum_dirent_mem) + node->d.nsize, GFP_KERNEL);
232 
233 			if (!temp)
234 				goto no_mem;
235 
236 			temp->nodetype = node->d.nodetype;
237 			temp->totlen = node->d.totlen;
238 			temp->offset = cpu_to_je32(ofs);
239 			temp->pino = node->d.pino;
240 			temp->version = node->d.version;
241 			temp->ino = node->d.ino;
242 			temp->nsize = node->d.nsize;
243 			temp->type = node->d.type;
244 			temp->next = NULL;
245 
246 			switch (count) {
247 				case 1:
248 					memcpy(temp->name,node->d.name,node->d.nsize);
249 					break;
250 
251 				case 2:
252 					memcpy(temp->name,invecs[1].iov_base,node->d.nsize);
253 					break;
254 
255 				default:
256 					BUG();	/* impossible count value */
257 					break;
258 			}
259 
260 			return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
261 		}
262 
263 		case JFFS2_NODETYPE_PADDING:
264 			dbg_summary("node PADDING\n");
265 			c->summary->sum_padded += je32_to_cpu(node->u.totlen);
266 			break;
267 
268 		case JFFS2_NODETYPE_CLEANMARKER:
269 			dbg_summary("node CLEANMARKER\n");
270 			break;
271 
272 		case JFFS2_NODETYPE_SUMMARY:
273 			dbg_summary("node SUMMARY\n");
274 			break;
275 
276 		default:
277 			/* If you implement a new node type you should also implement
278 			   summary support for it or disable summary.
279 			*/
280 			BUG();
281 			break;
282 	}
283 
284 	return 0;
285 
286 no_mem:
287 	JFFS2_WARNING("MEMORY ALLOCATION ERROR!");
288 	return -ENOMEM;
289 }
290 
291 
292 /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */
293 
294 static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
295 				struct jffs2_raw_summary *summary, uint32_t *pseudo_random)
296 {
297 	struct jffs2_raw_node_ref *raw;
298 	struct jffs2_inode_cache *ic;
299 	struct jffs2_full_dirent *fd;
300 	void *sp;
301 	int i, ino;
302 
303 	sp = summary->sum;
304 
305 	for (i=0; i<je32_to_cpu(summary->sum_num); i++) {
306 		dbg_summary("processing summary index %d\n", i);
307 
308 		switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) {
309 			case JFFS2_NODETYPE_INODE: {
310 				struct jffs2_sum_inode_flash *spi;
311 				spi = sp;
312 
313 				ino = je32_to_cpu(spi->inode);
314 
315 				dbg_summary("Inode at 0x%08x\n",
316 							jeb->offset + je32_to_cpu(spi->offset));
317 
318 				raw = jffs2_alloc_raw_node_ref();
319 				if (!raw) {
320 					JFFS2_NOTICE("allocation of node reference failed\n");
321 					return -ENOMEM;
322 				}
323 
324 				ic = jffs2_scan_make_ino_cache(c, ino);
325 				if (!ic) {
326 					JFFS2_NOTICE("scan_make_ino_cache failed\n");
327 					jffs2_free_raw_node_ref(raw);
328 					return -ENOMEM;
329 				}
330 
331 				raw->flash_offset = (jeb->offset + je32_to_cpu(spi->offset)) | REF_UNCHECKED;
332 				raw->__totlen = PAD(je32_to_cpu(spi->totlen));
333 				raw->next_phys = NULL;
334 				raw->next_in_ino = ic->nodes;
335 
336 				ic->nodes = raw;
337 				if (!jeb->first_node)
338 					jeb->first_node = raw;
339 				if (jeb->last_node)
340 					jeb->last_node->next_phys = raw;
341 				jeb->last_node = raw;
342 				*pseudo_random += je32_to_cpu(spi->version);
343 
344 				UNCHECKED_SPACE(PAD(je32_to_cpu(spi->totlen)));
345 
346 				sp += JFFS2_SUMMARY_INODE_SIZE;
347 
348 				break;
349 			}
350 
351 			case JFFS2_NODETYPE_DIRENT: {
352 				struct jffs2_sum_dirent_flash *spd;
353 				spd = sp;
354 
355 				dbg_summary("Dirent at 0x%08x\n",
356 							jeb->offset + je32_to_cpu(spd->offset));
357 
358 				fd = jffs2_alloc_full_dirent(spd->nsize+1);
359 				if (!fd)
360 					return -ENOMEM;
361 
362 				memcpy(&fd->name, spd->name, spd->nsize);
363 				fd->name[spd->nsize] = 0;
364 
365 				raw = jffs2_alloc_raw_node_ref();
366 				if (!raw) {
367 					jffs2_free_full_dirent(fd);
368 					JFFS2_NOTICE("allocation of node reference failed\n");
369 					return -ENOMEM;
370 				}
371 
372 				ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino));
373 				if (!ic) {
374 					jffs2_free_full_dirent(fd);
375 					jffs2_free_raw_node_ref(raw);
376 					return -ENOMEM;
377 				}
378 
379 				raw->__totlen = PAD(je32_to_cpu(spd->totlen));
380 				raw->flash_offset = (jeb->offset + je32_to_cpu(spd->offset)) | REF_PRISTINE;
381 				raw->next_phys = NULL;
382 				raw->next_in_ino = ic->nodes;
383 				ic->nodes = raw;
384 				if (!jeb->first_node)
385 					jeb->first_node = raw;
386 				if (jeb->last_node)
387 					jeb->last_node->next_phys = raw;
388 				jeb->last_node = raw;
389 
390 				fd->raw = raw;
391 				fd->next = NULL;
392 				fd->version = je32_to_cpu(spd->version);
393 				fd->ino = je32_to_cpu(spd->ino);
394 				fd->nhash = full_name_hash(fd->name, spd->nsize);
395 				fd->type = spd->type;
396 				USED_SPACE(PAD(je32_to_cpu(spd->totlen)));
397 				jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
398 
399 				*pseudo_random += je32_to_cpu(spd->version);
400 
401 				sp += JFFS2_SUMMARY_DIRENT_SIZE(spd->nsize);
402 
403 				break;
404 			}
405 
406 			default : {
407 				JFFS2_WARNING("Unsupported node type found in summary! Exiting...");
408 				return -EIO;
409 			}
410 		}
411 	}
412 
413 	return 0;
414 }
415 
416 /* Process the summary node - called from jffs2_scan_eraseblock() */
417 int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
418 			   struct jffs2_raw_summary *summary, uint32_t sumsize,
419 			   uint32_t *pseudo_random)
420 {
421 	struct jffs2_unknown_node crcnode;
422 	struct jffs2_raw_node_ref *cache_ref;
423 	int ret, ofs;
424 	uint32_t crc;
425 
426 	ofs = jeb->offset + c->sector_size - sumsize;
427 
428 	dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n",
429 		    jeb->offset, ofs, sumsize);
430 
431 	/* OK, now check for node validity and CRC */
432 	crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
433 	crcnode.nodetype = cpu_to_je16(JFFS2_NODETYPE_SUMMARY);
434 	crcnode.totlen = summary->totlen;
435 	crc = crc32(0, &crcnode, sizeof(crcnode)-4);
436 
437 	if (je32_to_cpu(summary->hdr_crc) != crc) {
438 		dbg_summary("Summary node header is corrupt (bad CRC or "
439 				"no summary at all)\n");
440 		goto crc_err;
441 	}
442 
443 	if (je32_to_cpu(summary->totlen) != sumsize) {
444 		dbg_summary("Summary node is corrupt (wrong erasesize?)\n");
445 		goto crc_err;
446 	}
447 
448 	crc = crc32(0, summary, sizeof(struct jffs2_raw_summary)-8);
449 
450 	if (je32_to_cpu(summary->node_crc) != crc) {
451 		dbg_summary("Summary node is corrupt (bad CRC)\n");
452 		goto crc_err;
453 	}
454 
455 	crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_raw_summary));
456 
457 	if (je32_to_cpu(summary->sum_crc) != crc) {
458 		dbg_summary("Summary node data is corrupt (bad CRC)\n");
459 		goto crc_err;
460 	}
461 
462 	if ( je32_to_cpu(summary->cln_mkr) ) {
463 
464 		dbg_summary("Summary : CLEANMARKER node \n");
465 
466 		if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) {
467 			dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n",
468 				je32_to_cpu(summary->cln_mkr), c->cleanmarker_size);
469 			UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr)));
470 		} else if (jeb->first_node) {
471 			dbg_summary("CLEANMARKER node not first node in block "
472 					"(0x%08x)\n", jeb->offset);
473 			UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr)));
474 		} else {
475 			struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref();
476 
477 			if (!marker_ref) {
478 				JFFS2_NOTICE("Failed to allocate node ref for clean marker\n");
479 				return -ENOMEM;
480 			}
481 
482 			marker_ref->next_in_ino = NULL;
483 			marker_ref->next_phys = NULL;
484 			marker_ref->flash_offset = jeb->offset | REF_NORMAL;
485 			marker_ref->__totlen = je32_to_cpu(summary->cln_mkr);
486 			jeb->first_node = jeb->last_node = marker_ref;
487 
488 			USED_SPACE( PAD(je32_to_cpu(summary->cln_mkr)) );
489 		}
490 	}
491 
492 	if (je32_to_cpu(summary->padded)) {
493 		DIRTY_SPACE(je32_to_cpu(summary->padded));
494 	}
495 
496 	ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random);
497 	if (ret)
498 		return ret;
499 
500 	/* for PARANOIA_CHECK */
501 	cache_ref = jffs2_alloc_raw_node_ref();
502 
503 	if (!cache_ref) {
504 		JFFS2_NOTICE("Failed to allocate node ref for cache\n");
505 		return -ENOMEM;
506 	}
507 
508 	cache_ref->next_in_ino = NULL;
509 	cache_ref->next_phys = NULL;
510 	cache_ref->flash_offset = ofs | REF_NORMAL;
511 	cache_ref->__totlen = sumsize;
512 
513 	if (!jeb->first_node)
514 		jeb->first_node = cache_ref;
515 	if (jeb->last_node)
516 		jeb->last_node->next_phys = cache_ref;
517 	jeb->last_node = cache_ref;
518 
519 	USED_SPACE(sumsize);
520 
521 	jeb->wasted_size += jeb->free_size;
522 	c->wasted_size += jeb->free_size;
523 	c->free_size -= jeb->free_size;
524 	jeb->free_size = 0;
525 
526 	return jffs2_scan_classify_jeb(c, jeb);
527 
528 crc_err:
529 	JFFS2_WARNING("Summary node crc error, skipping summary information.\n");
530 
531 	return 0;
532 }
533 
534 /* Write summary data to flash - helper function for jffs2_sum_write_sumnode() */
535 
536 static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
537 					uint32_t infosize, uint32_t datasize, int padsize)
538 {
539 	struct jffs2_raw_summary isum;
540 	union jffs2_sum_mem *temp;
541 	struct jffs2_sum_marker *sm;
542 	struct kvec vecs[2];
543 	void *wpage;
544 	int ret;
545 	size_t retlen;
546 
547 	memset(c->summary->sum_buf, 0xff, datasize);
548 	memset(&isum, 0, sizeof(isum));
549 
550 	isum.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
551 	isum.nodetype = cpu_to_je16(JFFS2_NODETYPE_SUMMARY);
552 	isum.totlen = cpu_to_je32(infosize);
553 	isum.hdr_crc = cpu_to_je32(crc32(0, &isum, sizeof(struct jffs2_unknown_node) - 4));
554 	isum.padded = cpu_to_je32(c->summary->sum_padded);
555 	isum.cln_mkr = cpu_to_je32(c->cleanmarker_size);
556 	isum.sum_num = cpu_to_je32(c->summary->sum_num);
557 	wpage = c->summary->sum_buf;
558 
559 	while (c->summary->sum_num) {
560 		temp = c->summary->sum_list_head;
561 
562 		switch (je16_to_cpu(temp->u.nodetype)) {
563 			case JFFS2_NODETYPE_INODE: {
564 				struct jffs2_sum_inode_flash *sino_ptr = wpage;
565 
566 				sino_ptr->nodetype = temp->i.nodetype;
567 				sino_ptr->inode = temp->i.inode;
568 				sino_ptr->version = temp->i.version;
569 				sino_ptr->offset = temp->i.offset;
570 				sino_ptr->totlen = temp->i.totlen;
571 
572 				wpage += JFFS2_SUMMARY_INODE_SIZE;
573 
574 				break;
575 			}
576 
577 			case JFFS2_NODETYPE_DIRENT: {
578 				struct jffs2_sum_dirent_flash *sdrnt_ptr = wpage;
579 
580 				sdrnt_ptr->nodetype = temp->d.nodetype;
581 				sdrnt_ptr->totlen = temp->d.totlen;
582 				sdrnt_ptr->offset = temp->d.offset;
583 				sdrnt_ptr->pino = temp->d.pino;
584 				sdrnt_ptr->version = temp->d.version;
585 				sdrnt_ptr->ino = temp->d.ino;
586 				sdrnt_ptr->nsize = temp->d.nsize;
587 				sdrnt_ptr->type = temp->d.type;
588 
589 				memcpy(sdrnt_ptr->name, temp->d.name,
590 							temp->d.nsize);
591 
592 				wpage += JFFS2_SUMMARY_DIRENT_SIZE(temp->d.nsize);
593 
594 				break;
595 			}
596 
597 			default : {
598 				BUG();	/* unknown node in summary information */
599 			}
600 		}
601 
602 		c->summary->sum_list_head = temp->u.next;
603 		kfree(temp);
604 
605 		c->summary->sum_num--;
606 	}
607 
608 	jffs2_sum_reset_collected(c->summary);
609 
610 	wpage += padsize;
611 
612 	sm = wpage;
613 	sm->offset = cpu_to_je32(c->sector_size - jeb->free_size);
614 	sm->magic = cpu_to_je32(JFFS2_SUM_MAGIC);
615 
616 	isum.sum_crc = cpu_to_je32(crc32(0, c->summary->sum_buf, datasize));
617 	isum.node_crc = cpu_to_je32(crc32(0, &isum, sizeof(isum) - 8));
618 
619 	vecs[0].iov_base = &isum;
620 	vecs[0].iov_len = sizeof(isum);
621 	vecs[1].iov_base = c->summary->sum_buf;
622 	vecs[1].iov_len = datasize;
623 
624 	dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n",
625 			jeb->offset + c->sector_size - jeb->free_size);
626 
627 	spin_unlock(&c->erase_completion_lock);
628 	ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size -
629 				jeb->free_size, &retlen, 0);
630 	spin_lock(&c->erase_completion_lock);
631 
632 
633 	if (ret || (retlen != infosize)) {
634 		JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n",
635 			infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen);
636 
637 		c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
638 		WASTED_SPACE(infosize);
639 
640 		return 1;
641 	}
642 
643 	return 0;
644 }
645 
646 /* Write out summary information - called from jffs2_do_reserve_space */
647 
648 int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
649 {
650 	struct jffs2_raw_node_ref *summary_ref;
651 	int datasize, infosize, padsize, ret;
652 	struct jffs2_eraseblock *jeb;
653 
654 	dbg_summary("called\n");
655 
656 	jeb = c->nextblock;
657 
658 	if (!c->summary->sum_num || !c->summary->sum_list_head) {
659 		JFFS2_WARNING("Empty summary info!!!\n");
660 		BUG();
661 	}
662 
663 	datasize = c->summary->sum_size + sizeof(struct jffs2_sum_marker);
664 	infosize = sizeof(struct jffs2_raw_summary) + datasize;
665 	padsize = jeb->free_size - infosize;
666 	infosize += padsize;
667 	datasize += padsize;
668 
669 	/* Is there enough space for summary? */
670 	if (padsize < 0) {
671 		/* don't try to write out summary for this jeb */
672 		jffs2_sum_disable_collecting(c->summary);
673 
674 		JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize);
675 		return 0;
676 	}
677 
678 	ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize);
679 	if (ret)
680 		return 0; /* can't write out summary, block is marked as NOSUM_SIZE */
681 
682 	/* for ACCT_PARANOIA_CHECK */
683 	spin_unlock(&c->erase_completion_lock);
684 	summary_ref = jffs2_alloc_raw_node_ref();
685 	spin_lock(&c->erase_completion_lock);
686 
687 	if (!summary_ref) {
688 		JFFS2_NOTICE("Failed to allocate node ref for summary\n");
689 		return -ENOMEM;
690 	}
691 
692 	summary_ref->next_in_ino = NULL;
693 	summary_ref->next_phys = NULL;
694 	summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL;
695 	summary_ref->__totlen = infosize;
696 
697 	if (!jeb->first_node)
698 		jeb->first_node = summary_ref;
699 	if (jeb->last_node)
700 		jeb->last_node->next_phys = summary_ref;
701 	jeb->last_node = summary_ref;
702 
703 	USED_SPACE(infosize);
704 
705 	return 0;
706 }
707