fix hotplug2 event processing deadlock
when bringing up ethernet on ixp4xx, the driver may request a firmware while hotplug2 waits for the netdev bringup to complete. change the event processing loop to keep an event backlog to allow unthrottled events to pass through while throttled events are being waited for SVN-Revision: 12019
This commit is contained in:
parent
79aebec9e0
commit
c5ecc1790a
1 changed files with 135 additions and 0 deletions
135
package/hotplug2/patches/120-throttling.patch
Normal file
135
package/hotplug2/patches/120-throttling.patch
Normal file
|
@ -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 {
|
Loading…
Reference in a new issue