|
@@ -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;
|