]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: introduce reference counter for Request object
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 27 Feb 2022 06:18:01 +0000 (15:18 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 11 Mar 2022 05:20:31 +0000 (14:20 +0900)
Currently, all Request object are always owned by Manager, and freed
when it is processed, especially, soon after a netlink message is sent.
So, it is not necessary to introduce the reference counter.

In a later commit, the Request object will _not_ be freed at the time
when a netlink message is sent, but assigned to the relevant netlink
slot as a userdata, and will be freed when a reply is received. So, the
owner of the Request object is changed in its lifetime. In that case, it
is convenient that the object has reference counter to avoid memleak or
double free.

src/network/networkd-queue.c
src/network/networkd-queue.h

index 830802324ef72646061e4f3f828de50e25aeeedb..06a0cb066e276a0895bfda2231ab36e29fb02c6f 100644 (file)
@@ -92,7 +92,7 @@ static Request *request_free(Request *req) {
         return mfree(req);
 }
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_free);
+DEFINE_TRIVIAL_REF_UNREF_FUNC(Request, request, request_free);
 
 void request_drop(Request *req) {
         if (!req)
@@ -101,7 +101,7 @@ void request_drop(Request *req) {
         if (req->message_counter)
                 (*req->message_counter)--;
 
-        request_free(req);
+        request_unref(req);
 }
 
 static void request_hash_func(const Request *req, struct siphash *state) {
@@ -238,13 +238,13 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
                 Request,
                 request_hash_func,
                 request_compare_func,
-                request_free);
+                request_unref);
 
 int netdev_queue_request(
                 NetDev *netdev,
                 Request **ret) {
 
-        _cleanup_(request_freep) Request *req = NULL;
+        _cleanup_(request_unrefp) Request *req = NULL;
         Request *existing;
         int r;
 
@@ -256,6 +256,7 @@ int netdev_queue_request(
                 return -ENOMEM;
 
         *req = (Request) {
+                .n_ref = 1,
                 .netdev = netdev_ref(netdev),
                 .type = REQUEST_TYPE_NETDEV_INDEPENDENT,
                 .consume_object = true,
@@ -291,7 +292,7 @@ int link_queue_request(
                 link_netlink_message_handler_t netlink_handler,
                 Request **ret) {
 
-        _cleanup_(request_freep) Request *req = NULL;
+        _cleanup_(request_unrefp) Request *req = NULL;
         Request *existing;
         int r;
 
@@ -324,6 +325,7 @@ int link_queue_request(
         }
 
         *req = (Request) {
+                .n_ref = 1,
                 .link = link_ref(link),
                 .type = type,
                 .object = object,
@@ -439,7 +441,7 @@ int manager_process_requests(sd_event_source *s, void *userdata) {
                                         link_enter_failed(req->link);
                         } else if (r > 0) {
                                 ordered_set_remove(manager->request_queue, req);
-                                request_free(req);
+                                request_unref(req);
                                 processed = true;
                         }
                 }
index 593f3dde6e473cbf735b14969b77a79af4585429..7410e5c8612dba9c398d7e90653a5ee730bb34ad 100644 (file)
@@ -44,6 +44,8 @@ typedef enum RequestType {
 } RequestType;
 
 typedef struct Request {
+        unsigned n_ref;
+
         Link *link;
         RequestType type;
         bool consume_object;
@@ -68,6 +70,10 @@ typedef struct Request {
         link_netlink_message_handler_t netlink_handler;
 } Request;
 
+Request *request_ref(Request *req);
+Request *request_unref(Request *req);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_unref);
+
 void request_drop(Request *req);
 
 int netdev_queue_request(