5

I have an old 64MB CF card which I use in my laptop(kernel 2.6.38) with CardBus adapter. If I write a 64MB image to this CF card, then the write speed is more than 200MB/s:

T42 ~ # fdisk -lu

Disk /dev/sda: 40.0 GB, 40007761920 bytes
255 heads, 63 sectors/track, 4864 cylinders, total 78140160 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00043afc

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048    73947135    36972544   83  Linux
/dev/sda2        73949182    78139391     2095105    5  Extended
/dev/sda5        73949184    78139391     2095104   82  Linux swap / Solaris

Disk /dev/sdb: 64 MB, 64225280 bytes
8 heads, 32 sectors/track, 490 cylinders, total 125440 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1   *          32      125300       62634+   4  FAT16 <32M
Partition 1 has different physical/logical endings:
     phys=(488, 7, 32) logical=(489, 3, 21)
T42 ~ # mount | grep -i sdb
T42 ~ # time dd if=64MB of=/dev/sdb bs=10M
6+1 records in
6+1 records out
64225280 bytes (64 MB) copied, 0.320419 s, 200 MB/s

real    0m0.624s
user    0m0.000s
sys 0m0.304s
T42 ~ #

64MB within 0.32s in obviously unrealistic in case of 10 year old CF card and if I remove the card from the laptop right after the dd if=64MB of=/dev/sdb bs=10M has finished, I see lot of <timestamp> end_request: I/O error, dev sdb, sector <sector number> errors in dmesg output. What might cause such behavior?

Martin
  • 7,516

2 Answers2

6

Block device writes are buffered by the kernel. This is clearly visible when a filesystem is mounted (when you unmount, the buffers have to be flushed, leading to a sometimes very long delay before the umount returns). This delay is seemingly getting worse as the available RAM is getting larger and larger. You may be able to write half a GB instantly before the kernel even initializes the data transfer. The kernel may transparently write to the device for minutes after you see the transfer complete.

This feature is very good for many reasons. It allows for much faster response for reading and writing to devices, the data can be also transparently read from the buffer after the write, before the actual physical write is even completed. For hard drives that are mounted on the long term, the kernel schedules writes for when it has time while making the device respond faster from the user's perspective. Especially for magnetic hard drives, writing in big chunks sequentially is also faster than writing small pieces in several places all over the drive: the chunks can be sorted and grouped before pushing to the physical device (although hard drives also do some buffering and data sorting internally in hardware). In short, you don't notice slowness of the device that much, and you also don't notice initial delays (in case of network mounted drives or hard drives that have to spin up from hibernation).

For direct access to a block device, buffering is somewhat unfortunate, because you don't call umount and you don't really notice when the transfer is complete. You should call sync in any case.

orion
  • 12,502
3

The OS is caching the data for dd (and other commands), you should do an sync before removing the CF and wait until the sync is finished.

The caching/buffering is important for performance reasons and also allows the kernel/drivers to rearrange writes to the underlying hardware so that e.g. all writes to a single track on a HD get done in the right order in one go (less head moves).

Anthon
  • 79,293