UBIFS robustness questions
adrian.hunter at nokia.com
Mon Jul 27 04:09:11 EDT 2009
Jamie Lokier wrote:
> Adrian Hunter wrote:
>> Jamie Lokier wrote:
>>> Adrian Hunter wrote:
>>>> Sorry to drag this out but it seems like it can be done with symlinks
>>> That's right. It should be powerfail safe.
>>> Don't forget to "rm -fr version1" at the end :-)
>>> However, if you are looking to use this for atomic update of a
>>> directory while there are programs still running which use the
>>> directory, it won't work.
>>> You can't delete the old directory, because programs might still be
>>> inside it...
>> Are you sure about that. I can do this:
>> / # mkdir test2
>> / # cd test2
>> /test2 # cp /bin/bash .
>> /test2 # ls -al
>> drwxr-xr-x 2 root root 224 Jan 3 22:20 .
>> drwxrwxrwx 25 root root 1768 Jan 3 22:20 ..
>> -rwxr-xr-x 1 root root 612764 Jan 3 22:20 bash
>> /test2 # ./bash -c "sleep 30;echo Done" &
>> /test2 # rm bash
>> /test2 # cd ..
>> / # rmdir test2
>> / # ps | grep bash
>> 1261 root 2500 S ./bash -c sleep 30;echo Done
>> / #
>> / #
>> / # Done
>>  + Done ./bash -c "sleep 30;echo Done"
> (By the way, Linux has not always allowed an empty but in-use directory
> to be rmdir'd, but it does these days).
> What I mean is, you can delete the old directory, but it's not always
> safe because you might break programs which are depending on the
> directory's contents when you do.
> For example:
> $ mkdir dir1
> $ echo "message1" > dir1/message
> $ ln -sfT dir1 new
> $ mv -T new current
> $ sh -c 'cd current; while :; do cat message > /dev/ttyAM0; sleep 1; done' &
> ==> Writes "message1" to the serial port every second.
> $ mkdir dir2
> $ echo "message2" > dir2/message
> $ ln -sfT dir2 new
> $ mv -T new current # Looks atomic
> ==> Still writes "message1" to the serial port every second.
> ==> Maybe that's ok, maybe not.
> $ rm -fr dir2 # Old version, no longer in use?
> ==> The background script Writes "File not found" error every second...
> ==> Clearly not ok.
> If the script is written differently as
> $ sh -c 'while :; do cat current/message > /dev/ttyAM0; sleep 1; done' &
> then it works better, changing the message in this example most of time.
> It's not obvious, but even that version has an extremely rare race
> condition: "cat current/message" does path traversal in the kernel,
> which may open "current" just before the symlink changes, then (due to
> preemptive scheduling or SMP) look up "message" after that's been
> deleted. It is probably very hard to trigger, but it's a race condition.
> And even without that race condition, the method doesn't work in
> general. If it was reading two different files, it could easily see
> one file from the old version and one file from the new version for a
> moment. The inconsistency could be harmless or fatal depending on the
> It's a hard problem to solve properly, unless you analyse each
> application or kill each application before the change and restart
> them afterwards. In which case maybe you don't need the change to be
> atomic :-)
> Databases solve it with transactions, which are nice to use and
> understand, but they introduces coordination problems in a different
> way if they aren't used consistently and correctly.
> This is why every Linux distro has occasional glitches when package
> managers update a running system, and reports of things going wrong
> which are too rare to fix, to transient to repeat, and go away on the
> next reboot.
Another problem is that unlinked files that have not been deleted because
they are open, still consume file system space. So on a little embedded
system, you can unexpectedly run out of space.
More information about the linux-mtd