JFFS2: truncated files after power loss scenario

Artem Bityutskiy dedekind1 at gmail.com
Fri Feb 11 09:00:41 EST 2011


Hi,

sorry for delay, I was very busy.

On Sun, 2011-02-06 at 19:40 +0100, Albrecht Dreß wrote:
> Unfortunately, they are more more about ubi & ext4, but I am in
> particular interested in JFFS2's behaviour, so please excuse my
> questions, but it's a really critical point...

OK, but you do realize that proper portable applications should not rely
on JFFS2-specific behavior.

Also, if this is crucial for you, you should not generally rely on the
answer of a random mailing list guy like me, of course :-)

>   Currently, I use the following sequence to write my configs to jffs2
> (both NOR flash and mtd-ram):
> 
> open(scratch, O_RDWR | O_CREAT | O_TRUNC, perms);
OK, if scratch existed, at this point you truncate it. The change goes
to the JFFS2 write buffer. And the write-buffer is flushed by time-out,
or if some other app wrote anything else to the file-system, of if
someone issued sync.

So if power cut happens, you may either end up with intact "scratch" or
with "scratch" truncated to zero.

If you do not want it, you have to first copy "scratch" to
"scratch_saved" and 'fsync()' "scratch_saved".

> write();

OK, you write to "scratch". What is your flash? NAND, NOR? In case of
typical 2KiB per page NAND, you can lose the last 0-8KiB of written data
in the worst case. Not sure how much, depends, and I do not remember the
details well enough.

> fsync();

OK, if you get a power cut now, you are safe, you'll have modified
"scratch".

> close();

Not necessary to do, but does not hurt. 'fsync()' was enough.

> sync();		// #1

The same, not needed. You fsync()'ed "scratch" already.

> rename(scratch, realname);

Now if you have a power cut, you'll either have "scratch" or "realname"
with correct data.

> sync();		// #2

You can just do "fsync(realname)" instead. In case of JFFS2 there is not
big difference, but if you ever migrate to another FS, there will be big
difference.

> As far as I understand the information you cited, this should be safe
> under all circumstances for jffs2.  Is that assumption correct?

Not sure what is your definition of "safe". Step 1 does truncation, I've
explained possible outcome of this above.

> As calling sync() might be a lot more expensive than fsync() if other
> file systems are used simultaneously (I have a vfat fs on a CF card
> open), my question is now if I can safely omit either sync() #1 or #2
> or both?

You do not need 'sync()' #1 at all. And 'sync()' #2 may be turned into
'fsync(realname)'.

> When reading, I first try realname, and if that fails scratch, as to
> cover the case that rename() was killed in mid-air so realname has
> already been removed from the directory, but scratch is still there.
> Can this case happen at all for jffs2?

I think this can happen, AFAIR, rename will just do the change and put
it to the write-buffer, or you can have a power cut while doing re-name.

But you are not safe at the open(O_TRUNC) and write() stages.

I explained the steps of the reliable file (e.g., config file) update
here:

http://www.linux-mtd.infradead.org/faq/ubifs.html#L_atomic_change

You can read about UBIFS write-buffer here (JFFS2 write-buffer is almost
the same, but there is only one write-buffer in JFFS2):

http://www.linux-mtd.infradead.org/doc/ubifs.html#L_writebuffer

I mean, the concept is the same, we borrowed it from JFFS2.

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)




More information about the linux-mtd mailing list