1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-06 13:17:44 +03:00

core: split out device validation from device_found_node()

Let's separate the validate step out. Also, let's update some comments
which have long ceased to be true.

No change in behaviour.
This commit is contained in:
Lennart Poettering 2018-06-04 21:35:30 +02:00
parent 485ae697ba
commit 34c20ee09f

View File

@ -941,56 +941,76 @@ static bool device_supported(void) {
return read_only <= 0;
}
void device_found_node(Manager *m, const char *node, DeviceFound found, DeviceFound mask) {
_cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
static int validate_node(Manager *m, const char *node, struct udev_device **ret) {
struct stat st;
assert(m);
assert(node);
assert(ret);
/* Validates a device node that showed up in /proc/swaps or /proc/self/mountinfo if it makes sense for us to
* track. Note that this validator is fine within missing device nodes, but not with badly set up ones! */
if (!path_startswith(node, "/dev")) {
*ret = NULL;
return 0; /* bad! */
}
if (stat(node, &st) < 0) {
if (errno != ENOENT)
return log_error_errno(errno, "Failed to stat() device node file %s: %m", node);
*ret = NULL;
return 1; /* good! (though missing) */
} else {
_cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) {
*ret = NULL;
return 0; /* bad! */
}
dev = udev_device_new_from_devnum(m->udev, S_ISBLK(st.st_mode) ? 'b' : 'c', st.st_rdev);
if (!dev) {
if (errno != ENOENT)
return log_error_errno(errno, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev));
*ret = NULL;
return 1; /* good! (though missing) */
}
*ret = TAKE_PTR(dev);
return 1; /* good! */
}
}
void device_found_node(Manager *m, const char *node, DeviceFound found, DeviceFound mask) {
int r;
assert(m);
assert(node);
if (!device_supported())
return;
/* This is called whenever we find a device referenced in
* /proc/swaps or /proc/self/mounts. Such a device might be
* mounted/enabled at a time where udev has not finished
* probing it yet, and we thus haven't learned about it
* yet. In this case we will set the device unit to
* "tentative" state. */
if (mask == 0)
return;
/* This is called whenever we find a device referenced in /proc/swaps or /proc/self/mounts. Such a device might
* be mounted/enabled at a time where udev has not finished probing it yet, and we thus haven't learned about
* it yet. In this case we will set the device unit to "tentative" state. */
if ((found & mask) != 0) {
if (!path_startswith(node, "/dev"))
return;
_cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
/* We make an extra check here, if the device node
* actually exists. If it's missing, then this is an
* indication that device was unplugged but is still
* referenced in /proc/swaps or
* /proc/self/mountinfo. Note that this check doesn't
* really cover all cases where a device might be gone
* away, since drives that can have a medium inserted
* will still have a device node even when the medium
* is not there... */
/* If the device is known in the kernel and newly appeared, then we'll create a device unit for it,
* under the name referenced in /proc/swaps or /proc/self/mountinfo. But first, let's validate if
* everything is alright with the device node. */
if (stat(node, &st) >= 0) {
if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
return;
dev = udev_device_new_from_devnum(m->udev, S_ISBLK(st.st_mode) ? 'b' : 'c', st.st_rdev);
if (!dev && errno != ENOENT) {
log_error_errno(errno, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev));
return;
}
} else if (errno != ENOENT) {
log_error_errno(errno, "Failed to stat device node file %s: %m", node);
return;
}
/* If the device is known in the kernel and newly
* appeared, then we'll create a device unit for it,
* under the name referenced in /proc/swaps or
* /proc/self/mountinfo. */
r = validate_node(m, node, &dev);
if (r <= 0)
return; /* Don't create a device unit for this if the device node is borked. */
(void) device_setup_unit(m, dev, node, false);
}