diff options
author | Dan Duval <dan.duval@oracle.com> | 2013-09-16 11:11:12 -0400 |
---|---|---|
committer | Eric Paris <eparis@redhat.com> | 2014-01-13 22:28:08 -0500 |
commit | db897319401e1c111aef59deadd59ea08e11d879 (patch) | |
tree | 2bad7e546ecc69874e18a5846b01c4bc315dfaa3 /kernel | |
parent | ae887e0bdcddb9d7acd8f1eb7b7795b438aa4950 (diff) |
audit: efficiency fix 1: only wake up if queue shorter than backlog limit
These and similar errors were seen on a patched 3.8 kernel when the
audit subsystem was overrun during boot:
udevd[876]: worker [887] unexpectedly returned with status 0x0100
udevd[876]: worker [887] failed while handling
'/devices/pci0000:00/0000:00:03.0/0000:40:00.0'
udevd[876]: worker [880] unexpectedly returned with status 0x0100
udevd[876]: worker [880] failed while handling
'/devices/LNXSYSTM:00/LNXPWRBN:00/input/input1/event1'
udevadm settle - timeout of 180 seconds reached, the event queue
contains:
/sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input1/event1 (3995)
/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/INT3F0D:00 (4034)
audit: audit_backlog=258 > audit_backlog_limit=256
audit: audit_lost=1 audit_rate_limit=0 audit_backlog_limit=256
The change below increases the efficiency of the audit code and prevents it
from being overrun:
Only issue a wake_up in kauditd if the length of the skb queue is less than the
backlog limit. Otherwise, threads waiting in wait_for_auditd() will simply
wake up, discover that the queue is still too long for them to proceed, and go
back to sleep. This results in wasted context switches and machine cycles.
kauditd_thread() is the only function that removes buffers from audit_skb_queue
so we can't race. If we did, the timeout in wait_for_auditd() would expire and
the waiting thread would continue.
See: https://lkml.org/lkml/2013/9/2/479
Signed-off-by: Dan Duval <dan.duval@oracle.com>
Signed-off-by: Chuck Anderson <chuck.anderson@oracle.com>
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/audit.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index 09e287b1dc0e..854f4829e654 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -462,8 +462,10 @@ static int kauditd_thread(void *dummy) | |||
462 | flush_hold_queue(); | 462 | flush_hold_queue(); |
463 | 463 | ||
464 | skb = skb_dequeue(&audit_skb_queue); | 464 | skb = skb_dequeue(&audit_skb_queue); |
465 | wake_up(&audit_backlog_wait); | 465 | |
466 | if (skb) { | 466 | if (skb) { |
467 | if (skb_queue_len(&audit_skb_queue) <= audit_backlog_limit) | ||
468 | wake_up(&audit_backlog_wait); | ||
467 | if (audit_pid) | 469 | if (audit_pid) |
468 | kauditd_send_skb(skb); | 470 | kauditd_send_skb(skb); |
469 | else | 471 | else |