PATA delays - nomis/sr-test GitHub Wiki
With a per-device sr_mutex
, when there are two PATA devices (master and slave) on the same host, one of them is somehow inevitably blocked for over a second by the other. This can happen anywhere in the open
/ioctl
/close
sequence.
3 out of 4 of the PATA devices return SCSI ASC 0x04 (LOGICAL UNIT NOT READY, CAUSE NOT REPORTABLE) on close
immediately after closing the tray without any media, causing sr_check_events
to decide that media is present. They then return 0x3A (MEDIUM NOT PRESENT) on the next open
.
This causes a DISK_EVENT_MEDIA_CHANGE
event that requires extra calls to revalidate_disk()
on every open
and close
. The call to revalidate_disk()
takes longer if the other device on the same host is concurrently opening or closing the tray.
If the pair of devices both have these DISK_EVENT_MEDIA_CHANGE
events, they usually experience the same timing and the open
is not delayed. Instead, the ioctl
of one and the close
from of the other will be delayed.
The SCSI host layer won't send more than one request at a time and the START_STOP
commands take at least a second to return.
systemd-udevd
This process likes to interfere by opening and closing the device. Make sure it's stopped before testing.
systemctl stop systemd-udevd-kernel.socket
systemctl stop systemd-udevd-control.socket
systemctl stop udev
sr_block_open()
__blkdev_get() {
sr_block_open() {
check_disk_change() {
disk_clear_events() {
sr_check_events() {
last_present (1) != cd->media_present (0), set cd->device->changed = 1
pending event DISK_EVENT_MEDIA_CHANGE
}
}
if (DISK_EVENT_MEDIA_CHANGE is pending) {
flush_disk() {
bdev->bd_invalidated = 1
}
revalidate_disk() {
// A: +72ms
}
}
}
}
bdev_disk_changed() {
if (bdev->bd_invalidated) {
revalidate_disk() {
// B: +1.2s
}
}
}
}
scsi_cmd_ioctl()
sr_block_release()
sr_block_release() {
sr_check_events() {
last_present (0) != cd->media_present (1), set cd->device->changed = 1
pending event DISK_EVENT_MEDIA_CHANGE
}
}