Linux – Is it guaranteed that nested file systems are synced before the containing file systems with sync(1)

cachefilesystemslinuxmount

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.

Best Answer

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.