mirror of
https://github.com/systemd/systemd
synced 2026-03-14 09:04:47 +01:00
Compare commits
No commits in common. "d49b881eafe25c2efd2816d1ad6164c43e5896fa" and "c068a17f6a18d3ebfabe88fc49e24a923d0bdd0a" have entirely different histories.
d49b881eaf
...
c068a17f6a
@ -67,7 +67,7 @@ struct sd_device {
|
|||||||
char *driver_subsystem; /* only set for the 'drivers' subsystem */
|
char *driver_subsystem; /* only set for the 'drivers' subsystem */
|
||||||
char *driver;
|
char *driver;
|
||||||
|
|
||||||
char *device_id;
|
char *id_filename;
|
||||||
|
|
||||||
usec_t usec_initialized;
|
usec_t usec_initialized;
|
||||||
|
|
||||||
@ -84,7 +84,9 @@ struct sd_device {
|
|||||||
bool property_tags_outdated:1; /* need to update TAGS= or CURRENT_TAGS= property */
|
bool property_tags_outdated:1; /* need to update TAGS= or CURRENT_TAGS= property */
|
||||||
bool property_devlinks_outdated:1; /* need to update DEVLINKS= property */
|
bool property_devlinks_outdated:1; /* need to update DEVLINKS= property */
|
||||||
bool properties_buf_outdated:1; /* need to reread hashmap */
|
bool properties_buf_outdated:1; /* need to reread hashmap */
|
||||||
|
bool sysname_set:1; /* don't reread sysname */
|
||||||
bool subsystem_set:1; /* don't reread subsystem */
|
bool subsystem_set:1; /* don't reread subsystem */
|
||||||
|
bool driver_subsystem_set:1; /* don't reread subsystem */
|
||||||
bool driver_set:1; /* don't reread driver */
|
bool driver_set:1; /* don't reread driver */
|
||||||
bool uevent_loaded:1; /* don't reread uevent */
|
bool uevent_loaded:1; /* don't reread uevent */
|
||||||
bool db_loaded; /* don't reread db */
|
bool db_loaded; /* don't reread db */
|
||||||
|
|||||||
@ -20,7 +20,6 @@
|
|||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
#include "stdio-util.h"
|
|
||||||
#include "string-table.h"
|
#include "string-table.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
@ -569,142 +568,28 @@ int device_get_devlink_priority(sd_device *device, int *priority) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int device_get_watch_handle(sd_device *device) {
|
int device_get_watch_handle(sd_device *device, int *handle) {
|
||||||
char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
|
|
||||||
_cleanup_free_ char *buf = NULL;
|
|
||||||
const char *id, *path_id;
|
|
||||||
int wd, r;
|
|
||||||
|
|
||||||
assert(device);
|
|
||||||
|
|
||||||
if (device->watch_handle >= 0)
|
|
||||||
return device->watch_handle;
|
|
||||||
|
|
||||||
r = device_get_device_id(device, &id);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
path_id = strjoina("/run/udev/watch/", id);
|
|
||||||
r = readlink_malloc(path_id, &buf);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
r = safe_atoi(buf, &wd);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (wd < 0)
|
|
||||||
return -EBADF;
|
|
||||||
|
|
||||||
buf = mfree(buf);
|
|
||||||
xsprintf(path_wd, "/run/udev/watch/%d", wd);
|
|
||||||
r = readlink_malloc(path_wd, &buf);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (!streq(buf, id))
|
|
||||||
return -EBADF;
|
|
||||||
|
|
||||||
return device->watch_handle = wd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void device_remove_watch_handle(sd_device *device) {
|
|
||||||
const char *id;
|
|
||||||
int wd;
|
|
||||||
|
|
||||||
assert(device);
|
|
||||||
|
|
||||||
/* First, remove the symlink from handle to device id. */
|
|
||||||
wd = device_get_watch_handle(device);
|
|
||||||
if (wd >= 0) {
|
|
||||||
char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
|
|
||||||
|
|
||||||
xsprintf(path_wd, "/run/udev/watch/%d", wd);
|
|
||||||
if (unlink(path_wd) < 0 && errno != ENOENT)
|
|
||||||
log_device_debug_errno(device, errno,
|
|
||||||
"sd-device: failed to remove %s, ignoring: %m",
|
|
||||||
path_wd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Next, remove the symlink from device id to handle. */
|
|
||||||
if (device_get_device_id(device, &id) >= 0) {
|
|
||||||
const char *path_id;
|
|
||||||
|
|
||||||
path_id = strjoina("/run/udev/watch/", id);
|
|
||||||
if (unlink(path_id) < 0 && errno != ENOENT)
|
|
||||||
log_device_debug_errno(device, errno,
|
|
||||||
"sd-device: failed to remove %s, ignoring: %m",
|
|
||||||
path_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
device->watch_handle = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int device_set_watch_handle(sd_device *device, int wd) {
|
|
||||||
char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
|
|
||||||
const char *id, *path_id;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(device);
|
assert(device);
|
||||||
|
|
||||||
if (wd >= 0 && wd == device->watch_handle)
|
r = device_read_db(device);
|
||||||
return 0;
|
|
||||||
|
|
||||||
device_remove_watch_handle(device);
|
|
||||||
|
|
||||||
if (wd < 0)
|
|
||||||
/* negative wd means that the caller requests to clear saved watch handle. */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
r = device_get_device_id(device, &id);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
path_id = strjoina("/run/udev/watch/", id);
|
if (device->watch_handle < 0)
|
||||||
xsprintf(path_wd, "/run/udev/watch/%d", wd);
|
return -ENOENT;
|
||||||
|
|
||||||
r = mkdir_parents(path_wd, 0755);
|
if (handle)
|
||||||
if (r < 0)
|
*handle = device->watch_handle;
|
||||||
return r;
|
|
||||||
|
|
||||||
if (symlink(id, path_wd) < 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
if (symlink(path_wd + STRLEN("/run/udev/watch/"), path_id) < 0) {
|
|
||||||
r = -errno;
|
|
||||||
if (unlink(path_wd) < 0 && errno != ENOENT)
|
|
||||||
log_device_debug_errno(device, errno,
|
|
||||||
"sd-device: failed to remove %s, ignoring: %m",
|
|
||||||
path_wd);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
device->watch_handle = wd;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int device_new_from_watch_handle_at(sd_device **ret, int dirfd, int wd) {
|
void device_set_watch_handle(sd_device *device, int handle) {
|
||||||
char path_wd[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
|
assert(device);
|
||||||
_cleanup_free_ char *id = NULL;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(ret);
|
device->watch_handle = handle;
|
||||||
|
|
||||||
if (wd < 0)
|
|
||||||
return -EBADF;
|
|
||||||
|
|
||||||
if (dirfd >= 0) {
|
|
||||||
xsprintf(path_wd, "%d", wd);
|
|
||||||
r = readlinkat_malloc(dirfd, path_wd, &id);
|
|
||||||
} else {
|
|
||||||
xsprintf(path_wd, "/run/udev/watch/%d", wd);
|
|
||||||
r = readlink_malloc(path_wd, &id);
|
|
||||||
}
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
return sd_device_new_from_device_id(ret, id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int device_rename(sd_device *device, const char *name) {
|
int device_rename(sd_device *device, const char *name) {
|
||||||
@ -876,7 +761,7 @@ static int device_tag(sd_device *device, const char *tag, bool add) {
|
|||||||
assert(device);
|
assert(device);
|
||||||
assert(tag);
|
assert(tag);
|
||||||
|
|
||||||
r = device_get_device_id(device, &id);
|
r = device_get_id_filename(device, &id);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -937,6 +822,9 @@ static bool device_has_info(sd_device *device) {
|
|||||||
if (!set_isempty(device->current_tags))
|
if (!set_isempty(device->current_tags))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (device->watch_handle >= 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -958,7 +846,7 @@ int device_update_db(sd_device *device) {
|
|||||||
|
|
||||||
has_info = device_has_info(device);
|
has_info = device_has_info(device);
|
||||||
|
|
||||||
r = device_get_device_id(device, &id);
|
r = device_get_id_filename(device, &id);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1011,6 +899,9 @@ int device_update_db(sd_device *device) {
|
|||||||
|
|
||||||
if (device->devlink_priority != 0)
|
if (device->devlink_priority != 0)
|
||||||
fprintf(f, "L:%i\n", device->devlink_priority);
|
fprintf(f, "L:%i\n", device->devlink_priority);
|
||||||
|
|
||||||
|
if (device->watch_handle >= 0)
|
||||||
|
fprintf(f, "W:%i\n", device->watch_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device->usec_initialized > 0)
|
if (device->usec_initialized > 0)
|
||||||
@ -1059,7 +950,7 @@ int device_delete_db(sd_device *device) {
|
|||||||
|
|
||||||
assert(device);
|
assert(device);
|
||||||
|
|
||||||
r = device_get_device_id(device, &id);
|
r = device_get_id_filename(device, &id);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -12,22 +12,18 @@
|
|||||||
|
|
||||||
int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len);
|
int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len);
|
||||||
int device_new_from_strv(sd_device **ret, char **strv);
|
int device_new_from_strv(sd_device **ret, char **strv);
|
||||||
int device_new_from_watch_handle_at(sd_device **ret, int dirfd, int wd);
|
|
||||||
static inline int device_new_from_watch_handle(sd_device **ret, int wd) {
|
|
||||||
return device_new_from_watch_handle_at(ret, -1, wd);
|
|
||||||
}
|
|
||||||
|
|
||||||
int device_get_device_id(sd_device *device, const char **ret);
|
int device_get_id_filename(sd_device *device, const char **ret);
|
||||||
|
|
||||||
int device_get_devlink_priority(sd_device *device, int *priority);
|
int device_get_devlink_priority(sd_device *device, int *priority);
|
||||||
int device_get_watch_handle(sd_device *device);
|
int device_get_watch_handle(sd_device *device, int *handle);
|
||||||
int device_get_devnode_mode(sd_device *device, mode_t *mode);
|
int device_get_devnode_mode(sd_device *device, mode_t *mode);
|
||||||
int device_get_devnode_uid(sd_device *device, uid_t *uid);
|
int device_get_devnode_uid(sd_device *device, uid_t *uid);
|
||||||
int device_get_devnode_gid(sd_device *device, gid_t *gid);
|
int device_get_devnode_gid(sd_device *device, gid_t *gid);
|
||||||
|
|
||||||
void device_seal(sd_device *device);
|
void device_seal(sd_device *device);
|
||||||
void device_set_is_initialized(sd_device *device);
|
void device_set_is_initialized(sd_device *device);
|
||||||
int device_set_watch_handle(sd_device *device, int wd);
|
void device_set_watch_handle(sd_device *device, int fd);
|
||||||
void device_set_db_persist(sd_device *device);
|
void device_set_db_persist(sd_device *device);
|
||||||
void device_set_devlink_priority(sd_device *device, int priority);
|
void device_set_devlink_priority(sd_device *device, int priority);
|
||||||
int device_ensure_usec_initialized(sd_device *device, sd_device *device_old);
|
int device_ensure_usec_initialized(sd_device *device, sd_device *device_old);
|
||||||
|
|||||||
@ -62,7 +62,7 @@ static sd_device *device_free(sd_device *device) {
|
|||||||
free(device->subsystem);
|
free(device->subsystem);
|
||||||
free(device->driver_subsystem);
|
free(device->driver_subsystem);
|
||||||
free(device->driver);
|
free(device->driver);
|
||||||
free(device->device_id);
|
free(device->id_filename);
|
||||||
free(device->properties_strv);
|
free(device->properties_strv);
|
||||||
free(device->properties_nulstr);
|
free(device->properties_nulstr);
|
||||||
|
|
||||||
@ -623,7 +623,7 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
|
|||||||
struct ifreq ifr = {};
|
struct ifreq ifr = {};
|
||||||
int ifindex;
|
int ifindex;
|
||||||
|
|
||||||
r = ifr.ifr_ifindex = parse_ifindex(id + 1);
|
r = ifr.ifr_ifindex = parse_ifindex(&id[1]);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -652,14 +652,15 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case '+': {
|
case '+': {
|
||||||
char subsys[NAME_MAX+1]; /* NAME_MAX does not include the trailing NUL. */
|
char subsys[PATH_MAX];
|
||||||
const char *sysname;
|
char *sysname;
|
||||||
|
|
||||||
sysname = strchr(id + 1, ':');
|
(void) strscpy(subsys, sizeof(subsys), id + 1);
|
||||||
|
sysname = strchr(subsys, ':');
|
||||||
if (!sysname)
|
if (!sysname)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
(void) strnscpy(subsys, sizeof(subsys), id + 1, sysname - id - 1);
|
sysname[0] = '\0';
|
||||||
sysname++;
|
sysname++;
|
||||||
|
|
||||||
return sd_device_new_from_subsystem_sysname(ret, subsys, sysname);
|
return sd_device_new_from_subsystem_sysname(ret, subsys, sysname);
|
||||||
@ -751,34 +752,15 @@ int device_set_subsystem(sd_device *device, const char *_subsystem) {
|
|||||||
return free_and_replace(device->subsystem, subsystem);
|
return free_and_replace(device->subsystem, subsystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int device_set_drivers_subsystem(sd_device *device) {
|
static int device_set_drivers_subsystem(sd_device *device, const char *_subsystem) {
|
||||||
_cleanup_free_ char *subsystem = NULL;
|
_cleanup_free_ char *subsystem = NULL;
|
||||||
const char *syspath, *drivers, *p;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(device);
|
assert(device);
|
||||||
|
assert(_subsystem);
|
||||||
|
assert(*_subsystem);
|
||||||
|
|
||||||
r = sd_device_get_syspath(device, &syspath);
|
subsystem = strdup(_subsystem);
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
drivers = strstr(syspath, "/drivers/");
|
|
||||||
if (!drivers)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
for (p = drivers - 1; p >= syspath; p--)
|
|
||||||
if (*p == '/')
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (p <= syspath)
|
|
||||||
/* syspath does not start with /sys/ ?? */
|
|
||||||
return -EINVAL;
|
|
||||||
p++;
|
|
||||||
if (p >= drivers)
|
|
||||||
/* refuse duplicated slashes */
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
subsystem = strndup(p, drivers - p);
|
|
||||||
if (!subsystem)
|
if (!subsystem)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -790,46 +772,60 @@ static int device_set_drivers_subsystem(sd_device *device) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
|
_public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
|
||||||
|
const char *syspath, *drivers = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert_return(device, -EINVAL);
|
assert_return(device, -EINVAL);
|
||||||
|
|
||||||
if (!device->subsystem_set) {
|
|
||||||
_cleanup_free_ char *subsystem = NULL;
|
|
||||||
const char *syspath;
|
|
||||||
char *path;
|
|
||||||
|
|
||||||
r = sd_device_get_syspath(device, &syspath);
|
r = sd_device_get_syspath(device, &syspath);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if (!device->subsystem_set) {
|
||||||
|
_cleanup_free_ char *subsystem = NULL;
|
||||||
|
char *path;
|
||||||
|
|
||||||
/* read 'subsystem' link */
|
/* read 'subsystem' link */
|
||||||
path = strjoina(syspath, "/subsystem");
|
path = strjoina(syspath, "/subsystem");
|
||||||
r = readlink_value(path, &subsystem);
|
r = readlink_value(path, &subsystem);
|
||||||
if (r < 0 && r != -ENOENT)
|
if (r >= 0)
|
||||||
return log_device_debug_errno(device, r,
|
|
||||||
"sd-device: Failed to read subsystem for %s: %m",
|
|
||||||
device->devpath);
|
|
||||||
|
|
||||||
if (subsystem)
|
|
||||||
r = device_set_subsystem(device, subsystem);
|
r = device_set_subsystem(device, subsystem);
|
||||||
/* use implicit names */
|
/* use implicit names */
|
||||||
else if (path_startswith(device->devpath, "/module/"))
|
else if (path_startswith(device->devpath, "/module/"))
|
||||||
r = device_set_subsystem(device, "module");
|
r = device_set_subsystem(device, "module");
|
||||||
else if (strstr(syspath, "/drivers/"))
|
else if (!(drivers = strstr(syspath, "/drivers/")) &&
|
||||||
r = device_set_drivers_subsystem(device);
|
PATH_STARTSWITH_SET(device->devpath, "/subsystem/",
|
||||||
else if (PATH_STARTSWITH_SET(device->devpath, "/subsystem/",
|
|
||||||
"/class/",
|
"/class/",
|
||||||
"/bus/"))
|
"/bus/"))
|
||||||
r = device_set_subsystem(device, "subsystem");
|
r = device_set_subsystem(device, "subsystem");
|
||||||
else {
|
if (r < 0 && r != -ENOENT)
|
||||||
|
return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem for %s: %m", device->devpath);
|
||||||
|
|
||||||
device->subsystem_set = true;
|
device->subsystem_set = true;
|
||||||
r = 0;
|
} else if (!device->driver_subsystem_set)
|
||||||
|
drivers = strstr(syspath, "/drivers/");
|
||||||
|
|
||||||
|
if (!device->driver_subsystem_set) {
|
||||||
|
if (drivers) {
|
||||||
|
_cleanup_free_ char *subpath = NULL;
|
||||||
|
|
||||||
|
subpath = strndup(syspath, drivers - syspath);
|
||||||
|
if (!subpath)
|
||||||
|
r = -ENOMEM;
|
||||||
|
else {
|
||||||
|
const char *subsys;
|
||||||
|
|
||||||
|
subsys = strrchr(subpath, '/');
|
||||||
|
if (!subsys)
|
||||||
|
r = -EINVAL;
|
||||||
|
else
|
||||||
|
r = device_set_drivers_subsystem(device, subsys + 1);
|
||||||
}
|
}
|
||||||
if (r < 0)
|
if (r < 0 && r != -ENOENT)
|
||||||
return log_device_debug_errno(device, r,
|
return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem for driver %s: %m", device->devpath);
|
||||||
"sd-device: Failed to set subsystem for %s: %m",
|
}
|
||||||
device->devpath);
|
|
||||||
|
device->driver_subsystem_set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!device->subsystem)
|
if (!device->subsystem)
|
||||||
@ -991,7 +987,7 @@ _public_ int sd_device_get_devname(sd_device *device, const char **devname) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int device_set_sysname_and_sysnum(sd_device *device) {
|
static int device_set_sysname(sd_device *device) {
|
||||||
_cleanup_free_ char *sysname = NULL;
|
_cleanup_free_ char *sysname = NULL;
|
||||||
const char *sysnum = NULL;
|
const char *sysnum = NULL;
|
||||||
const char *pos;
|
const char *pos;
|
||||||
@ -1028,6 +1024,7 @@ static int device_set_sysname_and_sysnum(sd_device *device) {
|
|||||||
if (len == 0)
|
if (len == 0)
|
||||||
sysnum = NULL;
|
sysnum = NULL;
|
||||||
|
|
||||||
|
device->sysname_set = true;
|
||||||
device->sysnum = sysnum;
|
device->sysnum = sysnum;
|
||||||
return free_and_replace(device->sysname, sysname);
|
return free_and_replace(device->sysname, sysname);
|
||||||
}
|
}
|
||||||
@ -1037,12 +1034,14 @@ _public_ int sd_device_get_sysname(sd_device *device, const char **ret) {
|
|||||||
|
|
||||||
assert_return(device, -EINVAL);
|
assert_return(device, -EINVAL);
|
||||||
|
|
||||||
if (!device->sysname) {
|
if (!device->sysname_set) {
|
||||||
r = device_set_sysname_and_sysnum(device);
|
r = device_set_sysname(device);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert_return(device->sysname, -ENOENT);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
*ret = device->sysname;
|
*ret = device->sysname;
|
||||||
return 0;
|
return 0;
|
||||||
@ -1053,8 +1052,8 @@ _public_ int sd_device_get_sysnum(sd_device *device, const char **ret) {
|
|||||||
|
|
||||||
assert_return(device, -EINVAL);
|
assert_return(device, -EINVAL);
|
||||||
|
|
||||||
if (!device->sysname) {
|
if (!device->sysname_set) {
|
||||||
r = device_set_sysname_and_sysnum(device);
|
r = device_set_sysname(device);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -1238,10 +1237,10 @@ static int handle_db_line(sd_device *device, char key, const char *value) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case 'W':
|
case 'W':
|
||||||
/* Deprecated. Previously, watch handle is both saved in database and /run/udev/watch.
|
r = safe_atoi(value, &device->watch_handle);
|
||||||
* However, the handle saved in database may not be updated when the handle is updated
|
if (r < 0)
|
||||||
* or removed. Moreover, it is not necessary to store the handle within the database,
|
return r;
|
||||||
* as its value becomes meaningless when udevd is restarted. */
|
|
||||||
break;
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
r = safe_atou(value, &device->database_version);
|
r = safe_atou(value, &device->database_version);
|
||||||
@ -1256,11 +1255,11 @@ static int handle_db_line(sd_device *device, char key, const char *value) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int device_get_device_id(sd_device *device, const char **ret) {
|
int device_get_id_filename(sd_device *device, const char **ret) {
|
||||||
assert(device);
|
assert(device);
|
||||||
assert(ret);
|
assert(ret);
|
||||||
|
|
||||||
if (!device->device_id) {
|
if (!device->id_filename) {
|
||||||
_cleanup_free_ char *id = NULL;
|
_cleanup_free_ char *id = NULL;
|
||||||
const char *subsystem;
|
const char *subsystem;
|
||||||
dev_t devnum;
|
dev_t devnum;
|
||||||
@ -1297,6 +1296,7 @@ int device_get_device_id(sd_device *device, const char **ret) {
|
|||||||
if (!subsystem)
|
if (!subsystem)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
||||||
if (streq(subsystem, "drivers"))
|
if (streq(subsystem, "drivers"))
|
||||||
/* the 'drivers' pseudo-subsystem is special, and needs the real subsystem
|
/* the 'drivers' pseudo-subsystem is special, and needs the real subsystem
|
||||||
* encoded as well */
|
* encoded as well */
|
||||||
@ -1307,13 +1307,10 @@ int device_get_device_id(sd_device *device, const char **ret) {
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!filename_is_valid(id))
|
device->id_filename = TAKE_PTR(id);
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
device->device_id = TAKE_PTR(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*ret = device->device_id;
|
*ret = device->id_filename;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1410,7 +1407,7 @@ int device_read_db_internal(sd_device *device, bool force) {
|
|||||||
if (device->db_loaded || (!force && device->sealed))
|
if (device->db_loaded || (!force && device->sealed))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = device_get_device_id(device, &id);
|
r = device_get_id_filename(device, &id);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -52,7 +52,7 @@ int config_parse_can_bitrate(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
@ -60,24 +60,53 @@ static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
|
|||||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
r = sd_netlink_message_get_errno(m);
|
||||||
|
if (r < 0)
|
||||||
|
/* we warn but don't fail the link, as it may be brought up later */
|
||||||
|
log_link_message_warning_errno(link, m, r, "Could not bring up interface");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int link_up_can(Link *link) {
|
||||||
|
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(link);
|
||||||
|
|
||||||
|
log_link_debug(link, "Bringing CAN link up");
|
||||||
|
|
||||||
|
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
|
||||||
|
if (r < 0)
|
||||||
|
return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
|
||||||
|
|
||||||
|
r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
|
||||||
|
if (r < 0)
|
||||||
|
return log_link_error_errno(link, r, "Could not set link flags: %m");
|
||||||
|
|
||||||
|
r = netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler,
|
||||||
|
link_netlink_destroy_callback, link);
|
||||||
|
if (r < 0)
|
||||||
|
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
|
||||||
|
|
||||||
|
link_ref(link);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(link);
|
||||||
|
|
||||||
|
log_link_debug(link, "Set link");
|
||||||
|
|
||||||
r = sd_netlink_message_get_errno(m);
|
r = sd_netlink_message_get_errno(m);
|
||||||
if (r < 0 && r != -EEXIST) {
|
if (r < 0 && r != -EEXIST) {
|
||||||
log_link_message_warning_errno(link, m, r, "Failed to configure CAN link");
|
log_link_message_warning_errno(link, m, r, "Failed to configure CAN link");
|
||||||
link_enter_failed(link);
|
link_enter_failed(link);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log_link_debug(link, "Link set");
|
|
||||||
|
|
||||||
r = link_activate(link);
|
|
||||||
if (r < 0) {
|
|
||||||
link_enter_failed(link);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
link->can_configured = true;
|
|
||||||
link_check_ready(link);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,6 +255,9 @@ static int link_set_can(Link *link) {
|
|||||||
|
|
||||||
link_ref(link);
|
link_ref(link);
|
||||||
|
|
||||||
|
if (!(link->flags & IFF_UP))
|
||||||
|
return link_up_can(link);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,21 +290,30 @@ int link_configure_can(Link *link) {
|
|||||||
|
|
||||||
if (streq_ptr(link->kind, "can")) {
|
if (streq_ptr(link->kind, "can")) {
|
||||||
/* The CAN interface must be down to configure bitrate, etc... */
|
/* The CAN interface must be down to configure bitrate, etc... */
|
||||||
if ((link->flags & IFF_UP))
|
if ((link->flags & IFF_UP)) {
|
||||||
r = link_down(link, link_down_handler);
|
r = link_down(link, link_down_handler);
|
||||||
else
|
if (r < 0) {
|
||||||
r = link_set_can(link);
|
|
||||||
if (r < 0)
|
|
||||||
link_enter_failed(link);
|
link_enter_failed(link);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
r = link_activate(link);
|
r = link_set_can(link);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
|
link_enter_failed(link);
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
link->can_configured = true;
|
return 0;
|
||||||
link_check_ready(link);
|
}
|
||||||
|
|
||||||
|
if (!(link->flags & IFF_UP)) {
|
||||||
|
r = link_up_can(link);
|
||||||
|
if (r < 0) {
|
||||||
|
link_enter_failed(link);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -764,15 +764,6 @@ void link_check_ready(Link *link) {
|
|||||||
if (!link->network)
|
if (!link->network)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (link->iftype == ARPHRD_CAN) {
|
|
||||||
/* let's shortcut things for CAN which doesn't need most of checks below. */
|
|
||||||
if (!link->can_configured)
|
|
||||||
return (void) log_link_debug(link, "%s(): CAN device is not configured.", __func__);
|
|
||||||
|
|
||||||
link_enter_configured(link);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!link->addresses_configured)
|
if (!link->addresses_configured)
|
||||||
return (void) log_link_debug(link, "%s(): static addresses are not configured.", __func__);
|
return (void) log_link_debug(link, "%s(): static addresses are not configured.", __func__);
|
||||||
|
|
||||||
@ -1385,7 +1376,7 @@ static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int link_up(Link *link) {
|
static int link_up(Link *link) {
|
||||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -1780,7 +1771,7 @@ static void link_drop(Link *link) {
|
|||||||
link_detach_from_manager(link);
|
link_detach_from_manager(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
int link_activate(Link *link) {
|
static int link_joined(Link *link) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
@ -1798,8 +1789,10 @@ int link_activate(Link *link) {
|
|||||||
_fallthrough_;
|
_fallthrough_;
|
||||||
case ACTIVATION_POLICY_ALWAYS_UP:
|
case ACTIVATION_POLICY_ALWAYS_UP:
|
||||||
r = link_up(link);
|
r = link_up(link);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
|
link_enter_failed(link);
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ACTIVATION_POLICY_DOWN:
|
case ACTIVATION_POLICY_DOWN:
|
||||||
if (link->activated)
|
if (link->activated)
|
||||||
@ -1807,27 +1800,16 @@ int link_activate(Link *link) {
|
|||||||
_fallthrough_;
|
_fallthrough_;
|
||||||
case ACTIVATION_POLICY_ALWAYS_DOWN:
|
case ACTIVATION_POLICY_ALWAYS_DOWN:
|
||||||
r = link_down(link, NULL);
|
r = link_down(link, NULL);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
|
link_enter_failed(link);
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
link->activated = true;
|
link->activated = true;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int link_joined(Link *link) {
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(link);
|
|
||||||
assert(link->network);
|
|
||||||
|
|
||||||
r = link_activate(link);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (link->network->bridge) {
|
if (link->network->bridge) {
|
||||||
r = link_set_bridge(link);
|
r = link_set_bridge(link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -2094,7 +2076,6 @@ int link_configure(Link *link) {
|
|||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (link->iftype == ARPHRD_CAN)
|
if (link->iftype == ARPHRD_CAN)
|
||||||
/* let's shortcut things for CAN which doesn't need most of what's done below. */
|
|
||||||
return link_configure_can(link);
|
return link_configure_can(link);
|
||||||
|
|
||||||
r = link_set_sysctl(link);
|
r = link_set_sysctl(link);
|
||||||
@ -2586,10 +2567,6 @@ static int link_carrier_gained(Link *link) {
|
|||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
|
|
||||||
if (link->iftype == ARPHRD_CAN)
|
|
||||||
/* let's shortcut things for CAN which doesn't need most of what's done below. */
|
|
||||||
return link_handle_bound_by_list(link);
|
|
||||||
|
|
||||||
r = wifi_get_info(link);
|
r = wifi_get_info(link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -2648,10 +2625,6 @@ static int link_carrier_lost(Link *link) {
|
|||||||
if (link->network && link->network->ignore_carrier_loss)
|
if (link->network && link->network->ignore_carrier_loss)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (link->iftype == ARPHRD_CAN)
|
|
||||||
/* let's shortcut things for CAN which doesn't need most of what's done below. */
|
|
||||||
return link_handle_bound_by_list(link);
|
|
||||||
|
|
||||||
/* Some devices reset itself while setting the MTU. This causes the DHCP client fall into a loop.
|
/* Some devices reset itself while setting the MTU. This causes the DHCP client fall into a loop.
|
||||||
* setting_mtu keep track whether the device got reset because of setting MTU and does not drop the
|
* setting_mtu keep track whether the device got reset because of setting MTU and does not drop the
|
||||||
* configuration and stop the clients as well. */
|
* configuration and stop the clients as well. */
|
||||||
@ -2739,10 +2712,6 @@ static int link_admin_state_down(Link *link) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (link->network->activation_policy == ACTIVATION_POLICY_ALWAYS_UP) {
|
if (link->network->activation_policy == ACTIVATION_POLICY_ALWAYS_UP) {
|
||||||
if (streq_ptr(link->kind, "can") && !link->can_configured)
|
|
||||||
/* CAN device needs to be down on configure. */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
log_link_info(link, "ActivationPolicy is \"always-on\", forcing link up");
|
log_link_info(link, "ActivationPolicy is \"always-on\", forcing link up");
|
||||||
return link_up(link);
|
return link_up(link);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -131,7 +131,6 @@ typedef struct Link {
|
|||||||
bool setting_genmode:1;
|
bool setting_genmode:1;
|
||||||
bool ipv6_mtu_set:1;
|
bool ipv6_mtu_set:1;
|
||||||
bool bridge_mdb_configured:1;
|
bool bridge_mdb_configured:1;
|
||||||
bool can_configured:1;
|
|
||||||
bool activated:1;
|
bool activated:1;
|
||||||
|
|
||||||
sd_dhcp_server *dhcp_server;
|
sd_dhcp_server *dhcp_server;
|
||||||
@ -208,9 +207,7 @@ DEFINE_TRIVIAL_DESTRUCTOR(link_netlink_destroy_callback, Link, link_unref);
|
|||||||
|
|
||||||
int link_get(Manager *m, int ifindex, Link **ret);
|
int link_get(Manager *m, int ifindex, Link **ret);
|
||||||
|
|
||||||
int link_up(Link *link);
|
|
||||||
int link_down(Link *link, link_netlink_message_handler_t callback);
|
int link_down(Link *link, link_netlink_message_handler_t callback);
|
||||||
int link_activate(Link *link);
|
|
||||||
|
|
||||||
void link_enter_failed(Link *link);
|
void link_enter_failed(Link *link);
|
||||||
|
|
||||||
|
|||||||
@ -130,7 +130,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
udev_event_execute_rules(event, -1, 3 * USEC_PER_SEC, SIGKILL, NULL, rules);
|
udev_event_execute_rules(event, 3 * USEC_PER_SEC, SIGKILL, NULL, rules);
|
||||||
udev_event_execute_run(event, 3 * USEC_PER_SEC, SIGKILL);
|
udev_event_execute_run(event, 3 * USEC_PER_SEC, SIGKILL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -911,9 +911,8 @@ static int update_devnode(UdevEvent *event) {
|
|||||||
return udev_node_add(dev, apply_mac, event->mode, event->uid, event->gid, event->seclabel_list);
|
return udev_node_add(dev, apply_mac, event->mode, event->uid, event->gid, event->seclabel_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int event_execute_rules_on_remove(
|
static void event_execute_rules_on_remove(
|
||||||
UdevEvent *event,
|
UdevEvent *event,
|
||||||
int inotify_fd,
|
|
||||||
usec_t timeout_usec,
|
usec_t timeout_usec,
|
||||||
int timeout_signal,
|
int timeout_signal,
|
||||||
Hashmap *properties_list,
|
Hashmap *properties_list,
|
||||||
@ -934,14 +933,13 @@ static int event_execute_rules_on_remove(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_device_debug_errno(dev, r, "Failed to delete database under /run/udev/data/, ignoring: %m");
|
log_device_debug_errno(dev, r, "Failed to delete database under /run/udev/data/, ignoring: %m");
|
||||||
|
|
||||||
(void) udev_watch_end(inotify_fd, dev);
|
if (sd_device_get_devnum(dev, NULL) >= 0)
|
||||||
|
(void) udev_watch_end(dev);
|
||||||
|
|
||||||
r = udev_rules_apply_to_event(rules, event, timeout_usec, timeout_signal, properties_list);
|
(void) udev_rules_apply_to_event(rules, event, timeout_usec, timeout_signal, properties_list);
|
||||||
|
|
||||||
if (sd_device_get_devnum(dev, NULL) >= 0)
|
if (sd_device_get_devnum(dev, NULL) >= 0)
|
||||||
(void) udev_node_remove(dev);
|
(void) udev_node_remove(dev);
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int udev_event_on_move(sd_device *dev) {
|
static int udev_event_on_move(sd_device *dev) {
|
||||||
@ -973,14 +971,12 @@ static int copy_all_tags(sd_device *d, sd_device *s) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int udev_event_execute_rules(
|
int udev_event_execute_rules(UdevEvent *event,
|
||||||
UdevEvent *event,
|
|
||||||
int inotify_fd, /* This may be negative */
|
|
||||||
usec_t timeout_usec,
|
usec_t timeout_usec,
|
||||||
int timeout_signal,
|
int timeout_signal,
|
||||||
Hashmap *properties_list,
|
Hashmap *properties_list,
|
||||||
UdevRules *rules) {
|
UdevRules *rules) {
|
||||||
|
const char *subsystem;
|
||||||
sd_device_action_t action;
|
sd_device_action_t action;
|
||||||
sd_device *dev;
|
sd_device *dev;
|
||||||
int r;
|
int r;
|
||||||
@ -990,15 +986,18 @@ int udev_event_execute_rules(
|
|||||||
|
|
||||||
dev = event->dev;
|
dev = event->dev;
|
||||||
|
|
||||||
|
r = sd_device_get_subsystem(dev, &subsystem);
|
||||||
|
if (r < 0)
|
||||||
|
return log_device_error_errno(dev, r, "Failed to get subsystem: %m");
|
||||||
|
|
||||||
r = sd_device_get_action(dev, &action);
|
r = sd_device_get_action(dev, &action);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_device_error_errno(dev, r, "Failed to get ACTION: %m");
|
return log_device_error_errno(dev, r, "Failed to get ACTION: %m");
|
||||||
|
|
||||||
if (action == SD_DEVICE_REMOVE)
|
if (action == SD_DEVICE_REMOVE) {
|
||||||
return event_execute_rules_on_remove(event, inotify_fd, timeout_usec, timeout_signal, properties_list, rules);
|
event_execute_rules_on_remove(event, timeout_usec, timeout_signal, properties_list, rules);
|
||||||
|
return 0;
|
||||||
/* Disable watch during event processing. */
|
}
|
||||||
(void) udev_watch_end(inotify_fd, event->dev);
|
|
||||||
|
|
||||||
r = device_clone_with_db(dev, &event->dev_db_clone);
|
r = device_clone_with_db(dev, &event->dev_db_clone);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -1008,6 +1007,10 @@ int udev_event_execute_rules(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_device_warning_errno(dev, r, "Failed to copy all tags from old database entry, ignoring: %m");
|
log_device_warning_errno(dev, r, "Failed to copy all tags from old database entry, ignoring: %m");
|
||||||
|
|
||||||
|
if (sd_device_get_devnum(dev, NULL) >= 0)
|
||||||
|
/* Disable watch during event processing. */
|
||||||
|
(void) udev_watch_end(event->dev_db_clone);
|
||||||
|
|
||||||
if (action == SD_DEVICE_MOVE) {
|
if (action == SD_DEVICE_MOVE) {
|
||||||
r = udev_event_on_move(event->dev);
|
r = udev_event_on_move(event->dev);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -1045,7 +1048,11 @@ int udev_event_execute_rules(
|
|||||||
/* Yes, we run update_devnode() twice, because in the first invocation, that is before update of udev database,
|
/* Yes, we run update_devnode() twice, because in the first invocation, that is before update of udev database,
|
||||||
* it could happen that two contenders are replacing each other's symlink. Hence we run it again to make sure
|
* it could happen that two contenders are replacing each other's symlink. Hence we run it again to make sure
|
||||||
* symlinks point to devices that claim them with the highest priority. */
|
* symlinks point to devices that claim them with the highest priority. */
|
||||||
return update_devnode(event);
|
r = update_devnode(event);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_signal) {
|
void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_signal) {
|
||||||
@ -1080,24 +1087,3 @@ void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int udev_event_process_inotify_watch(UdevEvent *event, int inotify_fd) {
|
|
||||||
sd_device *dev;
|
|
||||||
|
|
||||||
assert(event);
|
|
||||||
assert(inotify_fd >= 0);
|
|
||||||
|
|
||||||
dev = event->dev;
|
|
||||||
|
|
||||||
assert(dev);
|
|
||||||
|
|
||||||
if (device_for_action(dev, SD_DEVICE_REMOVE))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (event->inotify_watch)
|
|
||||||
(void) udev_watch_begin(inotify_fd, dev);
|
|
||||||
else
|
|
||||||
(void) udev_watch_end(inotify_fd, dev);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -51,30 +51,21 @@ UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rt
|
|||||||
UdevEvent *udev_event_free(UdevEvent *event);
|
UdevEvent *udev_event_free(UdevEvent *event);
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(UdevEvent*, udev_event_free);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(UdevEvent*, udev_event_free);
|
||||||
|
|
||||||
size_t udev_event_apply_format(
|
size_t udev_event_apply_format(UdevEvent *event,
|
||||||
UdevEvent *event,
|
const char *src, char *dest, size_t size,
|
||||||
const char *src,
|
|
||||||
char *dest,
|
|
||||||
size_t size,
|
|
||||||
bool replace_whitespace);
|
bool replace_whitespace);
|
||||||
int udev_check_format(const char *value, size_t *offset, const char **hint);
|
int udev_check_format(const char *value, size_t *offset, const char **hint);
|
||||||
int udev_event_spawn(
|
int udev_event_spawn(UdevEvent *event,
|
||||||
UdevEvent *event,
|
|
||||||
usec_t timeout_usec,
|
usec_t timeout_usec,
|
||||||
int timeout_signal,
|
int timeout_signal,
|
||||||
bool accept_failure,
|
bool accept_failure,
|
||||||
const char *cmd,
|
const char *cmd, char *result, size_t ressize);
|
||||||
char *result,
|
int udev_event_execute_rules(UdevEvent *event,
|
||||||
size_t ressize);
|
|
||||||
int udev_event_execute_rules(
|
|
||||||
UdevEvent *event,
|
|
||||||
int inotify_fd,
|
|
||||||
usec_t timeout_usec,
|
usec_t timeout_usec,
|
||||||
int timeout_signal,
|
int timeout_signal,
|
||||||
Hashmap *properties_list,
|
Hashmap *properties_list,
|
||||||
UdevRules *rules);
|
UdevRules *rules);
|
||||||
void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_signal);
|
void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_signal);
|
||||||
int udev_event_process_inotify_watch(UdevEvent *event, int inotify_fd);
|
|
||||||
|
|
||||||
static inline usec_t udev_warn_timeout(usec_t timeout_usec) {
|
static inline usec_t udev_warn_timeout(usec_t timeout_usec) {
|
||||||
return DIV_ROUND_UP(timeout_usec, 3);
|
return DIV_ROUND_UP(timeout_usec, 3);
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
static int node_symlink(sd_device *dev, const char *node, const char *slink) {
|
static int node_symlink(sd_device *dev, const char *node, const char *slink) {
|
||||||
_cleanup_free_ char *slink_dirname = NULL, *target = NULL;
|
_cleanup_free_ char *slink_dirname = NULL, *target = NULL;
|
||||||
const char *id, *slink_tmp;
|
const char *id_filename, *slink_tmp;
|
||||||
struct stat stats;
|
struct stat stats;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -81,10 +81,10 @@ static int node_symlink(sd_device *dev, const char *node, const char *slink) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log_device_debug(dev, "Atomically replace '%s'", slink);
|
log_device_debug(dev, "Atomically replace '%s'", slink);
|
||||||
r = device_get_device_id(dev, &id);
|
r = device_get_id_filename(dev, &id_filename);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_device_error_errno(dev, r, "Failed to get device id: %m");
|
return log_device_error_errno(dev, r, "Failed to get id_filename: %m");
|
||||||
slink_tmp = strjoina(slink, ".tmp-", id);
|
slink_tmp = strjoina(slink, ".tmp-", id_filename);
|
||||||
(void) unlink(slink_tmp);
|
(void) unlink(slink_tmp);
|
||||||
do {
|
do {
|
||||||
r = mkdir_parents_label(slink_tmp, 0755);
|
r = mkdir_parents_label(slink_tmp, 0755);
|
||||||
@ -147,7 +147,7 @@ static int link_find_prioritized(sd_device *dev, bool add, const char *stackdir,
|
|||||||
|
|
||||||
FOREACH_DIRENT_ALL(dent, dir, break) {
|
FOREACH_DIRENT_ALL(dent, dir, break) {
|
||||||
_cleanup_(sd_device_unrefp) sd_device *dev_db = NULL;
|
_cleanup_(sd_device_unrefp) sd_device *dev_db = NULL;
|
||||||
const char *devnode, *id;
|
const char *devnode, *id_filename;
|
||||||
int db_prio = 0;
|
int db_prio = 0;
|
||||||
|
|
||||||
if (dent->d_name[0] == '\0')
|
if (dent->d_name[0] == '\0')
|
||||||
@ -157,11 +157,11 @@ static int link_find_prioritized(sd_device *dev, bool add, const char *stackdir,
|
|||||||
|
|
||||||
log_device_debug(dev, "Found '%s' claiming '%s'", dent->d_name, stackdir);
|
log_device_debug(dev, "Found '%s' claiming '%s'", dent->d_name, stackdir);
|
||||||
|
|
||||||
if (device_get_device_id(dev, &id) < 0)
|
if (device_get_id_filename(dev, &id_filename) < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* did we find ourself? */
|
/* did we find ourself? */
|
||||||
if (streq(dent->d_name, id))
|
if (streq(dent->d_name, id_filename))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (sd_device_new_from_device_id(&dev_db, dent->d_name) < 0)
|
if (sd_device_new_from_device_id(&dev_db, dent->d_name) < 0)
|
||||||
@ -229,21 +229,21 @@ static size_t escape_path(const char *src, char *dest, size_t size) {
|
|||||||
static int link_update(sd_device *dev, const char *slink, bool add) {
|
static int link_update(sd_device *dev, const char *slink, bool add) {
|
||||||
_cleanup_free_ char *filename = NULL, *dirname = NULL;
|
_cleanup_free_ char *filename = NULL, *dirname = NULL;
|
||||||
char name_enc[PATH_MAX];
|
char name_enc[PATH_MAX];
|
||||||
const char *id;
|
const char *id_filename;
|
||||||
int i, r, retries;
|
int i, r, retries;
|
||||||
|
|
||||||
assert(dev);
|
assert(dev);
|
||||||
assert(slink);
|
assert(slink);
|
||||||
|
|
||||||
r = device_get_device_id(dev, &id);
|
r = device_get_id_filename(dev, &id_filename);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_device_debug_errno(dev, r, "Failed to get device id: %m");
|
return log_device_debug_errno(dev, r, "Failed to get id_filename: %m");
|
||||||
|
|
||||||
escape_path(slink + STRLEN("/dev"), name_enc, sizeof(name_enc));
|
escape_path(slink + STRLEN("/dev"), name_enc, sizeof(name_enc));
|
||||||
dirname = path_join("/run/udev/links/", name_enc);
|
dirname = path_join("/run/udev/links/", name_enc);
|
||||||
if (!dirname)
|
if (!dirname)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
filename = path_join(dirname, id);
|
filename = path_join(dirname, id_filename);
|
||||||
if (!filename)
|
if (!filename)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
@ -348,7 +348,7 @@ int udev_node_update_old_links(sd_device *dev, sd_device *dev_old) {
|
|||||||
static int node_permissions_apply(sd_device *dev, bool apply_mac,
|
static int node_permissions_apply(sd_device *dev, bool apply_mac,
|
||||||
mode_t mode, uid_t uid, gid_t gid,
|
mode_t mode, uid_t uid, gid_t gid,
|
||||||
OrderedHashmap *seclabel_list) {
|
OrderedHashmap *seclabel_list) {
|
||||||
const char *devnode, *subsystem, *id = NULL;
|
const char *devnode, *subsystem, *id_filename = NULL;
|
||||||
bool apply_mode, apply_uid, apply_gid;
|
bool apply_mode, apply_uid, apply_gid;
|
||||||
_cleanup_close_ int node_fd = -1;
|
_cleanup_close_ int node_fd = -1;
|
||||||
struct stat stats;
|
struct stat stats;
|
||||||
@ -366,7 +366,7 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac,
|
|||||||
r = sd_device_get_devnum(dev, &devnum);
|
r = sd_device_get_devnum(dev, &devnum);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_device_debug_errno(dev, r, "Failed to get devnum: %m");
|
return log_device_debug_errno(dev, r, "Failed to get devnum: %m");
|
||||||
(void) device_get_device_id(dev, &id);
|
(void) device_get_id_filename(dev, &id_filename);
|
||||||
|
|
||||||
if (streq(subsystem, "block"))
|
if (streq(subsystem, "block"))
|
||||||
mode |= S_IFBLK;
|
mode |= S_IFBLK;
|
||||||
@ -388,7 +388,7 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac,
|
|||||||
|
|
||||||
if ((mode != MODE_INVALID && (stats.st_mode & S_IFMT) != (mode & S_IFMT)) || stats.st_rdev != devnum) {
|
if ((mode != MODE_INVALID && (stats.st_mode & S_IFMT) != (mode & S_IFMT)) || stats.st_rdev != devnum) {
|
||||||
log_device_debug(dev, "Found node '%s' with non-matching devnum %s, skipping handling.",
|
log_device_debug(dev, "Found node '%s' with non-matching devnum %s, skipping handling.",
|
||||||
devnode, strna(id));
|
devnode, id_filename);
|
||||||
return 0; /* We might process a device that already got replaced by the time we have a look
|
return 0; /* We might process a device that already got replaced by the time we have a look
|
||||||
* at it, handle this gracefully and step away. */
|
* at it, handle this gracefully and step away. */
|
||||||
}
|
}
|
||||||
@ -509,10 +509,10 @@ int udev_node_add(sd_device *dev, bool apply,
|
|||||||
return log_device_debug_errno(dev, r, "Failed to get devnode: %m");
|
return log_device_debug_errno(dev, r, "Failed to get devnode: %m");
|
||||||
|
|
||||||
if (DEBUG_LOGGING) {
|
if (DEBUG_LOGGING) {
|
||||||
const char *id = NULL;
|
const char *id_filename = NULL;
|
||||||
|
|
||||||
(void) device_get_device_id(dev, &id);
|
(void) device_get_id_filename(dev, &id_filename);
|
||||||
log_device_debug(dev, "Handling device node '%s', devnum=%s", devnode, strna(id));
|
log_device_debug(dev, "Handling device node '%s', devnum=%s", devnode, strnull(id_filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
r = node_permissions_apply(dev, apply, mode, uid, gid, seclabel_list);
|
r = node_permissions_apply(dev, apply, mode, uid, gid, seclabel_list);
|
||||||
|
|||||||
@ -5,60 +5,72 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "device-private.h"
|
#include "device-private.h"
|
||||||
#include "device-util.h"
|
#include "device-util.h"
|
||||||
#include "dirent-util.h"
|
#include "dirent-util.h"
|
||||||
#include "fs-util.h"
|
#include "fs-util.h"
|
||||||
#include "parse-util.h"
|
#include "mkdir.h"
|
||||||
|
#include "stdio-util.h"
|
||||||
#include "udev-watch.h"
|
#include "udev-watch.h"
|
||||||
|
|
||||||
int udev_watch_restore(int inotify_fd) {
|
static int inotify_fd = -1;
|
||||||
|
|
||||||
|
/* inotify descriptor, will be shared with rules directory;
|
||||||
|
* set to cloexec since we need our children to be able to add
|
||||||
|
* watches for us. */
|
||||||
|
int udev_watch_init(void) {
|
||||||
|
inotify_fd = inotify_init1(IN_CLOEXEC);
|
||||||
|
if (inotify_fd < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return inotify_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move any old watches directory out of the way, and then restore the watches. */
|
||||||
|
int udev_watch_restore(void) {
|
||||||
struct dirent *ent;
|
struct dirent *ent;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* Move any old watches directory out of the way, and then restore the watches. */
|
if (inotify_fd < 0)
|
||||||
|
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
assert(inotify_fd >= 0);
|
"Invalid inotify descriptor.");
|
||||||
|
|
||||||
if (rename("/run/udev/watch", "/run/udev/watch.old") < 0) {
|
if (rename("/run/udev/watch", "/run/udev/watch.old") < 0) {
|
||||||
if (errno != ENOENT)
|
if (errno != ENOENT)
|
||||||
return log_warning_errno(errno, "Failed to move watches directory /run/udev/watch. "
|
return log_warning_errno(errno, "Failed to move watches directory /run/udev/watch. Old watches will not be restored: %m");
|
||||||
"Old watches will not be restored: %m");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = opendir("/run/udev/watch.old");
|
dir = opendir("/run/udev/watch.old");
|
||||||
if (!dir)
|
if (!dir)
|
||||||
return log_warning_errno(errno, "Failed to open old watches directory /run/udev/watch.old. "
|
return log_warning_errno(errno, "Failed to open old watches directory /run/udev/watch.old. Old watches will not be restored: %m");
|
||||||
"Old watches will not be restored: %m");
|
|
||||||
|
|
||||||
FOREACH_DIRENT_ALL(ent, dir, break) {
|
FOREACH_DIRENT_ALL(ent, dir, break) {
|
||||||
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
|
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
|
||||||
int wd;
|
_cleanup_free_ char *device = NULL;
|
||||||
|
|
||||||
if (ent->d_name[0] == '.')
|
if (ent->d_name[0] == '.')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* For backward compatibility, read symlink from watch handle to device id, and ignore
|
r = readlinkat_malloc(dirfd(dir), ent->d_name, &device);
|
||||||
* the opposite direction symlink. */
|
|
||||||
|
|
||||||
if (safe_atoi(ent->d_name, &wd) < 0)
|
|
||||||
goto unlink;
|
|
||||||
|
|
||||||
r = device_new_from_watch_handle_at(&dev, dirfd(dir), wd);
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_full_errno(r == -ENODEV ? LOG_DEBUG : LOG_WARNING, r,
|
log_debug_errno(r, "Failed to read link '/run/udev/watch.old/%s', ignoring: %m", ent->d_name);
|
||||||
"Failed to create sd_device object from saved watch handle '%s', ignoring: %m",
|
goto unlink;
|
||||||
ent->d_name);
|
}
|
||||||
|
|
||||||
|
r = sd_device_new_from_device_id(&dev, device);
|
||||||
|
if (r < 0) {
|
||||||
|
log_debug_errno(r, "Failed to create sd_device object for '%s', ignoring: %m", device);
|
||||||
goto unlink;
|
goto unlink;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_device_debug(dev, "Restoring old watch");
|
log_device_debug(dev, "Restoring old watch");
|
||||||
(void) udev_watch_begin(inotify_fd, dev);
|
(void) udev_watch_begin(dev);
|
||||||
unlink:
|
unlink:
|
||||||
(void) unlinkat(dirfd(dir), ent->d_name, 0);
|
(void) unlinkat(dirfd(dir), ent->d_name, 0);
|
||||||
}
|
}
|
||||||
@ -69,54 +81,94 @@ unlink:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int udev_watch_begin(int inotify_fd, sd_device *dev) {
|
int udev_watch_begin(sd_device *dev) {
|
||||||
const char *devnode;
|
char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
|
||||||
|
const char *devnode, *id_filename;
|
||||||
int wd, r;
|
int wd, r;
|
||||||
|
|
||||||
assert(inotify_fd >= 0);
|
if (inotify_fd < 0)
|
||||||
assert(dev);
|
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"Invalid inotify descriptor.");
|
||||||
|
|
||||||
r = sd_device_get_devname(dev, &devnode);
|
r = sd_device_get_devname(dev, &devnode);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_device_debug_errno(dev, r, "Failed to get device name: %m");
|
return log_device_error_errno(dev, r, "Failed to get device name: %m");
|
||||||
|
|
||||||
log_device_debug(dev, "Adding watch on '%s'", devnode);
|
log_device_debug(dev, "Adding watch on '%s'", devnode);
|
||||||
wd = inotify_add_watch(inotify_fd, devnode, IN_CLOSE_WRITE);
|
wd = inotify_add_watch(inotify_fd, devnode, IN_CLOSE_WRITE);
|
||||||
if (wd < 0) {
|
if (wd < 0)
|
||||||
r = log_device_full_errno(dev, errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
|
return log_device_full_errno(dev, errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
|
||||||
errno, "Failed to add device '%s' to watch: %m", devnode);
|
"Failed to add device '%s' to watch: %m", devnode);
|
||||||
|
|
||||||
(void) device_set_watch_handle(dev, -1);
|
device_set_watch_handle(dev, wd);
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = device_set_watch_handle(dev, wd);
|
xsprintf(filename, "/run/udev/watch/%d", wd);
|
||||||
|
r = mkdir_parents(filename, 0755);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_device_warning_errno(dev, r, "Failed to save watch handle in /run/udev/watch: %m");
|
return log_device_error_errno(dev, r, "Failed to create parent directory of '%s': %m", filename);
|
||||||
|
(void) unlink(filename);
|
||||||
|
|
||||||
|
r = device_get_id_filename(dev, &id_filename);
|
||||||
|
if (r < 0)
|
||||||
|
return log_device_error_errno(dev, r, "Failed to get device id-filename: %m");
|
||||||
|
|
||||||
|
if (symlink(id_filename, filename) < 0)
|
||||||
|
return log_device_error_errno(dev, errno, "Failed to create symlink %s: %m", filename);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int udev_watch_end(int inotify_fd, sd_device *dev) {
|
int udev_watch_end(sd_device *dev) {
|
||||||
int wd;
|
char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
|
||||||
|
int wd, r;
|
||||||
|
|
||||||
assert(dev);
|
|
||||||
|
|
||||||
/* This may be called by 'udevadm test'. In that case, inotify_fd is not initialized. */
|
|
||||||
if (inotify_fd < 0)
|
if (inotify_fd < 0)
|
||||||
return 0;
|
return 0; /* Nothing to do. */
|
||||||
|
|
||||||
if (sd_device_get_devname(dev, NULL) < 0)
|
r = device_get_watch_handle(dev, &wd);
|
||||||
|
if (r == -ENOENT)
|
||||||
return 0;
|
return 0;
|
||||||
|
if (r < 0)
|
||||||
|
return log_device_debug_errno(dev, r, "Failed to get watch handle, ignoring: %m");
|
||||||
|
|
||||||
wd = device_get_watch_handle(dev);
|
|
||||||
if (wd < 0)
|
|
||||||
log_device_debug_errno(dev, wd, "Failed to get watch handle, ignoring: %m");
|
|
||||||
else {
|
|
||||||
log_device_debug(dev, "Removing watch");
|
log_device_debug(dev, "Removing watch");
|
||||||
(void) inotify_rm_watch(inotify_fd, wd);
|
(void) inotify_rm_watch(inotify_fd, wd);
|
||||||
}
|
|
||||||
(void) device_set_watch_handle(dev, -1);
|
xsprintf(filename, "/run/udev/watch/%d", wd);
|
||||||
|
(void) unlink(filename);
|
||||||
|
|
||||||
|
device_set_watch_handle(dev, -1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int udev_watch_lookup(int wd, sd_device **ret) {
|
||||||
|
char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
|
||||||
|
_cleanup_free_ char *device = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
if (inotify_fd < 0)
|
||||||
|
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"Invalid inotify descriptor.");
|
||||||
|
|
||||||
|
if (wd < 0)
|
||||||
|
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"Invalid watch handle.");
|
||||||
|
|
||||||
|
xsprintf(filename, "/run/udev/watch/%d", wd);
|
||||||
|
r = readlink_malloc(filename, &device);
|
||||||
|
if (r == -ENOENT)
|
||||||
|
return 0;
|
||||||
|
if (r < 0)
|
||||||
|
return log_debug_errno(r, "Failed to read link '%s': %m", filename);
|
||||||
|
|
||||||
|
r = sd_device_new_from_device_id(ret, device);
|
||||||
|
if (r == -ENODEV)
|
||||||
|
return 0;
|
||||||
|
if (r < 0)
|
||||||
|
return log_debug_errno(r, "Failed to create sd_device object for '%s': %m", device);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "sd-device.h"
|
#include "sd-device.h"
|
||||||
|
|
||||||
int udev_watch_restore(int inotify_fd);
|
int udev_watch_init(void);
|
||||||
int udev_watch_begin(int inotify_fd, sd_device *dev);
|
int udev_watch_restore(void);
|
||||||
int udev_watch_end(int inotify_fd, sd_device *dev);
|
int udev_watch_begin(sd_device *dev);
|
||||||
|
int udev_watch_end(sd_device *dev);
|
||||||
|
int udev_watch_lookup(int wd, sd_device **ret);
|
||||||
|
|||||||
@ -141,7 +141,7 @@ int test_main(int argc, char *argv[], void *userdata) {
|
|||||||
assert_se(sigfillset(&mask) >= 0);
|
assert_se(sigfillset(&mask) >= 0);
|
||||||
assert_se(sigprocmask(SIG_SETMASK, &mask, &sigmask_orig) >= 0);
|
assert_se(sigprocmask(SIG_SETMASK, &mask, &sigmask_orig) >= 0);
|
||||||
|
|
||||||
udev_event_execute_rules(event, -1, 60 * USEC_PER_SEC, SIGKILL, NULL, rules);
|
udev_event_execute_rules(event, 60 * USEC_PER_SEC, SIGKILL, NULL, rules);
|
||||||
|
|
||||||
FOREACH_DEVICE_PROPERTY(dev, key, value)
|
FOREACH_DEVICE_PROPERTY(dev, key, value)
|
||||||
printf("%s=%s\n", key, value);
|
printf("%s=%s\n", key, value);
|
||||||
|
|||||||
@ -92,12 +92,10 @@ typedef struct Manager {
|
|||||||
|
|
||||||
sd_device_monitor *monitor;
|
sd_device_monitor *monitor;
|
||||||
struct udev_ctrl *ctrl;
|
struct udev_ctrl *ctrl;
|
||||||
|
int fd_inotify;
|
||||||
int worker_watch[2];
|
int worker_watch[2];
|
||||||
|
|
||||||
/* used by udev-watch */
|
|
||||||
int inotify_fd;
|
|
||||||
sd_event_source *inotify_event;
|
sd_event_source *inotify_event;
|
||||||
|
|
||||||
sd_event_source *kill_workers_event;
|
sd_event_source *kill_workers_event;
|
||||||
|
|
||||||
usec_t last_usec;
|
usec_t last_usec;
|
||||||
@ -306,7 +304,7 @@ static Manager* manager_free(Manager *manager) {
|
|||||||
hashmap_free_free_free(manager->properties);
|
hashmap_free_free_free(manager->properties);
|
||||||
udev_rules_free(manager->rules);
|
udev_rules_free(manager->rules);
|
||||||
|
|
||||||
safe_close(manager->inotify_fd);
|
safe_close(manager->fd_inotify);
|
||||||
safe_close_pair(manager->worker_watch);
|
safe_close_pair(manager->worker_watch);
|
||||||
|
|
||||||
return mfree(manager);
|
return mfree(manager);
|
||||||
@ -475,7 +473,7 @@ static int worker_process_device(Manager *manager, sd_device *dev) {
|
|||||||
* degree — they go hand-in-hand after all. */
|
* degree — they go hand-in-hand after all. */
|
||||||
|
|
||||||
log_device_debug(dev, "Block device is currently locked, installing watch to wait until the lock is released.");
|
log_device_debug(dev, "Block device is currently locked, installing watch to wait until the lock is released.");
|
||||||
(void) udev_watch_begin(manager->inotify_fd, dev);
|
(void) udev_watch_begin(dev);
|
||||||
|
|
||||||
/* Now the watch is installed, let's lock the device again, maybe in the meantime things changed */
|
/* Now the watch is installed, let's lock the device again, maybe in the meantime things changed */
|
||||||
r = worker_lock_block_device(dev, &fd_lock);
|
r = worker_lock_block_device(dev, &fd_lock);
|
||||||
@ -486,13 +484,7 @@ static int worker_process_device(Manager *manager, sd_device *dev) {
|
|||||||
(void) worker_mark_block_device_read_only(dev);
|
(void) worker_mark_block_device_read_only(dev);
|
||||||
|
|
||||||
/* apply rules, create node, symlinks */
|
/* apply rules, create node, symlinks */
|
||||||
r = udev_event_execute_rules(
|
r = udev_event_execute_rules(udev_event, arg_event_timeout_usec, arg_timeout_signal, manager->properties, manager->rules);
|
||||||
udev_event,
|
|
||||||
manager->inotify_fd,
|
|
||||||
arg_event_timeout_usec,
|
|
||||||
arg_timeout_signal,
|
|
||||||
manager->properties,
|
|
||||||
manager->rules);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -502,9 +494,14 @@ static int worker_process_device(Manager *manager, sd_device *dev) {
|
|||||||
/* in case rtnl was initialized */
|
/* in case rtnl was initialized */
|
||||||
manager->rtnl = sd_netlink_ref(udev_event->rtnl);
|
manager->rtnl = sd_netlink_ref(udev_event->rtnl);
|
||||||
|
|
||||||
r = udev_event_process_inotify_watch(udev_event, manager->inotify_fd);
|
/* apply/restore/end inotify watch */
|
||||||
|
if (udev_event->inotify_watch) {
|
||||||
|
(void) udev_watch_begin(dev);
|
||||||
|
r = device_update_db(dev);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/: %m");
|
||||||
|
} else
|
||||||
|
(void) udev_watch_end(dev);
|
||||||
|
|
||||||
log_device_uevent(dev, "Device processed");
|
log_device_uevent(dev, "Device processed");
|
||||||
return 0;
|
return 0;
|
||||||
@ -875,7 +872,7 @@ static void manager_exit(Manager *manager) {
|
|||||||
manager->ctrl = udev_ctrl_unref(manager->ctrl);
|
manager->ctrl = udev_ctrl_unref(manager->ctrl);
|
||||||
|
|
||||||
manager->inotify_event = sd_event_source_unref(manager->inotify_event);
|
manager->inotify_event = sd_event_source_unref(manager->inotify_event);
|
||||||
manager->inotify_fd = safe_close(manager->inotify_fd);
|
manager->fd_inotify = safe_close(manager->fd_inotify);
|
||||||
|
|
||||||
manager->monitor = sd_device_monitor_unref(manager->monitor);
|
manager->monitor = sd_device_monitor_unref(manager->monitor);
|
||||||
|
|
||||||
@ -1302,21 +1299,17 @@ static int on_inotify(sd_event_source *s, int fd, uint32_t revents, void *userda
|
|||||||
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
|
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
|
||||||
const char *devnode;
|
const char *devnode;
|
||||||
|
|
||||||
r = device_new_from_watch_handle(&dev, e->wd);
|
if (udev_watch_lookup(e->wd, &dev) <= 0)
|
||||||
if (r < 0) {
|
|
||||||
log_debug_errno(r, "Failed to create sd_device object from watch handle, ignoring: %m");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (sd_device_get_devname(dev, &devnode) < 0)
|
if (sd_device_get_devname(dev, &devnode) < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
log_device_debug(dev, "Inotify event: %x for %s", e->mask, devnode);
|
log_device_debug(dev, "Inotify event: %x for %s", e->mask, devnode);
|
||||||
if (e->mask & IN_CLOSE_WRITE)
|
if (e->mask & IN_CLOSE_WRITE)
|
||||||
(void) synthesize_change(dev);
|
synthesize_change(dev);
|
||||||
|
else if (e->mask & IN_IGNORED)
|
||||||
/* Do not handle IN_IGNORED here. It should be handled by worker in 'remove' uevent;
|
udev_watch_end(dev);
|
||||||
* udev_event_execute_rules() -> event_execute_rules_on_remove() -> udev_watch_end(). */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -1676,7 +1669,7 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
|
|||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
*manager = (Manager) {
|
*manager = (Manager) {
|
||||||
.inotify_fd = -1,
|
.fd_inotify = -1,
|
||||||
.worker_watch = { -1, -1 },
|
.worker_watch = { -1, -1 },
|
||||||
.cgroup = cgroup,
|
.cgroup = cgroup,
|
||||||
};
|
};
|
||||||
@ -1729,11 +1722,12 @@ static int main_loop(Manager *manager) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to enable SO_PASSCRED: %m");
|
return log_error_errno(r, "Failed to enable SO_PASSCRED: %m");
|
||||||
|
|
||||||
manager->inotify_fd = inotify_init1(IN_CLOEXEC);
|
r = udev_watch_init();
|
||||||
if (manager->inotify_fd < 0)
|
if (r < 0)
|
||||||
return log_error_errno(errno, "Failed to create inotify descriptor: %m");
|
return log_error_errno(r, "Failed to create inotify descriptor: %m");
|
||||||
|
manager->fd_inotify = r;
|
||||||
|
|
||||||
udev_watch_restore(manager->inotify_fd);
|
udev_watch_restore();
|
||||||
|
|
||||||
/* block and listen to all signals on signalfd */
|
/* block and listen to all signals on signalfd */
|
||||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0);
|
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0);
|
||||||
@ -1778,7 +1772,7 @@ static int main_loop(Manager *manager) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to set IDLE event priority for udev control event source: %m");
|
return log_error_errno(r, "Failed to set IDLE event priority for udev control event source: %m");
|
||||||
|
|
||||||
r = sd_event_add_io(manager->event, &manager->inotify_event, manager->inotify_fd, EPOLLIN, on_inotify, manager);
|
r = sd_event_add_io(manager->event, &manager->inotify_event, manager->fd_inotify, EPOLLIN, on_inotify, manager);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to create inotify event source: %m");
|
return log_error_errno(r, "Failed to create inotify event source: %m");
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ TEST_NO_NSPAWN=1
|
|||||||
# shellcheck source=test/test-functions
|
# shellcheck source=test/test-functions
|
||||||
. "${TEST_BASE_DIR:?}/test-functions"
|
. "${TEST_BASE_DIR:?}/test-functions"
|
||||||
|
|
||||||
QEMU_TIMEOUT=800
|
QEMU_TIMEOUT=500
|
||||||
|
|
||||||
test_append_files() {
|
test_append_files() {
|
||||||
(
|
(
|
||||||
|
|||||||
@ -227,10 +227,10 @@ if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then
|
|||||||
QEMU_SMP="${QEMU_SMP:-4}"
|
QEMU_SMP="${QEMU_SMP:-4}"
|
||||||
|
|
||||||
# We need to correctly distinguish between gcc's and clang's ASan DSOs.
|
# We need to correctly distinguish between gcc's and clang's ASan DSOs.
|
||||||
if ASAN_RT_NAME="$(awk '/libasan.so/ {x=$1; exit} END {print x; exit x==""}' < <(ldd "$SYSTEMD"))"; then
|
if ASAN_RT_NAME="$(ldd "$SYSTEMD" | awk '/libasan.so/ {x=$1; exit} END {print x; exit x==""}')"; then
|
||||||
ASAN_COMPILER=gcc
|
ASAN_COMPILER=gcc
|
||||||
ASAN_RT_PATH="$(readlink -f "$(${CC:-gcc} --print-file-name "$ASAN_RT_NAME")")"
|
ASAN_RT_PATH="$(readlink -f "$(${CC:-gcc} --print-file-name "$ASAN_RT_NAME")")"
|
||||||
elif ASAN_RT_NAME="$(awk '/libclang_rt.asan/ {x=$1; exit} END {print x; exit x==""}' < <(ldd "$SYSTEMD"))"; then
|
elif ASAN_RT_NAME="$(ldd "$SYSTEMD" | awk '/libclang_rt.asan/ {x=$1; exit} END {print x; exit x==""}')"; then
|
||||||
ASAN_COMPILER=clang
|
ASAN_COMPILER=clang
|
||||||
ASAN_RT_PATH="$(readlink -f "$(${CC:-clang} --print-file-name "$ASAN_RT_NAME")")"
|
ASAN_RT_PATH="$(readlink -f "$(${CC:-clang} --print-file-name "$ASAN_RT_NAME")")"
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,6 @@ while : ; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
cat >/run/udev/rules.d/50-testsuite.rules <<EOF
|
cat >/run/udev/rules.d/50-testsuite.rules <<EOF
|
||||||
SUBSYSTEM=="block", KERNEL=="sda", OPTIONS="log_level=debug"
|
|
||||||
ACTION!="remove", SUBSYSTEM=="block", KERNEL=="sda", ENV{SYSTEMD_WANTS}="foobar.service"
|
ACTION!="remove", SUBSYSTEM=="block", KERNEL=="sda", ENV{SYSTEMD_WANTS}="foobar.service"
|
||||||
EOF
|
EOF
|
||||||
udevadm control --reload
|
udevadm control --reload
|
||||||
@ -38,7 +37,6 @@ while : ; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
cat >/run/udev/rules.d/50-testsuite.rules <<EOF
|
cat >/run/udev/rules.d/50-testsuite.rules <<EOF
|
||||||
SUBSYSTEM=="block", KERNEL=="sda", OPTIONS="log_level=debug"
|
|
||||||
ACTION!="remove", SUBSYSTEM=="block", KERNEL=="sda", ENV{SYSTEMD_WANTS}="waldo.service"
|
ACTION!="remove", SUBSYSTEM=="block", KERNEL=="sda", ENV{SYSTEMD_WANTS}="waldo.service"
|
||||||
EOF
|
EOF
|
||||||
udevadm control --reload
|
udevadm control --reload
|
||||||
|
|||||||
@ -7,7 +7,6 @@ mkdir -p /run/udev/rules.d/
|
|||||||
cat >/run/udev/rules.d/50-testsuite.rules <<EOF
|
cat >/run/udev/rules.d/50-testsuite.rules <<EOF
|
||||||
ACTION=="remove", GOTO="lo_end"
|
ACTION=="remove", GOTO="lo_end"
|
||||||
|
|
||||||
SUBSYSTEM=="net", KERNEL=="lo", OPTIONS="log_level=debug"
|
|
||||||
SUBSYSTEM=="net", KERNEL=="lo", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/net/devices/lo"
|
SUBSYSTEM=="net", KERNEL=="lo", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/net/devices/lo"
|
||||||
|
|
||||||
ACTION!="change", GOTO="lo_end"
|
ACTION!="change", GOTO="lo_end"
|
||||||
|
|||||||
@ -7,10 +7,7 @@ test_rule="/run/udev/rules.d/49-test.rules"
|
|||||||
setup() {
|
setup() {
|
||||||
mkdir -p "${test_rule%/*}"
|
mkdir -p "${test_rule%/*}"
|
||||||
cp -f /etc/udev/udev.conf /etc/udev/udev.conf.bckp
|
cp -f /etc/udev/udev.conf /etc/udev/udev.conf.bckp
|
||||||
cat >"${test_rule}" <<EOF
|
echo 'KERNEL=="lo", SUBSYSTEM=="net", PROGRAM=="/bin/sleep 60"' >"${test_rule}"
|
||||||
SUBSYSTEM=="net", KERNEL=="lo", OPTIONS="log_level=debug"
|
|
||||||
SUBSYSTEM=="net", KERNEL=="lo", PROGRAM=="/bin/sleep 60"
|
|
||||||
EOF
|
|
||||||
echo "event_timeout=30" >>/etc/udev/udev.conf
|
echo "event_timeout=30" >>/etc/udev/udev.conf
|
||||||
echo "timeout_signal=SIGABRT" >>/etc/udev/udev.conf
|
echo "timeout_signal=SIGABRT" >>/etc/udev/udev.conf
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,6 @@ test ! -f /run/udev/tags/changed/c1:3
|
|||||||
udevadm info /dev/null | grep -E 'E: (TAGS|CURRENT_TAGS)=.*:(added|changed):' && exit 1
|
udevadm info /dev/null | grep -E 'E: (TAGS|CURRENT_TAGS)=.*:(added|changed):' && exit 1
|
||||||
|
|
||||||
cat >/run/udev/rules.d/50-testsuite.rules <<EOF
|
cat >/run/udev/rules.d/50-testsuite.rules <<EOF
|
||||||
SUBSYSTEM=="mem", KERNEL=="null", OPTIONS="log_level=debug"
|
|
||||||
ACTION=="add", SUBSYSTEM=="mem", KERNEL=="null", TAG+="added"
|
ACTION=="add", SUBSYSTEM=="mem", KERNEL=="null", TAG+="added"
|
||||||
ACTION=="change", SUBSYSTEM=="mem", KERNEL=="null", TAG+="changed"
|
ACTION=="change", SUBSYSTEM=="mem", KERNEL=="null", TAG+="changed"
|
||||||
EOF
|
EOF
|
||||||
|
|||||||
@ -1,75 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -ex
|
|
||||||
set -o pipefail
|
|
||||||
|
|
||||||
# tests for udev watch
|
|
||||||
|
|
||||||
function check_validity() {
|
|
||||||
local f ID_OR_HANDLE
|
|
||||||
|
|
||||||
for f in /run/udev/watch/*; do
|
|
||||||
ID_OR_HANDLE=$(readlink $f)
|
|
||||||
test -L /run/udev/watch/${ID_OR_HANDLE}
|
|
||||||
test $(readlink /run/udev/watch/${ID_OR_HANDLE}) = $(basename $f)
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
function check() {
|
|
||||||
local i j
|
|
||||||
|
|
||||||
for ((i=0;i<2;i++)); do
|
|
||||||
systemctl restart systemd-udevd.service
|
|
||||||
udevadm control --ping
|
|
||||||
udevadm settle
|
|
||||||
sleep 1
|
|
||||||
check_validity
|
|
||||||
|
|
||||||
for ((j=0;j<2;j++)); do
|
|
||||||
udevadm trigger -w --action add --subsystem-match=block
|
|
||||||
udevadm settle
|
|
||||||
sleep 1
|
|
||||||
check_validity
|
|
||||||
done
|
|
||||||
|
|
||||||
for ((j=0;j<2;j++)); do
|
|
||||||
udevadm trigger -w --action change --subsystem-match=block
|
|
||||||
udevadm settle
|
|
||||||
sleep 1
|
|
||||||
check_validity
|
|
||||||
done
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
mkdir -p /run/udev/rules.d/
|
|
||||||
|
|
||||||
cat >/run/udev/rules.d/00-debug.rules <<EOF
|
|
||||||
SUBSYSTEM=="block", KERNEL=="sda*", OPTIONS="log_level=debug"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
cat >/run/udev/rules.d/50-testsuite.rules <<EOF
|
|
||||||
ACTION=="add", SUBSYSTEM=="block", KERNEL=="sda", OPTIONS:="watch"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
check
|
|
||||||
|
|
||||||
MAJOR=$(udevadm info /dev/sda | grep -e '^E: MAJOR=' | sed -e 's/^E: MAJOR=//')
|
|
||||||
MINOR=$(udevadm info /dev/sda | grep -e '^E: MINOR=' | sed -e 's/^E: MINOR=//')
|
|
||||||
test -L /run/udev/watch/b${MAJOR}:${MINOR}
|
|
||||||
|
|
||||||
cat >/run/udev/rules.d/50-testsuite.rules <<EOF
|
|
||||||
ACTION=="change", SUBSYSTEM=="block", KERNEL=="sda", OPTIONS:="nowatch"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
check
|
|
||||||
|
|
||||||
MAJOR=$(udevadm info /dev/sda | grep -e '^E: MAJOR=' | sed -e 's/^E: MAJOR=//')
|
|
||||||
MINOR=$(udevadm info /dev/sda | grep -e '^E: MINOR=' | sed -e 's/^E: MINOR=//')
|
|
||||||
test ! -e /run/udev/watch/b${MAJOR}:${MINOR}
|
|
||||||
|
|
||||||
rm /run/udev/rules.d/00-debug.rules
|
|
||||||
rm /run/udev/rules.d/50-testsuite.rules
|
|
||||||
|
|
||||||
udevadm control --reload
|
|
||||||
udevadm trigger -w --action add --subsystem-match=block
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
@ -5,8 +5,6 @@ set -o pipefail
|
|||||||
|
|
||||||
: >/failed
|
: >/failed
|
||||||
|
|
||||||
udevadm settle
|
|
||||||
|
|
||||||
for t in "${0%.sh}".*.sh; do
|
for t in "${0%.sh}".*.sh; do
|
||||||
echo "Running $t"; ./"$t"
|
echo "Running $t"; ./"$t"
|
||||||
done
|
done
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user