diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2011-03-25 09:31:11 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-11-08 10:44:57 -0500 |
commit | 88ef594ed7367a76e53f4a33b3d866f4dfb1d4ff (patch) | |
tree | 1d70714d2d69887899d150bac5c48f80028b986c /drivers/block/drbd/drbd_state.c | |
parent | bd0c824a9db54bfbf5a26a5bb9b604d65c25b904 (diff) |
drbd: Fixed logging of old connection state
During a disconnect the oc variable in _conn_request_state()
could become outdated. Determin the common old state after
sleeping.
While at it, I implemented that for all parts of the state
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd/drbd_state.c')
-rw-r--r-- | drivers/block/drbd/drbd_state.c | 117 |
1 files changed, 87 insertions, 30 deletions
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c index 85cfbeadd513..2a170bf7cc29 100644 --- a/drivers/block/drbd/drbd_state.c +++ b/drivers/block/drbd/drbd_state.c | |||
@@ -1377,42 +1377,100 @@ static void print_conn_state_change(struct drbd_tconn *tconn, enum drbd_conns oc | |||
1377 | conn_info(tconn, "%s\n", pb); | 1377 | conn_info(tconn, "%s\n", pb); |
1378 | } | 1378 | } |
1379 | 1379 | ||
1380 | struct _is_valid_itr_params { | 1380 | enum sp_state { |
1381 | enum drbd_conns oc; | 1381 | OC_UNINITIALIZED, |
1382 | enum { | 1382 | OC_CONSISTENT, |
1383 | OC_UNINITIALIZED, | 1383 | OC_INCONSISTENT, |
1384 | OC_CONSISTENT, | 1384 | } oc_state; |
1385 | OC_INCONSISTENT, | 1385 | |
1386 | } oc_state; | 1386 | static void common_state_part(enum sp_state *sps, int *sp, int nsp) |
1387 | }; | 1387 | { |
1388 | switch (*sps) { | ||
1389 | case OC_UNINITIALIZED: | ||
1390 | *sp = nsp; | ||
1391 | *sps = OC_CONSISTENT; | ||
1392 | break; | ||
1393 | case OC_CONSISTENT: | ||
1394 | if (*sp != nsp) | ||
1395 | *sps = OC_INCONSISTENT; | ||
1396 | break; | ||
1397 | case OC_INCONSISTENT: | ||
1398 | break; | ||
1399 | } | ||
1400 | } | ||
1401 | |||
1402 | void conn_old_common_state(struct drbd_tconn *tconn, union drbd_state *pcs, union drbd_state *pmask) | ||
1403 | { | ||
1404 | union drbd_state css = {}; /* common state state */ | ||
1405 | union drbd_state os, cs = {}; /* old_state, common_state */ | ||
1406 | union drbd_state mask = {}; | ||
1407 | enum sp_state sps; /* state part state */ | ||
1408 | int sp; /* state part */ | ||
1409 | struct drbd_conf *mdev; | ||
1410 | int vnr; | ||
1411 | |||
1412 | idr_for_each_entry(&tconn->volumes, mdev, vnr) { | ||
1413 | os = mdev->state; | ||
1414 | |||
1415 | sps = css.role; | ||
1416 | sp = cs.role; | ||
1417 | common_state_part(&sps, &sp, os.role); | ||
1418 | css.role = sps; | ||
1419 | cs.role = sp; | ||
1420 | |||
1421 | sps = css.peer; | ||
1422 | sp = cs.peer; | ||
1423 | common_state_part(&sps, &sp, os.peer); | ||
1424 | css.peer = sps; | ||
1425 | cs.peer = sp; | ||
1426 | |||
1427 | sps = css.conn; | ||
1428 | sp = cs.conn; | ||
1429 | common_state_part(&sps, &sp, os.conn); | ||
1430 | css.conn = sps; | ||
1431 | cs.conn = sp; | ||
1432 | |||
1433 | sps = css.disk; | ||
1434 | sp = cs.disk; | ||
1435 | common_state_part(&sps, &sp, os.disk); | ||
1436 | css.disk = sps; | ||
1437 | cs.disk = sp; | ||
1438 | |||
1439 | sps = css.pdsk; | ||
1440 | sp = cs.pdsk; | ||
1441 | common_state_part(&sps, &sp, os.pdsk); | ||
1442 | css.pdsk = sps; | ||
1443 | cs.pdsk = sp; | ||
1444 | } | ||
1445 | |||
1446 | if (css.role == OC_CONSISTENT) | ||
1447 | mask.role = R_MASK; | ||
1448 | if (css.peer == OC_CONSISTENT) | ||
1449 | mask.peer = R_MASK; | ||
1450 | if (css.conn == OC_CONSISTENT) | ||
1451 | mask.conn = C_MASK; | ||
1452 | if (css.disk == OC_CONSISTENT) | ||
1453 | mask.disk = D_MASK; | ||
1454 | if (css.pdsk == OC_CONSISTENT) | ||
1455 | mask.pdsk = D_MASK; | ||
1456 | |||
1457 | *pcs = cs; | ||
1458 | *pmask = mask; | ||
1459 | } | ||
1388 | 1460 | ||
1389 | static enum drbd_state_rv | 1461 | static enum drbd_state_rv |
1390 | conn_is_valid_transition(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val, | 1462 | conn_is_valid_transition(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val, |
1391 | enum chg_state_flags flags, struct _is_valid_itr_params *params) | 1463 | enum chg_state_flags flags) |
1392 | { | 1464 | { |
1393 | enum drbd_state_rv rv = SS_SUCCESS; | 1465 | enum drbd_state_rv rv = SS_SUCCESS; |
1394 | union drbd_state ns, os; | 1466 | union drbd_state ns, os; |
1395 | struct drbd_conf *mdev; | 1467 | struct drbd_conf *mdev; |
1396 | int vnr; | 1468 | int vnr; |
1397 | 1469 | ||
1398 | params->oc_state = OC_UNINITIALIZED; | ||
1399 | idr_for_each_entry(&tconn->volumes, mdev, vnr) { | 1470 | idr_for_each_entry(&tconn->volumes, mdev, vnr) { |
1400 | os = mdev->state; | 1471 | os = mdev->state; |
1401 | ns = sanitize_state(mdev, apply_mask_val(os, mask, val), NULL); | 1472 | ns = sanitize_state(mdev, apply_mask_val(os, mask, val), NULL); |
1402 | 1473 | ||
1403 | switch (params->oc_state) { | ||
1404 | case OC_UNINITIALIZED: | ||
1405 | params->oc = os.conn; | ||
1406 | params->oc_state = OC_CONSISTENT; | ||
1407 | break; | ||
1408 | case OC_CONSISTENT: | ||
1409 | if (params->oc != os.conn) | ||
1410 | params->oc_state = OC_INCONSISTENT; | ||
1411 | break; | ||
1412 | case OC_INCONSISTENT: | ||
1413 | break; | ||
1414 | } | ||
1415 | |||
1416 | if (ns.i == os.i) | 1474 | if (ns.i == os.i) |
1417 | continue; | 1475 | continue; |
1418 | 1476 | ||
@@ -1471,7 +1529,6 @@ conn_set_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state | |||
1471 | static enum drbd_state_rv | 1529 | static enum drbd_state_rv |
1472 | _conn_rq_cond(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val) | 1530 | _conn_rq_cond(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state val) |
1473 | { | 1531 | { |
1474 | struct _is_valid_itr_params params; | ||
1475 | enum drbd_state_rv rv; | 1532 | enum drbd_state_rv rv; |
1476 | 1533 | ||
1477 | if (test_and_clear_bit(CONN_WD_ST_CHG_OKAY, &tconn->flags)) | 1534 | if (test_and_clear_bit(CONN_WD_ST_CHG_OKAY, &tconn->flags)) |
@@ -1484,7 +1541,7 @@ _conn_rq_cond(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state | |||
1484 | rv = tconn->cstate != C_WF_REPORT_PARAMS ? SS_CW_NO_NEED : SS_UNKNOWN_ERROR; | 1541 | rv = tconn->cstate != C_WF_REPORT_PARAMS ? SS_CW_NO_NEED : SS_UNKNOWN_ERROR; |
1485 | 1542 | ||
1486 | if (rv == SS_UNKNOWN_ERROR) | 1543 | if (rv == SS_UNKNOWN_ERROR) |
1487 | rv = conn_is_valid_transition(tconn, mask, val, CS_NO_CSTATE_CHG, ¶ms); | 1544 | rv = conn_is_valid_transition(tconn, mask, val, CS_NO_CSTATE_CHG); |
1488 | 1545 | ||
1489 | if (rv == SS_SUCCESS) | 1546 | if (rv == SS_SUCCESS) |
1490 | rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */ | 1547 | rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */ |
@@ -1524,16 +1581,15 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_ | |||
1524 | enum chg_state_flags flags) | 1581 | enum chg_state_flags flags) |
1525 | { | 1582 | { |
1526 | enum drbd_state_rv rv = SS_SUCCESS; | 1583 | enum drbd_state_rv rv = SS_SUCCESS; |
1527 | struct _is_valid_itr_params params; | ||
1528 | struct after_conn_state_chg_work *acscw; | 1584 | struct after_conn_state_chg_work *acscw; |
1529 | enum drbd_conns oc = tconn->cstate; | 1585 | enum drbd_conns oc = tconn->cstate; |
1530 | union drbd_state ms; | 1586 | union drbd_state ms, os_val, os_mask; |
1531 | 1587 | ||
1532 | rv = is_valid_conn_transition(oc, val.conn); | 1588 | rv = is_valid_conn_transition(oc, val.conn); |
1533 | if (rv < SS_SUCCESS) | 1589 | if (rv < SS_SUCCESS) |
1534 | goto abort; | 1590 | goto abort; |
1535 | 1591 | ||
1536 | rv = conn_is_valid_transition(tconn, mask, val, flags, ¶ms); | 1592 | rv = conn_is_valid_transition(tconn, mask, val, flags); |
1537 | if (rv < SS_SUCCESS) | 1593 | if (rv < SS_SUCCESS) |
1538 | goto abort; | 1594 | goto abort; |
1539 | 1595 | ||
@@ -1544,8 +1600,9 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_ | |||
1544 | goto abort; | 1600 | goto abort; |
1545 | } | 1601 | } |
1546 | 1602 | ||
1547 | if (params.oc_state == OC_CONSISTENT) { | 1603 | conn_old_common_state(tconn, &os_val, &os_mask); |
1548 | oc = params.oc; | 1604 | if (os_mask.conn == C_MASK) { |
1605 | oc = os_val.conn; | ||
1549 | print_conn_state_change(tconn, oc, val.conn); | 1606 | print_conn_state_change(tconn, oc, val.conn); |
1550 | flags |= CS_NO_CSTATE_CHG; | 1607 | flags |= CS_NO_CSTATE_CHG; |
1551 | } | 1608 | } |