md: raid5: Make raid5_percpu handling RT aware
authorThomas Gleixner <tglx@linutronix.de>
Tue, 6 Apr 2010 14:51:31 +0000 (16:51 +0200)
committerClark Williams <williams@redhat.com>
Wed, 15 Feb 2012 16:32:53 +0000 (10:32 -0600)
__raid_run_ops() disables preemption with get_cpu() around the access
to the raid5_percpu variables. That causes scheduling while atomic
spews on RT.

Serialize the access to the percpu data with a lock and keep the code
preemptible.

Reported-by: Udo van den Heuvel <udovdh@xs4all.nl>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Udo van den Heuvel <udovdh@xs4all.nl>
drivers/md/raid5.c
drivers/md/raid5.h

index 858fdbb7eb07a24ceb18a4d6214218c9205089e7..c2401e86b271b0440f5bb8db0c287ecbe24fe0af 100644 (file)
@@ -1245,8 +1245,9 @@ static void __raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
        struct raid5_percpu *percpu;
        unsigned long cpu;
 
-       cpu = get_cpu();
+       cpu = get_cpu_light();
        percpu = per_cpu_ptr(conf->percpu, cpu);
+       spin_lock(&percpu->lock);
        if (test_bit(STRIPE_OP_BIOFILL, &ops_request)) {
                ops_run_biofill(sh);
                overlap_clear++;
@@ -1298,7 +1299,8 @@ static void __raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
                        if (test_and_clear_bit(R5_Overlap, &dev->flags))
                                wake_up(&sh->raid_conf->wait_for_overlap);
                }
-       put_cpu();
+       spin_unlock(&percpu->lock);
+       put_cpu_light();
 }
 
 #ifdef CONFIG_MULTICORE_RAID456
@@ -4539,6 +4541,7 @@ static int raid5_alloc_percpu(struct r5conf *conf)
                        break;
                }
                per_cpu_ptr(conf->percpu, cpu)->scribble = scribble;
+               spin_lock_init(&per_cpu_ptr(conf->percpu, cpu)->lock);
        }
 #ifdef CONFIG_HOTPLUG_CPU
        conf->cpu_notify.notifier_call = raid456_cpu_notify;
index e10c5531f9c55c11804ea8168a76c1806add4646..010a96916bc20f4d126838a02d0eb3580b311384 100644 (file)
@@ -405,6 +405,7 @@ struct r5conf {
        int                     recovery_disabled;
        /* per cpu variables */
        struct raid5_percpu {
+               spinlock_t      lock;        /* Protection for -RT */
                struct page     *spare_page; /* Used when checking P/Q in raid6 */
                void            *scribble;   /* space for constructing buffer
                                              * lists and performing address