Skip to content

Commit 4e2cbfd

Browse files
udev/udev-builtin-path_id.c: Add ATA support for builtin path_id
Core of the work comes from this upstream commit 9b3278d90704416bfe51a05d5681caf99445fb2f but needed to create the unported handle_scsi_ata() The associated changes in 60-persistent-storage.rules have already been applied in 247724d
1 parent 611b6fb commit 4e2cbfd

File tree

1 file changed

+74
-22
lines changed

1 file changed

+74
-22
lines changed

src/udev/udev-builtin-path_id.c

+74-22
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,54 @@ static struct udev_device *handle_scsi_default(struct udev_device *parent, char
390390
return hostdev;
391391
}
392392

393+
static struct udev_device *handle_scsi_ata(struct udev_device *parent, char **path, char **compat_path) {
394+
struct udev_device *targetdev, *target_parent;
395+
struct udev_device *atadev = NULL;
396+
struct udev *udev = udev_device_get_udev(parent);
397+
const char *port_no, *sysname, *name;
398+
unsigned host, bus, target, lun;
399+
400+
assert(parent);
401+
assert(path);
402+
403+
name = udev_device_get_sysname(parent);
404+
if (sscanf(name, "%u:%u:%u:%u", &host, &bus, &target, &lun) != 4)
405+
return NULL;
406+
407+
targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host");
408+
if (targetdev == NULL)
409+
return NULL;
410+
411+
target_parent = udev_device_get_parent(targetdev);
412+
if (target_parent == NULL)
413+
return NULL;
414+
415+
sysname = udev_device_get_sysname(target_parent);
416+
if (sysname == NULL)
417+
return NULL;
418+
419+
atadev = udev_device_new_from_subsystem_sysname(udev, "ata_port", udev_device_get_sysname(target_parent));
420+
if (atadev == NULL)
421+
return NULL;
422+
423+
port_no = udev_device_get_sysattr_value(atadev, "port_no");
424+
if (port_no == NULL)
425+
return NULL;
426+
427+
if (bus != 0)
428+
/* Devices behind port multiplier have a bus != 0 */
429+
path_prepend(path, "ata-%s.%u.0", port_no, bus);
430+
else
431+
/* Master/slave are distinguished by target id */
432+
path_prepend(path, "ata-%s.%u", port_no, target);
433+
434+
/* old compatible persistent link for ATA devices */
435+
if (compat_path)
436+
path_prepend(compat_path, "ata-%s", port_no);
437+
438+
return parent;
439+
}
440+
393441
static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char **path) {
394442
struct udev_device *hostdev;
395443
struct udev_device *vmbusdev;
@@ -426,7 +474,7 @@ static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char *
426474
return parent;
427475
}
428476

429-
static struct udev_device *handle_scsi(struct udev_device *parent, char **path, bool *supported_parent) {
477+
static struct udev_device *handle_scsi(struct udev_device *parent, char **path, char **compat_path, bool *supported_parent) {
430478
const char *devtype;
431479
const char *name;
432480
const char *id;
@@ -465,19 +513,8 @@ static struct udev_device *handle_scsi(struct udev_device *parent, char **path,
465513
goto out;
466514
}
467515

468-
/*
469-
* We do not support the ATA transport class, it uses global counters
470-
* to name the ata devices which numbers spread across multiple
471-
* controllers.
472-
*
473-
* The real link numbers are not exported. Also, possible chains of ports
474-
* behind port multipliers cannot be composed that way.
475-
*
476-
* Until all that is solved at the kernel level, there are no by-path/
477-
* links for ATA devices.
478-
*/
479516
if (strstr(name, "/ata") != NULL) {
480-
parent = NULL;
517+
parent = handle_scsi_ata(parent, path, compat_path);
481518
goto out;
482519
}
483520

@@ -578,7 +615,8 @@ static struct udev_device *handle_ccw(struct udev_device *parent, struct udev_de
578615

579616
static int builtin_path_id(struct udev_device *dev, int argc __attribute__((unused)), char *argv[] __attribute__((unused)), bool test) {
580617
struct udev_device *parent;
581-
char *path = NULL;
618+
_cleanup_free_ char *path = NULL;
619+
_cleanup_free_ char *compat_path = NULL;
582620
bool supported_transport = false;
583621
bool supported_parent = false;
584622

@@ -600,7 +638,7 @@ static int builtin_path_id(struct udev_device *dev, int argc __attribute__((unus
600638
} else if (streq(subsys, "scsi_tape")) {
601639
handle_scsi_tape(parent, &path);
602640
} else if (streq(subsys, "scsi")) {
603-
parent = handle_scsi(parent, &path, &supported_parent);
641+
parent = handle_scsi(parent, &path, &compat_path, &supported_parent);
604642
supported_transport = true;
605643
} else if (streq(subsys, "cciss")) {
606644
parent = handle_cciss(parent, &path);
@@ -616,23 +654,33 @@ static int builtin_path_id(struct udev_device *dev, int argc __attribute__((unus
616654
parent = skip_subsystem(parent, "serio");
617655
} else if (streq(subsys, "pci")) {
618656
path_prepend(&path, "pci-%s", udev_device_get_sysname(parent));
657+
if (compat_path)
658+
path_prepend(&compat_path, "pci-%s", udev_device_get_sysname(parent));
619659
parent = skip_subsystem(parent, "pci");
620660
supported_parent = true;
621661
} else if (streq(subsys, "platform")) {
622662
path_prepend(&path, "platform-%s", udev_device_get_sysname(parent));
663+
if (compat_path)
664+
path_prepend(&compat_path, "platform-%s", udev_device_get_sysname(parent));
623665
parent = skip_subsystem(parent, "platform");
624666
supported_transport = true;
625667
supported_parent = true;
626668
} else if (streq(subsys, "acpi")) {
627669
path_prepend(&path, "acpi-%s", udev_device_get_sysname(parent));
670+
if (compat_path)
671+
path_prepend(&compat_path, "acpi-%s", udev_device_get_sysname(parent));
628672
parent = skip_subsystem(parent, "acpi");
629673
supported_parent = true;
630674
} else if (streq(subsys, "xen")) {
631675
path_prepend(&path, "xen-%s", udev_device_get_sysname(parent));
676+
if (compat_path)
677+
path_prepend(&compat_path, "xen-%s", udev_device_get_sysname(parent));
632678
parent = skip_subsystem(parent, "xen");
633679
supported_parent = true;
634680
} else if (streq(subsys, "scm")) {
635681
path_prepend(&path, "scm-%s", udev_device_get_sysname(parent));
682+
if (compat_path)
683+
path_prepend(&compat_path, "scm-%s", udev_device_get_sysname(parent));
636684
parent = skip_subsystem(parent, "scm");
637685
supported_transport = true;
638686
supported_parent = true;
@@ -655,20 +703,16 @@ static int builtin_path_id(struct udev_device *dev, int argc __attribute__((unus
655703
* might produce conflicting IDs if the parent does not provide a
656704
* unique and predictable name.
657705
*/
658-
if (!supported_parent) {
659-
free(path);
706+
if (!supported_parent)
660707
path = NULL;
661-
}
662708

663709
/*
664710
* Do not return block devices without a well-known transport. Some
665711
* devices do not expose their buses and do not provide a unique
666712
* and predictable name that way.
667713
*/
668-
if (streq(udev_device_get_subsystem(dev), "block") && !supported_transport) {
669-
free(path);
714+
if (streq(udev_device_get_subsystem(dev), "block") && !supported_transport)
670715
path = NULL;
671-
}
672716

673717
out:
674718
if (path != NULL) {
@@ -703,7 +747,15 @@ static int builtin_path_id(struct udev_device *dev, int argc __attribute__((unus
703747

704748
udev_builtin_add_property(dev, test, "ID_PATH", path);
705749
udev_builtin_add_property(dev, test, "ID_PATH_TAG", tag);
706-
free(path);
750+
751+
/*
752+
* Compatible link generation for ATA devices
753+
* we assign compat_link to the env variable
754+
* ID_PATH_ATA_COMPAT
755+
*/
756+
if (compat_path)
757+
udev_builtin_add_property(dev, test, "ID_PATH_ATA_COMPAT", compat_path);
758+
707759
return EXIT_SUCCESS;
708760
}
709761
return EXIT_FAILURE;

0 commit comments

Comments
 (0)