Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 617049aa authored by Philipp Reisner's avatar Philipp Reisner
Browse files

drbd: Fixed an issue with AHEAD -> SYNC_SOURCE transitions



Create a new barrier when leaving the AHEAD mode.

  Otherwise we trigger the assertion in req_mod(, barrier_acked)
  D_ASSERT(req->rq_state & RQ_NET_SENT);

The new barrier is created by recycling the newest existing one.

Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
parent 07194272
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -335,6 +335,24 @@ void tl_release(struct drbd_conf *mdev, unsigned int barrier_nr,
	drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
}


/* 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
 * @mdev:	DRBD device.
@@ -1242,6 +1260,9 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
	if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED)
		drbd_resume_al(mdev);

	if (os.conn == C_AHEAD && ns.conn != C_AHEAD)
		tl_forget(mdev);

	ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC);
	if (ascw) {
		ascw->os = os;