diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2010-06-22 05:26:48 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2010-10-14 08:36:51 -0400 |
commit | b9b98716f83856b928f1c985ab55520c67663dd2 (patch) | |
tree | d935bc8efc8a7ecc6a05225ff941a16ee1d8bfcf | |
parent | 11b58e73a3a3d1bbb582370d59f9b2c4d0136b42 (diff) |
drbd: Do not send two barriers without any writes between them
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index a8a0341fce53..7d359863ae32 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -344,7 +344,7 @@ bail: | |||
344 | static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what) | 344 | static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what) |
345 | { | 345 | { |
346 | struct drbd_tl_epoch *b, *tmp, **pn; | 346 | struct drbd_tl_epoch *b, *tmp, **pn; |
347 | struct list_head *le, *tle; | 347 | struct list_head *le, *tle, carry_reads; |
348 | struct drbd_request *req; | 348 | struct drbd_request *req; |
349 | int rv, n_writes, n_reads; | 349 | int rv, n_writes, n_reads; |
350 | 350 | ||
@@ -353,6 +353,7 @@ static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what) | |||
353 | while (b) { | 353 | while (b) { |
354 | n_writes = 0; | 354 | n_writes = 0; |
355 | n_reads = 0; | 355 | n_reads = 0; |
356 | INIT_LIST_HEAD(&carry_reads); | ||
356 | list_for_each_safe(le, tle, &b->requests) { | 357 | list_for_each_safe(le, tle, &b->requests) { |
357 | req = list_entry(le, struct drbd_request, tl_requests); | 358 | req = list_entry(le, struct drbd_request, tl_requests); |
358 | rv = _req_mod(req, what); | 359 | rv = _req_mod(req, what); |
@@ -362,7 +363,7 @@ static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what) | |||
362 | } | 363 | } |
363 | tmp = b->next; | 364 | tmp = b->next; |
364 | 365 | ||
365 | if (n_writes + n_reads) { | 366 | if (n_writes) { |
366 | if (what == resend) { | 367 | if (what == resend) { |
367 | b->n_writes = n_writes; | 368 | b->n_writes = n_writes; |
368 | if (b->w.cb == NULL) { | 369 | if (b->w.cb == NULL) { |
@@ -375,6 +376,8 @@ static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what) | |||
375 | } | 376 | } |
376 | pn = &b->next; | 377 | pn = &b->next; |
377 | } else { | 378 | } else { |
379 | if (n_reads) | ||
380 | list_add(&carry_reads, &b->requests); | ||
378 | /* there could still be requests on that ring list, | 381 | /* there could still be requests on that ring list, |
379 | * in case local io is still pending */ | 382 | * in case local io is still pending */ |
380 | list_del(&b->requests); | 383 | list_del(&b->requests); |
@@ -389,6 +392,7 @@ static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what) | |||
389 | /* recycle, but reinit! */ | 392 | /* recycle, but reinit! */ |
390 | D_ASSERT(tmp == NULL); | 393 | D_ASSERT(tmp == NULL); |
391 | INIT_LIST_HEAD(&b->requests); | 394 | INIT_LIST_HEAD(&b->requests); |
395 | list_splice(&carry_reads, &b->requests); | ||
392 | INIT_LIST_HEAD(&b->w.list); | 396 | INIT_LIST_HEAD(&b->w.list); |
393 | b->w.cb = NULL; | 397 | b->w.cb = NULL; |
394 | b->br_number = net_random(); | 398 | b->br_number = net_random(); |
@@ -401,6 +405,7 @@ static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what) | |||
401 | kfree(b); | 405 | kfree(b); |
402 | } | 406 | } |
403 | b = tmp; | 407 | b = tmp; |
408 | list_splice(&carry_reads, &b->requests); | ||
404 | } | 409 | } |
405 | } | 410 | } |
406 | 411 | ||