[OpenAFS-devel] Very simple patch for libafs CPU hog on signal
Nickolai Zeldovich
kolya@MIT.EDU
Mon, 28 Jan 2002 18:59:15 -0500
> I finally got a chance to look closer at the code to figure out why signals
> cause tight looping in the libafs-libafs-2.4.x. kernel module.
Coincidentally, I was just looking at the same problem today as well..
> The desired behavior would be to flush the pending signals (if any) before
> the call to the Linux interruptible_sleep_on(). This will eliminate the
> tight looping.
I'm not convinced this is the right solution, though. This means that
any signals sent to the process while it's waiting in AFS (e.g. in Rx
code, waiting for the server to respond) will be lost. I think having
the signal delivered when the AFS syscall completes would be a better
solution.
A simple fix that addresses the concern above is to replace the
interruptible_sleep_on() call with just sleep_on(). Unfortunately,
this has the side effect of artificially increasing the system load
to ~4 when AFS is idle, because the background daemons block waiting
for requests.
Something like the patch below would address both of these concerns,
and appears to work on my 2.4.17 test machine.
> Still, signals are not handled the way I'd like them to be, but at least with
> this fix, processes interrupted in certain libafs syscalls do not completely
> hog the CPU.
Did you have concerns about signal handling beyond the loss of signals
while in AFS wait?
-- kolya
--- src/afs/LINUX/osi_sleep.c 2002/01/24 20:13:22 1.10
+++ src/afs/LINUX/osi_sleep.c 2002/01/28 23:55:55
@@ -223,9 +223,22 @@
seq = evp->seq;
while (seq == evp->seq) {
+ sigset_t saved_set;
+
AFS_ASSERT_GLOCK();
AFS_GUNLOCK();
+ spin_lock_irq(¤t->sigmask_lock);
+ saved_set = current->blocked;
+ sigfillset(¤t->blocked);
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
+
interruptible_sleep_on(&evp->cond);
+
+ spin_lock_irq(¤t->sigmask_lock);
+ current->blocked = saved_set;
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
AFS_GLOCK();
}
relevent(evp);