Merge pull request #1944 from poettering/randoms-ec
add RandomSec= setting to timer units, and more
This commit is contained in:
@@ -88,6 +88,14 @@ CHANGES WITH 228:
|
||||
from PID1's environment block into the environment block of
|
||||
the service.
|
||||
|
||||
* Timer units gained support for a new RemainAfterElapse=
|
||||
setting which takes a boolean argument. It defaults on on,
|
||||
exposing behaviour unchanged to previous releases. If set to
|
||||
off, timer units are unloaded after they elapsed if they
|
||||
cannot elapse again. This is particularly useful for
|
||||
transient timer units, which shall not stay around longer
|
||||
than until they first elapse.
|
||||
|
||||
* systemd will now bump the net.unix.max_dgram_qlen to 512 by
|
||||
default now (the kernel default is 16). This is beneficial
|
||||
for avoiding blocking on AF_UNIX/SOCK_DGRAM sockets since it
|
||||
|
||||
@@ -71,8 +71,6 @@ Features:
|
||||
|
||||
* install: include generator dirs in unit file search paths
|
||||
|
||||
* invent a better systemd-run scheme for naming scopes, that works with remoting
|
||||
|
||||
* rework C11 utf8.[ch] to use char32_t instead of uint32_t when referring
|
||||
to unicode chars, to make things more expressive.
|
||||
|
||||
@@ -103,7 +101,7 @@ Features:
|
||||
|
||||
* Rework systemctl's GetAll property parsing to use the generic bus_map_all_properties() API
|
||||
|
||||
* core/cgroup: support net_cls modules, and support automatically allocating class ids, then add support for making firewall changes depending on it, to implement a per-service firewall
|
||||
* implement a per-service firewall based on net_cls
|
||||
|
||||
* Port various tools to make use of verbs.[ch], where applicable
|
||||
|
||||
@@ -155,8 +153,6 @@ Features:
|
||||
|
||||
* maybe provide an API to allow migration of foreign PIDs into existing scopes.
|
||||
|
||||
* maybe support a new very "soft" reboot mode, that simply kills all processes, disassembles everything, flushes /run and sysvipc, and then reexecs systemd again
|
||||
|
||||
* man: maybe use the word "inspect" rather than "introspect"?
|
||||
|
||||
* systemctl: if some operation fails, show log output?
|
||||
@@ -213,8 +209,6 @@ Features:
|
||||
|
||||
* generator that automatically discovers btrfs subvolumes, identifies their purpose based on some xattr on them.
|
||||
|
||||
* timer units: actually add extra delays to timer units with high AccuracySec values, don't start them already when we are awake...
|
||||
|
||||
* a way for container managers to turn off getty starting via $container_headless= or so...
|
||||
|
||||
* figure out a nice way how we can let the admin know what child/sibling unit causes cgroup membership for a specific unit
|
||||
@@ -736,7 +730,6 @@ Features:
|
||||
- Support --test based on current system state
|
||||
- If we show an error about a unit (such as not showing up) and it has no Description string, then show a description string generated form the reverse of unit_name_mangle().
|
||||
- after deserializing sockets in socket.c we should reapply sockopts and things
|
||||
- make timer units go away after they elapsed
|
||||
- drop PID 1 reloading, only do reexecing (difficult: Reload()
|
||||
currently is properly synchronous, Reexec() is weird, because we
|
||||
cannot delay the response properly until we are back, so instead of
|
||||
|
||||
+49
-9
@@ -190,13 +190,12 @@
|
||||
<varname>OnUnitInactiveSec=</varname> and ending the time
|
||||
configured with <varname>AccuracySec=</varname> later. Within
|
||||
this time window, the expiry time will be placed at a
|
||||
host-specific, randomized but stable position that is
|
||||
host-specific, randomized, but stable position that is
|
||||
synchronized between all local timer units. This is done in
|
||||
order to distribute the wake-up time in networked
|
||||
installations, as well as optimizing power consumption to
|
||||
suppress unnecessary CPU wake-ups. To get best accuracy, set
|
||||
this option to 1us. Note that the timer is still subject to
|
||||
the timer slack configured via
|
||||
order to optimize power consumption to suppress unnecessary
|
||||
CPU wake-ups. To get best accuracy, set this option to
|
||||
1us. Note that the timer is still subject to the timer slack
|
||||
configured via
|
||||
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>'s
|
||||
<varname>TimerSlackNSec=</varname> setting. See
|
||||
<citerefentry><refentrytitle>prctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
||||
@@ -204,6 +203,38 @@
|
||||
this value as high as possible and as low as
|
||||
necessary.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>RandomSec=</varname></term>
|
||||
|
||||
<listitem><para>Delay the timer by a randomly selected, evenly
|
||||
distributed amount of time between 0 and the specified time
|
||||
value. Defaults to 0, indicating that no randomized delay
|
||||
shall be applied. Each timer unit will determine this delay
|
||||
randomly each time it is started, and the delay will simply be
|
||||
added on top of the next determined elapsing time. This is
|
||||
useful to stretch dispatching of similarly configured timer
|
||||
events over a certain amount time, to avoid that they all fire
|
||||
at the same time, possibly resulting in resource
|
||||
congestion. Note the relation to
|
||||
<varname>AccuracySec=</varname> above: the latter allows the
|
||||
service manager to coalesce timer events within a specified
|
||||
time range in order to minimize wakeups, the former does the
|
||||
opposite: it stretches timer events over a time range, to make
|
||||
it unlikely that they fire simultaneously. If
|
||||
<varname>RandomSec=</varname> and
|
||||
<varname>AccuracySec=</varname> are used in conjunction, first
|
||||
the a randomized time is added, and the result is then
|
||||
possibly shifted further to coalesce it with other timer
|
||||
events possibly happening on the system. As mentioned above
|
||||
<varname>AccuracySec=</varname> defaults to 1min and
|
||||
<varname>RandomSec=</varname> to 0, thus encouraging
|
||||
coalescing of timer events. In order to optimally stretch
|
||||
timer events over a certain range of time, make sure to set
|
||||
<varname>RandomSec=</varname> to a higher value, and
|
||||
<varname>AccuracySec=1us</varname>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>Unit=</varname></term>
|
||||
|
||||
@@ -245,11 +276,20 @@
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>RemainAfterExit=</varname></term>
|
||||
<term><varname>RemainAfterElapse=</varname></term>
|
||||
|
||||
<listitem><para>Takes a boolean argument. If true, an elapsed
|
||||
timer will stay loaded, and its state remains
|
||||
queriable. Defaults to
|
||||
timer will stay loaded, and its state remains queriable. If
|
||||
false, an elapsed timer unit that cannot elapse anymore is
|
||||
unloaded. Turning this off is particularly useful for
|
||||
transient timer units that shall disappear after they first
|
||||
elapse. Note that this setting has an effect on repeatedly
|
||||
starting the a timer unit that only elapses once: if
|
||||
<varname>RemainAfterElapse=</varname> is on, it will not be
|
||||
started again, and is guaranteed to elapse only once. However,
|
||||
if <varname>RemainAfterLeapse=</varname> is off, it might be
|
||||
started again if it is already elapsed, and thus be triggered
|
||||
multiple times. Defaults to
|
||||
<varname>yes</varname>.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
@@ -180,6 +180,7 @@ const sd_bus_vtable bus_timer_vtable[] = {
|
||||
BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RandomUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RemainAfterElapse", "b", bus_property_get_bool, offsetof(Timer, remain_after_elapse), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@@ -283,6 +284,22 @@ static int bus_timer_set_transient_property(
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "RandomUSec")) {
|
||||
usec_t u = 0;
|
||||
|
||||
r = sd_bus_message_read(message, "t", &u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (mode != UNIT_CHECK) {
|
||||
char time[FORMAT_TIMESPAN_MAX];
|
||||
|
||||
t->random_usec = u;
|
||||
unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomSec=%s\n", format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "WakeSystem")) {
|
||||
int b;
|
||||
|
||||
|
||||
@@ -347,6 +347,7 @@ Timer.Persistent, config_parse_bool, 0,
|
||||
Timer.WakeSystem, config_parse_bool, 0, offsetof(Timer, wake_system)
|
||||
Timer.RemainAfterElapse, config_parse_bool, 0, offsetof(Timer, remain_after_elapse)
|
||||
Timer.AccuracySec, config_parse_sec, 0, offsetof(Timer, accuracy_usec)
|
||||
Timer.RandomSec, config_parse_sec, 0, offsetof(Timer, random_usec)
|
||||
Timer.Unit, config_parse_trigger_unit, 0, 0
|
||||
m4_dnl
|
||||
Path.PathExists, config_parse_path_spec, 0, 0
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "dbus-timer.h"
|
||||
#include "fs-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "random-util.h"
|
||||
#include "special.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
@@ -330,6 +331,28 @@ static usec_t monotonic_to_boottime(usec_t t) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void add_random(Timer *t, usec_t *v) {
|
||||
char s[FORMAT_TIMESPAN_MAX];
|
||||
usec_t add;
|
||||
|
||||
assert(t);
|
||||
assert(*v);
|
||||
|
||||
if (t->random_usec == 0)
|
||||
return;
|
||||
if (*v == USEC_INFINITY)
|
||||
return;
|
||||
|
||||
add = random_u64() % t->random_usec;
|
||||
|
||||
if (*v + add < *v) /* overflow */
|
||||
*v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */
|
||||
else
|
||||
*v += add;
|
||||
|
||||
log_unit_info(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0));
|
||||
}
|
||||
|
||||
static void timer_enter_waiting(Timer *t, bool initial) {
|
||||
bool found_monotonic = false, found_realtime = false;
|
||||
usec_t ts_realtime, ts_monotonic;
|
||||
@@ -452,6 +475,8 @@ static void timer_enter_waiting(Timer *t, bool initial) {
|
||||
char buf[FORMAT_TIMESPAN_MAX];
|
||||
usec_t left;
|
||||
|
||||
add_random(t, &t->next_elapse_monotonic_or_boottime);
|
||||
|
||||
left = t->next_elapse_monotonic_or_boottime > ts_monotonic ? t->next_elapse_monotonic_or_boottime - ts_monotonic : 0;
|
||||
log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", format_timespan(buf, sizeof(buf), left, 0));
|
||||
|
||||
@@ -486,6 +511,9 @@ static void timer_enter_waiting(Timer *t, bool initial) {
|
||||
|
||||
if (found_realtime) {
|
||||
char buf[FORMAT_TIMESTAMP_MAX];
|
||||
|
||||
add_random(t, &t->next_elapse_realtime);
|
||||
|
||||
log_unit_debug(UNIT(t), "Realtime timer elapses at %s.", format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
|
||||
|
||||
if (t->realtime_event_source) {
|
||||
|
||||
@@ -58,6 +58,7 @@ struct Timer {
|
||||
Unit meta;
|
||||
|
||||
usec_t accuracy_usec;
|
||||
usec_t random_usec;
|
||||
|
||||
LIST_HEAD(TimerValue, values);
|
||||
usec_t next_elapse_realtime;
|
||||
|
||||
@@ -543,6 +543,7 @@ static void dns_scope_verify_conflicts(DnsScope *s, DnsPacket *p) {
|
||||
void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
|
||||
_cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
|
||||
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
|
||||
DnsResourceKey *key = NULL;
|
||||
bool tentative = false;
|
||||
int r, fd;
|
||||
|
||||
@@ -576,7 +577,10 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
|
||||
return;
|
||||
}
|
||||
|
||||
r = dns_zone_lookup(&s->zone, p->question, &answer, &soa, &tentative);
|
||||
assert(p->question->n_keys == 1);
|
||||
key = p->question->keys[0];
|
||||
|
||||
r = dns_zone_lookup(&s->zone, key, &answer, &soa, &tentative);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to lookup key: %m");
|
||||
return;
|
||||
|
||||
@@ -626,6 +626,20 @@ int dns_transaction_go(DnsTransaction *t) {
|
||||
t->cached = dns_answer_unref(t->cached);
|
||||
t->cached_rcode = 0;
|
||||
|
||||
/* Check the zone, but obly if this transaction is not used
|
||||
* for probing or verifying a zone item. */
|
||||
if (set_isempty(t->zone_items)) {
|
||||
|
||||
r = dns_zone_lookup(&t->scope->zone, t->key, &t->cached, NULL, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0) {
|
||||
t->cached_rcode = DNS_RCODE_SUCCESS;
|
||||
dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the cache, but only if this transaction is not used
|
||||
* for probing or verifying a zone item. */
|
||||
if (set_isempty(t->zone_items)) {
|
||||
|
||||
+129
-136
@@ -283,97 +283,76 @@ int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) {
|
||||
int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) {
|
||||
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
|
||||
unsigned i, n_answer = 0, n_soa = 0;
|
||||
bool tentative = true;
|
||||
unsigned n_answer = 0;
|
||||
DnsZoneItem *j, *first;
|
||||
bool tentative = true, need_soa = false;
|
||||
int r;
|
||||
|
||||
assert(z);
|
||||
assert(q);
|
||||
assert(key);
|
||||
assert(ret_answer);
|
||||
assert(ret_soa);
|
||||
|
||||
if (q->n_keys <= 0) {
|
||||
*ret_answer = NULL;
|
||||
*ret_soa = NULL;
|
||||
|
||||
if (ret_tentative)
|
||||
*ret_tentative = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* First iteration, count what we have */
|
||||
for (i = 0; i < q->n_keys; i++) {
|
||||
DnsZoneItem *j, *first;
|
||||
|
||||
if (q->keys[i]->type == DNS_TYPE_ANY ||
|
||||
q->keys[i]->class == DNS_CLASS_ANY) {
|
||||
bool found = false, added = false;
|
||||
int k;
|
||||
if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
|
||||
bool found = false, added = false;
|
||||
int k;
|
||||
|
||||
/* If this is a generic match, then we have to
|
||||
* go through the list by the name and look
|
||||
* for everything manually */
|
||||
/* If this is a generic match, then we have to
|
||||
* go through the list by the name and look
|
||||
* for everything manually */
|
||||
|
||||
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
|
||||
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
|
||||
LIST_FOREACH(by_name, j, first) {
|
||||
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
|
||||
k = dns_resource_key_match_rr(key, j->rr);
|
||||
if (k < 0)
|
||||
return k;
|
||||
if (k > 0) {
|
||||
n_answer++;
|
||||
added = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (found && !added)
|
||||
need_soa = true;
|
||||
|
||||
} else {
|
||||
bool found = false;
|
||||
|
||||
/* If this is a specific match, then look for
|
||||
* the right key immediately */
|
||||
|
||||
first = hashmap_get(z->by_key, key);
|
||||
LIST_FOREACH(by_key, j, first) {
|
||||
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
n_answer++;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
|
||||
LIST_FOREACH(by_name, j, first) {
|
||||
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
|
||||
k = dns_resource_key_match_rr(q->keys[i], j->rr);
|
||||
if (k < 0)
|
||||
return k;
|
||||
if (k > 0) {
|
||||
n_answer++;
|
||||
added = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (found && !added)
|
||||
n_soa++;
|
||||
|
||||
} else {
|
||||
bool found = false;
|
||||
|
||||
/* If this is a specific match, then look for
|
||||
* the right key immediately */
|
||||
|
||||
first = hashmap_get(z->by_key, q->keys[i]);
|
||||
LIST_FOREACH(by_key, j, first) {
|
||||
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
n_answer++;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
|
||||
LIST_FOREACH(by_name, j, first) {
|
||||
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
|
||||
continue;
|
||||
|
||||
n_soa++;
|
||||
break;
|
||||
}
|
||||
need_soa = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (n_answer <= 0 && n_soa <= 0) {
|
||||
*ret_answer = NULL;
|
||||
*ret_soa = NULL;
|
||||
|
||||
if (ret_tentative)
|
||||
*ret_tentative = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (n_answer <= 0 && !need_soa)
|
||||
goto return_empty;
|
||||
|
||||
if (n_answer > 0) {
|
||||
answer = dns_answer_new(n_answer);
|
||||
@@ -381,99 +360,113 @@ int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **ret_answer, DnsAnswe
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (n_soa > 0) {
|
||||
soa = dns_answer_new(n_soa);
|
||||
if (need_soa) {
|
||||
soa = dns_answer_new(1);
|
||||
if (!soa)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Second iteration, actually add the RRs to the answers */
|
||||
for (i = 0; i < q->n_keys; i++) {
|
||||
DnsZoneItem *j, *first;
|
||||
if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
|
||||
bool found = false, added = false;
|
||||
int k;
|
||||
|
||||
if (q->keys[i]->type == DNS_TYPE_ANY ||
|
||||
q->keys[i]->class == DNS_CLASS_ANY) {
|
||||
bool found = false, added = false;
|
||||
int k;
|
||||
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
|
||||
LIST_FOREACH(by_name, j, first) {
|
||||
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
|
||||
continue;
|
||||
|
||||
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
|
||||
found = true;
|
||||
|
||||
if (j->state != DNS_ZONE_ITEM_PROBING)
|
||||
tentative = false;
|
||||
|
||||
k = dns_resource_key_match_rr(key, j->rr);
|
||||
if (k < 0)
|
||||
return k;
|
||||
if (k > 0) {
|
||||
r = dns_answer_add(answer, j->rr, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found && !added) {
|
||||
r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(key), LLMNR_DEFAULT_TTL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
bool found = false;
|
||||
|
||||
first = hashmap_get(z->by_key, key);
|
||||
LIST_FOREACH(by_key, j, first) {
|
||||
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
|
||||
if (j->state != DNS_ZONE_ITEM_PROBING)
|
||||
tentative = false;
|
||||
|
||||
r = dns_answer_add(answer, j->rr, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
bool add_soa = false;
|
||||
|
||||
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
|
||||
LIST_FOREACH(by_name, j, first) {
|
||||
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
|
||||
if (j->state != DNS_ZONE_ITEM_PROBING)
|
||||
tentative = false;
|
||||
|
||||
k = dns_resource_key_match_rr(q->keys[i], j->rr);
|
||||
if (k < 0)
|
||||
return k;
|
||||
if (k > 0) {
|
||||
r = dns_answer_add(answer, j->rr, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
added = true;
|
||||
}
|
||||
add_soa = true;
|
||||
}
|
||||
|
||||
if (found && !added) {
|
||||
r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(q->keys[i]), LLMNR_DEFAULT_TTL);
|
||||
if (add_soa) {
|
||||
r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(key), LLMNR_DEFAULT_TTL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
bool found = false;
|
||||
|
||||
first = hashmap_get(z->by_key, q->keys[i]);
|
||||
LIST_FOREACH(by_key, j, first) {
|
||||
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
|
||||
if (j->state != DNS_ZONE_ITEM_PROBING)
|
||||
tentative = false;
|
||||
|
||||
r = dns_answer_add(answer, j->rr, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
bool add_soa = false;
|
||||
|
||||
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
|
||||
LIST_FOREACH(by_name, j, first) {
|
||||
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
|
||||
continue;
|
||||
|
||||
if (j->state != DNS_ZONE_ITEM_PROBING)
|
||||
tentative = false;
|
||||
|
||||
add_soa = true;
|
||||
}
|
||||
|
||||
if (add_soa) {
|
||||
r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(q->keys[i]), LLMNR_DEFAULT_TTL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If the caller sets ret_tentative to NULL, then use this as
|
||||
* indication to not return tentative entries */
|
||||
|
||||
if (!ret_tentative && tentative)
|
||||
goto return_empty;
|
||||
|
||||
*ret_answer = answer;
|
||||
answer = NULL;
|
||||
|
||||
*ret_soa = soa;
|
||||
soa = NULL;
|
||||
if (ret_soa) {
|
||||
*ret_soa = soa;
|
||||
soa = NULL;
|
||||
}
|
||||
|
||||
if (ret_tentative)
|
||||
*ret_tentative = tentative;
|
||||
|
||||
return 1;
|
||||
|
||||
return_empty:
|
||||
*ret_answer = NULL;
|
||||
|
||||
if (ret_soa)
|
||||
*ret_soa = NULL;
|
||||
|
||||
if (ret_tentative)
|
||||
*ret_tentative = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dns_zone_item_conflict(DnsZoneItem *i) {
|
||||
|
||||
@@ -67,7 +67,7 @@ void dns_zone_flush(DnsZone *z);
|
||||
int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe);
|
||||
void dns_zone_remove_rr(DnsZone *z, DnsResourceRecord *rr);
|
||||
|
||||
int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **answer, DnsAnswer **soa, bool *tentative);
|
||||
int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **answer, DnsAnswer **soa, bool *tentative);
|
||||
|
||||
void dns_zone_item_conflict(DnsZoneItem *i);
|
||||
void dns_zone_item_ready(DnsZoneItem *i);
|
||||
|
||||
+25
-7
@@ -1428,16 +1428,36 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
|
||||
return bus_log_create_error(r);
|
||||
|
||||
return 0;
|
||||
|
||||
} else if (streq(field, "EnvironmentFile")) {
|
||||
|
||||
r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "EnvironmentFiles");
|
||||
if (r < 0)
|
||||
return r;
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_append(m, "v", "a(sb)", 1,
|
||||
eq[0] == '-' ? eq + 1 : eq,
|
||||
eq[0] == '-');
|
||||
if (r < 0)
|
||||
return r;
|
||||
return bus_log_create_error(r);
|
||||
|
||||
return 0;
|
||||
|
||||
} else if (streq(field, "RandomSec")) {
|
||||
usec_t t;
|
||||
|
||||
r = parse_sec(eq, &t);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse RandomSec= parameter: %s", eq);
|
||||
|
||||
r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "RandomUSec");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_append(m, "v", "t", t);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1450,13 +1470,11 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
|
||||
"SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
|
||||
"IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
|
||||
"PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges",
|
||||
"SyslogLevelPrefix", "Delegate")) {
|
||||
"SyslogLevelPrefix", "Delegate", "RemainAfterElapse")) {
|
||||
|
||||
r = parse_boolean(eq);
|
||||
if (r < 0) {
|
||||
log_error("Failed to parse boolean assignment %s.", assignment);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse boolean assignment %s.", assignment);
|
||||
|
||||
r = sd_bus_message_append(m, "v", "b", r);
|
||||
|
||||
|
||||
@@ -3360,6 +3360,7 @@ typedef struct UnitStatusInfo {
|
||||
usec_t inactive_enter_timestamp;
|
||||
|
||||
bool need_daemon_reload;
|
||||
bool transient;
|
||||
|
||||
/* Service */
|
||||
pid_t main_pid;
|
||||
@@ -3459,7 +3460,7 @@ static void print_status_info(
|
||||
|
||||
path = i->source_path ? i->source_path : i->fragment_path;
|
||||
|
||||
if (i->load_error)
|
||||
if (i->load_error != 0)
|
||||
printf(" Loaded: %s%s%s (Reason: %s)\n",
|
||||
on, strna(i->load_state), off, i->load_error);
|
||||
else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset))
|
||||
@@ -3475,6 +3476,9 @@ static void print_status_info(
|
||||
printf(" Loaded: %s%s%s\n",
|
||||
on, strna(i->load_state), off);
|
||||
|
||||
if (i->transient)
|
||||
printf("Transient: yes\n");
|
||||
|
||||
if (!strv_isempty(i->dropin_paths)) {
|
||||
_cleanup_free_ char *dir = NULL;
|
||||
bool last = false;
|
||||
@@ -3839,6 +3843,8 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *
|
||||
i->condition_result = b;
|
||||
else if (streq(name, "AssertResult"))
|
||||
i->assert_result = b;
|
||||
else if (streq(name, "Transient"))
|
||||
i->transient = b;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -4646,8 +4652,7 @@ static int show(int argc, char *argv[], void *userdata) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (show_properties)
|
||||
pager_open_if_enabled();
|
||||
pager_open_if_enabled();
|
||||
|
||||
if (show_status)
|
||||
/* Increase max number of open files to 16K if we can, we
|
||||
|
||||
Reference in New Issue
Block a user