Skip to content

Commit 1b228c9

Browse files
lgeaxboe
authored andcommitted
drbd: fix regression: protocol A sometimes synchronous, C sometimes double-latency
Regression introduced with 8.4.5 drbd: application writes may set-in-sync in protocol != C Overwriting the same block (LBA) while a former version is still "in-flight" to the peer (to be exact: we did not receive the P_BARRIER_ACK for its epoch yet) would wait for the full epoch of that former version to be acknowledged by the peer. In synchronous and quasi-synchronous protocols C and B, this may double the latency on overwrites. With protocol A, which is supposed to be asynchronous and only wait for local completion, it is even worse: it would make overwrites quasi-synchronous, they would be hit by the full RTT, which protocol A was specifically meant to avoid, and possibly the additional time it takes to drain the buffers first. Particularly bad for databases, or anything else that does frequent updates to the same blocks (various file system meta data). No impact if >= rtt passes between updates to the same block. Signed-off-by: Philipp Reisner <[email protected]> Signed-off-by: Lars Ellenberg <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent bca1cba commit 1b228c9

File tree

1 file changed

+11
-7
lines changed

1 file changed

+11
-7
lines changed

drivers/block/drbd/drbd_req.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -977,16 +977,20 @@ static void complete_conflicting_writes(struct drbd_request *req)
977977
sector_t sector = req->i.sector;
978978
int size = req->i.size;
979979

980-
i = drbd_find_overlap(&device->write_requests, sector, size);
981-
if (!i)
982-
return;
983-
984980
for (;;) {
985-
prepare_to_wait(&device->misc_wait, &wait, TASK_UNINTERRUPTIBLE);
986-
i = drbd_find_overlap(&device->write_requests, sector, size);
987-
if (!i)
981+
drbd_for_each_overlap(i, &device->write_requests, sector, size) {
982+
/* Ignore, if already completed to upper layers. */
983+
if (i->completed)
984+
continue;
985+
/* Handle the first found overlap. After the schedule
986+
* we have to restart the tree walk. */
988987
break;
988+
}
989+
if (!i) /* if any */
990+
break;
991+
989992
/* Indicate to wake up device->misc_wait on progress. */
993+
prepare_to_wait(&device->misc_wait, &wait, TASK_UNINTERRUPTIBLE);
990994
i->waiting = true;
991995
spin_unlock_irq(&device->resource->req_lock);
992996
schedule();

0 commit comments

Comments
 (0)