[PATCH] lockdep: fix delayacct locking bug

Make the delayacct lock irqsave; this avoids the possible deadlock where
an interrupt is taken while holding the delayacct lock which needs to
take the delayacct lock.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Acked-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Balbir Singh <balbir@in.ibm.com>
Cc: Shailabh Nagar <nagar@watson.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by Peter Zijlstra and committed by Linus Torvalds 64efade1 e5b9a335

+9 -6
+9 -6
kernel/delayacct.c
··· 66 66 { 67 67 struct timespec ts; 68 68 s64 ns; 69 + unsigned long flags; 69 70 70 71 do_posix_clock_monotonic_gettime(end); 71 72 ts = timespec_sub(*end, *start); ··· 74 73 if (ns < 0) 75 74 return; 76 75 77 - spin_lock(&current->delays->lock); 76 + spin_lock_irqsave(&current->delays->lock, flags); 78 77 *total += ns; 79 78 (*count)++; 80 - spin_unlock(&current->delays->lock); 79 + spin_unlock_irqrestore(&current->delays->lock, flags); 81 80 } 82 81 83 82 void __delayacct_blkio_start(void) ··· 105 104 s64 tmp; 106 105 struct timespec ts; 107 106 unsigned long t1,t2,t3; 107 + unsigned long flags; 108 108 109 109 /* Though tsk->delays accessed later, early exit avoids 110 110 * unnecessary returning of other data ··· 138 136 139 137 /* zero XXX_total, non-zero XXX_count implies XXX stat overflowed */ 140 138 141 - spin_lock(&tsk->delays->lock); 139 + spin_lock_irqsave(&tsk->delays->lock, flags); 142 140 tmp = d->blkio_delay_total + tsk->delays->blkio_delay; 143 141 d->blkio_delay_total = (tmp < d->blkio_delay_total) ? 0 : tmp; 144 142 tmp = d->swapin_delay_total + tsk->delays->swapin_delay; 145 143 d->swapin_delay_total = (tmp < d->swapin_delay_total) ? 0 : tmp; 146 144 d->blkio_count += tsk->delays->blkio_count; 147 145 d->swapin_count += tsk->delays->swapin_count; 148 - spin_unlock(&tsk->delays->lock); 146 + spin_unlock_irqrestore(&tsk->delays->lock, flags); 149 147 150 148 done: 151 149 return 0; ··· 154 152 __u64 __delayacct_blkio_ticks(struct task_struct *tsk) 155 153 { 156 154 __u64 ret; 155 + unsigned long flags; 157 156 158 - spin_lock(&tsk->delays->lock); 157 + spin_lock_irqsave(&tsk->delays->lock, flags); 159 158 ret = nsec_to_clock_t(tsk->delays->blkio_delay + 160 159 tsk->delays->swapin_delay); 161 - spin_unlock(&tsk->delays->lock); 160 + spin_unlock_irqrestore(&tsk->delays->lock, flags); 162 161 return ret; 163 162 } 164 163