mtd/fs/jffs2 gc.c,1.98,1.99
David Woodhouse
dwmw2 at infradead.org
Wed Jan 22 07:08:00 EST 2003
Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv26695
Modified Files:
gc.c
Log Message:
Fix GC of REF_PRISTINE dirent nodes. If you treat them like they're a data node
then the CRC is _going_ to fail :)
Index: gc.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/gc.c,v
retrieving revision 1.98
retrieving revision 1.99
diff -u -r1.98 -r1.99
--- gc.c 21 Jan 2003 18:11:28 -0000 1.98
+++ gc.c 22 Jan 2003 12:07:58 -0000 1.99
@@ -458,7 +458,7 @@
struct jffs2_inode_cache *ic,
struct jffs2_raw_node_ref *raw)
{
- struct jffs2_raw_inode *ri;
+ union jffs2_node_union *node;
struct jffs2_raw_node_ref *nraw;
size_t retlen;
int ret;
@@ -467,7 +467,10 @@
D1(printk(KERN_DEBUG "Going to GC REF_PRISTINE node at 0x%08x\n", ref_offset(raw)));
- ret = jffs2_reserve_space_gc(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN,
+ /* Ask for a small amount of space (or the totlen if smaller) because we
+ don't want to force wastage of the end of a block if splitting would
+ work. */
+ ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN, raw->totlen),
&phys_ofs, &alloclen);
if (ret)
return ret;
@@ -477,43 +480,69 @@
return -EBADFD;
}
- ri = kmalloc(raw->totlen, GFP_KERNEL);
- if (!ri)
+ node = kmalloc(raw->totlen, GFP_KERNEL);
+ if (!node)
return -ENOMEM;
- ret = jffs2_flash_read(c, ref_offset(raw), raw->totlen, &retlen, (char *)ri);
+ ret = jffs2_flash_read(c, ref_offset(raw), raw->totlen, &retlen, (char *)node);
if (!ret && retlen != raw->totlen)
ret = -EIO;
if (ret)
- goto out_ri;
+ goto out_node;
- crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4);
- if (je32_to_cpu(ri->hdr_crc) != crc) {
+ crc = crc32(0, node, sizeof(struct jffs2_unknown_node)-4);
+ if (je32_to_cpu(node->u.hdr_crc) != crc) {
printk(KERN_WARNING "Header CRC failed on REF_PRISTINE node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
- ref_offset(raw), je32_to_cpu(ri->hdr_crc), crc);
+ ref_offset(raw), je32_to_cpu(node->u.hdr_crc), crc);
goto bail;
}
- crc = crc32(0, ri, sizeof(*ri)-8);
- if (je32_to_cpu(ri->node_crc) != crc) {
- printk(KERN_WARNING "Node CRC failed on REF_PRISTINE node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
- ref_offset(raw), je32_to_cpu(ri->node_crc), crc);
- goto bail;
- }
+ switch(je16_to_cpu(node->u.nodetype)) {
+ case JFFS2_NODETYPE_INODE:
+ crc = crc32(0, node, sizeof(node->i)-8);
+ if (je32_to_cpu(node->i.node_crc) != crc) {
+ printk(KERN_WARNING "Node CRC failed on REF_PRISTINE data node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
+ ref_offset(raw), je32_to_cpu(node->i.node_crc), crc);
+ goto bail;
+ }
- if (je32_to_cpu(ri->dsize)) {
- crc = crc32(0, &ri[1], je32_to_cpu(ri->csize));
- if (je32_to_cpu(ri->data_crc) != crc) {
- printk(KERN_WARNING "Data CRC failed on REF_PRISTINE node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
- ref_offset(raw), je32_to_cpu(ri->data_crc), crc);
+ if (je32_to_cpu(node->i.dsize)) {
+ crc = crc32(0, node->i.data, je32_to_cpu(node->i.csize));
+ if (je32_to_cpu(node->i.data_crc) != crc) {
+ printk(KERN_WARNING "Data CRC failed on REF_PRISTINE data node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
+ ref_offset(raw), je32_to_cpu(node->i.data_crc), crc);
+ goto bail;
+ }
+ }
+ break;
+
+ case JFFS2_NODETYPE_DIRENT:
+ crc = crc32(0, node, sizeof(node->d)-8);
+ if (je32_to_cpu(node->d.node_crc) != crc) {
+ printk(KERN_WARNING "Node CRC failed on REF_PRISTINE dirent node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
+ ref_offset(raw), je32_to_cpu(node->d.node_crc), crc);
goto bail;
}
+
+ if (node->d.nsize) {
+ crc = crc32(0, node->d.name, node->d.nsize);
+ if (je32_to_cpu(node->d.name_crc) != crc) {
+ printk(KERN_WARNING "Name CRC failed on REF_PRISTINE dirent ode at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
+ ref_offset(raw), je32_to_cpu(node->d.name_crc), crc);
+ goto bail;
+ }
+ }
+ break;
+ default:
+ printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n",
+ ref_offset(raw), je16_to_cpu(node->u.nodetype));
+ goto bail;
}
nraw = jffs2_alloc_raw_node_ref();
if (!nraw) {
ret = -ENOMEM;
- goto out_ri;
+ goto out_node;
}
nraw->flash_offset = phys_ofs;
nraw->totlen = raw->totlen;
@@ -521,7 +550,7 @@
/* OK, all the CRCs are good; this node can just be copied as-is. */
- ret = jffs2_flash_write(c, phys_ofs, raw->totlen, &retlen, (char *)ri);
+ ret = jffs2_flash_write(c, phys_ofs, raw->totlen, &retlen, (char *)node);
if (ret || (retlen != raw->totlen)) {
printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n",
raw->totlen, phys_ofs, ret, retlen);
@@ -538,25 +567,27 @@
}
if (!ret)
ret = -EIO;
- goto out_ri;
+ goto out_node;
}
nraw->flash_offset |= REF_PRISTINE;
jffs2_add_physical_node_ref(c, nraw);
/* Link into per-inode list. This is safe because of the ic
- state being INO_STATE_GC. */
+ state being INO_STATE_GC. Note that if we're doing this
+ for an inode which is in-code, the 'nraw' pointer is then
+ going to be fetched from ic->nodes by our caller. */
nraw->next_in_ino = ic->nodes;
ic->nodes = nraw;
jffs2_mark_node_obsolete(c, raw);
- D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x\n", ref_offset(raw)));
+ D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw)));
- out_ri:
- kfree(ri);
+ out_node:
+ kfree(node);
return ret;
bail:
ret = -EBADFD;
- goto out_ri;
+ goto out_node;
}
static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
More information about the linux-mtd-cvs
mailing list