Intereting Posts

Гарантируется ли, что вложенные файловые системы синхронизируются перед содержащими файловыми системами с помощью sync (1)?

У меня есть файл ext4 с шифрованием luks в файле, который я использую для хранения конфиденциальных данных (давайте назовем эту FS «внутренней»). Сам файл снова находится на другом ext4, который находится на физическом SSD. Давайте назовем эту ФС “внешней”. Внутренняя ФС монтируется с помощью петлевого устройства, указывающего на файл на внешней ФС.

Когда я вызываю sync (1), гарантируется ли, что все ожидающие записи внутренней FS сохраняются?

Если синхронизация происходит в неудачном порядке, возможно (в моем понимании) произойдет следующее:

  1. Данные записываются во Внутреннюю ФС.
  2. sync вызвана.
  3. Внешние записи в кэше FS записываются на диск.
  4. Кэшированные записи внутренней FS записываются в файл на Outer FS.
  5. Записи из Inner FS на Outer FS все еще в кеше.
  6. Авария случается.
  7. Записи во Внутреннюю ФС теряются, несмотря на то, что происходит до sync .

Гарантирует ли синхронизация, что этого не происходит, или я должен вызывать синхронизацию столько раз, сколько я вложил в слои файловых систем, чтобы быть уверенным?

Я прошу Linux, но если POSIX знает об этом, меня это тоже заинтересует.

К сожалению, на странице руководства Debian по sync(1) или sync(2) нет информации по этому делу.

Да, это гарантировано.
Вы явно не заявляете, как вы делаете вложенную файловую систему, но я собираюсь предположить, что вы используете блочное устройство обратной связи.

В этом случае ключевой бит можно увидеть здесь в исходном коде ядра :

 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; } 

Обратите внимание на вызов vfs_fsync(file, 0) . Это означает, что драйвер обратной петли явно вызывает синхронизацию с файлом, поддерживающим блочное устройство обратной связи.

Порядок не предоставляется, но наиболее вероятный способ состоит в том, что kernel ​​пересекает таблицу монтирования при вызове sync(2) . Этот метод используется в Solaris и, скорее всего, также используется в Linux.

Кажется, это то, что вам не нравится, поэтому в вашем случае следует выдавать больше, чем синхронный вызов.