Переименован() без fsync() безопасен?

Безопасно ли вызывать 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)

Ответ 1

Нет.

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

Ешьте мои данные: как каждый получает файл IO Wrong

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

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

Если он находится в автономном режиме/недоступен, я сохраняю его копию:

Ответ 2

От документация 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 (читать).

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

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

Ответ 3

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

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