diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2010-12-22 06:48:31 -0500 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2011-03-10 05:45:23 -0500 |
commit | 617049aa7d753e8c821ac77126ab90e9f1b66d6d (patch) | |
tree | 1cabbc19e2efa054bf585d92f42c0bf7bf0c01b5 /drivers/block | |
parent | 071942727824bab03b1a3f6b6eeb5b269697b333 (diff) |
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: 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_main.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 9bd53cf2cdb2..90050ab7adf3 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -335,6 +335,24 @@ bail: | |||
335 | drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR)); | 335 | drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR)); |
336 | } | 336 | } |
337 | 337 | ||
338 | |||
339 | /* In C_AHEAD mode only out_of_sync packets are sent for requests. Detach | ||
340 | * those requests from the newsest barrier when changing to an other cstate. | ||
341 | * | ||
342 | * That headless list vanishes when the last request finished its write or | ||
343 | * send out_of_sync packet. */ | ||
344 | static void tl_forget(struct drbd_conf *mdev) | ||
345 | { | ||
346 | struct drbd_tl_epoch *b; | ||
347 | |||
348 | if (test_bit(CREATE_BARRIER, &mdev->flags)) | ||
349 | return; | ||
350 | |||
351 | b = mdev->newest_tle; | ||
352 | list_del(&b->requests); | ||
353 | _tl_add_barrier(mdev, b); | ||
354 | } | ||
355 | |||
338 | /** | 356 | /** |
339 | * _tl_restart() - Walks the transfer log, and applies an action to all requests | 357 | * _tl_restart() - Walks the transfer log, and applies an action to all requests |
340 | * @mdev: DRBD device. | 358 | * @mdev: DRBD device. |
@@ -1242,6 +1260,9 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns, | |||
1242 | if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) | 1260 | if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) |
1243 | drbd_resume_al(mdev); | 1261 | drbd_resume_al(mdev); |
1244 | 1262 | ||
1263 | if (os.conn == C_AHEAD && ns.conn != C_AHEAD) | ||
1264 | tl_forget(mdev); | ||
1265 | |||
1245 | ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC); | 1266 | ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC); |
1246 | if (ascw) { | 1267 | if (ascw) { |
1247 | ascw->os = os; | 1268 | ascw->os = os; |