Discussion:
Possible bug in file truncation code
Andrew Lunn
2005-02-25 16:46:43 UTC
Permalink
Hi Folks

Im tracking down a bug reported on the eCos mailing list. Please see
the thread:

http://ecos.sourceware.org/ml/ecos-discuss/2005-02/msg00319.html

In summary, the following causes the filesystem to be corrupted:


fd = fopen("foobar", "w");
fclose(fd);

ie openning a file so that it gets truncated and then closing
it. There ie an eCos test case in the thread.

I've looked at the code. The achive the truncation eCos does:

jffs2_truncate_fraglist(c, &f->fragtree, 0);

this in turn does

jffs2_obsolete_node_frag(c, frag);

for every fragment the node has. jffs2_obsolete_node_frag() has this
bit of code:

if (!this->node->frags) {
/* The node has no valid frags left. It's totally obsoleted */
D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) obsolete\n",
ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size));
jffs2_mark_node_obsolete(c, this->node->raw);
jffs2_free_full_dnode(this->node);
} else {

ie if the node does not have any fragments left its marked as
obsolete. These appears to remove the node, but still leaves it
referenced in the directory. Hence the filesystem is corrupt. Just
removing this bit of code does not seem to correctly fix the
problem. One of the other eCos test cases then fails....

So could somebody point me in the right direction for fixing this.

Thanks
Andrew

To unsubscribe from this list: send the line "unsubscribe jffs-dev" in
the body of a message to ***@axis.com
David Woodhouse
2005-02-25 17:21:41 UTC
Permalink
Post by Andrew Lunn
ie if the node does not have any fragments left its marked as
obsolete. These appears to remove the node, but still leaves it
referenced in the directory. Hence the filesystem is corrupt.
Directories don't refer to data nodes. They refer to inodes. This inode
still exists and is zero-length because it has no valid data nodes. The
directory still refers to it -- that's fine. What's the actual problem?
--
dwmw2


To unsubscribe from this list: send the line "unsubscribe jffs-dev" in
the body of a message to ***@axis.com
Andrew Lunn
2005-02-25 17:43:32 UTC
Permalink
Post by David Woodhouse
Post by Andrew Lunn
ie if the node does not have any fragments left its marked as
obsolete. These appears to remove the node, but still leaves it
referenced in the directory. Hence the filesystem is corrupt.
Directories don't refer to data nodes. They refer to inodes. This inode
still exists and is zero-length because it has no valid data nodes. The
directory still refers to it -- that's fine. What's the actual problem?
The test case does the open, followed by a close then umount and then
mounts. The mount then reports:

<5>Eep. Child "TestFile.txt" (ino #10) of dir ino #1 doesn't exist!

I've attached the test case if you want to try it.

Andrew
David Woodhouse
2005-02-25 17:59:40 UTC
Permalink
Post by Andrew Lunn
The test case does the open, followed by a close then umount and then
<5>Eep. Child "TestFile.txt" (ino #10) of dir ino #1 doesn't exist!
The inode #10 has no nodes at all, but it should have been left with one
-- a metadata node, which contains uid, gid, size, etc. information but
no data payload. This should have been written before calling
jffs2_truncate_fraglist().

Remember that the actual obsoletion of nodes on the medium is just an
optimisation, and it may not happen with NAND or other types of flash.

Any truncation (to zero, or to any other length) should first write a
new node with the appropriate i_size, before calling
jffs2_truncate_fraglist().

If you support truncate-to-longer (Linux generally does but POSIX
doesn't require it) then your new metadata node should also have a data
payload make sure the space between the old EOF and the new EOF is
filled with zeroes and prevent old data from before a previous
truncation from 'showing through' where the file is now extended. Zeroes
compress quite easily with JFFS2_COMPR_ZERO -- there's no actual payload
on the medium at all.

See jffs2_do_setattr() in fs.c for the Linux version -- in Linux, that
function also handles changes to i_size.
--
dwmw2


To unsubscribe from this list: send the line "unsubscribe jffs-dev" in
the body of a message to ***@axis.com
Andrew Lunn
2005-02-25 20:28:20 UTC
Permalink
Post by David Woodhouse
Any truncation (to zero, or to any other length) should first write a
new node with the appropriate i_size, before calling
jffs2_truncate_fraglist().
Thanks David, that was what was wrong. The eCos code just set the
inode->isize to zero and did not create any new node.

I just committed the patch to eCos and mtd.

Andrew

To unsubscribe from this list: send the line "unsubscribe jffs-dev" in
the body of a message to ***@axis.com

Loading...