drbd: fix potential imbalance of ap_in_flight
When we receive a barrier ack, we walk the ring list of drbd requests in the transfer log of the respective epoch, do some housekeeping, and free those objects. We tried to keep epochs of mirrored and unmirrored drbd requests separate, and assert that no local-only requests are present in a barrier_acked epoch. It turns out that this has quite a number of corner cases and would add bloated code without functional benefit. We now revert the (insufficient) commits drbd: Fixed an issue with AHEAD -> SYNC_SOURCE transitions drbd: Ensure that an epoch contains only requests of one kind and instead fix the processing of barrier acks to cope with a mix of local-only and mirrored requests. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
This commit is contained in:
parent
0ddc5549f8
commit
e636db5b95
|
@ -337,23 +337,6 @@ bail:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* In C_AHEAD mode only out_of_sync packets are sent for requests. Detach
|
|
||||||
* those requests from the newsest barrier when changing to an other cstate.
|
|
||||||
*
|
|
||||||
* That headless list vanishes when the last request finished its write or
|
|
||||||
* send out_of_sync packet. */
|
|
||||||
static void tl_forget(struct drbd_conf *mdev)
|
|
||||||
{
|
|
||||||
struct drbd_tl_epoch *b;
|
|
||||||
|
|
||||||
if (test_bit(CREATE_BARRIER, &mdev->flags))
|
|
||||||
return;
|
|
||||||
|
|
||||||
b = mdev->newest_tle;
|
|
||||||
list_del(&b->requests);
|
|
||||||
_tl_add_barrier(mdev, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _tl_restart() - Walks the transfer log, and applies an action to all requests
|
* _tl_restart() - Walks the transfer log, and applies an action to all requests
|
||||||
* @mdev: DRBD device.
|
* @mdev: DRBD device.
|
||||||
|
@ -1265,14 +1248,6 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
|
||||||
if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED)
|
if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED)
|
||||||
drbd_resume_al(mdev);
|
drbd_resume_al(mdev);
|
||||||
|
|
||||||
/* Start a new epoch in case we start to mirror write requests */
|
|
||||||
if (!drbd_should_do_remote(os) && drbd_should_do_remote(ns))
|
|
||||||
tl_forget(mdev);
|
|
||||||
|
|
||||||
/* Do not add local-only requests to an epoch with mirrored requests */
|
|
||||||
if (drbd_should_do_remote(os) && !drbd_should_do_remote(ns))
|
|
||||||
set_bit(CREATE_BARRIER, &mdev->flags);
|
|
||||||
|
|
||||||
ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC);
|
ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC);
|
||||||
if (ascw) {
|
if (ascw) {
|
||||||
ascw->os = os;
|
ascw->os = os;
|
||||||
|
|
|
@ -712,10 +712,11 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
|
||||||
dev_err(DEV, "FIXME (barrier_acked but pending)\n");
|
dev_err(DEV, "FIXME (barrier_acked but pending)\n");
|
||||||
list_move(&req->tl_requests, &mdev->out_of_sequence_requests);
|
list_move(&req->tl_requests, &mdev->out_of_sequence_requests);
|
||||||
}
|
}
|
||||||
D_ASSERT(req->rq_state & RQ_NET_SENT);
|
if ((req->rq_state & RQ_NET_MASK) != 0) {
|
||||||
req->rq_state |= RQ_NET_DONE;
|
req->rq_state |= RQ_NET_DONE;
|
||||||
if (mdev->net_conf->wire_protocol == DRBD_PROT_A)
|
if (mdev->net_conf->wire_protocol == DRBD_PROT_A)
|
||||||
atomic_sub(req->size>>9, &mdev->ap_in_flight);
|
atomic_sub(req->size>>9, &mdev->ap_in_flight);
|
||||||
|
}
|
||||||
_req_may_be_done(req, m); /* Allowed while state.susp */
|
_req_may_be_done(req, m); /* Allowed while state.susp */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue