aboutsummaryrefslogtreecommitdiff
path: root/drivers/block
diff options
context:
space:
mode:
authorLars Ellenberg2012-03-26 16:55:46 +0200
committerPhilipp Reisner2012-11-08 16:58:23 +0100
commit8d6cdd784818fd8812f185cd6768d09e43e6f71f (patch)
tree5d62eb6ffd24930829c573724add0cf358b1ceea /drivers/block
parent0afd569a40323b8b50bcf553cf9c0fbca9c9e229 (diff)
drbd: conflicting writes: make wake_up of waiting peer_requests explicit
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/drbd/drbd_req.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 938a57bf73c1..c0326f54d3ab 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -212,6 +212,16 @@ static void drbd_remove_request_interval(struct rb_root *root,
wake_up(&mdev->misc_wait);
}
+static void maybe_wakeup_conflicting_requests(struct drbd_request *req)
+{
+ const unsigned long s = req->rq_state;
+ if (s & RQ_LOCAL_PENDING && !(s & RQ_LOCAL_ABORTED))
+ return;
+ if (req->i.waiting)
+ /* Retry all conflicting peer requests. */
+ wake_up(&req->w.mdev->misc_wait);
+}
+
/* Helper for __req_mod().
* Set m->bio to the master bio, if it is fit to be completed,
* or leave it alone (it is initialized to NULL in __req_mod),
@@ -235,10 +245,6 @@ void _req_may_be_done(struct drbd_request *req, struct bio_and_error *m)
*/
if (s & RQ_LOCAL_PENDING && !(s & RQ_LOCAL_ABORTED))
return;
- if (req->i.waiting) {
- /* Retry all conflicting peer requests. */
- wake_up(&mdev->misc_wait);
- }
if (s & RQ_NET_QUEUED)
return;
if (s & RQ_NET_PENDING)
@@ -388,6 +394,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
req->rq_state |= (RQ_LOCAL_COMPLETED|RQ_LOCAL_OK);
req->rq_state &= ~RQ_LOCAL_PENDING;
+ maybe_wakeup_conflicting_requests(req);
_req_may_be_done_not_susp(req, m);
put_ldev(mdev);
break;
@@ -405,6 +412,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
req->rq_state &= ~RQ_LOCAL_PENDING;
__drbd_chk_io_error(mdev, false);
+ maybe_wakeup_conflicting_requests(req);
_req_may_be_done_not_susp(req, m);
put_ldev(mdev);
break;
@@ -615,6 +623,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
dec_ap_pending(mdev);
atomic_sub(req->i.size >> 9, &mdev->ap_in_flight);
req->rq_state &= ~RQ_NET_PENDING;
+ maybe_wakeup_conflicting_requests(req);
_req_may_be_done_not_susp(req, m);
break;
@@ -626,6 +635,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
*/
D_ASSERT(req->rq_state & RQ_NET_PENDING);
req->rq_state |= RQ_POSTPONED;
+ maybe_wakeup_conflicting_requests(req);
_req_may_be_done_not_susp(req, m);
break;
@@ -643,6 +653,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
if (!(req->rq_state & RQ_WRITE))
goto goto_read_retry_local;
+ maybe_wakeup_conflicting_requests(req);
_req_may_be_done_not_susp(req, m);
/* else: done by HANDED_OVER_TO_NETWORK */
break;