summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/raid10.c21
-rw-r--r--drivers/md/raid10.h3
2 files changed, 14 insertions, 10 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index f7f3c8a63419..cb1d88709ff0 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -905,7 +905,7 @@ static void raise_barrier(struct r10conf *conf, int force)
/* Now wait for all pending IO to complete */
wait_event_lock_irq(conf->wait_barrier,
- !conf->nr_pending && conf->barrier < RESYNC_DEPTH,
+ !atomic_read(&conf->nr_pending) && conf->barrier < RESYNC_DEPTH,
conf->resync_lock);
spin_unlock_irq(&conf->resync_lock);
@@ -936,23 +936,23 @@ static void wait_barrier(struct r10conf *conf)
*/
wait_event_lock_irq(conf->wait_barrier,
!conf->barrier ||
- (conf->nr_pending &&
+ (atomic_read(&conf->nr_pending) &&
current->bio_list &&
!bio_list_empty(current->bio_list)),
conf->resync_lock);
conf->nr_waiting--;
+ if (!conf->nr_waiting)
+ wake_up(&conf->wait_barrier);
}
- conf->nr_pending++;
+ atomic_inc(&conf->nr_pending);
spin_unlock_irq(&conf->resync_lock);
}
static void allow_barrier(struct r10conf *conf)
{
- unsigned long flags;
- spin_lock_irqsave(&conf->resync_lock, flags);
- conf->nr_pending--;
- spin_unlock_irqrestore(&conf->resync_lock, flags);
- wake_up(&conf->wait_barrier);
+ if ((atomic_dec_and_test(&conf->nr_pending)) ||
+ (conf->array_freeze_pending))
+ wake_up(&conf->wait_barrier);
}
static void freeze_array(struct r10conf *conf, int extra)
@@ -970,13 +970,15 @@ static void freeze_array(struct r10conf *conf, int extra)
* we continue.
*/
spin_lock_irq(&conf->resync_lock);
+ conf->array_freeze_pending++;
conf->barrier++;
conf->nr_waiting++;
wait_event_lock_irq_cmd(conf->wait_barrier,
- conf->nr_pending == conf->nr_queued+extra,
+ atomic_read(&conf->nr_pending) == conf->nr_queued+extra,
conf->resync_lock,
flush_pending_writes(conf));
+ conf->array_freeze_pending--;
spin_unlock_irq(&conf->resync_lock);
}
@@ -3542,6 +3544,7 @@ static struct r10conf *setup_conf(struct mddev *mddev)
spin_lock_init(&conf->resync_lock);
init_waitqueue_head(&conf->wait_barrier);
+ atomic_set(&conf->nr_pending, 0);
conf->thread = md_register_thread(raid10d, mddev, "raid10");
if (!conf->thread)
diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h
index 6fc2c75759bf..18ec1f7a98bf 100644
--- a/drivers/md/raid10.h
+++ b/drivers/md/raid10.h
@@ -64,10 +64,11 @@ struct r10conf {
int pending_count;
spinlock_t resync_lock;
- int nr_pending;
+ atomic_t nr_pending;
int nr_waiting;
int nr_queued;
int barrier;
+ int array_freeze_pending;
sector_t next_resync;
int fullsync; /* set to 1 if a full sync is needed,
* (fresh device added).