¿Es seguro renombrar() sin fsync ()?


¿Es seguro llamar a rename(tmppath, path) sin llamar primero a fsync(tmppath_fd)?

Quiero que la ruta siempre apunte a un archivo completo. Me importa principalmente Ext4 . ¿Se promete que rename() será seguro en todas las futuras versiones del kernel de Linux?

Un ejemplo de uso en 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)
Author: Ivo Danihelka, 2011-09-15

3 answers

No.

Mira libeatmydata, y esta presentación:

Comer Mis Datos: Cómo Todo el Mundo Obtiene Archivo IO Mal

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

Por Stewart Smith de MySQL.

En caso de que esté desconectado/ya no esté disponible, guardo una copia:

 23
Author: sehe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-20 23:07:46

De documentación de 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.

A juzgar por la expresión "aplicaciones rotas", definitivamente se considera una mala práctica por los desarrolladores de ext4, pero en la práctica es un enfoque tan ampliamente utilizado que fue parcheado en ext4.

Así que si su uso se ajusta al patrón, debe estar seguro.

Si no, le sugiero que investigue más en lugar de insertar fsync aquí y allá solo para estar seguros. Eso podría no ser una buena idea ya que fsync puede ser una golpe de rendimiento en ext3 (read).

Por otro lado, el lavado antes de cambiar el nombre es la forma correcta de hacer el reemplazo en sistemas de archivos sin diario. Tal vez es por eso que ext4 al principio esperaba este comportamiento de los programas, la opción auto_da_alloc se agregó más tarde como una solución. También este parche ext3 para el modo writeback (sin diario) intenta ayudar a los programas descuidados al limpiar asincrónicamente el cambio de nombre para reducir la posibilidad de pérdida de datos.

Puede leer más sobre el problema ext4 aquí.

 3
Author: user,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-28 14:38:07

Si solo te importa ext4 y no ext3, entonces te recomendaría usar fsync en el nuevo archivo antes de cambiar el nombre. El rendimiento de fsync en ext4 parece ser mucho mejor que en ext3 sin los retrasos muy largos. O podría ser el hecho de que writeback es el modo predeterminado (al menos en mi sistema Linux).

Si solo le importa que el archivo esté completo y no qué archivo se nombra en el directorio, entonces solo necesita fsync el nuevo archivo. No hay necesidad de fsync el directorio también desde apuntará al nuevo archivo con sus datos completos, o al archivo antiguo.

 1
Author: Zan Lynx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-15 16:02:37