|
@@ -870,6 +870,44 @@ do_sync_io:
|
|
|
pr_debug("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
|
|
|
}
|
|
|
|
|
|
+struct raid1_plug_cb {
|
|
|
+ struct blk_plug_cb cb;
|
|
|
+ struct bio_list pending;
|
|
|
+ int pending_cnt;
|
|
|
+};
|
|
|
+
|
|
|
+static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule)
|
|
|
+{
|
|
|
+ struct raid1_plug_cb *plug = container_of(cb, struct raid1_plug_cb,
|
|
|
+ cb);
|
|
|
+ struct mddev *mddev = plug->cb.data;
|
|
|
+ struct r1conf *conf = mddev->private;
|
|
|
+ struct bio *bio;
|
|
|
+
|
|
|
+ if (from_schedule) {
|
|
|
+ spin_lock_irq(&conf->device_lock);
|
|
|
+ bio_list_merge(&conf->pending_bio_list, &plug->pending);
|
|
|
+ conf->pending_count += plug->pending_cnt;
|
|
|
+ spin_unlock_irq(&conf->device_lock);
|
|
|
+ md_wakeup_thread(mddev->thread);
|
|
|
+ kfree(plug);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* we aren't scheduling, so we can do the write-out directly. */
|
|
|
+ bio = bio_list_get(&plug->pending);
|
|
|
+ bitmap_unplug(mddev->bitmap);
|
|
|
+ wake_up(&conf->wait_barrier);
|
|
|
+
|
|
|
+ while (bio) { /* submit pending writes */
|
|
|
+ struct bio *next = bio->bi_next;
|
|
|
+ bio->bi_next = NULL;
|
|
|
+ generic_make_request(bio);
|
|
|
+ bio = next;
|
|
|
+ }
|
|
|
+ kfree(plug);
|
|
|
+}
|
|
|
+
|
|
|
static void make_request(struct mddev *mddev, struct bio * bio)
|
|
|
{
|
|
|
struct r1conf *conf = mddev->private;
|
|
@@ -883,6 +921,8 @@ static void make_request(struct mddev *mddev, struct bio * bio)
|
|
|
const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
|
|
|
const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA));
|
|
|
struct md_rdev *blocked_rdev;
|
|
|
+ struct blk_plug_cb *cb;
|
|
|
+ struct raid1_plug_cb *plug = NULL;
|
|
|
int first_clone;
|
|
|
int sectors_handled;
|
|
|
int max_sectors;
|
|
@@ -1185,11 +1225,22 @@ read_again:
|
|
|
mbio->bi_private = r1_bio;
|
|
|
|
|
|
atomic_inc(&r1_bio->remaining);
|
|
|
+
|
|
|
+ cb = blk_check_plugged(raid1_unplug, mddev, sizeof(*plug));
|
|
|
+ if (cb)
|
|
|
+ plug = container_of(cb, struct raid1_plug_cb, cb);
|
|
|
+ else
|
|
|
+ plug = NULL;
|
|
|
spin_lock_irqsave(&conf->device_lock, flags);
|
|
|
- bio_list_add(&conf->pending_bio_list, mbio);
|
|
|
- conf->pending_count++;
|
|
|
+ if (plug) {
|
|
|
+ bio_list_add(&plug->pending, mbio);
|
|
|
+ plug->pending_cnt++;
|
|
|
+ } else {
|
|
|
+ bio_list_add(&conf->pending_bio_list, mbio);
|
|
|
+ conf->pending_count++;
|
|
|
+ }
|
|
|
spin_unlock_irqrestore(&conf->device_lock, flags);
|
|
|
- if (!mddev_check_plugged(mddev))
|
|
|
+ if (!plug)
|
|
|
md_wakeup_thread(mddev->thread);
|
|
|
}
|
|
|
/* Mustn't call r1_bio_write_done before this next test,
|