Skip to content

Commit 49f11d4

Browse files
committed
[JFFS2] Mark gaps in summary list as dirty space
Make sure we allocate a ref for any dirty space which exists between nodes which we find in an eraseblock summary. Signed-off-by: David Woodhouse <dwmw2@infradead.org>
1 parent 25090a6 commit 49f11d4

File tree

1 file changed

+42
-29
lines changed

1 file changed

+42
-29
lines changed

fs/jffs2/summary.c

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,23 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
369369
return -ENOMEM;
370370
}
371371

372+
static 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+
}
372389

373390
/* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */
374391

@@ -397,7 +414,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
397414
dbg_summary("Inode at 0x%08x\n",
398415
jeb->offset + je32_to_cpu(spi->offset));
399416

400-
raw = jffs2_alloc_raw_node_ref();
417+
raw = alloc_ref_at(c, jeb, je32_to_cpu(spi->offset));
401418
if (!raw) {
402419
JFFS2_NOTICE("allocation of node reference failed\n");
403420
return -ENOMEM;
@@ -410,7 +427,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
410427
return -ENOMEM;
411428
}
412429

413-
raw->flash_offset = (jeb->offset + je32_to_cpu(spi->offset)) | REF_UNCHECKED;
430+
raw->flash_offset |= REF_UNCHECKED;
414431

415432
raw->next_in_ino = ic->nodes;
416433
ic->nodes = raw;
@@ -438,7 +455,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
438455
memcpy(&fd->name, spd->name, spd->nsize);
439456
fd->name[spd->nsize] = 0;
440457

441-
raw = jffs2_alloc_raw_node_ref();
458+
raw = alloc_ref_at(c, jeb, je32_to_cpu(spd->offset));
442459
if (!raw) {
443460
jffs2_free_full_dirent(fd);
444461
JFFS2_NOTICE("allocation of node reference failed\n");
@@ -452,7 +469,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
452469
return -ENOMEM;
453470
}
454471

455-
raw->flash_offset = (jeb->offset + je32_to_cpu(spd->offset)) | REF_PRISTINE;
472+
raw->flash_offset |= REF_PRISTINE;
456473
raw->next_in_ino = ic->nodes;
457474
ic->nodes = raw;
458475

@@ -477,13 +494,12 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
477494
case JFFS2_NODETYPE_XATTR: {
478495
struct jffs2_xattr_datum *xd;
479496
struct jffs2_sum_xattr_flash *spx;
480-
uint32_t ofs;
481497

482498
spx = (struct jffs2_sum_xattr_flash *)sp;
483-
ofs = jeb->offset + je32_to_cpu(spx->offset);
484-
dbg_summary("xattr at %#08x (xid=%u, version=%u)\n", ofs,
499+
dbg_summary("xattr at %#08x (xid=%u, version=%u)\n",
500+
jeb->offset + je32_to_cpu(spx->offset),
485501
je32_to_cpu(spx->xid), je32_to_cpu(spx->version));
486-
raw = jffs2_alloc_raw_node_ref();
502+
raw = alloc_ref_at(c, jeb, je32_to_cpu(spx->offset));
487503
if (!raw) {
488504
JFFS2_NOTICE("allocation of node reference failed\n");
489505
kfree(summary);
@@ -506,7 +522,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
506522
}
507523
xd->node = raw;
508524

509-
raw->flash_offset = ofs | REF_UNCHECKED;
525+
raw->flash_offset |= REF_UNCHECKED;
510526
raw->next_in_ino = (void *)xd;
511527

512528
jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spx->totlen)));
@@ -519,13 +535,12 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
519535
case JFFS2_NODETYPE_XREF: {
520536
struct jffs2_xattr_ref *ref;
521537
struct jffs2_sum_xref_flash *spr;
522-
uint32_t ofs;
523538

524539
spr = (struct jffs2_sum_xref_flash *)sp;
525-
ofs = jeb->offset + je32_to_cpu(spr->offset);
526-
dbg_summary("xref at %#08x (xid=%u, ino=%u)\n", ofs,
540+
dbg_summary("xref at %#08x (xid=%u, ino=%u)\n",
541+
jeb->offset + je32_to_cpu(spr->offset),
527542
je32_to_cpu(spr->xid), je32_to_cpu(spr->ino));
528-
raw = jffs2_alloc_raw_node_ref();
543+
raw = alloc_ref_at(c, jeb, je32_to_cpu(spr->offset));
529544
if (!raw) {
530545
JFFS2_NOTICE("allocation of node reference failed\n");
531546
kfree(summary);
@@ -544,12 +559,12 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
544559
ref->next = c->xref_temp;
545560
c->xref_temp = ref;
546561

547-
raw->flash_offset = ofs | REF_UNCHECKED;
562+
raw->flash_offset |= REF_UNCHECKED;
548563
raw->next_in_ino = (void *)ref;
549564

550565
jffs2_link_node_ref(c, jeb, raw, PAD(sizeof(struct jffs2_raw_xref)));
551566

552-
*pseudo_random += ofs;
567+
*pseudo_random += raw->flash_offset;
553568
sp += JFFS2_SUMMARY_XREF_SIZE;
554569

555570
break;
@@ -589,10 +604,10 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
589604
uint32_t crc;
590605
int err;
591606

592-
ofs = jeb->offset + c->sector_size - sumsize;
607+
ofs = c->sector_size - sumsize;
593608

594609
dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n",
595-
jeb->offset, ofs, sumsize);
610+
jeb->offset, jeb->offset + ofs, sumsize);
596611

597612
/* OK, now check for node validity and CRC */
598613
crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -654,11 +669,6 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
654669
}
655670
}
656671

657-
if (je32_to_cpu(summary->padded)) {
658-
if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(summary->padded))))
659-
return err;
660-
}
661-
662672
ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random);
663673
/* -ENOTRECOVERABLE isn't a fatal error -- it means we should do a full
664674
scan of this eraseblock. So return zero */
@@ -668,23 +678,26 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
668678
return ret; /* real error */
669679

670680
/* for PARANOIA_CHECK */
671-
cache_ref = jffs2_alloc_raw_node_ref();
681+
cache_ref = alloc_ref_at(c, jeb, ofs);
672682

673683
if (!cache_ref) {
674684
JFFS2_NOTICE("Failed to allocate node ref for cache\n");
675685
return -ENOMEM;
676686
}
677687

678688
cache_ref->next_in_ino = NULL;
679-
cache_ref->next_phys = NULL;
680-
cache_ref->flash_offset = ofs | REF_NORMAL;
689+
cache_ref->flash_offset |= REF_NORMAL;
681690

682691
jffs2_link_node_ref(c, jeb, cache_ref, sumsize);
683692

684-
jeb->wasted_size += jeb->free_size;
685-
c->wasted_size += jeb->free_size;
686-
c->free_size -= jeb->free_size;
687-
jeb->free_size = 0;
693+
if (unlikely(jeb->free_size)) {
694+
JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n",
695+
jeb->free_size, jeb->offset);
696+
jeb->wasted_size += jeb->free_size;
697+
c->wasted_size += jeb->free_size;
698+
c->free_size -= jeb->free_size;
699+
jeb->free_size = 0;
700+
}
688701

689702
return jffs2_scan_classify_jeb(c, jeb);
690703

0 commit comments

Comments
 (0)