|
@@ -592,6 +592,37 @@ static int raid1_congested(void *data, int bits)
|
|
|
}
|
|
|
|
|
|
|
|
|
+static int flush_pending_writes(conf_t *conf)
|
|
|
+{
|
|
|
+ /* Any writes that have been queued but are awaiting
|
|
|
+ * bitmap updates get flushed here.
|
|
|
+ * We return 1 if any requests were actually submitted.
|
|
|
+ */
|
|
|
+ int rv = 0;
|
|
|
+
|
|
|
+ spin_lock_irq(&conf->device_lock);
|
|
|
+
|
|
|
+ if (conf->pending_bio_list.head) {
|
|
|
+ struct bio *bio;
|
|
|
+ bio = bio_list_get(&conf->pending_bio_list);
|
|
|
+ blk_remove_plug(conf->mddev->queue);
|
|
|
+ spin_unlock_irq(&conf->device_lock);
|
|
|
+ /* flush any pending bitmap writes to
|
|
|
+ * disk before proceeding w/ I/O */
|
|
|
+ bitmap_unplug(conf->mddev->bitmap);
|
|
|
+
|
|
|
+ while (bio) { /* submit pending writes */
|
|
|
+ struct bio *next = bio->bi_next;
|
|
|
+ bio->bi_next = NULL;
|
|
|
+ generic_make_request(bio);
|
|
|
+ bio = next;
|
|
|
+ }
|
|
|
+ rv = 1;
|
|
|
+ } else
|
|
|
+ spin_unlock_irq(&conf->device_lock);
|
|
|
+ return rv;
|
|
|
+}
|
|
|
+
|
|
|
/* Barriers....
|
|
|
* Sometimes we need to suspend IO while we do something else,
|
|
|
* either some resync/recovery, or reconfigure the array.
|
|
@@ -681,7 +712,8 @@ static void freeze_array(conf_t *conf)
|
|
|
wait_event_lock_irq(conf->wait_barrier,
|
|
|
conf->barrier+conf->nr_pending == conf->nr_queued+2,
|
|
|
conf->resync_lock,
|
|
|
- raid1_unplug(conf->mddev->queue));
|
|
|
+ ({ flush_pending_writes(conf);
|
|
|
+ raid1_unplug(conf->mddev->queue); }));
|
|
|
spin_unlock_irq(&conf->resync_lock);
|
|
|
}
|
|
|
static void unfreeze_array(conf_t *conf)
|
|
@@ -907,6 +939,9 @@ static int make_request(struct request_queue *q, struct bio * bio)
|
|
|
blk_plug_device(mddev->queue);
|
|
|
spin_unlock_irqrestore(&conf->device_lock, flags);
|
|
|
|
|
|
+ /* In case raid1d snuck into freeze_array */
|
|
|
+ wake_up(&conf->wait_barrier);
|
|
|
+
|
|
|
if (do_sync)
|
|
|
md_wakeup_thread(mddev->thread);
|
|
|
#if 0
|
|
@@ -1473,28 +1508,14 @@ static void raid1d(mddev_t *mddev)
|
|
|
|
|
|
for (;;) {
|
|
|
char b[BDEVNAME_SIZE];
|
|
|
- spin_lock_irqsave(&conf->device_lock, flags);
|
|
|
-
|
|
|
- if (conf->pending_bio_list.head) {
|
|
|
- bio = bio_list_get(&conf->pending_bio_list);
|
|
|
- blk_remove_plug(mddev->queue);
|
|
|
- spin_unlock_irqrestore(&conf->device_lock, flags);
|
|
|
- /* flush any pending bitmap writes to disk before proceeding w/ I/O */
|
|
|
- bitmap_unplug(mddev->bitmap);
|
|
|
|
|
|
- while (bio) { /* submit pending writes */
|
|
|
- struct bio *next = bio->bi_next;
|
|
|
- bio->bi_next = NULL;
|
|
|
- generic_make_request(bio);
|
|
|
- bio = next;
|
|
|
- }
|
|
|
- unplug = 1;
|
|
|
+ unplug += flush_pending_writes(conf);
|
|
|
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- if (list_empty(head))
|
|
|
+ spin_lock_irqsave(&conf->device_lock, flags);
|
|
|
+ if (list_empty(head)) {
|
|
|
+ spin_unlock_irqrestore(&conf->device_lock, flags);
|
|
|
break;
|
|
|
+ }
|
|
|
r1_bio = list_entry(head->prev, r1bio_t, retry_list);
|
|
|
list_del(head->prev);
|
|
|
conf->nr_queued--;
|
|
@@ -1590,7 +1611,6 @@ static void raid1d(mddev_t *mddev)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- spin_unlock_irqrestore(&conf->device_lock, flags);
|
|
|
if (unplug)
|
|
|
unplug_slaves(mddev);
|
|
|
}
|