Вопрос

Как правильно переименовать файл в файловой системе POSIX?В частности, интересно узнать о fsyncs на каталоги.(Если это зависит от ОС/ФС, я спрашиваю о Linux и ext3/ext4).

Примечание:на StackOverflow есть и другие вопросы о долгосрочных переименованиях, но AFAICT они не касаются fsync-синхронизации каталогов (что для меня важно - я даже не изменяю данные файла).

В настоящее время у меня есть (в Python):

dstdirfd = open(dstdirpath, O_DIRECTORY|O_RDONLY)
rename(srcdirpath + '/' + filename, dstdirpath + '/' + filename)
fsync(dstdirfd)

Конкретные вопросы:

  • Означает ли это также неявную синхронизацию исходного каталога?Или же после выключения и включения питания файл появится в обоих каталогах (то есть мне придется проверить количество жестких ссылок и вручную выполнить восстановление), т.е.невозможно гарантировать долговременную операцию атомарного перемещения?
  • Если я синхронизирую исходный каталог вместо каталог назначения, будет ли это также неявно синхронизировать каталог назначения?
  • Существуют ли какие-либо полезные инструменты тестирования/отладки/обучения (инжекторы ошибок, инструменты самоанализа, макеты файловых систем и т. д.)?

Заранее спасибо.

Это было полезно?

Решение

Posix определяет, что Переименовать функцию должен быть атомной.

Поэтому, если вы переименуете (a, b), ни при каких обстоятельствах вы не должны видеть состояние с файлом как в каталогах, либо ни в каталоге. Там всегда будет именно один, независимо от того, что вы делаете с fsync () или вылетают ли система.

Но это не решает проблему убедиться, что операция Rename () длительна. Posix отвечает на этот вопрос:

Если определен _posix_synchronized_io, функция fsync () должна принуждать все в настоящее время операции ввода / вывода ввода / вывода, связанные с файлом, обозначенным файловым дескриптором, улучшенным синхронизированным состоянием завершения ввода / вывода. Все операции ввода / вывода должны быть выполнены, как определено для синхронизированного завершения целостности файла ввода / вывода.

Таким образом, если вы fsync () каталог, в ожидании переименования операций должен быть передан на диск к тому времени, когда это возвращает. fsync () любого каталога должен быть достаточным, потому что атомачность операции Rename () потребует бы, чтобы изменения каталогов были синхронизированы атомным образом.

Наконец, в отличие от утверждения в сообщении в блоге, упомянутых в другом ответе, обоснование этого объясняет следующее:

Функция fsync () предназначена для форсирования физической записи данных из буферного кэша, и для обеспечения того, чтобы после сбоя системы или другой отказ, чтобы все данные до времени вызова fsync () записаны на диске. Поскольку концепции «буферного кэша», «System Crash», «Физическая запись» и «Нестантивное хранение» здесь не определены, формулировка должна быть более абстрактной.

Система, которая утверждала, что соответствует POSIX, и считает его правильным поведением (то есть не ошибка или ошибка аппаратного обеспечения) для завершения FSync (), и не сохранять эти изменения в стерсении системы, должны будут сознательно искажать себя в отношении спецификации Отказ

(Обновлено дополнительной информацией Re: Linux-специфическое против портативного поведения)

Другие советы

К сожалению, ответ Дэйва неверен.

Не все системы POSIX могут иметь долговременное хранилище.И даже если они это сделают, их все равно «разрешат» очистить после сбоя системы.Для этих систем имеет смысл неактивная функция fsync(), и такая функция fsync() явно разрешена в POSIX.Также законно, что файл можно восстановить в старом каталоге, в новом каталоге, в обоих или в любом другом месте.POSIX не дает никаких гарантий на случай сбоя системы или восстановления файловой системы.

Настоящий вопрос должен быть:

Как выполнить надежное переименование в системах, которые поддерживают это через POSIX API?

Вам нужно выполнить fsync() для обоих, источник и каталог назначения, потому что минимум, который должны делать эти fsync(), — это сохранять то, как должен выглядеть исходный или целевой каталог.

Выполняет ли fsync(destdirfd) неявную синхронизацию исходного каталога?

  • POSIX в целом:нет, ничто не подразумевает, что
  • доб3/4:Я не уверен, что оба изменения в исходном и целевом каталоге попадают в одну и ту же транзакцию в журнале.Если они это сделают, они оба будут преданы друг другу.

Или я могу получить, что файл появится в обоих каталогах после выключения и включения («сбоя»), т.е.невозможно гарантировать долговременную операцию атомарного перемещения?

  • POSIX в целом:никаких гарантий, но вы должны выполнить fsync() оба каталога, что может не быть атомарно-надежным
  • доб3/4:минимальный объем fsync(), который вам понадобится, зависит от параметров монтирования.Например.если смонтировано с помощью «dirsync», вам не понадобится ни одна из этих двух функций fsync().В лучшем случае вам понадобятся обе функции fsync(), но я почти уверен, что достаточно одной (тогда с атомарной надежностью).

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

  • ПОСИКС:нет
  • доб3/4:Я действительно верю, что оба в конечном итоге попадают в одну и ту же транзакцию, поэтому не имеет значения, какой из них вы используете fsync().
  • старые ядра ext3:(если они не находятся в одной и той же транзакции) какая-то не очень оптимальная реализация выполняла слишком большую синхронизацию с помощью fsync(), держу пари, что она фиксировала каждую предыдущую транзакцию.И да, нормальная реализация сначала свяжет его с местом назначения, а затем удалит из источника.Таким образом, fsync(srcdirfd) также вызовет fsync() пункта назначения.
  • ext4/последний ext3:если они не участвуют в одной транзакции, вы можете полностью синхронизировать их независимо (так сделайте и то, и другое).

Существуют ли какие-либо полезные инструменты тестирования/отладки/обучения (инжекторы ошибок, инструменты самоанализа, макеты файловых систем и т. д.)?

Для настоящего краха - нет.Кстати, реальный сбой выходит за рамки поля зрения ядра.Аппаратное обеспечение может изменить порядок записи (и не записать все), что приведет к повреждению файловой системы.Ext4 лучше подготовлена ​​к этому, поскольку по умолчанию включает запреты на запись (опции монтирования) (ext3 нет) и может обнаруживать повреждения с помощью контрольных сумм журнала (также опция монтирования).

И для обучения:узнайте, связаны ли как-то оба изменения в журнале!:-П

Ответ на ваш вопрос собирается вообще будет зависеть от конкретной используемой ОС, тип используемого файловой системы и будь то источник и Dest на одном устройстве или нет.

Я начну с чтения страницы Rename (2) на платформе, которую вы используете.

Мне кажется, что вы пытаетесь выполнить работу файловой системы.Если вы перемещаете файл, за атомарную операцию и восстановление после сбоев отвечают ядро ​​и файловая система, а не ваш код.

В любом случае, эта статья, кажется, отвечает на ваши вопросы относительно fsync:http://blogs.gnome.org/alexl/2009/03/16/ext4-vs-fsync-my-take/

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top