У одного хостера работает C++ приложение, которое периодически делает следующее:
int fd = open(filename_tmp, O_CREAT | O_TRUNC | O_NOATIME | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP);
// запишем несколько буферов:
for ( auto &buff : _buffchain ) {
r = write(fd, buff.ptr, buff.size);
// тут (r == buff.size) && (buff.size > 0)
}
fsync(fd); // возможно это надо сделать после close(), но не вижу причин почему, да это и невозможно, дескриптор будет закрыт.
close(fd);
// А пока не произойдёт этого rename, наша работа вообще никому не видна.
rename(filename_tmp, filename);
Иногда, когда после этой процедуры через пару МИНУТ следует внезапный ребут, содержимое файла становится испорченным. Как будто его порубили на куски и немного подвигали эти куски с копированием, обрезанием и наслоением этих кусков. Ошибки в buffchain быть точно не может, там всё мега-примитивно — блок заголовок, блок 1, блок 2. Порча данных случается ВНУТРИ блоков — внутри блока 2, например. И только в ситуациях с внезапным ребутом после некоторого времени после записи. Без ребутов - никогда никакой порчи данных за пару лет работы этого кода замечено не было.
Спасибо.
Вот так запущена виртуалка:
/usr/libexec/qemu-kvm
-name guest=zzzzzz,debug-threads=on
-S
-object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-12-zzzzzz/master-key.aes
-machine pc-i440fx-rhel7.3.0,accel=kvm,usb=off
-m 2048
-realtime mlock=off
-smp 1,sockets=1,cores=1,threads=1
-uuid 4444-4444-4444-4444-4444
-no-user-config
-nodefaults
-chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/domain-12-zzzz/monitor.sock,server,nowait
-mon chardev=charmonitor,id=monitor,mode=control
-rtc base=utc
-no-shutdown
-boot menu=on,strict=on
-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2
-drive file=/vm/zzzz,format=qcow2,if=none,id=drive-virtio-disk0
-device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1
-netdev tap,fd=30,id=hostnet0,vhost=on,vhostfd=32
-device virtio-net-pci,netdev=hostnet0,id=net0,mac=11:22:33:44:55:66,bus=pci.0,addr=0x3
-chardev pty,id=charserial0
-device isa-serial,chardev=charserial0,id=serial0
-device usb-tablet,id=input2,bus=usb.0,port=1
-vnc 111.222.111.222:888,password
-device cirrus-vga,id=video0,bus=pci.0,addr=0x2
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
-msg timestamp=on