diff options
author | Lars Ellenberg | 2012-03-26 16:55:46 +0200 |
---|---|---|
committer | Philipp Reisner | 2012-11-08 16:58:23 +0100 |
commit | 8d6cdd784818fd8812f185cd6768d09e43e6f71f (patch) | |
tree | 5d62eb6ffd24930829c573724add0cf358b1ceea /drivers/block | |
parent | 0afd569a40323b8b50bcf553cf9c0fbca9c9e229 (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.c | 19 |
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; |