forked from Imagelibrary/rtems
cpukit/jffs2: Handle used empty file system
On JFFS2 file systems on NOR flash or dataflash that does not have spare area for metadata and thus does not invoke delayed writes, it is possible to put the file system into a state where all blocks have been written to and all files have been deleted from the filesystem. There is a bug in the JFFS2 file system scan routine that detects this situation as a corrupted file system since the scan routine relies on "used" space to discriminate a valid file system when there are blocks that need to be erased. The correct fix would require a partial rewrite of the scan routine, so instead this patch tracks the space marked as obsolete along with space at the end of each block that is otherwise too small to contain a JFFS2 node so that it can me compared with the dirty space. Corrupted data (or otherwise non-JFFS2 blocks) will still cause this check to fail as corrupted data isn't recognized as obsoleted (deleted) nodes.
This commit is contained in:
committed by
Joel Sherrill
parent
5df1d15e8b
commit
e3972d71ef
@@ -75,6 +75,9 @@ struct jffs2_sb_info {
|
|||||||
uint32_t bad_size;
|
uint32_t bad_size;
|
||||||
uint32_t sector_size;
|
uint32_t sector_size;
|
||||||
uint32_t unchecked_size;
|
uint32_t unchecked_size;
|
||||||
|
#ifdef __rtems__
|
||||||
|
uint32_t obsolete_size;
|
||||||
|
#endif
|
||||||
|
|
||||||
uint32_t nr_free_blocks;
|
uint32_t nr_free_blocks;
|
||||||
uint32_t nr_erasing_blocks;
|
uint32_t nr_erasing_blocks;
|
||||||
|
|||||||
@@ -264,14 +264,32 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (c->nr_erasing_blocks) {
|
if (c->nr_erasing_blocks) {
|
||||||
|
#ifdef __rtems__
|
||||||
|
if (c->obsolete_size != c->dirty_size) {
|
||||||
|
#endif
|
||||||
if (!c->used_size && !c->unchecked_size &&
|
if (!c->used_size && !c->unchecked_size &&
|
||||||
((c->nr_free_blocks+empty_blocks+bad_blocks) != c->nr_blocks || bad_blocks == c->nr_blocks)) {
|
((c->nr_free_blocks+empty_blocks+bad_blocks) != c->nr_blocks || bad_blocks == c->nr_blocks)) {
|
||||||
pr_notice("Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n");
|
pr_notice("Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n");
|
||||||
pr_notice("empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n",
|
pr_notice("empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n",
|
||||||
empty_blocks, bad_blocks, c->nr_blocks);
|
empty_blocks, bad_blocks, c->nr_blocks);
|
||||||
|
#ifdef __rtems__
|
||||||
|
pr_notice("nr_erasing_blocks %d, used 0x%x, dirty 0x%x, wasted 0x%x, free 0x%x, erasing 0x%x, bad 0x%x, obsolete 0x%x, unchecked 0x%x\n",
|
||||||
|
c->nr_erasing_blocks,
|
||||||
|
c->used_size,
|
||||||
|
c->dirty_size,
|
||||||
|
c->wasted_size,
|
||||||
|
c->free_size,
|
||||||
|
c->erasing_size,
|
||||||
|
c->bad_size,
|
||||||
|
c->obsolete_size,
|
||||||
|
c->unchecked_size);
|
||||||
|
#endif
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
#ifdef __rtems__
|
||||||
|
}
|
||||||
|
#endif
|
||||||
spin_lock(&c->erase_completion_lock);
|
spin_lock(&c->erase_completion_lock);
|
||||||
jffs2_garbage_collect_trigger(c);
|
jffs2_garbage_collect_trigger(c);
|
||||||
spin_unlock(&c->erase_completion_lock);
|
spin_unlock(&c->erase_completion_lock);
|
||||||
@@ -646,6 +664,9 @@ scan_more:
|
|||||||
sizeof(struct jffs2_unknown_node),
|
sizeof(struct jffs2_unknown_node),
|
||||||
jeb->offset, c->sector_size, ofs,
|
jeb->offset, c->sector_size, ofs,
|
||||||
sizeof(*node));
|
sizeof(*node));
|
||||||
|
#ifdef __rtems__
|
||||||
|
c->obsolete_size += (jeb->offset + c->sector_size - ofs);
|
||||||
|
#endif
|
||||||
if ((err = jffs2_scan_dirty_space(c, jeb, (jeb->offset + c->sector_size)-ofs)))
|
if ((err = jffs2_scan_dirty_space(c, jeb, (jeb->offset + c->sector_size)-ofs)))
|
||||||
return err;
|
return err;
|
||||||
break;
|
break;
|
||||||
@@ -796,6 +817,9 @@ scan_more:
|
|||||||
if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
|
if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
|
||||||
return err;
|
return err;
|
||||||
ofs += PAD(je32_to_cpu(node->totlen));
|
ofs += PAD(je32_to_cpu(node->totlen));
|
||||||
|
#ifdef __rtems__
|
||||||
|
c->obsolete_size += PAD(je32_to_cpu(node->totlen));
|
||||||
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user