aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2010-12-22 06:48:31 -0500
committerPhilipp Reisner <philipp.reisner@linbit.com>2011-03-10 05:45:23 -0500
commit617049aa7d753e8c821ac77126ab90e9f1b66d6d (patch)
tree1cabbc19e2efa054bf585d92f42c0bf7bf0c01b5 /drivers/block
parent071942727824bab03b1a3f6b6eeb5b269697b333 (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.c21
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. */
344static 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;