Comment 30 for bug 148003

Revision history for this message
Jan Klötzke (jan-kloetzke) wrote :

The problem is originally caused by a race condition between cryptsetup (actually libdevicemapper) and UDEV. In a UDEV system cryptsetup should not add or remove the device node by itself but this is not so easy to fix I think.

Anyway, it should be no problem if HAL correctly recognizes all additions/removals of nodes under /dev/mapper but this is not the case. If UDEV gets a 'device added' notification and the node is already in place then it leaves the node as it is and continues. On the other hand if UDEV gets a 'device removed' kernel notification and the device node is not present then no 'RUN' rules are executed! One can see this in the debug logs below. In the failed case the 'udev_node_remove' call is missing and, most important, also the 'pass_env_to_socket' calls. Due to this HAL will not know that the device node was removed!

== good notification ==
Jan 10 20:26:30 axel udevd[2679]: udev_event_run: seq 2918 forked, pid [8792], 'remove' 'block', 0 seconds old
Jan 10 20:26:30 axel udevd-event[8792]: name_index: removing index: '/dev/.udev/names/mapper\x2fluks_crypto_10926a57-5d12-4800-9422-e16288e999db/\x2fblock\x2fdm-2'
Jan 10 20:26:30 axel udevd-event[8792]: name_index: removing index: '/dev/.udev/names/disk\x2fby-id\x2fdm-name-luks_crypto_10926a57-5d12-4800-9422-e16288e999db/\x2fblock\x2fdm-2'
Jan 10 20:26:30 axel udevd-event[8792]: name_index: removing index: '/dev/.udev/names/disk\x2fby-uuid\x2fd66d2764-0ebf-4dd0-8b38-19b96d58a1cf/\x2fblock\x2fdm-2'
Jan 10 20:26:30 axel udevd-event[8792]: name_index: removing index: '/dev/.udev/names/disk\x2fby-label\x2fBackup/\x2fblock\x2fdm-2'
Jan 10 20:26:30 axel udevd-event[8792]: udev_node_remove: removing device node '/dev/mapper/luks_crypto_10926a57-5d12-4800-9422-e16288e999db'
Jan 10 20:26:30 axel udevd-event[8792]: udev_node_update_symlinks: update symlink 'disk/by-id/dm-name-luks_crypto_10926a57-5d12-4800-9422-e16288e999db' of '/block/dm-2'
Jan 10 20:26:30 axel udevd-event[8792]: udev_db_get_devices_by_name: no index directory '/dev/.udev/names/disk\x2fby-id\x2fdm-name-luks_crypto_10926a57-5d12-4800-9422-e16288e999db': No such file or directory
Jan 10 20:26:30 axel udevd-event[8792]: update_link: found -1 devices with name 'disk/by-id/dm-name-luks_crypto_10926a57-5d12-4800-9422-e16288e999db'
Jan 10 20:26:30 axel udevd-event[8792]: update_link: no reference left, remove 'disk/by-id/dm-name-luks_crypto_10926a57-5d12-4800-9422-e16288e999db'
Jan 10 20:26:30 axel udevd-event[8792]: udev_node_update_symlinks: update symlink 'disk/by-uuid/d66d2764-0ebf-4dd0-8b38-19b96d58a1cf'of '/block/dm-2'
Jan 10 20:26:30 axel udevd-event[8792]: udev_db_get_devices_by_name: no index directory '/dev/.udev/names/disk\x2fby-uuid\x2fd66d2764-0ebf-4dd0-8b38-19b96d58a1cf': No such file or directory
Jan 10 20:26:30 axel udevd-event[8792]: update_link: found -1 devices with name 'disk/by-uuid/d66d2764-0ebf-4dd0-8b38-19b96d58a1cf'
Jan 10 20:26:30 axel udevd-event[8792]: update_link: no reference left, remove 'disk/by-uuid/d66d2764-0ebf-4dd0-8b38-19b96d58a1cf'
Jan 10 20:26:30 axel udevd-event[8792]: udev_node_update_symlinks: update symlink 'disk/by-label/Backup' of '/block/dm-2'
Jan 10 20:26:30 axel udevd-event[8792]: udev_db_get_devices_by_name: no index directory '/dev/.udev/names/disk\x2fby-label\x2fBackup': No such file or directory
Jan 10 20:26:30 axel udevd-event[8792]: update_link: found -1 devices with name 'disk/by-label/Backup'
Jan 10 20:26:30 axel udevd-event[8792]: update_link: no reference left, remove 'disk/by-label/Backup'
Jan 10 20:26:30 axel udevd-event[8792]: pass_env_to_socket: passed 770 bytes to socket '/org/freedesktop/hal/udev_event',
Jan 10 20:26:30 axel udevd-event[8792]: pass_env_to_socket: passed -1 bytes to socket '/org/kernel/udev/monitor',
Jan 10 20:26:30 axel udevd-event[8792]: udev_event_run: seq 2918 finished

== failed notification ==
Jan 10 20:27:08 axel udevd[2679]: udev_event_run: seq 2950 forked, pid [8911], 'remove' 'block', 0 seconds old
Jan 10 20:27:08 axel udevd-event[8911]: name_index: removing index: '/dev/.udev/names/mapper\x2fluks_crypto_10926a57-5d12-4800-9422-e16288e999db/\x2fblock\x2fdm-2'
Jan 10 20:27:08 axel udevd-event[8911]: name_index: removing index: '/dev/.udev/names/disk\x2fby-id\x2fdm-name-luks_crypto_10926a57-5d12-4800-9422-e16288e999db/\x2fblock\x2fdm-2'
Jan 10 20:27:08 axel udevd-event[8911]: name_index: removing index: '/dev/.udev/names/disk\x2fby-uuid\x2fd66d2764-0ebf-4dd0-8b38-19b96d58a1cf/\x2fblock\x2fdm-2'
Jan 10 20:27:08 axel udevd-event[8911]: name_index: removing index: '/dev/.udev/names/disk\x2fby-label\x2fBackup/\x2fblock\x2fdm-2'
Jan 10 20:27:08 axel udevd-event[8911]: udev_node_update_symlinks: update symlink 'disk/by-id/dm-name-luks_crypto_10926a57-5d12-4800-9422-e16288e999db' of '/block/dm-2'
Jan 10 20:27:08 axel udevd-event[8911]: udev_db_get_devices_by_name: no index directory '/dev/.udev/names/disk\x2fby-id\x2fdm-name-luks_crypto_10926a57-5d12-4800-9422-e16288e999db': No such file or directory
Jan 10 20:27:08 axel udevd-event[8911]: update_link: found -1 devices with name 'disk/by-id/dm-name-luks_crypto_10926a57-5d12-4800-9422-e16288e999db'
Jan 10 20:27:08 axel udevd-event[8911]: update_link: no reference left, remove 'disk/by-id/dm-name-luks_crypto_10926a57-5d12-4800-9422-e16288e999db'
Jan 10 20:27:08 axel udevd-event[8911]: udev_node_update_symlinks: update symlink 'disk/by-uuid/d66d2764-0ebf-4dd0-8b38-19b96d58a1cf'of '/block/dm-2'
Jan 10 20:27:08 axel udevd-event[8911]: udev_db_get_devices_by_name: no index directory '/dev/.udev/names/disk\x2fby-uuid\x2fd66d2764-0ebf-4dd0-8b38-19b96d58a1cf': No such file or directory
Jan 10 20:27:08 axel udevd-event[8911]: update_link: found -1 devices with name 'disk/by-uuid/d66d2764-0ebf-4dd0-8b38-19b96d58a1cf'
Jan 10 20:27:08 axel udevd-event[8911]: update_link: no reference left, remove 'disk/by-uuid/d66d2764-0ebf-4dd0-8b38-19b96d58a1cf'
Jan 10 20:27:08 axel udevd-event[8911]: udev_node_update_symlinks: update symlink 'disk/by-label/Backup' of '/block/dm-2'
Jan 10 20:27:08 axel udevd-event[8911]: udev_db_get_devices_by_name: no index directory '/dev/.udev/names/disk\x2fby-label\x2fBackup': No such file or directory
Jan 10 20:27:08 axel udevd-event[8911]: update_link: found -1 devices with name 'disk/by-label/Backup'
Jan 10 20:27:08 axel udevd-event[8911]: update_link: no reference left, remove 'disk/by-label/Backup'
Jan 10 20:27:08 axel udevd-event[8911]: udev_event_run: seq 2950 finished
Jan 10 20:27:08 axel udevd[2679]: udev_done: seq 2950, pid [8911] exit with 1, 0 seconds old

In fact this bug shows up in two problems which were already described above:

1. Volume not mounted
Cause: cryptsetup first creates a temporary device node (temporary-cryptsetup-XXXXX), immediately removes it and creates the final node. If cryptsetup removes the temporary node _before_ UDEV then no notification is passed to HAL. After this the final node is created -> notification is passed to HAL but is ignored because HAL already knows '/sys/block/dm-X' -> HAL keeps pointing to the temporary node -> cannot mount

2. No passphrase popup
Cause: When the device was disconnected last time UDEV came too late and the clear text device node was already removed by cryptsetup -> no notification of device removal is passed to HAL -> HAL keeps the clear text device node -> when device is plugged again HAL thinks it is already decrypted because of the stale clear text node entry

The fix should be quite simple by patching UDEV to tolerate the fact that a device node may have already been removed. It looks also more consistent because when a device is added and the device node is already there then UDEV happily keeps the node and proceeds. The following patch worked for me on Gutsy to surpress the artifacts...

--- old/udev_node.c 2007-06-23 17:44:48.000000000 +0200
+++ new/udev_node.c 2008-01-14 23:21:56.000000000 +0100
@@ -401,7 +401,7 @@ int udev_node_remove(struct udevice *ude
  strlcat(filename, udev->name, sizeof(filename));
  if (stat(filename, &stats) != 0) {
   dbg("device node '%s' not found", filename);
- return -1;
+ goto already_removed;
  }
  if (udev->devt && stats.st_rdev != udev->devt) {
   info("device node '%s' points to a different device, skip removal", filename);
@@ -414,6 +414,7 @@ int udev_node_remove(struct udevice *ude
  if (retval)
   return retval;

+already_removed:
  setenv("DEVNAME", filename, 1);
  num = udev->partitions;
  if (num > 0) {