From d7b3196286f78445ab7843ba000faf326a8673fd Mon Sep 17 00:00:00 2001 From: Vineeth Vijayan Date: Thu, 13 Jun 2024 15:32:35 +0200 Subject: [PATCH] zdev: fix warning about failed ATTR writes by udev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The qeth-udev-rule execution logs a warning as below in the journalfs. Failed to write ATTR{/sys/bus/ccwgroup/drivers/qeth/group}, \ ignoring: Invalid argument This occurs because the udev rule for qeth devices is triggered by multiple ccw devices and can be invoked in parallel. This can lead to a situation where each of the three parallel-running udev rules tries to group the devices simultaneously. As a result, only the first rule succeeds, while the others fail with an -EINVAL error because the CCW devices have already been grouped. To prevent this, schedule a new change uevent for the base device, which will verify the sysfs before attempting the grouping. The change event is triggered by all three devices, ensuring that the actual write to the attribute occurs only once and only when the sysfs attribute is ready. Hence the add events on different devices are serialized to change event on the base device, which then prevent duplicate concurrent grouping attempts. Suggested-by: Peter Oberparleiter Signed-off-by: Vineeth Vijayan Reviewed-by: Peter Oberparleiter Signed-off-by: Jan Höppner --- zdev/src/udev_ccwgroup.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/zdev/src/udev_ccwgroup.c b/zdev/src/udev_ccwgroup.c index c2f4bee4..465bd5b2 100644 --- a/zdev/src/udev_ccwgroup.c +++ b/zdev/src/udev_ccwgroup.c @@ -251,11 +251,12 @@ exit_code_t udev_ccwgroup_write_device(struct device *dev, bool autoconf) fprintf(fd, "# Generated by chzdev\n"); /* Triggers. */ - fprintf(fd, "ACTION==\"add\", SUBSYSTEM==\"drivers\", " + fprintf(fd, "ACTION!=\"add|change\", GOTO=\"%s\"\n", end_label); + fprintf(fd, "SUBSYSTEM==\"drivers\", " "KERNEL==\"%s\", GOTO=\"%s\"\n", drv, group_label); for (i = 0; i < devid.num; i++) { chan_id = ccw_devid_to_str(&devid.devid[i]); - fprintf(fd, "ACTION==\"add\", SUBSYSTEM==\"ccw\", " + fprintf(fd, "SUBSYSTEM==\"ccw\", " "KERNEL==\"%s\", DRIVER==\"%s\", " "GOTO=\"%s\"\n", chan_id, drv, group_label); free(chan_id); @@ -275,7 +276,19 @@ exit_code_t udev_ccwgroup_write_device(struct device *dev, bool autoconf) end_label); free(chan_id); } - fprintf(fd, "ATTR{[drivers/ccwgroup:%s]group}=\"", drv); + + /* Parallel execution of the ccwgroup devices udev rule can lead to + * udevadm warnings. To prevent this, serialize the execution. + */ + fprintf(fd, "\n# Note: Serialize add events on different devices to" + " change event on single\n# base device to prevent duplicate" + " concurrent grouping attempts\n"); + + /* The new change uevent should be generated to the base-device only */ + chan_id = ccw_devid_to_str(&devid.devid[0]); + fprintf(fd, "ACTION==\"add\", ATTR{[ccw/%s]uevent}=\"change\"\n", chan_id); + fprintf(fd, "ACTION==\"change\", ATTR{[drivers/ccwgroup:%s]group}=\"", drv); + free(chan_id); for (i = 0; i < devid.num; i++) { chan_id = ccw_devid_to_str(&devid.devid[i]); fprintf(fd, "%s%s", i > 0 ? "," : "", chan_id);