]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/address: forget address even if we could not remove it
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 2 Jan 2024 19:41:42 +0000 (04:41 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 12 Jan 2024 00:36:04 +0000 (09:36 +0900)
If we could not remove an address, then previously the corresponding
Address object was never removed, as it was freed only when we receive
remove notification from the kernel. So, we might confused that the
address still exists and being removed, and might block reconfiguring
the address.

With this change, even if we fail to remove an address, the
corresponding Address object will be freed.

src/network/networkd-address.c

index e54c12236140ab37aba2ecccb0a2f8ff11eab9d2..4c3393645e7e2e9956961766b7ff24cab35deffd 100644 (file)
@@ -1111,18 +1111,35 @@ static int address_set_netlink_message(const Address *address, sd_netlink_messag
         return 0;
 }
 
-static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, RemoveRequest *rreq) {
         int r;
 
         assert(m);
-        assert(link);
+        assert(rreq);
 
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+        Link *link = ASSERT_PTR(rreq->link);
+        Address *address = ASSERT_PTR(rreq->userdata);
+
+        if (link->state == LINK_STATE_LINGER)
                 return 0;
 
         r = sd_netlink_message_get_errno(m);
-        if (r < 0 && r != -EADDRNOTAVAIL)
-                log_link_message_warning_errno(link, m, r, "Could not drop address");
+        if (r < 0) {
+                log_link_message_full_errno(link, m,
+                                            (r == -EADDRNOTAVAIL || !address->link) ? LOG_DEBUG : LOG_WARNING,
+                                            r, "Could not drop address");
+
+                if (address->link) {
+                        /* If the address cannot be removed, then assume the address is already removed. */
+                        log_address_debug(address, "Forgetting", link);
+
+                        Request *req;
+                        if (address_get_request(link, address, &req) >= 0)
+                                address_enter_removed(req->userdata);
+
+                        (void) address_drop(address);
+                }
+        }
 
         return 1;
 }
@@ -1149,13 +1166,9 @@ int address_remove(Address *address, Link *link) {
         if (r < 0)
                 return log_link_warning_errno(link, r, "Could not set netlink attributes: %m");
 
-        r = netlink_call_async(link->manager->rtnl, NULL, m,
-                               address_remove_handler,
-                               link_netlink_destroy_callback, link);
+        r = link_remove_request_add(link, address, address, link->manager->rtnl, m, address_remove_handler);
         if (r < 0)
-                return log_link_warning_errno(link, r, "Could not send rtnetlink message: %m");
-
-        link_ref(link);
+                return log_link_warning_errno(link, r, "Could not queue rtnetlink message: %m");
 
         address_enter_removing(address);