diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 7f44b93726..9290fd8784 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -1614,7 +1614,7 @@ int path_is_encrypted(const char *path) { return blockdev_is_encrypted(p, 10 /* safety net: maximum recursion depth */); } -int conservative_rename( +int conservative_renameat( int olddirfd, const char *oldpath, int newdirfd, const char *newpath) { diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index 8bd8da1704..f036a19eb5 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -143,4 +143,7 @@ int open_parent(const char *path, int flags, mode_t mode); int path_is_encrypted(const char *path); -int conservative_rename(int olddirfd, const char *oldpath, int newdirfd, const char *newpath); +int conservative_renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath); +static inline int conservative_rename(const char *oldpath, const char *newpath) { + return conservative_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath); +} diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index 8a138ff4b6..69ded6d148 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -19,6 +19,7 @@ #include "env-file.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "hexdecoct.h" #include "hostname-util.h" #include "in-addr-util.h" @@ -1023,10 +1024,9 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { if (r < 0) goto fail; - if (rename(temp_path, lease_file) < 0) { - r = -errno; + r = conservative_rename(temp_path, lease_file); + if (r < 0) goto fail; - } return 0; diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 5d3af46d4a..bbdd31a93d 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -36,8 +36,6 @@ static int dhcp4_release_old_lease(Link *link) { log_link_debug(link, "Removing old DHCPv4 address and routes."); - link_dirty(link); - SET_FOREACH(route, link->dhcp_routes_old) { k = route_remove(route, NULL, link, NULL); if (k < 0) diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index d9b45a8a14..85a533b32f 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -160,8 +160,6 @@ static int dhcp6_pd_remove_old(Link *link, bool force) { log_link_debug(link, "Removing old DHCPv6 Prefix Delegation addresses and routes."); - link_dirty(link); - SET_FOREACH(route, link->dhcp6_pd_routes_old) { k = route_remove(route, NULL, link, NULL); if (k < 0) @@ -204,8 +202,6 @@ int dhcp6_pd_remove(Link *link) { log_link_debug(link, "Removing DHCPv6 Prefix Delegation addresses and routes."); - link_dirty(link); - SET_FOREACH(route, link->dhcp6_pd_routes) { k = route_remove(route, NULL, link, NULL); if (k < 0) @@ -352,12 +348,6 @@ static int dhcp6_pd_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Lin link_enter_failed(link); return 1; } - - r = link_set_routes(link); - if (r < 0) { - link_enter_failed(link); - return 1; - } } return 1; @@ -585,8 +575,6 @@ static int dhcp6_pd_prepare(Link *link) { if (!link_dhcp6_pd_is_enabled(link)) return 0; - link_dirty(link); - link->dhcp6_pd_address_configured = false; link->dhcp6_pd_route_configured = false; link->dhcp6_pd_prefixes_assigned = true; @@ -618,14 +606,8 @@ static int dhcp6_pd_finalize(Link *link) { if (link->dhcp6_pd_address_messages == 0) { if (link->dhcp6_pd_prefixes_assigned) link->dhcp6_pd_address_configured = true; - } else { + } else log_link_debug(link, "Setting DHCPv6 PD addresses"); - /* address_handler calls link_set_routes() and link_set_nexthop(). Before they are - * called, the related flags must be cleared. Otherwise, the link becomes configured - * state before routes are configured. */ - link->static_routes_configured = false; - link->static_nexthops_configured = false; - } if (link->dhcp6_pd_route_messages == 0) { if (link->dhcp6_pd_prefixes_assigned) @@ -708,8 +690,6 @@ static int dhcp6_remove_old(Link *link, bool force) { log_link_debug(link, "Removing old DHCPv6 addresses and routes."); - link_dirty(link); - SET_FOREACH(route, link->dhcp6_routes_old) { k = route_remove(route, NULL, link, NULL); if (k < 0) @@ -744,8 +724,6 @@ static int dhcp6_remove(Link *link) { log_link_debug(link, "Removing DHCPv6 addresses and routes."); - link_dirty(link); - SET_FOREACH(route, link->dhcp6_routes) { k = route_remove(route, NULL, link, NULL); if (k < 0) @@ -962,12 +940,6 @@ static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link * link_enter_failed(link); return 1; } - - r = link_set_routes(link); - if (r < 0) { - link_enter_failed(link); - return 1; - } } return 1; @@ -1114,8 +1086,6 @@ static int dhcp6_lease_ip_acquired(sd_dhcp6_client *client, Link *link) { link->dhcp6_address_configured = false; link->dhcp6_route_configured = false; - link_dirty(link); - while ((a = set_steal_first(link->dhcp6_addresses))) { r = set_ensure_put(&link->dhcp6_addresses_old, &address_hash_ops, a); if (r < 0) @@ -1149,14 +1119,8 @@ static int dhcp6_lease_ip_acquired(sd_dhcp6_client *client, Link *link) { if (link->dhcp6_address_messages == 0) link->dhcp6_address_configured = true; - else { + else log_link_debug(link, "Setting DHCPv6 addresses"); - /* address_handler calls link_set_routes() and link_set_nexthop(). Before they are - * called, the related flags must be cleared. Otherwise, the link becomes configured - * state before routes are configured. */ - link->static_routes_configured = false; - link->static_nexthops_configured = false; - } if (link->dhcp6_route_messages == 0) link->dhcp6_route_configured = true; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 204e0c57ff..fe6d3bd927 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -16,6 +16,7 @@ #include "ethtool-util.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "ipvlan.h" #include "missing_network.h" #include "netlink-util.h" @@ -596,14 +597,13 @@ void link_set_state(Link *link, LinkState state) { link->state = state; link_send_changed(link, "AdministrativeState", NULL); + link_dirty(link); } static void link_enter_unmanaged(Link *link) { assert(link); link_set_state(link, LINK_STATE_UNMANAGED); - - link_dirty(link); } int link_stop_engines(Link *link, bool may_keep_dhcp) { @@ -675,8 +675,6 @@ void link_enter_failed(Link *link) { link_set_state(link, LINK_STATE_FAILED); (void) link_stop_engines(link, false); - - link_dirty(link); } static int link_join_netdevs_after_configured(Link *link) { @@ -717,8 +715,6 @@ static void link_enter_configured(Link *link) { link_set_state(link, LINK_STATE_CONFIGURED); (void) link_join_netdevs_after_configured(link); - - link_dirty(link); } void link_check_ready(Link *link) { @@ -1605,6 +1601,8 @@ static int link_put_carrier(Link *link, Link *carrier, Hashmap **h) { if (r < 0) return r; + link_dirty(link); + return 0; } @@ -1612,7 +1610,6 @@ static int link_new_bound_by_list(Link *link) { Manager *m; Link *carrier; int r; - bool list_updated = false; assert(link); assert(link->manager); @@ -1630,20 +1627,13 @@ static int link_new_bound_by_list(Link *link) { r = link_put_carrier(link, carrier, &link->bound_by_links); if (r < 0) return r; - - list_updated = true; } } - if (list_updated) - link_dirty(link); - HASHMAP_FOREACH(carrier, link->bound_by_links) { r = link_put_carrier(carrier, link, &carrier->bound_to_links); if (r < 0) return r; - - link_dirty(carrier); } return 0; @@ -1653,7 +1643,6 @@ static int link_new_bound_to_list(Link *link) { Manager *m; Link *carrier; int r; - bool list_updated = false; assert(link); assert(link->manager); @@ -1671,20 +1660,13 @@ static int link_new_bound_to_list(Link *link) { r = link_put_carrier(link, carrier, &link->bound_to_links); if (r < 0) return r; - - list_updated = true; } } - if (list_updated) - link_dirty(link); - HASHMAP_FOREACH (carrier, link->bound_to_links) { r = link_put_carrier(carrier, link, &carrier->bound_by_links); if (r < 0) return r; - - link_dirty(carrier); } return 0; @@ -1713,23 +1695,32 @@ static int link_new_carrier_maps(Link *link) { } static void link_free_bound_to_list(Link *link) { + bool updated = false; Link *bound_to; - HASHMAP_FOREACH (bound_to, link->bound_to_links) { - hashmap_remove(link->bound_to_links, INT_TO_PTR(bound_to->ifindex)); + assert(link); + + while ((bound_to = hashmap_steal_first(link->bound_to_links))) { + updated = true; if (hashmap_remove(bound_to->bound_by_links, INT_TO_PTR(link->ifindex))) link_dirty(bound_to); } + if (updated) + link_dirty(link); + return; } static void link_free_bound_by_list(Link *link) { + bool updated = false; Link *bound_by; - HASHMAP_FOREACH (bound_by, link->bound_by_links) { - hashmap_remove(link->bound_by_links, INT_TO_PTR(bound_by->ifindex)); + assert(link); + + while ((bound_by = hashmap_steal_first(link->bound_by_links))) { + updated = true; if (hashmap_remove(bound_by->bound_to_links, INT_TO_PTR(link->ifindex))) { link_dirty(bound_by); @@ -1737,26 +1728,17 @@ static void link_free_bound_by_list(Link *link) { } } + if (updated) + link_dirty(link); + return; } static void link_free_carrier_maps(Link *link) { - bool list_updated = false; - assert(link); - if (!hashmap_isempty(link->bound_to_links)) { - link_free_bound_to_list(link); - list_updated = true; - } - - if (!hashmap_isempty(link->bound_by_links)) { - link_free_bound_by_list(link); - list_updated = true; - } - - if (list_updated) - link_dirty(link); + link_free_bound_to_list(link); + link_free_bound_by_list(link); return; } @@ -1943,7 +1925,6 @@ static int link_enter_join_netdev(Link *link) { link_set_state(link, LINK_STATE_CONFIGURING); - link_dirty(link); link->enslaving = 0; if (link->network->bond) { @@ -2266,9 +2247,8 @@ static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool for link_unref(set_remove(link->manager->links_requesting_uuid, link)); /* Then, apply new .network file */ - r = network_apply(network, link); - if (r < 0) - return r; + link->network = network_ref(network); + link_dirty(link); r = link_new_carrier_maps(link); if (r < 0) @@ -2276,7 +2256,6 @@ static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool for link_set_state(link, LINK_STATE_INITIALIZED); link->activated = false; - link_dirty(link); /* link_configure_duid() returns 0 if it requests product UUID. In that case, * link_configure() is called later asynchronously. */ @@ -2390,9 +2369,8 @@ static int link_initialized_and_synced(Link *link) { log_link_debug(link, "Ignoring DHCP server for loopback link"); } - r = network_apply(network, link); - if (r < 0) - return r; + link->network = network_ref(network); + link_dirty(link); } r = link_new_bound_to_list(link); @@ -3198,10 +3176,9 @@ int link_save(Link *link) { if (r < 0) goto fail; - if (rename(temp_path, link->state_file) < 0) { - r = -errno; + r = conservative_rename(temp_path, link->state_file); + if (r < 0) goto fail; - } return 0; diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index bf15ba6535..befecdc323 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -23,6 +23,7 @@ #include "fd-util.h" #include "fileio.h" #include "firewall-util.h" +#include "fs-util.h" #include "local-addresses.h" #include "netlink-util.h" #include "network-internal.h" @@ -709,10 +710,9 @@ static int manager_save(Manager *m) { if (r < 0) goto fail; - if (rename(temp_path, m->state_file) < 0) { - r = -errno; + r = conservative_rename(temp_path, m->state_file); + if (r < 0) goto fail; - } if (m->operational_state != operstate) { m->operational_state = operstate; diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 82de316bc3..e45301eb8c 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -118,6 +118,7 @@ static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool NDiscDNSSL *dnssl; NDiscRDNSS *rdnss; int k, r = 0; + bool updated = false; assert(link); assert(router); @@ -182,12 +183,19 @@ static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool } SET_FOREACH(rdnss, link->ndisc_rdnss) - if (rdnss->marked && IN6_ARE_ADDR_EQUAL(&rdnss->router, router)) + if (rdnss->marked && IN6_ARE_ADDR_EQUAL(&rdnss->router, router)) { free(set_remove(link->ndisc_rdnss, rdnss)); + updated = true; + } SET_FOREACH(dnssl, link->ndisc_dnssl) - if (dnssl->marked && IN6_ARE_ADDR_EQUAL(&dnssl->router, router)) + if (dnssl->marked && IN6_ARE_ADDR_EQUAL(&dnssl->router, router)) { free(set_remove(link->ndisc_dnssl, dnssl)); + updated = true; + } + + if (updated) + link_dirty(link); return r; } @@ -412,12 +420,6 @@ static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link * link_enter_failed(link); return 1; } - - r = link_set_routes(link); - if (r < 0) { - link_enter_failed(link); - return 1; - } } return 1; @@ -932,6 +934,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { struct in6_addr router; NDiscRDNSS *rdnss; usec_t time_now; + bool updated = false; int n, r; assert(link); @@ -993,8 +996,13 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { if (r < 0) return log_oom(); assert(r > 0); + + updated = true; } + if (updated) + link_dirty(link); + return 0; } @@ -1019,6 +1027,7 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { uint32_t lifetime; usec_t time_now; NDiscDNSSL *dnssl; + bool updated = false; char **j; int r; @@ -1078,8 +1087,13 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { if (r < 0) return log_oom(); assert(r > 0); + + updated = true; } + if (updated) + link_dirty(link); + return 0; } @@ -1204,8 +1218,6 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { link->ndisc_addresses_configured = false; link->ndisc_routes_configured = false; - link_dirty(link); - SET_FOREACH(na, link->ndisc_addresses) if (IN6_ARE_ADDR_EQUAL(&na->router, &router.in6)) na->marked = true; @@ -1244,16 +1256,9 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { if (link->ndisc_addresses_messages == 0) link->ndisc_addresses_configured = true; - else { + else log_link_debug(link, "Setting SLAAC addresses."); - /* address_handler calls link_set_routes() and link_set_nexthop(). Before they are - * called, the related flags must be cleared. Otherwise, the link becomes configured - * state before routes are configured. */ - link->static_routes_configured = false; - link->static_nexthops_configured = false; - } - if (link->ndisc_routes_messages == 0) link->ndisc_routes_configured = true; else @@ -1340,7 +1345,6 @@ void ndisc_vacuum(Link *link) { NDiscRDNSS *r; NDiscDNSSL *d; usec_t time_now; - bool updated = false; assert(link); @@ -1349,19 +1353,12 @@ void ndisc_vacuum(Link *link) { time_now = now(clock_boottime_or_monotonic()); SET_FOREACH(r, link->ndisc_rdnss) - if (r->valid_until < time_now) { + if (r->valid_until < time_now) free(set_remove(link->ndisc_rdnss, r)); - updated = true; - } SET_FOREACH(d, link->ndisc_dnssl) - if (d->valid_until < time_now) { + if (d->valid_until < time_now) free(set_remove(link->ndisc_dnssl, d)); - updated = true; - } - - if (updated) - link_dirty(link); } void ndisc_flush(Link *link) { diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index ad4cd46276..62e3ff0cc6 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -736,21 +736,6 @@ int network_get(Manager *manager, unsigned short iftype, sd_device *device, return -ENOENT; } -int network_apply(Network *network, Link *link) { - assert(network); - assert(link); - - link->network = network_ref(network); - - if (network->n_dns > 0 || - !strv_isempty(network->ntp) || - !ordered_set_isempty(network->search_domains) || - !ordered_set_isempty(network->route_domains)) - link_dirty(link); - - return 0; -} - bool network_has_static_ipv6_configurations(Network *network) { Address *address; Route *route; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 52aae6a31e..b1db17f7b7 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -329,7 +329,6 @@ int network_get(Manager *manager, unsigned short iftype, sd_device *device, const struct ether_addr *mac, const struct ether_addr *permanent_mac, enum nl80211_iftype wlan_iftype, const char *ssid, const struct ether_addr *bssid, Network **ret); -int network_apply(Network *network, Link *link); void network_apply_anonymize_if_set(Network *network); bool network_has_static_ipv6_configurations(Network *network); diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c index 029d5c93ed..2f06c9046f 100644 --- a/src/resolve/resolved-resolv-conf.c +++ b/src/resolve/resolved-resolv-conf.c @@ -360,7 +360,7 @@ int manager_write_resolv_conf(Manager *m) { goto fail; } - r = conservative_rename(AT_FDCWD, temp_path_stub, AT_FDCWD, PRIVATE_STUB_RESOLV_CONF); + r = conservative_rename(temp_path_stub, PRIVATE_STUB_RESOLV_CONF); if (r < 0) log_error_errno(r, "Failed to move new %s into place: %m", PRIVATE_STUB_RESOLV_CONF); @@ -370,7 +370,7 @@ int manager_write_resolv_conf(Manager *m) { log_error_errno(r, "Failed to symlink %s: %m", PRIVATE_STUB_RESOLV_CONF); } - r = conservative_rename(AT_FDCWD, temp_path_uplink, AT_FDCWD, PRIVATE_UPLINK_RESOLV_CONF); + r = conservative_rename(temp_path_uplink, PRIVATE_UPLINK_RESOLV_CONF); if (r < 0) log_error_errno(r, "Failed to move new %s into place: %m", PRIVATE_UPLINK_RESOLV_CONF); diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index e0ef8257bd..f01b08b2eb 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -847,37 +847,37 @@ static void test_conservative_rename(void) { /* Check that the hardlinked "copy" is detected */ assert_se(link(p, q) >= 0); - assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) == 0); + assert_se(conservative_renameat(AT_FDCWD, q, AT_FDCWD, p) == 0); assert_se(access(q, F_OK) < 0 && errno == ENOENT); /* Check that a manual copy is detected */ assert_se(copy_file(p, q, 0, (mode_t) -1, 0, 0, COPY_REFLINK) >= 0); - assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) == 0); + assert_se(conservative_renameat(AT_FDCWD, q, AT_FDCWD, p) == 0); assert_se(access(q, F_OK) < 0 && errno == ENOENT); /* Check that a manual new writeout is also detected */ assert_se(write_string_file(q, "this is a test", WRITE_STRING_FILE_CREATE) >= 0); - assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) == 0); + assert_se(conservative_renameat(AT_FDCWD, q, AT_FDCWD, p) == 0); assert_se(access(q, F_OK) < 0 && errno == ENOENT); /* Check that a minimally changed version is detected */ assert_se(write_string_file(q, "this is a_test", WRITE_STRING_FILE_CREATE) >= 0); - assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) > 0); + assert_se(conservative_renameat(AT_FDCWD, q, AT_FDCWD, p) > 0); assert_se(access(q, F_OK) < 0 && errno == ENOENT); /* Check that this really is new updated version */ assert_se(write_string_file(q, "this is a_test", WRITE_STRING_FILE_CREATE) >= 0); - assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) == 0); + assert_se(conservative_renameat(AT_FDCWD, q, AT_FDCWD, p) == 0); assert_se(access(q, F_OK) < 0 && errno == ENOENT); /* Make sure we detect extended files */ assert_se(write_string_file(q, "this is a_testx", WRITE_STRING_FILE_CREATE) >= 0); - assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) > 0); + assert_se(conservative_renameat(AT_FDCWD, q, AT_FDCWD, p) > 0); assert_se(access(q, F_OK) < 0 && errno == ENOENT); /* Make sure we detect truncated files */ assert_se(write_string_file(q, "this is a_test", WRITE_STRING_FILE_CREATE) >= 0); - assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) > 0); + assert_se(conservative_renameat(AT_FDCWD, q, AT_FDCWD, p) > 0); assert_se(access(q, F_OK) < 0 && errno == ENOENT); }