Common way to write an image to disk looks like:
dd if=file.img of=/dev/device
After this command, is it necessary to run sync?
sync(2) explains it only flushes filesystem caches. Since dd command is not related to any filesystem, I think it is not necessary to run sync. However, block layer is complex and in doubt, most people prefers to run sync.
Does anyone has a proof that it is useful or useless?
Advertisement
Answer
TL;DR: Run blockdev --flushbufs /dev/device after dd.
I tried to follow the different paths in kernel. Here is what I understood:
ioctl(block_dev, BLKFLSBUF, 0)callblkdev_flushbuf(). Considering its name, it should flush caches associated with device (or I think you can consider there is bug in device driver). I think it should also responsible to flush hardware caches if they exist. Noticee2fsprogsuseBLKFLSBUF.fdatasync()(andfsync()) will callblkdev_fsync(). It looks likeblkdev_flushbuf()but it only impact range of data written by current process (It usefilemap_write_and_wait_range()whileBLKFLSBUFusefilemap_write_and_wait).- Closing a block device calls
blkdev_close()that do not flush buffers. sync()will callsync_fs(). It will flush filesystem caches and callfsync()on underlying block device.- Command
sync /dev/devicewill callfsync()on/dev/device. However, I think it is useless sincedddidn’t touch to any filesystem.
So my conclusions is that call to sync has no (direct) impact on block device. However, passing fdatasync (or fsync) to dd is the only way to guarantee that data are correctly written on media.
If have you run dd but you missed to pass fdatasync, running sync /dev/device is not sufficient. You have have to run dd with fdatasync on whole device. Alternatively, you can call BLKFLSBUF to flush whole device. Unfortunately, there is no standard command for that.
EDIT
You can issue a BLKFLSBUF with blockdev --flushbufs /dev/device.