Clean up check_pf allocation pattern. addresses
authorOndřej Bílka <neleai@seznam.cz>
Tue, 6 Jan 2015 16:26:44 +0000 (17:26 +0100)
committerOndřej Bílka <neleai@seznam.cz>
Tue, 6 Jan 2015 16:26:44 +0000 (17:26 +0100)
We simplify allocation strategy there so instead of using temporary linked list
and then copying entries to output array we keep them in resizable
array.

sysdeps/unix/sysv/linux/check_pf.c

index d7efe72..162606d 100644 (file)
@@ -105,6 +105,11 @@ cache_valid_p (void)
 static struct cached_data *
 make_request (int fd, pid_t pid)
 {
+  struct cached_data *result = NULL;
+
+  size_t result_len = 0;
+  size_t result_cap = 32;
+
   struct req
   {
     struct nlmsghdr nlh;
@@ -130,26 +135,11 @@ make_request (int fd, pid_t pid)
   nladdr.nl_family = AF_NETLINK;
 
 #ifdef PAGE_SIZE
-  /* Help the compiler optimize out the malloc call if PAGE_SIZE
-     is constant and smaller or equal to PTHREAD_STACK_MIN/4.  */
   const size_t buf_size = PAGE_SIZE;
 #else
-  const size_t buf_size = __getpagesize ();
+  const size_t buf_size = 4096;
 #endif
-  bool use_malloc = false;
-  char *buf;
-  size_t alloca_used = 0;
-
-  if (__libc_use_alloca (buf_size))
-    buf = alloca_account (buf_size, alloca_used);
-  else
-    {
-      buf = malloc (buf_size);
-      if (buf != NULL)
-       use_malloc = true;
-      else
-       goto out_fail;
-    }
+  char buf[buf_size];
 
   struct iovec iov = { buf, buf_size };
 
@@ -159,13 +149,7 @@ make_request (int fd, pid_t pid)
     goto out_fail;
 
   bool done = false;
-  struct in6ailist
-  {
-    struct in6addrinfo info;
-    struct in6ailist *next;
-    bool use_malloc;
-  } *in6ailist = NULL;
-  size_t in6ailistlen = 0;
+
   bool seen_ipv4 = false;
   bool seen_ipv6 = false;
 
@@ -181,10 +165,10 @@ make_request (int fd, pid_t pid)
 
       ssize_t read_len = TEMP_FAILURE_RETRY (__recvmsg (fd, &msg, 0));
       if (read_len <= 0)
-       goto out_fail2;
+       goto out_fail;
 
       if (msg.msg_flags & MSG_TRUNC)
-       goto out_fail2;
+       goto out_fail;
 
       struct nlmsghdr *nlmh;
       for (nlmh = (struct nlmsghdr *) buf;
@@ -240,40 +224,35 @@ make_request (int fd, pid_t pid)
                    }
                }
 
-             struct in6ailist *newp;
-             if (__libc_use_alloca (alloca_used + sizeof (*newp)))
+             if (result_len == 0 || result_len == result_cap)
                {
-                 newp = alloca_account (sizeof (*newp), alloca_used);
-                 newp->use_malloc = false;
+                 result_cap = 2 * result_cap;
+                 result = realloc (result, sizeof (*result)
+                                   + result_cap
+                                     * sizeof (struct in6addrinfo));
                }
-             else
-               {
-                 newp = malloc (sizeof (*newp));
-                 if (newp == NULL)
-                   goto out_fail2;
-                 newp->use_malloc = true;
-               }
-             newp->info.flags = (((ifam->ifa_flags
-                                   & (IFA_F_DEPRECATED
-                                      | IFA_F_OPTIMISTIC))
-                                  ? in6ai_deprecated : 0)
-                                 | ((ifam->ifa_flags
-                                     & IFA_F_HOMEADDRESS)
-                                    ? in6ai_homeaddress : 0));
-             newp->info.prefixlen = ifam->ifa_prefixlen;
-             newp->info.index = ifam->ifa_index;
+
+             if (!result)
+               goto out_fail;
+
+             struct in6addrinfo *info = &result->in6ai[result_len++];
+
+             info->flags = (((ifam->ifa_flags
+                              & (IFA_F_DEPRECATED | IFA_F_OPTIMISTIC))
+                             ? in6ai_deprecated : 0)
+                            | ((ifam->ifa_flags & IFA_F_HOMEADDRESS)
+                                ? in6ai_homeaddress : 0));
+             info->prefixlen = ifam->ifa_prefixlen;
+             info->index = ifam->ifa_index;
              if (ifam->ifa_family == AF_INET)
                {
-                 newp->info.addr[0] = 0;
-                 newp->info.addr[1] = 0;
-                 newp->info.addr[2] = htonl (0xffff);
-                 newp->info.addr[3] = *(const in_addr_t *) address;
+                 info->addr[0] = 0;
+                 info->addr[1] = 0;
+                 info->addr[2] = htonl (0xffff);
+                 info->addr[3] = *(const in_addr_t *) address;
                }
              else
-               memcpy (newp->info.addr, address, sizeof (newp->info.addr));
-             newp->next = in6ailist;
-             in6ailist = newp;
-             ++in6ailistlen;
+               memcpy (info->addr, address, sizeof (info->addr));
            }
          else if (nlmh->nlmsg_type == NLMSG_DONE)
            /* We found the end, leave the loop.  */
@@ -282,53 +261,29 @@ make_request (int fd, pid_t pid)
     }
   while (! done);
 
-  struct cached_data *result;
-  if (seen_ipv6 && in6ailist != NULL)
+  if (seen_ipv6 && result != NULL)
     {
-      result = malloc (sizeof (*result)
-                      + in6ailistlen * sizeof (struct in6addrinfo));
-      if (result == NULL)
-       goto out_fail2;
-
       result->timestamp = get_nl_timestamp ();
       result->usecnt = 2;
       result->seen_ipv4 = seen_ipv4;
       result->seen_ipv6 = true;
-      result->in6ailen = in6ailistlen;
-
-      do
-       {
-         result->in6ai[--in6ailistlen] = in6ailist->info;
-         struct in6ailist *next = in6ailist->next;
-         if (in6ailist->use_malloc)
-           free (in6ailist);
-         in6ailist = next;
-       }
-      while (in6ailist != NULL);
+      result->in6ailen = result_len;
     }
   else
     {
+      free (result);
+
       atomic_add (&noai6ai_cached.usecnt, 2);
       noai6ai_cached.seen_ipv4 = seen_ipv4;
       noai6ai_cached.seen_ipv6 = seen_ipv6;
       result = &noai6ai_cached;
     }
 
-  if (use_malloc)
-    free (buf);
   return result;
 
- out_fail2:
-  while (in6ailist != NULL)
-    {
-      struct in6ailist *next = in6ailist->next;
-      if (in6ailist->use_malloc)
-       free (in6ailist);
-      in6ailist = next;
-    }
  out_fail:
-  if (use_malloc)
-    free (buf);
+
+  free (result);
   return NULL;
 }