linux - ¿Es seguro rename() sin fsync()?
ext4 (3)
De la 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 redacción de "aplicaciones rotas", los desarrolladores de ext4 definitivamente lo consideran una mala práctica, pero en la práctica es un método tan ampliamente utilizado que fue parcheado en ext4.
Así que si su uso se ajusta al patrón, debería estar seguro.
Si no, le sugiero que siga investigando en lugar de insertar fsync
aquí y allá para estar seguro. Puede que no sea una buena idea, ya que fsync
puede ser un gran éxito de rendimiento en ext3 ( read ).
Por otro lado, vaciar antes de cambiar el nombre es la forma correcta de realizar el reemplazo en sistemas de archivos que no son de diario. Tal vez por eso ext4 al principio esperaba este comportamiento de los programas, la opción auto_da_alloc
se agregó más tarde como una solución. Además, this parche ext3 para el modo de reescritura (no registro en diario) intenta ayudar a los programas descuidados al vaciar de forma asíncrona al cambiar el nombre para reducir la posibilidad de pérdida de datos.
Puedes leer más sobre el problema ext4 here .
¿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 preocupo principalmente por Ext4 . ¿Se promete que rename () será seguro en todas las versiones futuras 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)
No.
Mira libeatmydata, y esta presentación:
Coma mis datos: cómo todo el mundo obtiene un archivo IO incorrecto
http://www.oscon.com/oscon2008/public/schedule/detail/3172
por Stewart Smith de MySql.
En caso de que esté fuera de línea / ya no esté disponible, guardo una copia:
Si solo te importa ext4 y no ext3, te recomiendo 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 la escritura es el modo predeterminado (al menos en mi sistema Linux).
Si solo le importa que el archivo esté completo y no a qué archivo se nombra en el directorio, solo necesita fsync el nuevo archivo. No es necesario fsync el directorio también, ya que apuntará al archivo nuevo con sus datos completos o al archivo antiguo.