aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--package/hotplug2/patches/120-throttling.patch135
1 files changed, 135 insertions, 0 deletions
diff --git a/package/hotplug2/patches/120-throttling.patch b/package/hotplug2/patches/120-throttling.patch
new file mode 100644
index 0000000000..8d67b0cbf8
--- /dev/null
+++ b/package/hotplug2/patches/120-throttling.patch
@@ -0,0 +1,135 @@
+--- a/hotplug2.c
++++ b/hotplug2.c
+@@ -21,6 +21,7 @@
+ #include <sys/mman.h>
+ #include <linux/types.h>
+ #include <linux/netlink.h>
++#include <poll.h>
+
+ #include "mem_utils.h"
+ #include "filemap_utils.h"
+@@ -492,6 +493,11 @@
+ char *coldplug_command = NULL;
+ char *rules_file = HOTPLUG2_RULE_PATH;
+ sigset_t block_mask;
++ struct pollfd msg_poll;
++
++ struct hotplug2_event_t *backlog = NULL;
++ struct hotplug2_event_t *backlog_tail = NULL;
++ int n_backlog = 0;
+
+ struct rules_t *rules = NULL;
+ struct filemap_t filemap;
+@@ -602,6 +608,8 @@
+ * Open netlink socket to read the uevents
+ */
+ netlink_socket = init_netlink_socket(NETLINK_BIND);
++ msg_poll.fd = netlink_socket;
++ msg_poll.events = POLLIN;
+
+ if (netlink_socket == -1) {
+ ERROR("netlink init","Unable to open netlink socket.");
+@@ -642,20 +650,45 @@
+ * Main loop reading uevents
+ */
+ while (!terminate) {
+- /*
+- * Read the uevent packet
+- */
+- size = recv(netlink_socket, &buffer, sizeof(buffer), 0);
+- recv_errno = errno;
++ if ((n_backlog > 0) && (child_c < max_child_c)) {
++ /* dequeue backlog message */
++ tmpevent = backlog;
++ backlog = backlog->next;
++ n_backlog--;
++ if (backlog_tail == tmpevent)
++ backlog_tail = NULL;
++ } else {
++ /*
++ * Read the uevent packet
++ */
++ if (n_backlog >= HOTPLUG2_MSG_BACKLOG) {
++ usleep(HOTPLUG2_THROTTLE_INTERVAL * 1000);
++ continue;
++ }
++
++ if ((n_backlog > 0) && (child_c >= max_child_c)) {
++ int fds;
++ msg_poll.revents = 0;
++ fds = poll(&msg_poll, 1, HOTPLUG2_THROTTLE_INTERVAL);
++ if (fds < 0) {
++ perror("POLL FAILED");
++ continue;
++ }
++ if (fds == 0)
++ continue;
++ }
++ size = recv(netlink_socket, &buffer, sizeof(buffer), 0);
++ recv_errno = errno;
+
+- /*
+- * Parse the event into an event structure
+- */
+- tmpevent = get_hotplug2_event(buffer, size);
++ /*
++ * Parse the event into an event structure
++ */
++ tmpevent = get_hotplug2_event(buffer, size);
+
+- if (tmpevent == NULL) {
+- ERROR("reading events", "Malformed event read (missing action prefix).");
+- continue;
++ if (tmpevent == NULL) {
++ ERROR("reading events", "Malformed event read (missing action prefix).");
++ continue;
++ }
+ }
+
+ /*
+@@ -706,13 +739,16 @@
+ * Unless, of course, we've specified otherwise and no rules that match
+ * need throttling.
+ */
+- if (!flags & FLAG_NOTHROTTLE) {
+- /*
+- * Okay, throttle away!
+- */
+- while (child_c >= max_child_c) {
+- usleep(HOTPLUG2_THROTTLE_INTERVAL);
+- }
++ if (!(flags & FLAG_NOTHROTTLE) && (child_c >= max_child_c)) {
++ /* log the packet and process it later */
++ if (backlog_tail)
++ backlog_tail->next = tmpevent;
++ else
++ backlog = tmpevent;
++ tmpevent->next = NULL;
++ backlog_tail = tmpevent;
++ n_backlog++;
++ continue;
+ }
+
+ sigemptyset(&block_mask);
+--- a/hotplug2.h
++++ b/hotplug2.h
+@@ -45,9 +45,9 @@
+ #define DBG(action, fmt, arg...)
+ #endif
+
++#define HOTPLUG2_MSG_BACKLOG 64
+ #define UEVENT_BUFFER_SIZE 2048
+-#define HOTPLUG2_POLL_INTERVAL 20000
+-#define HOTPLUG2_THROTTLE_INTERVAL 10000
++#define HOTPLUG2_THROTTLE_INTERVAL 50
+ #define HOTPLUG2_RULE_PATH "/etc/hotplug2.rules"
+
+ #define ACTION_ADD 0
+@@ -76,6 +76,7 @@
+ int env_vars_c;
+ char *plain;
+ int plain_s;
++ struct hotplug2_event_t *next;
+ };
+
+ struct options_t {