Краткий ответ: решение проблемы на уровне приложения - неправильное место. EXT4 должен убедиться, что после того, как я закрою файл, данные будут записаны своевременно. В настоящее время EXT4 «оптимизирует» эту запись, чтобы иметь возможность собирать больше запросов на запись и обрабатывать их за один раз.
Проблема очевидна: независимо от того, что вы делаете, вы не можете быть уверены, что ваши данные заканчиваются на диске. Вызов fdisk () вручную только ухудшает ситуацию: вы в основном мешаете оптимизации EXT4, замедляя всю систему.
OTOH, EXT4 обладает всей информацией, необходимой для обоснованного предположения, когда необходимо записать данные на диск. В этом случае я переименовываю временный файл в имя существующего файла. Для EXT4 это означает, что он должен либо отложить переименование (чтобы данные исходного файла оставались нетронутыми после сбоя), либо он должен сбрасываться сразу. Поскольку переименование не может быть отложено (следующий процесс может захотеть увидеть новые данные), переименование неявно означает сброс, и это сброс должен происходить на уровне FS, а не на уровне приложения.
EXT4 может создать виртуальную копию файловой системы, которая содержит изменения, пока диск не изменен (пока). Но это не влияет на конечную цель: приложение не может знать, какие оптимизации ФС собирается выполнить, и поэтому ФС должна убедиться, что оно выполняет свою работу.
Это тот случай, когда безжалостная оптимизация зашла слишком далеко и испортила результаты. Золотое правило: оптимизация никогда не должна менять конечный результат. Если вы не можете поддерживать это, вы не должны оптимизировать.
Пока Tso считает, что более важно иметь быструю FS, а не ту, которая ведет себя правильно, я советую не обновляться до EXT4 и закрывать все сообщения об ошибках по этому поводу - «работает, как задумано Tso».
[ПРАВИТЬ] Еще несколько мыслей по этому поводу. Вы можете использовать базу данных вместо файла. Давайте на мгновение проигнорируем трату ресурсов. Может ли кто-нибудь гарантировать, что файлы, используемые базой данных, не будут повреждены в результате сбоя? Наверное. База данных может записывать данные и вызывать fsync () каждую минуту или около того. Но тогда вы можете сделать то же самое:
while True; do sync ; sleep 60 ; done
Опять же, ошибка в FS препятствует тому, чтобы это работало в каждом случае. В противном случае люди не будут так обеспокоены этой ошибкой.
Вы можете использовать демон настройки фона, например, реестр Windows. Демон записывает все конфиги в один большой файл. Он может вызвать fsync () после записи всего. Проблема решена ... для ваших конфигов. Теперь вам нужно сделать то же самое для всего остального, что пишут ваши приложения: текстовые документы, изображения, что угодно. Я имею в виду, что практически любой процесс Unix создает файл. Это чертовски основа всей идеи Unix!
Ясно, что это не жизнеспособный путь. Таким образом, ответ остается: нет решения на вашей стороне. Продолжайте беспокоить Tso и других разработчиков FS, пока они не исправят свои ошибки.