]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/block/drbd/drbd_req.c
drbd: fix regression: protocol A sometimes synchronous, C sometimes double-latency
[karo-tx-linux.git] / drivers / block / drbd / drbd_req.c
index eef6e9575b4e17c5d2b54e810206b416511a4d46..74903ab85ae9a8d27d236e7377ec2a51acb732c6 100644 (file)
@@ -977,16 +977,20 @@ static void complete_conflicting_writes(struct drbd_request *req)
        sector_t sector = req->i.sector;
        int size = req->i.size;
 
-       i = drbd_find_overlap(&device->write_requests, sector, size);
-       if (!i)
-               return;
-
        for (;;) {
-               prepare_to_wait(&device->misc_wait, &wait, TASK_UNINTERRUPTIBLE);
-               i = drbd_find_overlap(&device->write_requests, sector, size);
-               if (!i)
+               drbd_for_each_overlap(i, &device->write_requests, sector, size) {
+                       /* Ignore, if already completed to upper layers. */
+                       if (i->completed)
+                               continue;
+                       /* Handle the first found overlap.  After the schedule
+                        * we have to restart the tree walk. */
                        break;
+               }
+               if (!i) /* if any */
+                       break;
+
                /* Indicate to wake up device->misc_wait on progress.  */
+               prepare_to_wait(&device->misc_wait, &wait, TASK_UNINTERRUPTIBLE);
                i->waiting = true;
                spin_unlock_irq(&device->resource->req_lock);
                schedule();