Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+42 −29
Original line number Original line Diff line number Diff line
@@ -369,6 +369,23 @@ no_mem:
	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
				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
					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
				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
					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
			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
				}
				}
				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
			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
				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
	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
		}
		}
	}
	}


	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
		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
	}
	}


	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);


	if (unlikely(jeb->free_size)) {
		JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n",
			      jeb->free_size, jeb->offset);
		jeb->wasted_size += jeb->free_size;
		jeb->wasted_size += jeb->free_size;
		c->wasted_size += jeb->free_size;
		c->wasted_size += jeb->free_size;
		c->free_size -= jeb->free_size;
		c->free_size -= jeb->free_size;
		jeb->free_size = 0;
		jeb->free_size = 0;
	}


	return jffs2_scan_classify_jeb(c, jeb);
	return jffs2_scan_classify_jeb(c, jeb);