When multiple locks are acquired, they should be released in reverse order. For s_start() and s_stop() in mm/vmalloc.c, that is not the case. s_start: mutex_lock(&vmap_purge_lock); spin_lock(&vmap_area_lock); s_stop : mutex_unlock(&vmap_purge_lock); spin_unlock(&vmap_area_lock); This unlock sequence, though allowed, is not optimal. If a waiter is present, mutex_unlock() will need to go through the slowpath of waking up the waiter with preemption disabled. Fix that by releasing the spinlock first before the mutex.
Unified · Split
| @@ -3465,11 +3465,11 @@ static void *s_next(struct seq_file *m, void *p, loff_t *pos) · 3464 unmodified lines | ||
| 3465 | 3465 | } |
| 3466 | 3466 | |
| 3467 | 3467 | static void s_stop(struct seq_file *m, void *p) |
| 3468 | − __releases(&vmap_purge_lock) | |
| 3469 | 3468 | __releases(&vmap_area_lock) |
| 3469 | + __releases(&vmap_purge_lock) | |
| 3470 | 3470 | { |
| 3471 | − mutex_unlock(&vmap_purge_lock); | |
| 3472 | 3471 | spin_unlock(&vmap_area_lock); |
| 3472 | + mutex_unlock(&vmap_purge_lock); | |
| 3473 | 3473 | } |
| 3474 | 3474 | |
| 3475 | 3475 | static void show_numa_info(struct seq_file *m, struct vm_struct *v) |