mtd/fs/jffs2 gc.c,1.124,1.125
David Woodhouse
dwmw2 at infradead.org
Mon Nov 3 08:30:33 EST 2003
Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv28165
Modified Files:
gc.c
Log Message:
Make jffs2_garbage_collect_deletion_dirent() not completely bloody
stupidly inefficient.
Index: gc.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/gc.c,v
retrieving revision 1.124
retrieving revision 1.125
diff -u -r1.124 -r1.125
--- gc.c 2 Nov 2003 19:28:42 -0000 1.124
+++ gc.c 3 Nov 2003 13:30:29 -0000 1.125
@@ -292,7 +292,7 @@
can happen.
*/
printk(KERN_CRIT "Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n",
- ic->state);
+ ic->ino, ic->state);
up(&c->alloc_sem);
spin_unlock(&c->inocache_lock);
BUG();
@@ -823,13 +823,17 @@
delete a 'real' dirent with the same name that's still
somewhere else on the flash. */
if (!jffs2_can_mark_obsolete(c)) {
- struct jffs2_raw_dirent rd;
+ struct jffs2_raw_dirent *rd;
struct jffs2_raw_node_ref *raw;
int ret;
size_t retlen;
int name_len = strlen(fd->name);
uint32_t name_crc = crc32(0, fd->name, name_len);
- char *namebuf = NULL;
+ uint32_t rawlen = ref_totlen(c, jeb, fd->raw);
+
+ rd = kmalloc(rawlen, GFP_KERNEL);
+ if (!rd)
+ return -ENOMEM;
/* Prevent the erase code from nicking the obsolete node refs while
we're looking at them. I really don't like this extra lock but
@@ -837,91 +841,66 @@
down(&c->erase_free_sem);
for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) {
+
/* We only care about obsolete ones */
if (!(ref_obsolete(raw)))
continue;
+ /* Any dirent with the same name is going to have the same length... */
+ if (ref_totlen(c, NULL, raw) != rawlen)
+ continue;
+
/* Doesn't matter if there's one in the same erase block. We're going to
delete it too at the same time. */
if ((raw->flash_offset & ~(c->sector_size-1)) ==
(fd->raw->flash_offset & ~(c->sector_size-1)))
continue;
- /* This is an obsolete node belonging to the same directory */
- ret = jffs2_flash_read(c, ref_offset(raw), sizeof(struct jffs2_unknown_node), &retlen, (char *)&rd);
+ D1(printk(KERN_DEBUG "Check potential deletion dirent at %08x\n", ref_offset(raw)));
+
+ /* This is an obsolete node belonging to the same directory, and it's of the right
+ length. We need to take a closer look...*/
+ ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)rd);
if (ret) {
- printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading header from obsolete node at %08x\n", ret, ref_offset(raw));
+ printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading obsolete node at %08x\n", ret, ref_offset(raw));
/* If we can't read it, we don't need to continue to obsolete it. Continue */
continue;
}
- if (retlen != sizeof(struct jffs2_unknown_node)) {
+ if (retlen != rawlen) {
printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Short read (%zd not %zd) reading header from obsolete node at %08x\n",
- retlen, sizeof(struct jffs2_unknown_node), ref_offset(raw));
+ retlen, rawlen, ref_offset(raw));
continue;
}
- if (je16_to_cpu(rd.nodetype) != JFFS2_NODETYPE_DIRENT ||
- PAD(je32_to_cpu(rd.totlen)) != PAD(sizeof(rd) + name_len))
- continue;
- /* OK, it's a dirent node, it's the right length. We have to take a
- closer look at it... */
- ret = jffs2_flash_read(c, ref_offset(raw), sizeof(rd), &retlen, (char *)&rd);
- if (ret) {
- printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading from obsolete node at %08x\n", ret, ref_offset(raw));
- /* If we can't read it, we don't need to continune to obsolete it. Continue */
- continue;
- }
- if (retlen != sizeof(rd)) {
- printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Short read (%zd not %zd) reading from obsolete node at %08x\n",
- retlen, sizeof(rd), ref_offset(raw));
+ if (je16_to_cpu(rd->nodetype) != JFFS2_NODETYPE_DIRENT)
continue;
- }
/* If the name CRC doesn't match, skip */
- if (je32_to_cpu(rd.name_crc) != name_crc)
+ if (je32_to_cpu(rd->name_crc) != name_crc)
continue;
+
/* If the name length doesn't match, or it's another deletion dirent, skip */
- if (rd.nsize != name_len || !je32_to_cpu(rd.ino))
+ if (rd->nsize != name_len || !je32_to_cpu(rd->ino))
continue;
/* OK, check the actual name now */
- if (!namebuf) {
- namebuf = kmalloc(name_len + 1, GFP_KERNEL);
- if (!namebuf) {
- up(&c->erase_free_sem);
- return -ENOMEM;
- }
- }
- /* We read the extra byte before it so it's a word-aligned read */
- ret = jffs2_flash_read(c, (ref_offset(raw))+sizeof(rd)-1, name_len+1, &retlen, namebuf);
- if (ret) {
- printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Read error (%d) reading name from obsolete node at %08x\n", ret, ref_offset(raw));
- /* If we can't read it, we don't need to continune to obsolete it. Continue */
- continue;
- }
- if (retlen != name_len+1) {
- printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Short read (%zd not %d) reading name from obsolete node at %08x\n",
- retlen, name_len+1, ref_offset(raw));
- continue;
- }
- if (memcmp(namebuf+1, fd->name, name_len))
+ if (memcmp(rd->name, fd->name, name_len))
continue;
/* OK. The name really does match. There really is still an older node on
the flash which our deletion dirent obsoletes. So we have to write out
a new deletion dirent to replace it */
-
- if (namebuf)
- kfree(namebuf);
-
up(&c->erase_free_sem);
+
+ D1(printk(KERN_DEBUG "Deletion dirent at %08x still obsoletes real dirent \"%s\" at %08x for ino #%u\n",
+ ref_offset(fd->raw), fd->name, ref_offset(raw), je32_to_cpu(rd->ino)));
+ kfree(rd);
+
return jffs2_garbage_collect_dirent(c, jeb, f, fd);
}
up(&c->erase_free_sem);
-
- if (namebuf)
- kfree(namebuf);
+ kfree(rd);
}
/* No need for it any more. Just mark it obsolete and remove it from the list */
More information about the linux-mtd-cvs
mailing list