Search code examples
c++linuxfsync

C++: How to correctly actualize a file against power loss?


I have a linux embedded environment.

Here I have 2 scenarios:

A:

  1. Open and write a temporary file.
  2. Rename temporary file to the original file.
  3. Power loss

Result: After reboot, what I have is:

  • 0-size original file and there is no temporary file.

B:

  1. Open and write a temporary file.

  2. FSYNC temporary file.

  3. Rename temporary file to the original file.

  4. Power loss

Result: After reboot,

  • Original content of original file is kept, although not actualized
  • 0-size temporary file

As you see, between these 2 scenarios, the only difference is fsync of temporary file, and not the original file. In both, I did not fsync the original file.

So, why the original content of original file is kept in scenario B?

From point of view of original file, the change is, actualizing it by renaming non-fsynced file vs fsynced file.

How does this keep the original content?

Edit:

This scenario actualizing original file also failed to safely actualize original file:

  1. Open and write a temporary file.

  2. FSYNC temporary file.

  3. Rename temporary file to the original file.

  4. Fsync original file's directory

  5. Power loss

Result:

0-size original file.

So, how should I do that?


Solution

  • Normaly, if you want to be immune to a power loss, you use journaling. That means that (broadly speaking) you store what you want to write and where, you write it, and when it as successfully be written, you remove it (at least logically) from the journal. In case of major failure (power loss or other system crash), you read the journal and apply any changes still presend. Many file systems have options to enable it, and on a journaling file system, you can expect a rename to be atomic and immune to a power loss: the file will exist either under its previous or new name.

    So the common workflow is:

    • rename the old file to a backup name
    • write the new file to its definitive name
    • close the newfile to ensure it will reside on disk
    • remove the backup file (or give it a different name)

    In case of power loss (or any other crash condition), on next reboot things are simple:

    • if no backup file is present, the file is in a stable state
    • if a backup file is present, it contains the last stable state of the file: the file have to be removed if it exists and the backup must be renamed to the normal name