In the code in util-linux/mdev.c, there's this fragment: /* Make path point to "subsystem/device_name" */ if (path[5] == 'b') /* legacy /sys/block? */ path += sizeof("/sys/") - 1; else path += sizeof("/sys/class/") - 1; It assumes that the original path is starting either with "/sys/block" or "/sys/class". But this is only true when traversing sysfs for `mdev -s', ie, "manually". When mdev is called from /sbin/hotplug in response to actual kernel event, the path is like, for example, "/sys/devices/pci0000:00/0000:00:11.0/host0/target0:0:0/0:0:0:0/bsg/0:0:0:0" (actual example from my system). Ie, it starts with something entirely different. According to the kernel, the only reliable way to get subsystem name is to readlink("subsystem") in the device directory. That did not exist in earlier kernels (but it's not a recent addition either). Most of the time it's ok to assume that pre-last component of the path actually is the right thing, so it's ok to find pre-last slash on the pathname here. It will work on all cases which I have examples for (ie, on all my systems). So instead of the above, searching backwards for pre-last slash seems to be a good idea. And ab-using 'path' variable is NOT a good idea, at least I don't think it is :) Thanks!
This was just applied to git: /* Make path point to "subsystem/device_name" */ - if (path[5] == 'b') /* legacy /sys/block? */ + subsystem_slash_devname = NULL; + /* Check for coldplug invocations first */ + if (strncmp(path, "/sys/block/", 11) == 0) /* legacy case */ path += sizeof("/sys/") - 1; - else + else if (strncmp(path, "/sys/class/", 11) == 0) path += sizeof("/sys/class/") - 1; + else { + /* Example of a hotplug invocation: + * SUBSYSTEM="block" + * DEVPATH="/sys" + "/devices/virtual/mtd/mtd3/mtdblock3" + * ("/sys" is added by mdev_main) + * - path does not contain subsystem + */ + subsystem_slash_devname = concat_path_file(G.subsystem, device_name); + path = subsystem_slash_devname; + } does it fix your case too?