В правиле udev /lib/udev/rules.d/60-cdrom_id.rules, отвечающем за блокирование привода при вставленном диске, я обратил внимание на следующий комментарий:
Код: Выделить всё
# import device and media properties and lock tray to
# enable the receiving of media eject button events
IMPORT{program}="cdrom_id --lock-media $tempnode"
- вот как раз события-то и не приходят! Кроме того, как я уже
писал, известно, что udisks разблокирует привод после монтирования. Может, в этом и проблема?
Ну, выполнил
# /lib/udev/cdrom_id --lock-media /dev/sr1 - привод заблокировался, но на нажатие кнопки не реагировал, однако после размонтирования событие внезапно пришло, как будто всё это время стояло в очереди, ожидая чего-то.
Далее я решил проверить, определит ли udisks, что диска уже нет, если его об этом попросить. Для этого вынул диск, а затем выполнил
$ udisks --poll-for-media /dev/sr1 - пришло событие change. Ладно, а если вынуть диск и сразу вставить обратно? - после выполнения команды событие снова пришло. Самое удивительное, что даже если диск вообще не вынимать, событие change после выполнения данной команды приходит, отрабатывает правило udev, и лоток блокируется, как при вставке нового диска

. Причём повторные вызовы этой команды не имеют никакого эффекта вплоть до размонтирования и смены диска. Как будто после монтирования udev "забывает" о диске, а после udisks --poll-for-media "вспоминает", и "помнит" уже вплоть до его замены. То есть poll'инг работает как-то криво.
И тут я вспомнил комментарий в коде udisks, на который наткнулся в поиске
кода, разблокирующего привод после монтирования:
Код: Выделить всё
/* If the kernel and device support sending EJECT_REQUEST change uevents
* and we use in-kernel polling, keep the door locked, as udev calls
* eject on pressing the button. Otherwise unlock it, to keep the
* hardware button working without userspace support */
if (!device->priv->using_in_kernel_polling)
unlock_cd_tray (device);
Вспомнив упоминавшийся комментарий в правиле udev, утверждающий, что события кнопки извлечения приходят лишь при заблокированном лотке, решил проверить, используется ли in-kernel polling в Debian и Ubuntu. Результаты:
- Ubuntu
user
$ cat /sys/module/block/parameters/events_dfl_poll_msecs
0
$ cat /sys/block/sr1/events_poll_msecs
2000
- используется.
- Debian
user
$ cat /sys/module/block/parameters/events_dfl_poll_msecs
0
$ cat /sys/block/sr1/events_poll_msecs
-1
- не используется. Ну так давайте включим: # echo 2000 > /sys/block/sr1/events_poll_msecs - проблема исчезла.
В чём же дело, почему in-kernel polling не используется в Debian? Ответ нашёлся в списке патчей на udev, накладываемых в Ubuntu:
Код: Выделить всё
Description: Set default polling interval on CD drives as well. The events_dfl_poll_msecs will not trigger if "block" is not a module, but built in. This will avoid udisks etc. having to poll from userspace, and provide proper ejection when the hardware eject button is pressed.
Author: Martin Pitt <martin.pitt@ubuntu.com>
Bug-Ubuntu: https://launchpad.net/bugs/890592
Index: precise/rules/rules.d/60-persistent-storage.rules
===================================================================
--- precise.orig/rules/rules.d/60-persistent-storage.rules 2012-02-06 09:09:39.413371483 +0100
+++ precise/rules/rules.d/60-persistent-storage.rules 2012-03-28 11:33:05.900794721 +0200
@@ -10,6 +10,7 @@
# enable in-kernel media-presence polling
ACTION=="add", SUBSYSTEM=="module", KERNEL=="block", ATTR{parameters/events_dfl_poll_msecs}=="0", ATTR{parameters/events_dfl_poll_msecs}="2000"
+ACTION=="add", ATTR{removable}=="1", ATTR{events_poll_msecs}=="-1", ATTR{events_poll_msecs}="2000"
SUBSYSTEM!="block", GOTO="persistent_storage_end"
В Debian block также не является модулем, а вкомпилирован прямо в ядро. Вот и причина несрабатывания правила, включающего in-kernel polling.