I have a luks-encrypted ext4 in a file which I use to store sensitive data (let us call this FS "inner"). The file itself is again on another ext4, which resides on a physical SSD. Let us call that FS "outer". The Inner FS is mounted using a loopback device pointing to the file on the Outer FS.

When I invoke sync(1), is it guaranteed that all pending writes of the Inner FS are persisted?

If the sync happens in an unfortunate order, it would be (in my understanding) possible that the following happens:

  1. Data is written to Inner FS.
  2. sync invoked.
  3. Outer FS cached writes get written to disk.
  4. Inner FS cached writes get written to the file on Outer FS.
  5. Writes from Inner FS on Outer FS are still in caches.
  6. Crash happens.
  7. Writes to Inner FS are lost despite happening-before a sync.

Does sync guarantee that this does not happen, or do I have to invoke sync as many times as I have nested layers of file systems to be sure?

I am asking for Linux, but if POSIX has word on this, I’d be interested in that, too.

The Debian manpage on sync(1) or sync(2) unfortunately does not have information on this case.


Yes, it is guaranteed.
You don't explicitly state how you're doing the nested filesystem, but I'm going to assume you're using a block loopback device.

In this case, the key bit can be seen here in the kernel source code:

static int lo_req_flush(struct loop_device *lo, struct request *rq)
    struct file *file = lo->lo_backing_file;
    int ret = vfs_fsync(file, 0);
    if (unlikely(ret && ret != -EINVAL))
        ret = -EIO;

    return ret;

Note the call to vfs_fsync(file, 0). This means that the loopback driver is explicitly invoking a sync on the file which is backing the loopback block device.

  • 1
    -1 for missinterpreting the code. This is a call to fsync() not a call to sync(). BTW: I invented the fbk() driver (filesystem emulates block devide) 30 years ago and Linux did just copy that idea as "lo" ;-) – schily Jun 20 '18 at 13:24
  • 2
    "This is a call to fsync()". Yes it is. As I explained in the answer, it's a call to fsync on the backing file. The function lo_req_flush is called by the sync(). If you're going to criticize, please understand what it is you're criticizing. – Patrick Jun 20 '18 at 14:18
  • Your problem seems to be that you don't understand what you are writing about. Calling fsync() on a flesystem other than ZFS (COW) will make the related filesystem dirty even though one specific files on that filesystem is then granted to be on disk. – schily Jun 20 '18 at 14:57
  • 1
    @schily But if the Inner FS invokes fsync on the backing file on the Outer FS, there is a guarantee that the data written by the Inner FS is in fact persisted and will be recovered after a crash? Note that my question was not about the dirty-ness of the Outer FS, but about the persistency of writes in the Inner FS. If the Outer FS is dirty after sync(1) but in a state where the writes of the Inner FS are guaranteed to be recovered, that’s exactly what I was asking for (sorry if that was unclear). – Jonas Schäfer Jun 20 '18 at 18:08
  • @Patrick Yes, loopback device, I’ll add that to my question :) – Jonas Schäfer Jun 20 '18 at 18:08

There is no grant on the order, but the most probale way is that the kernel traverses the mount table when sync(2) has been called. This method is used by Solaris and most likely is used by Linux as well.

This seems to be what you don't like, so should issue more than sync call in your case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.