@@ -390,6 +390,54 @@ static struct udev_device *handle_scsi_default(struct udev_device *parent, char
390
390
return hostdev ;
391
391
}
392
392
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
+
393
441
static struct udev_device * handle_scsi_hyperv (struct udev_device * parent , char * * path ) {
394
442
struct udev_device * hostdev ;
395
443
struct udev_device * vmbusdev ;
@@ -426,7 +474,7 @@ static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char *
426
474
return parent ;
427
475
}
428
476
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 ) {
430
478
const char * devtype ;
431
479
const char * name ;
432
480
const char * id ;
@@ -465,19 +513,8 @@ static struct udev_device *handle_scsi(struct udev_device *parent, char **path,
465
513
goto out ;
466
514
}
467
515
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
- */
479
516
if (strstr (name , "/ata" ) != NULL ) {
480
- parent = NULL ;
517
+ parent = handle_scsi_ata ( parent , path , compat_path ) ;
481
518
goto out ;
482
519
}
483
520
@@ -578,7 +615,8 @@ static struct udev_device *handle_ccw(struct udev_device *parent, struct udev_de
578
615
579
616
static int builtin_path_id (struct udev_device * dev , int argc __attribute__((unused )), char * argv [] __attribute__((unused )), bool test ) {
580
617
struct udev_device * parent ;
581
- char * path = NULL ;
618
+ _cleanup_free_ char * path = NULL ;
619
+ _cleanup_free_ char * compat_path = NULL ;
582
620
bool supported_transport = false;
583
621
bool supported_parent = false;
584
622
@@ -600,7 +638,7 @@ static int builtin_path_id(struct udev_device *dev, int argc __attribute__((unus
600
638
} else if (streq (subsys , "scsi_tape" )) {
601
639
handle_scsi_tape (parent , & path );
602
640
} else if (streq (subsys , "scsi" )) {
603
- parent = handle_scsi (parent , & path , & supported_parent );
641
+ parent = handle_scsi (parent , & path , & compat_path , & supported_parent );
604
642
supported_transport = true;
605
643
} else if (streq (subsys , "cciss" )) {
606
644
parent = handle_cciss (parent , & path );
@@ -616,23 +654,33 @@ static int builtin_path_id(struct udev_device *dev, int argc __attribute__((unus
616
654
parent = skip_subsystem (parent , "serio" );
617
655
} else if (streq (subsys , "pci" )) {
618
656
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 ));
619
659
parent = skip_subsystem (parent , "pci" );
620
660
supported_parent = true;
621
661
} else if (streq (subsys , "platform" )) {
622
662
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 ));
623
665
parent = skip_subsystem (parent , "platform" );
624
666
supported_transport = true;
625
667
supported_parent = true;
626
668
} else if (streq (subsys , "acpi" )) {
627
669
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 ));
628
672
parent = skip_subsystem (parent , "acpi" );
629
673
supported_parent = true;
630
674
} else if (streq (subsys , "xen" )) {
631
675
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 ));
632
678
parent = skip_subsystem (parent , "xen" );
633
679
supported_parent = true;
634
680
} else if (streq (subsys , "scm" )) {
635
681
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 ));
636
684
parent = skip_subsystem (parent , "scm" );
637
685
supported_transport = true;
638
686
supported_parent = true;
@@ -655,20 +703,16 @@ static int builtin_path_id(struct udev_device *dev, int argc __attribute__((unus
655
703
* might produce conflicting IDs if the parent does not provide a
656
704
* unique and predictable name.
657
705
*/
658
- if (!supported_parent ) {
659
- free (path );
706
+ if (!supported_parent )
660
707
path = NULL ;
661
- }
662
708
663
709
/*
664
710
* Do not return block devices without a well-known transport. Some
665
711
* devices do not expose their buses and do not provide a unique
666
712
* and predictable name that way.
667
713
*/
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 )
670
715
path = NULL ;
671
- }
672
716
673
717
out :
674
718
if (path != NULL ) {
@@ -703,7 +747,15 @@ static int builtin_path_id(struct udev_device *dev, int argc __attribute__((unus
703
747
704
748
udev_builtin_add_property (dev , test , "ID_PATH" , path );
705
749
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
+
707
759
return EXIT_SUCCESS ;
708
760
}
709
761
return EXIT_FAILURE ;
0 commit comments