Commit 49f11d40 authored by David Woodhouse's avatar David Woodhouse

[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: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent 25090a6b
...@@ -369,6 +369,23 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs, ...@@ -369,6 +369,23 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
return -ENOMEM; return -ENOMEM;
} }
static struct jffs2_raw_node_ref *alloc_ref_at(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
uint32_t offset)
{
struct jffs2_raw_node_ref *ref;
/* If there was a gap, mark it dirty */
if (offset > c->sector_size - jeb->free_size) {
int ret = jffs2_scan_dirty_space(c, jeb, offset - (c->sector_size - jeb->free_size));
if (ret)
return NULL;
}
ref = jffs2_alloc_raw_node_ref();
if (!ref)
return NULL;
ref->flash_offset = jeb->offset + offset;
return ref;
}
/* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */
...@@ -397,7 +414,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras ...@@ -397,7 +414,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
dbg_summary("Inode at 0x%08x\n", dbg_summary("Inode at 0x%08x\n",
jeb->offset + je32_to_cpu(spi->offset)); jeb->offset + je32_to_cpu(spi->offset));
raw = jffs2_alloc_raw_node_ref(); raw = alloc_ref_at(c, jeb, je32_to_cpu(spi->offset));
if (!raw) { if (!raw) {
JFFS2_NOTICE("allocation of node reference failed\n"); JFFS2_NOTICE("allocation of node reference failed\n");
return -ENOMEM; return -ENOMEM;
...@@ -410,7 +427,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras ...@@ -410,7 +427,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
return -ENOMEM; return -ENOMEM;
} }
raw->flash_offset = (jeb->offset + je32_to_cpu(spi->offset)) | REF_UNCHECKED; raw->flash_offset |= REF_UNCHECKED;
raw->next_in_ino = ic->nodes; raw->next_in_ino = ic->nodes;
ic->nodes = raw; ic->nodes = raw;
...@@ -438,7 +455,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras ...@@ -438,7 +455,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
memcpy(&fd->name, spd->name, spd->nsize); memcpy(&fd->name, spd->name, spd->nsize);
fd->name[spd->nsize] = 0; fd->name[spd->nsize] = 0;
raw = jffs2_alloc_raw_node_ref(); raw = alloc_ref_at(c, jeb, je32_to_cpu(spd->offset));
if (!raw) { if (!raw) {
jffs2_free_full_dirent(fd); jffs2_free_full_dirent(fd);
JFFS2_NOTICE("allocation of node reference failed\n"); 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 ...@@ -452,7 +469,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
return -ENOMEM; return -ENOMEM;
} }
raw->flash_offset = (jeb->offset + je32_to_cpu(spd->offset)) | REF_PRISTINE; raw->flash_offset |= REF_PRISTINE;
raw->next_in_ino = ic->nodes; raw->next_in_ino = ic->nodes;
ic->nodes = raw; ic->nodes = raw;
...@@ -477,13 +494,12 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras ...@@ -477,13 +494,12 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
case JFFS2_NODETYPE_XATTR: { case JFFS2_NODETYPE_XATTR: {
struct jffs2_xattr_datum *xd; struct jffs2_xattr_datum *xd;
struct jffs2_sum_xattr_flash *spx; struct jffs2_sum_xattr_flash *spx;
uint32_t ofs;
spx = (struct jffs2_sum_xattr_flash *)sp; spx = (struct jffs2_sum_xattr_flash *)sp;
ofs = jeb->offset + je32_to_cpu(spx->offset); dbg_summary("xattr at %#08x (xid=%u, version=%u)\n",
dbg_summary("xattr at %#08x (xid=%u, version=%u)\n", ofs, jeb->offset + je32_to_cpu(spx->offset),
je32_to_cpu(spx->xid), je32_to_cpu(spx->version)); je32_to_cpu(spx->xid), je32_to_cpu(spx->version));
raw = jffs2_alloc_raw_node_ref(); raw = alloc_ref_at(c, jeb, je32_to_cpu(spx->offset));
if (!raw) { if (!raw) {
JFFS2_NOTICE("allocation of node reference failed\n"); JFFS2_NOTICE("allocation of node reference failed\n");
kfree(summary); kfree(summary);
...@@ -506,7 +522,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras ...@@ -506,7 +522,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
} }
xd->node = raw; xd->node = raw;
raw->flash_offset = ofs | REF_UNCHECKED; raw->flash_offset |= REF_UNCHECKED;
raw->next_in_ino = (void *)xd; raw->next_in_ino = (void *)xd;
jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spx->totlen))); 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 ...@@ -519,13 +535,12 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
case JFFS2_NODETYPE_XREF: { case JFFS2_NODETYPE_XREF: {
struct jffs2_xattr_ref *ref; struct jffs2_xattr_ref *ref;
struct jffs2_sum_xref_flash *spr; struct jffs2_sum_xref_flash *spr;
uint32_t ofs;
spr = (struct jffs2_sum_xref_flash *)sp; spr = (struct jffs2_sum_xref_flash *)sp;
ofs = jeb->offset + je32_to_cpu(spr->offset); dbg_summary("xref at %#08x (xid=%u, ino=%u)\n",
dbg_summary("xref at %#08x (xid=%u, ino=%u)\n", ofs, jeb->offset + je32_to_cpu(spr->offset),
je32_to_cpu(spr->xid), je32_to_cpu(spr->ino)); je32_to_cpu(spr->xid), je32_to_cpu(spr->ino));
raw = jffs2_alloc_raw_node_ref(); raw = alloc_ref_at(c, jeb, je32_to_cpu(spr->offset));
if (!raw) { if (!raw) {
JFFS2_NOTICE("allocation of node reference failed\n"); JFFS2_NOTICE("allocation of node reference failed\n");
kfree(summary); kfree(summary);
...@@ -544,12 +559,12 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras ...@@ -544,12 +559,12 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
ref->next = c->xref_temp; ref->next = c->xref_temp;
c->xref_temp = ref; c->xref_temp = ref;
raw->flash_offset = ofs | REF_UNCHECKED; raw->flash_offset |= REF_UNCHECKED;
raw->next_in_ino = (void *)ref; raw->next_in_ino = (void *)ref;
jffs2_link_node_ref(c, jeb, raw, PAD(sizeof(struct jffs2_raw_xref))); jffs2_link_node_ref(c, jeb, raw, PAD(sizeof(struct jffs2_raw_xref)));
*pseudo_random += ofs; *pseudo_random += raw->flash_offset;
sp += JFFS2_SUMMARY_XREF_SIZE; sp += JFFS2_SUMMARY_XREF_SIZE;
break; break;
...@@ -589,10 +604,10 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb ...@@ -589,10 +604,10 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
uint32_t crc; uint32_t crc;
int err; int err;
ofs = jeb->offset + c->sector_size - sumsize; ofs = c->sector_size - sumsize;
dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n",
jeb->offset, ofs, sumsize); jeb->offset, jeb->offset + ofs, sumsize);
/* OK, now check for node validity and CRC */ /* OK, now check for node validity and CRC */
crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 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 ...@@ -654,11 +669,6 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
} }
} }
if (je32_to_cpu(summary->padded)) {
if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(summary->padded))))
return err;
}
ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random); ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random);
/* -ENOTRECOVERABLE isn't a fatal error -- it means we should do a full /* -ENOTRECOVERABLE isn't a fatal error -- it means we should do a full
scan of this eraseblock. So return zero */ scan of this eraseblock. So return zero */
...@@ -668,7 +678,7 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb ...@@ -668,7 +678,7 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
return ret; /* real error */ return ret; /* real error */
/* for PARANOIA_CHECK */ /* for PARANOIA_CHECK */
cache_ref = jffs2_alloc_raw_node_ref(); cache_ref = alloc_ref_at(c, jeb, ofs);
if (!cache_ref) { if (!cache_ref) {
JFFS2_NOTICE("Failed to allocate node ref for cache\n"); JFFS2_NOTICE("Failed to allocate node ref for cache\n");
...@@ -676,15 +686,18 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb ...@@ -676,15 +686,18 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
} }
cache_ref->next_in_ino = NULL; cache_ref->next_in_ino = NULL;
cache_ref->next_phys = NULL; cache_ref->flash_offset |= REF_NORMAL;
cache_ref->flash_offset = ofs | REF_NORMAL;
jffs2_link_node_ref(c, jeb, cache_ref, sumsize); jffs2_link_node_ref(c, jeb, cache_ref, sumsize);
jeb->wasted_size += jeb->free_size; if (unlikely(jeb->free_size)) {
c->wasted_size += jeb->free_size; JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n",
c->free_size -= jeb->free_size; jeb->free_size, jeb->offset);
jeb->free_size = 0; jeb->wasted_size += jeb->free_size;
c->wasted_size += jeb->free_size;
c->free_size -= jeb->free_size;
jeb->free_size = 0;
}
return jffs2_scan_classify_jeb(c, jeb); return jffs2_scan_classify_jeb(c, jeb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment