File 1106-path_compat_id-phy-sas-disk-enumeration.patch of Package systemd.1472

Index: systemd-210/src/udev/path_id_compat/path_id_compat.c
===================================================================
--- systemd-210.orig/src/udev/path_id_compat/path_id_compat.c
+++ systemd-210/src/udev/path_id_compat/path_id_compat.c
@@ -61,6 +61,22 @@ static int path_prepend(char **path, con
 	return 0;
 }
 
+/*
+** Linux only supports 32 bit luns.
+** See drivers/scsi/scsi_scan.c::scsilun_to_int() for more details.
+*/
+static int format_lun_number(struct udev_device *dev, char **path)
+{
+	unsigned long lun = strtoul(udev_device_get_sysnum(dev), NULL, 10);
+
+	/* address method 0, peripheral device addressing with bus id of zero */
+	if (lun < 256)
+		return path_prepend(path, "lun-%d", lun);
+
+	/* handle all other lun addressing methods by using a variant of the original lun format */
+	return path_prepend(path, "lun-0x%04x%04x00000000", (lun & 0xffff), (lun >> 16) & 0xffff);
+}
+
 static struct udev_device *skip_subsystem(struct udev_device *dev, const char *subsys)
 {
 	struct udev_device *parent = dev;
@@ -160,6 +176,81 @@ out:
 	return hostdev;
 }
 
+static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **path)
+{
+	struct udev *udev  = udev_device_get_udev(parent);
+	struct udev_device *targetdev;
+	struct udev_device *target_parent;
+	struct udev_device *sasdev;
+	struct udev_device *portdev;
+	struct dirent *dent;
+	DIR *dir;
+	const char *sas_address;
+	int tmp_phy_id, phy_id = 255;
+	char *lun = NULL;
+
+	targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target");
+	if (!targetdev)
+		return NULL;
+
+	target_parent = udev_device_get_parent(targetdev);
+	if (!target_parent)
+		return NULL;
+
+	portdev = udev_device_get_parent(target_parent);
+	if (!portdev)
+		return NULL;
+
+	dir = opendir(udev_device_get_syspath(portdev));
+	if (!dir)
+		return NULL;
+
+	for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+		const char *name = dent->d_name;
+		char *phy_id_str;
+
+		if (dent->d_type != DT_LNK)
+			continue;
+
+		if (strncmp(dent->d_name, "phy", 3) != 0)
+			continue;
+
+		phy_id_str = strstr(name, ":");
+		if (phy_id_str == NULL)
+			continue;
+
+		phy_id_str++;
+
+		tmp_phy_id = atoi(phy_id_str);
+		if (tmp_phy_id >= 0 && tmp_phy_id < phy_id)
+			phy_id = tmp_phy_id;
+	}
+	closedir(dir);
+
+	if (phy_id == 255)
+		return NULL;
+
+	sasdev = udev_device_new_from_subsystem_sysname(udev, "sas_device",
+							udev_device_get_sysname(target_parent));
+	if (sasdev == NULL)
+		return NULL;
+
+	sas_address = udev_device_get_sysattr_value(sasdev, "sas_address");
+	if (sas_address == NULL) {
+		parent = NULL;
+		goto out;
+	}
+
+	format_lun_number(parent, &lun);
+	path_prepend(path, "sas-phy%d-%s-%s", phy_id, sas_address, lun);
+
+	if (lun)
+		free(lun);
+out:
+	udev_device_unref(sasdev);
+	return parent;
+}
+
 static struct udev_device *handle_scsi(struct udev_device *parent, char **path)
 {
 	const char *devtype;
@@ -172,6 +263,11 @@ static struct udev_device *handle_scsi(s
 	/* lousy scsi sysfs does not have a "subsystem" for the transport */
 	name = udev_device_get_syspath(parent);
 
+	if (strstr(name, "/end_device-") != NULL) {
+		parent = handle_scsi_sas(parent, path);
+		goto out;
+	}
+
 	if (strstr(name, "/ata") != NULL) {
 		parent = handle_ata(parent, path);
 		goto out;
Index: systemd-210/rules/60-persistent-storage.rules
===================================================================
--- systemd-210.orig/rules/60-persistent-storage.rules
+++ systemd-210/rules/60-persistent-storage.rules
@@ -65,8 +65,8 @@ ENV{DEVTYPE}=="disk", DEVPATH!="*/virtua
 ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}"
 ENV{DEVTYPE}=="partition", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-part%n"
 
-# by-path (parent device path, compat version, only for ATA/NVMe bus)
-ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata|nvme", DEVPATH!="*/virtual/*", IMPORT{program}="path_id_compat %p"
+# by-path (parent device path, compat version, only for ATA/NVMe/SAS bus)
+ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata|nvme|scsi", DEVPATH!="*/virtual/*", IMPORT{program}="path_id_compat %p"
 ENV{DEVTYPE}=="disk", ENV{ID_PATH_COMPAT}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH_COMPAT}"
 ENV{DEVTYPE}=="partition", ENV{ID_PATH_COMPAT}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH_COMPAT}-part%n"
 
openSUSE Build Service is sponsored by