Hello Kay. Kay Sievers wrote: > > recvmsg() waits until something is queued if udev_monitor->sock is blocking, > > Only on a blocking socket, which it isn't by default: I confirmed using strace utility that Ubuntu 12.04's wait-for-root (source code shown below) calls recvmsg() using blocking mode. # strace /usr/lib/initramfs-tools/bin/wait-for-root /dev/sdaX 5 > It's from a time where the socket was still blocking, but we still > used poll() in calling code. We didn't want to block the caller, hence > the poll() inside the library. So, "poll() in udev_monitor_receive_device() does not wait" is a feature? Then, wait-for-root is responsible for retrying the loop (line 91 to 104) when udev_monitor_receive_device() returned NULL (without waiting for a "block" subsystem event) caused by udev_monitor_receive_device() getting a non-"block" subsystem event at recvmsg(), isn't it? ---------- wait-for-root.c start ---------- 1:#include <libudev.h> 2: 3:#include <sys/types.h> 4:#include <sys/stat.h> 5: 6:#include <time.h> 7:#include <stdio.h> 8:#include <limits.h> 9:#include <signal.h> 10:#include <stdlib.h> 11:#include <string.h> 12:#include <unistd.h> 13: 14: 15:static int device_queued (struct udev *udev, const char *path); 16:static int matching_device (struct udev_device *device, const char *path); 17: 18:static void alarm_handler (int signum); 19: 20: 21:int 22:main (int argc, 23: char *argv[]) 24:{ 25: const char * devpath; 26: char path[PATH_MAX]; 27: int timeout; 28: struct udev * udev; 29: struct udev_monitor *udev_monitor; 30: struct stat devstat; 31: struct udev_device * udev_device; 32: const char * type; 33: 34: if (argc != 3) { 35: fprintf (stderr, "Usage: %s DEVICE TIMEOUT\n", argv[0]); 36: exit (2); 37: } 38: 39: devpath = argv[1]; 40: if (! strncmp (devpath, "UUID=", 5)) { 41: strcpy (path, "/dev/disk/by-uuid/"); 42: strcat (path, devpath + 5); 43: } else if (! strncmp (devpath, "LABEL=", 6)) { 44: strcpy (path, "/dev/disk/by-label/"); 45: strcat (path, devpath + 6); 46: } else { 47: strcpy (path, devpath); 48: } 49: 50: timeout = atoi (argv[2]); 51: 52: signal (SIGALRM, alarm_handler); 53: alarm (timeout); 54: 55: /* Connect to the udev monitor first; if we stat() first, the 56: * event might happen between the stat() and the time we actually 57: * get hooked up. 58: */ 59: udev = udev_new (); 60: udev_monitor = udev_monitor_new_from_netlink (udev, "udev"); 61: 62: udev_monitor_filter_add_match_subsystem_devtype (udev_monitor, "block", NULL); 63: udev_monitor_enable_receiving (udev_monitor); 64: 65: /* If the device is not being processed, check to see whether it 66: * exists already on the filesystem. If this is true, we don't need 67: * to wait for it can obtain the filesystem type by looking up the 68: * udevdb record by major/minor. 69: */ 70: if ((! device_queued (udev, devpath)) 71: && (stat (path, &devstat) == 0) 72: && S_ISBLK (devstat.st_mode)) 73: { 74: udev_device = udev_device_new_from_devnum (udev, 'b', devstat.st_rdev); 75: if (udev_device) { 76: type = udev_device_get_property_value (udev_device, "ID_FS_TYPE"); 77: if (type) { 78: printf ("%s\n", type); 79: 80: udev_device_unref (udev_device); 81: goto exit; 82: } 83: 84: udev_device_unref (udev_device); 85: } 86: } 87: 88: /* When the device doesn't exist yet, or is still being processed 89: * by udev, use the monitor socket to wait it to be done. 90: */ 91: while ((udev_device = udev_monitor_receive_device (udev_monitor)) != NULL) { 92: if (matching_device (udev_device, devpath)) { 93: type = udev_device_get_property_value (udev_device, "ID_FS_TYPE"); 94: if (type) { 95: printf ("%s\n", type); 96: 97: udev_device_unref (udev_device); 98: goto exit; 99: } 100: 101: } 102: 103: udev_device_unref (udev_device); 104: } 105: 106:exit: 107: udev_monitor_unref (udev_monitor); 108: udev_unref (udev); 109: 110: exit (0); 111:} 112: 113: 114:static int 115:device_queued (struct udev *udev, 116: const char * devpath) 117:{ 118: struct udev_queue * udev_queue; 119: struct udev_list_entry *queue_entry; 120: int found = 0; 121: 122: udev_queue = udev_queue_new (udev); 123: 124: for (queue_entry = udev_queue_get_queued_list_entry (udev_queue); 125: queue_entry != NULL; 126: queue_entry = udev_list_entry_get_next (queue_entry)) { 127: const char * syspath; 128: struct udev_device *udev_device; 129: 130: syspath = udev_list_entry_get_name (queue_entry); 131: udev_device = udev_device_new_from_syspath (udev, syspath); 132: if (udev_device) { 133: if (matching_device (udev_device, devpath)) 134: found = 1; 135: 136: udev_device_unref (udev_device); 137: } 138: } 139: 140: udev_queue_unref (udev_queue); 141: 142: return found; 143:} 144: 145:static int 146:matching_device (struct udev_device *device, 147: const char * path) 148:{ 149: const char * devnode; 150: struct udev_list_entry *devlinks_entry; 151: 152: /* Match by name */ 153: devnode = udev_device_get_devnode (device); 154: if (devnode && (! strcmp (path, devnode))) 155: return 1; 156: 157: /* Match by UUID */ 158: if (! strncmp (path, "UUID=", 5)) { 159: const char *uuid; 160: 161: uuid = udev_device_get_property_value (device, "ID_FS_UUID"); 162: if (uuid && (! strcmp (path + 5, uuid))) 163: return 1; 164: } 165: 166: /* Match by LABEL */ 167: if (! strncmp (path, "LABEL=", 6)) { 168: const char *label; 169: 170: label = udev_device_get_property_value (device, "ID_FS_LABEL"); 171: if (label && (! strcmp (path + 6, label))) 172: return 1; 173: } 174: 175: /* Match by symlink */ 176: for (devlinks_entry = udev_device_get_devlinks_list_entry (device); 177: devlinks_entry != NULL; 178: devlinks_entry = udev_list_entry_get_next (devlinks_entry)) 179: if (! strcmp (path, udev_list_entry_get_name (devlinks_entry))) 180: return 1; 181: 182: return 0; 183:} 184: 185: 186:static void 187:alarm_handler (int signum) 188:{ 189: exit (1); 190:} ---------- wait-for-root.c end ---------- -- To unsubscribe from this list: send the line "unsubscribe linux-hotplug" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html