Как прочно переименовать файл в POSIX? - PullRequest
18 голосов
/ 22 сентября 2010

Как правильно переименовать файл в файловой системе POSIX на длительный срок? Особенно интересует fsyncs в каталогах . (Если это зависит от OS / FS, я спрашиваю о Linux и ext3 / ext4).

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

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

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

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

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

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

Ответы [ 4 ]

15 голосов
/ 27 апреля 2011

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

Поэтому, если вы переименуете (A, B), ни при каких обстоятельствах вы никогда не увидите состояние с файлом в обоих каталогахили ни один каталог.Всегда будет точно один, независимо от того, что вы делаете с помощью fsync () или из-за сбоя системы.

Но это не решает проблему обеспечения надежности операции rename (). POSIX отвечает на этот вопрос :

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

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

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

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

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

(дополнено дополнительной информацией о поведении в зависимости от Linux и переносимости)

12 голосов
/ 11 мая 2013

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

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

Реальный вопрос должен быть следующим:

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

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

fsync (destdirfd) также неявно fsync каталог с исходным кодом?

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

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

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

Если я fsync вместо исходного каталога, fsync,Будет ли это также неявно fsync каталог назначения?

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

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

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

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

0 голосов
/ 13 апреля 2011

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

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

0 голосов
/ 12 апреля 2011

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

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

...