mirror of
https://github.com/systemd/systemd.git
synced 2024-11-30 22:03:41 +08:00
Merge pull request #11349 from yuwata/udevadm-control-ping
Add 'udevadm control --ping'
This commit is contained in:
commit
b0a28c2956
@ -319,6 +319,14 @@
|
||||
the same command to finish.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--wait-daemon[=<replaceable>SECONDS</replaceable>]</option></term>
|
||||
<listitem>
|
||||
<para>Before triggering uevents, wait for systemd-udevd daemon to be initialized.
|
||||
Optionally takes timeout value. Default timeout is 5 seconds. This is equivalent to invoke
|
||||
invoking <command>udevadm control --ping</command> before <command>udevadm trigger</command>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="standard-options.xml" xpointer="help" />
|
||||
</variablelist>
|
||||
@ -419,6 +427,13 @@
|
||||
same time.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--ping</option></term>
|
||||
<listitem>
|
||||
<para>Send a ping message to systemd-udevd and wait for the reply. This may be useful to check that
|
||||
systemd-udevd daemon is running.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-t</option></term>
|
||||
<term><option>--timeout=</option><replaceable>seconds</replaceable></term>
|
||||
|
@ -50,12 +50,12 @@ _udevadm() {
|
||||
[DEBUG]='-d --debug'
|
||||
[INFO_STANDALONE]='-r --root -a --attribute-walk -x --export -e --export-db -c --cleanup-db'
|
||||
[INFO_ARG]='-q --query -p --path -n --name -P --export-prefix -d --device-id-of-file'
|
||||
[TRIGGER_STANDALONE]='-v --verbose -n --dry-run -w --settle'
|
||||
[TRIGGER_STANDALONE]='-v --verbose -n --dry-run -w --settle --wait-daemon'
|
||||
[TRIGGER_ARG]='-t --type -c --action -s --subsystem-match -S --subsystem-nomatch
|
||||
-a --attr-match -A --attr-nomatch -p --property-match
|
||||
-g --tag-match -y --sysname-match --name-match -b --parent-match'
|
||||
[SETTLE]='-t --timeout -E --exit-if-exists'
|
||||
[CONTROL_STANDALONE]='-e --exit -s --stop-exec-queue -S --start-exec-queue -R --reload'
|
||||
[CONTROL_STANDALONE]='-e --exit -s --stop-exec-queue -S --start-exec-queue -R --reload --ping'
|
||||
[CONTROL_ARG]='-l --log-priority -p --property -m --children-max -t --timeout'
|
||||
[MONITOR_STANDALONE]='-k --kernel -u --udev -p --property'
|
||||
[MONITOR_ARG]='-s --subsystem-match -t --tag-match'
|
||||
|
@ -213,7 +213,7 @@ static struct udev_ctrl_connection *udev_ctrl_connection_free(struct udev_ctrl_c
|
||||
|
||||
DEFINE_TRIVIAL_REF_UNREF_FUNC(struct udev_ctrl_connection, udev_ctrl_connection, udev_ctrl_connection_free);
|
||||
|
||||
static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf, int timeout) {
|
||||
static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf, usec_t timeout) {
|
||||
struct udev_ctrl_msg_wire ctrl_msg_wire = {
|
||||
.version = "udev-" STRINGIFY(PROJECT_VERSION),
|
||||
.magic = UDEV_CTRL_MAGIC,
|
||||
@ -241,7 +241,7 @@ static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int
|
||||
};
|
||||
int r;
|
||||
|
||||
r = poll(&pfd, 1, timeout * MSEC_PER_SEC);
|
||||
r = poll(&pfd, 1, DIV_ROUND_UP(timeout, USEC_PER_MSEC));
|
||||
if (r < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
@ -255,35 +255,35 @@ static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int
|
||||
}
|
||||
}
|
||||
|
||||
int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, int timeout) {
|
||||
int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, usec_t timeout) {
|
||||
return ctrl_send(uctrl, UDEV_CTRL_SET_LOG_LEVEL, priority, NULL, timeout);
|
||||
}
|
||||
|
||||
int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, int timeout) {
|
||||
int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, usec_t timeout) {
|
||||
return ctrl_send(uctrl, UDEV_CTRL_STOP_EXEC_QUEUE, 0, NULL, timeout);
|
||||
}
|
||||
|
||||
int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, int timeout) {
|
||||
int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, usec_t timeout) {
|
||||
return ctrl_send(uctrl, UDEV_CTRL_START_EXEC_QUEUE, 0, NULL, timeout);
|
||||
}
|
||||
|
||||
int udev_ctrl_send_reload(struct udev_ctrl *uctrl, int timeout) {
|
||||
int udev_ctrl_send_reload(struct udev_ctrl *uctrl, usec_t timeout) {
|
||||
return ctrl_send(uctrl, UDEV_CTRL_RELOAD, 0, NULL, timeout);
|
||||
}
|
||||
|
||||
int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, int timeout) {
|
||||
int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, usec_t timeout) {
|
||||
return ctrl_send(uctrl, UDEV_CTRL_SET_ENV, 0, key, timeout);
|
||||
}
|
||||
|
||||
int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, int timeout) {
|
||||
int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, usec_t timeout) {
|
||||
return ctrl_send(uctrl, UDEV_CTRL_SET_CHILDREN_MAX, count, NULL, timeout);
|
||||
}
|
||||
|
||||
int udev_ctrl_send_ping(struct udev_ctrl *uctrl, int timeout) {
|
||||
int udev_ctrl_send_ping(struct udev_ctrl *uctrl, usec_t timeout) {
|
||||
return ctrl_send(uctrl, UDEV_CTRL_PING, 0, NULL, timeout);
|
||||
}
|
||||
|
||||
int udev_ctrl_send_exit(struct udev_ctrl *uctrl, int timeout) {
|
||||
int udev_ctrl_send_exit(struct udev_ctrl *uctrl, usec_t timeout) {
|
||||
return ctrl_send(uctrl, UDEV_CTRL_EXIT, 0, NULL, timeout);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "macro.h"
|
||||
#include "time-util.h"
|
||||
|
||||
struct udev_ctrl;
|
||||
struct udev_ctrl *udev_ctrl_new(void);
|
||||
@ -10,14 +11,14 @@ int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl);
|
||||
struct udev_ctrl *udev_ctrl_unref(struct udev_ctrl *uctrl);
|
||||
int udev_ctrl_cleanup(struct udev_ctrl *uctrl);
|
||||
int udev_ctrl_get_fd(struct udev_ctrl *uctrl);
|
||||
int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, int timeout);
|
||||
int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, int timeout);
|
||||
int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, int timeout);
|
||||
int udev_ctrl_send_reload(struct udev_ctrl *uctrl, int timeout);
|
||||
int udev_ctrl_send_ping(struct udev_ctrl *uctrl, int timeout);
|
||||
int udev_ctrl_send_exit(struct udev_ctrl *uctrl, int timeout);
|
||||
int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, int timeout);
|
||||
int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, int timeout);
|
||||
int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, usec_t timeout);
|
||||
int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, usec_t timeout);
|
||||
int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, usec_t timeout);
|
||||
int udev_ctrl_send_reload(struct udev_ctrl *uctrl, usec_t timeout);
|
||||
int udev_ctrl_send_ping(struct udev_ctrl *uctrl, usec_t timeout);
|
||||
int udev_ctrl_send_exit(struct udev_ctrl *uctrl, usec_t timeout);
|
||||
int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, usec_t timeout);
|
||||
int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, usec_t timeout);
|
||||
|
||||
struct udev_ctrl_connection;
|
||||
struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl);
|
||||
|
@ -40,6 +40,7 @@ static int help(void) {
|
||||
" -R --reload Reload rules and databases\n"
|
||||
" -p --property=KEY=VALUE Set a global property for all events\n"
|
||||
" -m --children-max=N Maximum number of children\n"
|
||||
" --ping Wait for udev to respond to a ping message\n"
|
||||
" -t --timeout=SECONDS Maximum time to block for a reply\n"
|
||||
, program_invocation_short_name);
|
||||
|
||||
@ -48,22 +49,27 @@ static int help(void) {
|
||||
|
||||
int control_main(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL;
|
||||
int timeout = 60;
|
||||
usec_t timeout = 60 * USEC_PER_SEC;
|
||||
int c, r;
|
||||
|
||||
enum {
|
||||
ARG_PING = 0x100,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "exit", no_argument, NULL, 'e' },
|
||||
{ "log-priority", required_argument, NULL, 'l' },
|
||||
{ "stop-exec-queue", no_argument, NULL, 's' },
|
||||
{ "start-exec-queue", no_argument, NULL, 'S' },
|
||||
{ "reload", no_argument, NULL, 'R' },
|
||||
{ "reload-rules", no_argument, NULL, 'R' }, /* alias for -R */
|
||||
{ "property", required_argument, NULL, 'p' },
|
||||
{ "env", required_argument, NULL, 'p' }, /* alias for -p */
|
||||
{ "children-max", required_argument, NULL, 'm' },
|
||||
{ "timeout", required_argument, NULL, 't' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "exit", no_argument, NULL, 'e' },
|
||||
{ "log-priority", required_argument, NULL, 'l' },
|
||||
{ "stop-exec-queue", no_argument, NULL, 's' },
|
||||
{ "start-exec-queue", no_argument, NULL, 'S' },
|
||||
{ "reload", no_argument, NULL, 'R' },
|
||||
{ "reload-rules", no_argument, NULL, 'R' }, /* alias for -R */
|
||||
{ "property", required_argument, NULL, 'p' },
|
||||
{ "env", required_argument, NULL, 'p' }, /* alias for -p */
|
||||
{ "children-max", required_argument, NULL, 'm' },
|
||||
{ "ping", no_argument, NULL, ARG_PING },
|
||||
{ "timeout", required_argument, NULL, 't' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{}
|
||||
};
|
||||
|
||||
@ -77,11 +83,12 @@ int control_main(int argc, char *argv[], void *userdata) {
|
||||
}
|
||||
|
||||
if (argc <= 1)
|
||||
log_error("Option missing");
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"This command expects one or more options.");
|
||||
|
||||
uctrl = udev_ctrl_new();
|
||||
if (!uctrl)
|
||||
return -ENOMEM;
|
||||
return log_oom();
|
||||
|
||||
while ((c = getopt_long(argc, argv, "el:sSRp:m:t:Vh", options, NULL)) >= 0)
|
||||
switch (c) {
|
||||
@ -115,10 +122,9 @@ int control_main(int argc, char *argv[], void *userdata) {
|
||||
return r;
|
||||
break;
|
||||
case 'p':
|
||||
if (!strchr(optarg, '=')) {
|
||||
log_error("expect <KEY>=<value> instead of '%s'", optarg);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!strchr(optarg, '='))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "expect <KEY>=<value> instead of '%s'", optarg);
|
||||
|
||||
r = udev_ctrl_send_set_env(uctrl, optarg, timeout);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -135,19 +141,16 @@ int control_main(int argc, char *argv[], void *userdata) {
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
case 't': {
|
||||
usec_t s;
|
||||
|
||||
r = parse_sec(optarg, &s);
|
||||
case ARG_PING:
|
||||
r = udev_ctrl_send_ping(uctrl, timeout);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse timeout value '%s'.", optarg);
|
||||
|
||||
if (DIV_ROUND_UP(s, USEC_PER_SEC) > INT_MAX)
|
||||
log_error("Timeout value is out of range, ignoring.");
|
||||
else
|
||||
timeout = s != USEC_INFINITY ? (int) DIV_ROUND_UP(s, USEC_PER_SEC) : INT_MAX;
|
||||
return log_error_errno(r, "Failed to connect to udev daemon: %m");
|
||||
break;
|
||||
case 't':
|
||||
r = parse_sec(optarg, &timeout);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg);
|
||||
break;
|
||||
}
|
||||
case 'V':
|
||||
return print_version();
|
||||
case 'h':
|
||||
@ -158,13 +161,9 @@ int control_main(int argc, char *argv[], void *userdata) {
|
||||
assert_not_reached("Unknown option.");
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
log_error("Extraneous argument: %s", argv[optind]);
|
||||
return -EINVAL;
|
||||
} else if (optind == 1) {
|
||||
log_error("Option missing");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (optind < argc)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Extraneous argument: %s", argv[optind]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -387,10 +387,8 @@ int info_main(int argc, char *argv[], void *userdata) {
|
||||
query = QUERY_PATH;
|
||||
else if (streq(optarg, "all"))
|
||||
query = QUERY_ALL;
|
||||
else {
|
||||
log_error("unknown query type");
|
||||
return -EINVAL;
|
||||
}
|
||||
else
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "unknown query type");
|
||||
break;
|
||||
case 'r':
|
||||
arg_root = true;
|
||||
|
@ -102,9 +102,9 @@ int settle_main(int argc, char *argv[], void *userdata) {
|
||||
|
||||
uctrl = udev_ctrl_new();
|
||||
if (uctrl) {
|
||||
r = udev_ctrl_send_ping(uctrl, MAX(5U, arg_timeout / USEC_PER_SEC));
|
||||
r = udev_ctrl_send_ping(uctrl, MAX(5 * USEC_PER_SEC, arg_timeout));
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to connect to udev daemon.");
|
||||
log_debug_errno(r, "Failed to connect to udev daemon: %m");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -10,11 +10,13 @@
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "set.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "udevadm.h"
|
||||
#include "udevadm-util.h"
|
||||
#include "udev-ctrl.h"
|
||||
#include "virt.h"
|
||||
|
||||
static bool arg_verbose = false;
|
||||
@ -118,6 +120,8 @@ static int help(void) {
|
||||
" --name-match=NAME Trigger devices with this /dev name\n"
|
||||
" -b --parent-match=NAME Trigger devices with that parent device\n"
|
||||
" -w --settle Wait for the triggered events to complete\n"
|
||||
" --wait-daemon[=SECONDS] Wait for udevd daemon to be initialized\n"
|
||||
" before triggering uevents\n"
|
||||
, program_invocation_short_name);
|
||||
|
||||
return 0;
|
||||
@ -126,6 +130,7 @@ static int help(void) {
|
||||
int trigger_main(int argc, char *argv[], void *userdata) {
|
||||
enum {
|
||||
ARG_NAME = 0x100,
|
||||
ARG_PING,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@ -143,6 +148,7 @@ int trigger_main(int argc, char *argv[], void *userdata) {
|
||||
{ "name-match", required_argument, NULL, ARG_NAME },
|
||||
{ "parent-match", required_argument, NULL, 'b' },
|
||||
{ "settle", no_argument, NULL, 'w' },
|
||||
{ "wait-daemon", optional_argument, NULL, ARG_PING },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{}
|
||||
@ -156,7 +162,8 @@ int trigger_main(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *m = NULL;
|
||||
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
|
||||
_cleanup_set_free_free_ Set *settle_set = NULL;
|
||||
bool settle = false;
|
||||
usec_t ping_timeout_usec = 5 * USEC_PER_SEC;
|
||||
bool settle = false, ping = false;
|
||||
int c, r;
|
||||
|
||||
if (running_in_chroot() > 0) {
|
||||
@ -188,18 +195,14 @@ int trigger_main(int argc, char *argv[], void *userdata) {
|
||||
device_type = TYPE_DEVICES;
|
||||
else if (streq(optarg, "subsystems"))
|
||||
device_type = TYPE_SUBSYSTEMS;
|
||||
else {
|
||||
log_error("Unknown type --type=%s", optarg);
|
||||
return -EINVAL;
|
||||
}
|
||||
else
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown type --type=%s", optarg);
|
||||
break;
|
||||
case 'c':
|
||||
if (STR_IN_SET(optarg, "add", "remove", "change"))
|
||||
action = optarg;
|
||||
else {
|
||||
log_error("Unknown action '%s'", optarg);
|
||||
return -EINVAL;
|
||||
}
|
||||
else
|
||||
log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown action '%s'", optarg);
|
||||
|
||||
break;
|
||||
case 's':
|
||||
@ -275,6 +278,16 @@ int trigger_main(int argc, char *argv[], void *userdata) {
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_PING: {
|
||||
ping = true;
|
||||
if (optarg) {
|
||||
r = parse_sec(optarg, &ping_timeout_usec);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed to parse timeout value '%s', ignoring: %m", optarg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'V':
|
||||
return print_version();
|
||||
case 'h':
|
||||
@ -286,6 +299,24 @@ int trigger_main(int argc, char *argv[], void *userdata) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!arg_dry_run || ping) {
|
||||
r = must_be_root();
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (ping) {
|
||||
_cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL;
|
||||
|
||||
uctrl = udev_ctrl_new();
|
||||
if (!uctrl)
|
||||
return log_oom();
|
||||
|
||||
r = udev_ctrl_send_ping(uctrl, ping_timeout_usec);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to connect to udev daemon: %m");
|
||||
}
|
||||
|
||||
for (; optind < argc; optind++) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
|
||||
|
||||
|
@ -113,12 +113,13 @@ static int run(int argc, char *argv[]) {
|
||||
udev_parse_config();
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
log_set_max_level_realm(LOG_REALM_SYSTEMD, log_get_max_level());
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
log_set_max_level_realm(LOG_REALM_SYSTEMD, log_get_max_level());
|
||||
|
||||
mac_selinux_init();
|
||||
return udevadm_main(argc, argv);
|
||||
}
|
||||
|
@ -1027,7 +1027,8 @@ static int on_ctrl_msg(sd_event_source *s, int fd, uint32_t revents, void *userd
|
||||
i = udev_ctrl_get_set_log_level(ctrl_msg);
|
||||
if (i >= 0) {
|
||||
log_debug("Received udev control message (SET_LOG_LEVEL), setting log_priority=%i", i);
|
||||
log_set_max_level(i);
|
||||
log_set_max_level_realm(LOG_REALM_UDEV, i);
|
||||
log_set_max_level_realm(LOG_REALM_SYSTEMD, i);
|
||||
manager_kill_workers(manager);
|
||||
}
|
||||
|
||||
@ -1112,7 +1113,7 @@ static int on_ctrl_msg(sd_event_source *s, int fd, uint32_t revents, void *userd
|
||||
}
|
||||
|
||||
if (udev_ctrl_get_ping(ctrl_msg) > 0)
|
||||
log_debug("Received udev control message (SYNC)");
|
||||
log_debug("Received udev control message (PING)");
|
||||
|
||||
if (udev_ctrl_get_exit(ctrl_msg) > 0) {
|
||||
log_debug("Received udev control message (EXIT)");
|
||||
|
Loading…
Reference in New Issue
Block a user