Skip to content

Commit

Permalink
zdev: fix warning about failed ATTR writes by udev
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Vineeth Vijayan <[email protected]>
Reviewed-by: Peter Oberparleiter <[email protected]>
Signed-off-by: Jan Höppner <[email protected]>
  • Loading branch information
vneethv authored and hoeppnerj committed Jul 8, 2024
1 parent b6c3040 commit d7b3196
Showing 1 changed file with 16 additions and 3 deletions.
19 changes: 16 additions & 3 deletions zdev/src/udev_ccwgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit d7b3196

Please sign in to comment.