Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

udev/udev-builtin-path_id.c: Add ATA support for builtin path_id #275

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 74 additions & 22 deletions src/udev/udev-builtin-path_id.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,54 @@ static struct udev_device *handle_scsi_default(struct udev_device *parent, char
return hostdev;
}

static struct udev_device *handle_scsi_ata(struct udev_device *parent, char **path, char **compat_path) {
struct udev_device *targetdev, *target_parent;
struct udev_device *atadev = NULL;
struct udev *udev = udev_device_get_udev(parent);
const char *port_no, *sysname, *name;
unsigned host, bus, target, lun;

assert(parent);
assert(path);

name = udev_device_get_sysname(parent);
if (sscanf(name, "%u:%u:%u:%u", &host, &bus, &target, &lun) != 4)
return NULL;

targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host");
if (targetdev == NULL)
return NULL;

target_parent = udev_device_get_parent(targetdev);
if (target_parent == NULL)
return NULL;

sysname = udev_device_get_sysname(target_parent);
if (sysname == NULL)
return NULL;

atadev = udev_device_new_from_subsystem_sysname(udev, "ata_port", udev_device_get_sysname(target_parent));
if (atadev == NULL)
return NULL;

port_no = udev_device_get_sysattr_value(atadev, "port_no");
if (port_no == NULL)
return NULL;

if (bus != 0)
/* Devices behind port multiplier have a bus != 0 */
path_prepend(path, "ata-%s.%u.0", port_no, bus);
else
/* Master/slave are distinguished by target id */
path_prepend(path, "ata-%s.%u", port_no, target);

/* old compatible persistent link for ATA devices */
if (compat_path)
path_prepend(compat_path, "ata-%s", port_no);

return parent;
}

static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char **path) {
struct udev_device *hostdev;
struct udev_device *vmbusdev;
Expand Down Expand Up @@ -426,7 +474,7 @@ static struct udev_device *handle_scsi_hyperv(struct udev_device *parent, char *
return parent;
}

static struct udev_device *handle_scsi(struct udev_device *parent, char **path, bool *supported_parent) {
static struct udev_device *handle_scsi(struct udev_device *parent, char **path, char **compat_path, bool *supported_parent) {
const char *devtype;
const char *name;
const char *id;
Expand Down Expand Up @@ -465,19 +513,8 @@ static struct udev_device *handle_scsi(struct udev_device *parent, char **path,
goto out;
}

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

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

static int builtin_path_id(struct udev_device *dev, int argc __attribute__((unused)), char *argv[] __attribute__((unused)), bool test) {
struct udev_device *parent;
char *path = NULL;
_cleanup_free_ char *path = NULL;
_cleanup_free_ char *compat_path = NULL;
bool supported_transport = false;
bool supported_parent = false;

Expand All @@ -600,7 +638,7 @@ static int builtin_path_id(struct udev_device *dev, int argc __attribute__((unus
} else if (streq(subsys, "scsi_tape")) {
handle_scsi_tape(parent, &path);
} else if (streq(subsys, "scsi")) {
parent = handle_scsi(parent, &path, &supported_parent);
parent = handle_scsi(parent, &path, &compat_path, &supported_parent);
supported_transport = true;
} else if (streq(subsys, "cciss")) {
parent = handle_cciss(parent, &path);
Expand All @@ -616,23 +654,33 @@ static int builtin_path_id(struct udev_device *dev, int argc __attribute__((unus
parent = skip_subsystem(parent, "serio");
} else if (streq(subsys, "pci")) {
path_prepend(&path, "pci-%s", udev_device_get_sysname(parent));
if (compat_path)
path_prepend(&compat_path, "pci-%s", udev_device_get_sysname(parent));
parent = skip_subsystem(parent, "pci");
supported_parent = true;
} else if (streq(subsys, "platform")) {
path_prepend(&path, "platform-%s", udev_device_get_sysname(parent));
if (compat_path)
path_prepend(&compat_path, "platform-%s", udev_device_get_sysname(parent));
parent = skip_subsystem(parent, "platform");
supported_transport = true;
supported_parent = true;
} else if (streq(subsys, "acpi")) {
path_prepend(&path, "acpi-%s", udev_device_get_sysname(parent));
if (compat_path)
path_prepend(&compat_path, "acpi-%s", udev_device_get_sysname(parent));
parent = skip_subsystem(parent, "acpi");
supported_parent = true;
} else if (streq(subsys, "xen")) {
path_prepend(&path, "xen-%s", udev_device_get_sysname(parent));
if (compat_path)
path_prepend(&compat_path, "xen-%s", udev_device_get_sysname(parent));
parent = skip_subsystem(parent, "xen");
supported_parent = true;
} else if (streq(subsys, "scm")) {
path_prepend(&path, "scm-%s", udev_device_get_sysname(parent));
if (compat_path)
path_prepend(&compat_path, "scm-%s", udev_device_get_sysname(parent));
parent = skip_subsystem(parent, "scm");
supported_transport = true;
supported_parent = true;
Expand All @@ -655,20 +703,16 @@ static int builtin_path_id(struct udev_device *dev, int argc __attribute__((unus
* might produce conflicting IDs if the parent does not provide a
* unique and predictable name.
*/
if (!supported_parent) {
free(path);
if (!supported_parent)
path = NULL;
}

/*
* Do not return block devices without a well-known transport. Some
* devices do not expose their buses and do not provide a unique
* and predictable name that way.
*/
if (streq(udev_device_get_subsystem(dev), "block") && !supported_transport) {
free(path);
if (streq(udev_device_get_subsystem(dev), "block") && !supported_transport)
path = NULL;
}

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

udev_builtin_add_property(dev, test, "ID_PATH", path);
udev_builtin_add_property(dev, test, "ID_PATH_TAG", tag);
free(path);

/*
* Compatible link generation for ATA devices
* we assign compat_link to the env variable
* ID_PATH_ATA_COMPAT
*/
if (compat_path)
udev_builtin_add_property(dev, test, "ID_PATH_ATA_COMPAT", compat_path);

return EXIT_SUCCESS;
}
return EXIT_FAILURE;
Expand Down
Loading