aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/summary.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2/summary.c')
-rw-r--r--fs/jffs2/summary.c385
1 files changed, 287 insertions, 98 deletions
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 48293c197f13..1451732e1fa7 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -5,6 +5,7 @@
5 * Zoltan Sogor <weth@inf.u-szeged.hu>, 5 * Zoltan Sogor <weth@inf.u-szeged.hu>,
6 * Patrik Kluba <pajko@halom.u-szeged.hu>, 6 * Patrik Kluba <pajko@halom.u-szeged.hu>,
7 * University of Szeged, Hungary 7 * University of Szeged, Hungary
8 * 2005 KaiGai Kohei <kaigai@ak.jp.nec.com>
8 * 9 *
9 * For licensing information, see the file 'LICENCE' in this directory. 10 * For licensing information, see the file 'LICENCE' in this directory.
10 * 11 *
@@ -81,6 +82,19 @@ static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item)
81 dbg_summary("dirent (%u) added to summary\n", 82 dbg_summary("dirent (%u) added to summary\n",
82 je32_to_cpu(item->d.ino)); 83 je32_to_cpu(item->d.ino));
83 break; 84 break;
85#ifdef CONFIG_JFFS2_FS_XATTR
86 case JFFS2_NODETYPE_XATTR:
87 s->sum_size += JFFS2_SUMMARY_XATTR_SIZE;
88 s->sum_num++;
89 dbg_summary("xattr (xid=%u, version=%u) added to summary\n",
90 je32_to_cpu(item->x.xid), je32_to_cpu(item->x.version));
91 break;
92 case JFFS2_NODETYPE_XREF:
93 s->sum_size += JFFS2_SUMMARY_XREF_SIZE;
94 s->sum_num++;
95 dbg_summary("xref added to summary\n");
96 break;
97#endif
84 default: 98 default:
85 JFFS2_WARNING("UNKNOWN node type %u\n", 99 JFFS2_WARNING("UNKNOWN node type %u\n",
86 je16_to_cpu(item->u.nodetype)); 100 je16_to_cpu(item->u.nodetype));
@@ -141,6 +155,40 @@ int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *r
141 return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp); 155 return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
142} 156}
143 157
158#ifdef CONFIG_JFFS2_FS_XATTR
159int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs)
160{
161 struct jffs2_sum_xattr_mem *temp;
162
163 temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
164 if (!temp)
165 return -ENOMEM;
166
167 temp->nodetype = rx->nodetype;
168 temp->xid = rx->xid;
169 temp->version = rx->version;
170 temp->offset = cpu_to_je32(ofs);
171 temp->totlen = rx->totlen;
172 temp->next = NULL;
173
174 return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
175}
176
177int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs)
178{
179 struct jffs2_sum_xref_mem *temp;
180
181 temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
182 if (!temp)
183 return -ENOMEM;
184
185 temp->nodetype = rr->nodetype;
186 temp->offset = cpu_to_je32(ofs);
187 temp->next = NULL;
188
189 return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
190}
191#endif
144/* Cleanup every collected summary information */ 192/* Cleanup every collected summary information */
145 193
146static void jffs2_sum_clean_collected(struct jffs2_summary *s) 194static void jffs2_sum_clean_collected(struct jffs2_summary *s)
@@ -259,7 +307,40 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
259 307
260 return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp); 308 return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
261 } 309 }
310#ifdef CONFIG_JFFS2_FS_XATTR
311 case JFFS2_NODETYPE_XATTR: {
312 struct jffs2_sum_xattr_mem *temp;
313 if (je32_to_cpu(node->x.version) == 0xffffffff)
314 return 0;
315 temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
316 if (!temp)
317 goto no_mem;
318
319 temp->nodetype = node->x.nodetype;
320 temp->xid = node->x.xid;
321 temp->version = node->x.version;
322 temp->totlen = node->x.totlen;
323 temp->offset = cpu_to_je32(ofs);
324 temp->next = NULL;
262 325
326 return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
327 }
328 case JFFS2_NODETYPE_XREF: {
329 struct jffs2_sum_xref_mem *temp;
330
331 if (je32_to_cpu(node->r.ino) == 0xffffffff
332 && je32_to_cpu(node->r.xid) == 0xffffffff)
333 return 0;
334 temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
335 if (!temp)
336 goto no_mem;
337 temp->nodetype = node->r.nodetype;
338 temp->offset = cpu_to_je32(ofs);
339 temp->next = NULL;
340
341 return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
342 }
343#endif
263 case JFFS2_NODETYPE_PADDING: 344 case JFFS2_NODETYPE_PADDING:
264 dbg_summary("node PADDING\n"); 345 dbg_summary("node PADDING\n");
265 c->summary->sum_padded += je32_to_cpu(node->u.totlen); 346 c->summary->sum_padded += je32_to_cpu(node->u.totlen);
@@ -288,6 +369,23 @@ no_mem:
288 return -ENOMEM; 369 return -ENOMEM;
289} 370}
290 371
372static struct jffs2_raw_node_ref *alloc_ref_at(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
373 uint32_t offset)
374{
375 struct jffs2_raw_node_ref *ref;
376 /* If there was a gap, mark it dirty */
377 if (offset > c->sector_size - jeb->free_size) {
378 int ret = jffs2_scan_dirty_space(c, jeb, offset - (c->sector_size - jeb->free_size));
379 if (ret)
380 return NULL;
381 }
382 ref = jffs2_alloc_raw_node_ref();
383 if (!ref)
384 return NULL;
385
386 ref->flash_offset = jeb->offset + offset;
387 return ref;
388}
291 389
292/* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ 390/* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */
293 391
@@ -299,6 +397,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
299 struct jffs2_full_dirent *fd; 397 struct jffs2_full_dirent *fd;
300 void *sp; 398 void *sp;
301 int i, ino; 399 int i, ino;
400 int err;
302 401
303 sp = summary->sum; 402 sp = summary->sum;
304 403
@@ -312,13 +411,13 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
312 411
313 ino = je32_to_cpu(spi->inode); 412 ino = je32_to_cpu(spi->inode);
314 413
315 dbg_summary("Inode at 0x%08x\n", 414 dbg_summary("Inode at 0x%08x-0x%08x\n",
316 jeb->offset + je32_to_cpu(spi->offset)); 415 jeb->offset + je32_to_cpu(spi->offset),
416 jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spu->totlen));
317 417
318 raw = jffs2_alloc_raw_node_ref(); 418 raw = alloc_ref_at(c, jeb, je32_to_cpu(spi->offset));
319 if (!raw) { 419 if (!raw) {
320 JFFS2_NOTICE("allocation of node reference failed\n"); 420 JFFS2_NOTICE("allocation of node reference failed\n");
321 kfree(summary);
322 return -ENOMEM; 421 return -ENOMEM;
323 } 422 }
324 423
@@ -326,24 +425,17 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
326 if (!ic) { 425 if (!ic) {
327 JFFS2_NOTICE("scan_make_ino_cache failed\n"); 426 JFFS2_NOTICE("scan_make_ino_cache failed\n");
328 jffs2_free_raw_node_ref(raw); 427 jffs2_free_raw_node_ref(raw);
329 kfree(summary);
330 return -ENOMEM; 428 return -ENOMEM;
331 } 429 }
332 430
333 raw->flash_offset = (jeb->offset + je32_to_cpu(spi->offset)) | REF_UNCHECKED; 431 raw->flash_offset |= REF_UNCHECKED;
334 raw->__totlen = PAD(je32_to_cpu(spi->totlen));
335 raw->next_phys = NULL;
336 raw->next_in_ino = ic->nodes;
337 432
433 raw->next_in_ino = ic->nodes;
338 ic->nodes = raw; 434 ic->nodes = raw;
339 if (!jeb->first_node)
340 jeb->first_node = raw;
341 if (jeb->last_node)
342 jeb->last_node->next_phys = raw;
343 jeb->last_node = raw;
344 *pseudo_random += je32_to_cpu(spi->version);
345 435
346 UNCHECKED_SPACE(PAD(je32_to_cpu(spi->totlen))); 436 jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spi->totlen)));
437
438 *pseudo_random += je32_to_cpu(spi->version);
347 439
348 sp += JFFS2_SUMMARY_INODE_SIZE; 440 sp += JFFS2_SUMMARY_INODE_SIZE;
349 441
@@ -355,22 +447,21 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
355 spd = sp; 447 spd = sp;
356 448
357 dbg_summary("Dirent at 0x%08x\n", 449 dbg_summary("Dirent at 0x%08x\n",
358 jeb->offset + je32_to_cpu(spd->offset)); 450 jeb->offset + je32_to_cpu(spd->offset),
451 jeb->offset + je32_to_cpu(spd->offset) + je32_to_cpu(spd->totlen));
452
359 453
360 fd = jffs2_alloc_full_dirent(spd->nsize+1); 454 fd = jffs2_alloc_full_dirent(spd->nsize+1);
361 if (!fd) { 455 if (!fd)
362 kfree(summary);
363 return -ENOMEM; 456 return -ENOMEM;
364 }
365 457
366 memcpy(&fd->name, spd->name, spd->nsize); 458 memcpy(&fd->name, spd->name, spd->nsize);
367 fd->name[spd->nsize] = 0; 459 fd->name[spd->nsize] = 0;
368 460
369 raw = jffs2_alloc_raw_node_ref(); 461 raw = alloc_ref_at(c, jeb, je32_to_cpu(spd->offset));
370 if (!raw) { 462 if (!raw) {
371 jffs2_free_full_dirent(fd); 463 jffs2_free_full_dirent(fd);
372 JFFS2_NOTICE("allocation of node reference failed\n"); 464 JFFS2_NOTICE("allocation of node reference failed\n");
373 kfree(summary);
374 return -ENOMEM; 465 return -ENOMEM;
375 } 466 }
376 467
@@ -378,20 +469,14 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
378 if (!ic) { 469 if (!ic) {
379 jffs2_free_full_dirent(fd); 470 jffs2_free_full_dirent(fd);
380 jffs2_free_raw_node_ref(raw); 471 jffs2_free_raw_node_ref(raw);
381 kfree(summary);
382 return -ENOMEM; 472 return -ENOMEM;
383 } 473 }
384 474
385 raw->__totlen = PAD(je32_to_cpu(spd->totlen)); 475 raw->flash_offset |= REF_PRISTINE;
386 raw->flash_offset = (jeb->offset + je32_to_cpu(spd->offset)) | REF_PRISTINE;
387 raw->next_phys = NULL;
388 raw->next_in_ino = ic->nodes; 476 raw->next_in_ino = ic->nodes;
389 ic->nodes = raw; 477 ic->nodes = raw;
390 if (!jeb->first_node) 478
391 jeb->first_node = raw; 479 jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spd->totlen)));
392 if (jeb->last_node)
393 jeb->last_node->next_phys = raw;
394 jeb->last_node = raw;
395 480
396 fd->raw = raw; 481 fd->raw = raw;
397 fd->next = NULL; 482 fd->next = NULL;
@@ -399,7 +484,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
399 fd->ino = je32_to_cpu(spd->ino); 484 fd->ino = je32_to_cpu(spd->ino);
400 fd->nhash = full_name_hash(fd->name, spd->nsize); 485 fd->nhash = full_name_hash(fd->name, spd->nsize);
401 fd->type = spd->type; 486 fd->type = spd->type;
402 USED_SPACE(PAD(je32_to_cpu(spd->totlen))); 487
403 jffs2_add_fd_to_list(c, fd, &ic->scan_dents); 488 jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
404 489
405 *pseudo_random += je32_to_cpu(spd->version); 490 *pseudo_random += je32_to_cpu(spd->version);
@@ -408,48 +493,122 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
408 493
409 break; 494 break;
410 } 495 }
496#ifdef CONFIG_JFFS2_FS_XATTR
497 case JFFS2_NODETYPE_XATTR: {
498 struct jffs2_xattr_datum *xd;
499 struct jffs2_sum_xattr_flash *spx;
500
501 spx = (struct jffs2_sum_xattr_flash *)sp;
502 dbg_summary("xattr at %#08x-%#08x (xid=%u, version=%u)\n",
503 jeb->offset + je32_to_cpu(spx->offset),
504 jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen),
505 je32_to_cpu(spx->xid), je32_to_cpu(spx->version));
506 raw = alloc_ref_at(c, jeb, je32_to_cpu(spx->offset));
507 if (!raw) {
508 JFFS2_NOTICE("allocation of node reference failed\n");
509 return -ENOMEM;
510 }
511 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid),
512 je32_to_cpu(spx->version));
513 if (IS_ERR(xd)) {
514 jffs2_free_raw_node_ref(raw);
515 if (PTR_ERR(xd) == -EEXIST) {
516 /* a newer version of xd exists */
517 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen))))
518 return err;
519 sp += JFFS2_SUMMARY_XATTR_SIZE;
520 break;
521 }
522 JFFS2_NOTICE("allocation of xattr_datum failed\n");
523 return PTR_ERR(xd);
524 }
525 xd->node = raw;
526
527 raw->flash_offset |= REF_UNCHECKED;
528 raw->next_in_ino = (void *)xd;
529
530 jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spx->totlen)));
531
532 *pseudo_random += je32_to_cpu(spx->xid);
533 sp += JFFS2_SUMMARY_XATTR_SIZE;
534
535 break;
536 }
537 case JFFS2_NODETYPE_XREF: {
538 struct jffs2_xattr_ref *ref;
539 struct jffs2_sum_xref_flash *spr;
540
541 spr = (struct jffs2_sum_xref_flash *)sp;
542 dbg_summary("xref at %#08x-%#08x\n",
543 jeb->offset + je32_to_cpu(spr->offset),
544 jeb->offset + je32_to_cpu(spr->offset) + PAD(sizeof(struct jffs2_raw_xref)));
545
546 raw = alloc_ref_at(c, jeb, je32_to_cpu(spr->offset));
547 if (!raw) {
548 JFFS2_NOTICE("allocation of node reference failed\n");
549 return -ENOMEM;
550 }
551 ref = jffs2_alloc_xattr_ref();
552 if (!ref) {
553 JFFS2_NOTICE("allocation of xattr_datum failed\n");
554 jffs2_free_raw_node_ref(raw);
555 return -ENOMEM;
556 }
557 ref->ino = 0xfffffffe;
558 ref->xid = 0xfffffffd;
559 ref->node = raw;
560 ref->next = c->xref_temp;
561 c->xref_temp = ref;
562
563 raw->flash_offset |= REF_UNCHECKED;
564 raw->next_in_ino = (void *)ref;
411 565
566 jffs2_link_node_ref(c, jeb, raw, PAD(sizeof(struct jffs2_raw_xref)));
567
568 *pseudo_random += raw->flash_offset;
569 sp += JFFS2_SUMMARY_XREF_SIZE;
570
571 break;
572 }
573#endif
412 default : { 574 default : {
413 JFFS2_WARNING("Unsupported node type found in summary! Exiting..."); 575 uint16_t nodetype = je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype);
414 kfree(summary); 576 JFFS2_WARNING("Unsupported node type %x found in summary! Exiting...\n", nodetype);
415 return -EIO; 577 if ((nodetype & JFFS2_COMPAT_MASK) == JFFS2_FEATURE_INCOMPAT)
578 return -EIO;
579
580 /* For compatible node types, just fall back to the full scan */
581 c->wasted_size -= jeb->wasted_size;
582 c->free_size += c->sector_size - jeb->free_size;
583 c->used_size -= jeb->used_size;
584 c->dirty_size -= jeb->dirty_size;
585 jeb->wasted_size = jeb->used_size = jeb->dirty_size = 0;
586 jeb->free_size = c->sector_size;
587
588 jffs2_free_all_node_refs(c, jeb);
589 return -ENOTRECOVERABLE;
416 } 590 }
417 } 591 }
418 } 592 }
419 593
420 kfree(summary);
421 return 0; 594 return 0;
422} 595}
423 596
424/* Process the summary node - called from jffs2_scan_eraseblock() */ 597/* Process the summary node - called from jffs2_scan_eraseblock() */
425
426int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 598int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
427 uint32_t ofs, uint32_t *pseudo_random) 599 struct jffs2_raw_summary *summary, uint32_t sumsize,
600 uint32_t *pseudo_random)
428{ 601{
429 struct jffs2_unknown_node crcnode; 602 struct jffs2_unknown_node crcnode;
430 struct jffs2_raw_node_ref *cache_ref; 603 struct jffs2_raw_node_ref *cache_ref;
431 struct jffs2_raw_summary *summary; 604 int ret, ofs;
432 int ret, sumsize;
433 uint32_t crc; 605 uint32_t crc;
606 int err;
434 607
435 sumsize = c->sector_size - ofs; 608 ofs = c->sector_size - sumsize;
436 ofs += jeb->offset;
437 609
438 dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", 610 dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n",
439 jeb->offset, ofs, sumsize); 611 jeb->offset, jeb->offset + ofs, sumsize);
440
441 summary = kmalloc(sumsize, GFP_KERNEL);
442
443 if (!summary) {
444 return -ENOMEM;
445 }
446
447 ret = jffs2_fill_scan_buf(c, (unsigned char *)summary, ofs, sumsize);
448
449 if (ret) {
450 kfree(summary);
451 return ret;
452 }
453 612
454 /* OK, now check for node validity and CRC */ 613 /* OK, now check for node validity and CRC */
455 crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 614 crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -489,40 +648,38 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
489 if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) { 648 if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) {
490 dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n", 649 dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n",
491 je32_to_cpu(summary->cln_mkr), c->cleanmarker_size); 650 je32_to_cpu(summary->cln_mkr), c->cleanmarker_size);
492 UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); 651 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
652 return err;
493 } else if (jeb->first_node) { 653 } else if (jeb->first_node) {
494 dbg_summary("CLEANMARKER node not first node in block " 654 dbg_summary("CLEANMARKER node not first node in block "
495 "(0x%08x)\n", jeb->offset); 655 "(0x%08x)\n", jeb->offset);
496 UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); 656 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
657 return err;
497 } else { 658 } else {
498 struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); 659 struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref();
499 660
500 if (!marker_ref) { 661 if (!marker_ref) {
501 JFFS2_NOTICE("Failed to allocate node ref for clean marker\n"); 662 JFFS2_NOTICE("Failed to allocate node ref for clean marker\n");
502 kfree(summary);
503 return -ENOMEM; 663 return -ENOMEM;
504 } 664 }
505 665
506 marker_ref->next_in_ino = NULL;
507 marker_ref->next_phys = NULL;
508 marker_ref->flash_offset = jeb->offset | REF_NORMAL; 666 marker_ref->flash_offset = jeb->offset | REF_NORMAL;
509 marker_ref->__totlen = je32_to_cpu(summary->cln_mkr); 667 marker_ref->next_in_ino = NULL;
510 jeb->first_node = jeb->last_node = marker_ref;
511 668
512 USED_SPACE( PAD(je32_to_cpu(summary->cln_mkr)) ); 669 jffs2_link_node_ref(c, jeb, marker_ref, je32_to_cpu(summary->cln_mkr));
513 } 670 }
514 } 671 }
515 672
516 if (je32_to_cpu(summary->padded)) {
517 DIRTY_SPACE(je32_to_cpu(summary->padded));
518 }
519
520 ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random); 673 ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random);
674 /* -ENOTRECOVERABLE isn't a fatal error -- it means we should do a full
675 scan of this eraseblock. So return zero */
676 if (ret == -ENOTRECOVERABLE)
677 return 0;
521 if (ret) 678 if (ret)
522 return ret; 679 return ret; /* real error */
523 680
524 /* for PARANOIA_CHECK */ 681 /* for PARANOIA_CHECK */
525 cache_ref = jffs2_alloc_raw_node_ref(); 682 cache_ref = alloc_ref_at(c, jeb, ofs);
526 683
527 if (!cache_ref) { 684 if (!cache_ref) {
528 JFFS2_NOTICE("Failed to allocate node ref for cache\n"); 685 JFFS2_NOTICE("Failed to allocate node ref for cache\n");
@@ -530,22 +687,18 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
530 } 687 }
531 688
532 cache_ref->next_in_ino = NULL; 689 cache_ref->next_in_ino = NULL;
533 cache_ref->next_phys = NULL; 690 cache_ref->flash_offset |= REF_NORMAL;
534 cache_ref->flash_offset = ofs | REF_NORMAL;
535 cache_ref->__totlen = sumsize;
536 691
537 if (!jeb->first_node) 692 jffs2_link_node_ref(c, jeb, cache_ref, sumsize);
538 jeb->first_node = cache_ref;
539 if (jeb->last_node)
540 jeb->last_node->next_phys = cache_ref;
541 jeb->last_node = cache_ref;
542 693
543 USED_SPACE(sumsize); 694 if (unlikely(jeb->free_size)) {
544 695 JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n",
545 jeb->wasted_size += jeb->free_size; 696 jeb->free_size, jeb->offset);
546 c->wasted_size += jeb->free_size; 697 jeb->wasted_size += jeb->free_size;
547 c->free_size -= jeb->free_size; 698 c->wasted_size += jeb->free_size;
548 jeb->free_size = 0; 699 c->free_size -= jeb->free_size;
700 jeb->free_size = 0;
701 }
549 702
550 return jffs2_scan_classify_jeb(c, jeb); 703 return jffs2_scan_classify_jeb(c, jeb);
551 704
@@ -617,9 +770,40 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
617 770
618 break; 771 break;
619 } 772 }
773#ifdef CONFIG_JFFS2_FS_XATTR
774 case JFFS2_NODETYPE_XATTR: {
775 struct jffs2_sum_xattr_flash *sxattr_ptr = wpage;
776
777 temp = c->summary->sum_list_head;
778 sxattr_ptr->nodetype = temp->x.nodetype;
779 sxattr_ptr->xid = temp->x.xid;
780 sxattr_ptr->version = temp->x.version;
781 sxattr_ptr->offset = temp->x.offset;
782 sxattr_ptr->totlen = temp->x.totlen;
783
784 wpage += JFFS2_SUMMARY_XATTR_SIZE;
785 break;
786 }
787 case JFFS2_NODETYPE_XREF: {
788 struct jffs2_sum_xref_flash *sxref_ptr = wpage;
620 789
790 temp = c->summary->sum_list_head;
791 sxref_ptr->nodetype = temp->r.nodetype;
792 sxref_ptr->offset = temp->r.offset;
793
794 wpage += JFFS2_SUMMARY_XREF_SIZE;
795 break;
796 }
797#endif
621 default : { 798 default : {
622 BUG(); /* unknown node in summary information */ 799 if ((je16_to_cpu(temp->u.nodetype) & JFFS2_COMPAT_MASK)
800 == JFFS2_FEATURE_RWCOMPAT_COPY) {
801 dbg_summary("Writing unknown RWCOMPAT_COPY node type %x\n",
802 je16_to_cpu(temp->u.nodetype));
803 jffs2_sum_disable_collecting(c->summary);
804 } else {
805 BUG(); /* unknown node in summary information */
806 }
623 } 807 }
624 } 808 }
625 809
@@ -651,19 +835,32 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
651 spin_unlock(&c->erase_completion_lock); 835 spin_unlock(&c->erase_completion_lock);
652 ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size - 836 ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size -
653 jeb->free_size, &retlen, 0); 837 jeb->free_size, &retlen, 0);
654 spin_lock(&c->erase_completion_lock);
655
656 838
657 if (ret || (retlen != infosize)) { 839 if (ret || (retlen != infosize)) {
840 struct jffs2_raw_node_ref *ref;
841
658 JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n", 842 JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n",
659 infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen); 843 infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen);
660 844
845 /* Waste remaining space */
846 ref = jffs2_alloc_raw_node_ref();
847 if (ref) {
848 spin_lock(&c->erase_completion_lock);
849
850 ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size;
851 ref->flash_offset |= REF_OBSOLETE;
852 ref->next_in_ino = 0;
853
854 jffs2_link_node_ref(c, jeb, ref, c->sector_size - jeb->free_size);
855 }
856
661 c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; 857 c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
662 WASTED_SPACE(infosize);
663 858
664 return 1; 859 return 1;
665 } 860 }
666 861
862 spin_lock(&c->erase_completion_lock);
863
667 return 0; 864 return 0;
668} 865}
669 866
@@ -706,7 +903,6 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
706 /* for ACCT_PARANOIA_CHECK */ 903 /* for ACCT_PARANOIA_CHECK */
707 spin_unlock(&c->erase_completion_lock); 904 spin_unlock(&c->erase_completion_lock);
708 summary_ref = jffs2_alloc_raw_node_ref(); 905 summary_ref = jffs2_alloc_raw_node_ref();
709 spin_lock(&c->erase_completion_lock);
710 906
711 if (!summary_ref) { 907 if (!summary_ref) {
712 JFFS2_NOTICE("Failed to allocate node ref for summary\n"); 908 JFFS2_NOTICE("Failed to allocate node ref for summary\n");
@@ -714,17 +910,10 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
714 } 910 }
715 911
716 summary_ref->next_in_ino = NULL; 912 summary_ref->next_in_ino = NULL;
717 summary_ref->next_phys = NULL;
718 summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL; 913 summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL;
719 summary_ref->__totlen = infosize;
720
721 if (!jeb->first_node)
722 jeb->first_node = summary_ref;
723 if (jeb->last_node)
724 jeb->last_node->next_phys = summary_ref;
725 jeb->last_node = summary_ref;
726 914
727 USED_SPACE(infosize); 915 spin_lock(&c->erase_completion_lock);
916 jffs2_link_node_ref(c, jeb, summary_ref, infosize);
728 917
729 return 0; 918 return 0;
730} 919}