Безопасно ли использовать rename () без fsync ()? - PullRequest
26 голосов
/ 15 сентября 2011

Безопасно ли вызывать rename(tmppath, path) без вызова fsync(tmppath_fd) первым?

Я хочу, чтобы путь всегда указывал на полный файл.Я забочусь в основном о Ext4 .Обещано ли, что rename () безопасен во всех будущих версиях ядра Linux?

Пример использования в Python:

def store_atomically(path, data):
    tmppath = path + ".tmp"
    output = open(tmppath, "wb")
    output.write(data)

    output.flush()
    os.fsync(output.fileno())  # The needed fsync().
    output.close()
    os.rename(tmppath, path)

Ответы [ 3 ]

27 голосов
/ 15 сентября 2011

Нет.

Посмотрите на libeatmydata и эту презентацию:

Съешь мои данные: как каждый получает файл IO неверно

http://www.oscon.com/oscon2008/public/schedule/detail/3172

от СтюартаСмит из MySql.

В случае, если он недоступен / больше не доступен, я сохраняю его копию:

3 голосов
/ 28 декабря 2016

Из документации ext4 :

When mounting an ext4 filesystem, the following option are accepted:
(*) == default

auto_da_alloc(*)    Many broken applications don't use fsync() when 
noauto_da_alloc     replacing existing files via patterns such as
                    fd = open("foo.new")/write(fd,..)/close(fd)/
                    rename("foo.new", "foo"), or worse yet,
                    fd = open("foo", O_TRUNC)/write(fd,..)/close(fd).
                    If auto_da_alloc is enabled, ext4 will detect
                    the replace-via-rename and replace-via-truncate
                    patterns and force that any delayed allocation
                    blocks are allocated such that at the next
                    journal commit, in the default data=ordered
                    mode, the data blocks of the new file are forced
                    to disk before the rename() operation is
                    committed.  This provides roughly the same level
                    of guarantees as ext3, and avoids the
                    "zero-length" problem that can happen when a
                    system crashes before the delayed allocation
                    blocks are forced to disk.

Судя по формулировке "испорченные приложения", разработчики ext4 определенно считают плохой практикой, но на практике это так широко используетсяПодход, что это было исправлено в самом ext4.

Так что, если ваше использование соответствует шаблону, вы должны быть в безопасности.

Если нет, я предлагаю вам исследовать дальше вместо вставки fsync здесьи там просто быть в безопасности.Это может быть не очень хорошей идеей, поскольку fsync может сильно повлиять на производительность в ext3 ( read ).

С другой стороны, очистка перед переименованием является правильным способом.замена в не журналируемых файловых системах.Может быть, поэтому ext4 сначала ожидал такого поведения от программ, опция auto_da_alloc была добавлена ​​позже как исправление.Также этот ext3 патч для режима обратной записи (без ведения журнала) пытается помочь неосторожным программам, асинхронно сбрасывая при переименовании, чтобы снизить вероятность потери данных.

Вы можете прочитать больше опроблема ext4 здесь .

1 голос
/ 15 сентября 2011

Если вы заботитесь только о ext4, а не ext3, я бы рекомендовал использовать fsync для нового файла перед переименованием. Производительность fsync в ext4, кажется, намного лучше, чем в ext3 без очень долгих задержек. Или это может быть тот факт, что обратная запись является режимом по умолчанию (по крайней мере, в моей системе Linux).

Если вы заботитесь только о том, чтобы файл был завершен, а не о том, какой файл назван в каталоге, вам нужно только fsync новый файл. Нет необходимости также fsync для каталога, так как он будет указывать либо на новый файл с его полными данными, либо на старый файл.

...