Problem deleting files with NAND/JFFS2 and a possible solution
Howard Gray
rhea at matrix-vision.de
Tue Jan 27 06:47:41 EST 2004
Hi,
I am using kernel 2.4.20 with the latest cvs MTD version. The system is a
PowerPC-based embedded device with both NOR and NAND flash. I have a
partition in NAND flash using JFFS2 as the file system.
If I mount a JFFS2 partition, delete a single file and unmount again,
everthing is o.k.
But if I mount the JFFS2 partition, delete a file and then (after a long pause
to ensure the garbage collector has finished) turn off the device without
unmounting, the file reappears after the reboot and new mount command. There
are various variations on this like mounting read-only before unmounting etc.
(with this device, I cannot assume that a user turns off this device in a
controlled way....)
It appears as if just deleting a file is not enough to mark any inodes as
dirty so that kupdated ignores them. It doesn't matter how long you wait for
the GC to be started because it won't be unless you do something else to the
file system too, like creating a new file or sending a SIGHUP to the GC. For
the same reason a "sync" doesn't help either.
After some time I came to the conclusion that there is a problem in the
function "jffs2_full_dirent" in the file "fs/jffs2/write.c". A call is made
to "jffs2_flash_writev" which has as its final parameter an inode number
(assuming alloc_mode is not ALLOC_GC). It looks like this:
write.c: approx. line 282.....
ret = jffs2_flash_writev(c, vecs, 2, flash_ofs, &retlen,
(alloc_mode==ALLOC_GC)?0:fd->ino);
"fd->ino" would appear always to be "0" in the case where a file is just being
deleted which, in turn, at the end of "jffs2_flash_writev" stops the inode
being dirtied (i.e. the superblock's "s_dirt" flag is not set to "1"): Here's
the call at the wnd of "jffs2_flash_writev":
wbuf.c: approx. line 752.....
if (c->wbuf_len && ino)
jffs2_wbuf_dirties_inode(c, ino);
I'm not sufficiently knowledgeable about the internals of JFFS2 to supply a
proper patch, but it would seem to me that the call to "jffs2_flash_writev"
in write.c at line 282 should be like this:
Suggestion....
write.c: approx. line 282.....
ret = jffs2_flash_writev(c, vecs, 2, flash_ofs, &retlen,
(alloc_mode==ALLOC_GC)?0:je32_to_cpu(rd->pino));
This would appear to be the inode of the directory entry and this is really
what we are changing when we delete a file, or am I missing something here ?
In any case, this change seems to have the desired effect and the problem is
cured.
Any comments would be appreciated. Thanks.
--
Howard
More information about the linux-mtd
mailing list