diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2011-03-25 10:11:30 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-11-08 10:44:57 -0500 |
commit | 435693e89b7a918b14ea67968971a2d8d9e88df2 (patch) | |
tree | be2d9272bec975aef6b2392eb4a967ffdda2dcb0 /drivers/block/drbd/drbd_state.c | |
parent | 88ef594ed7367a76e53f4a33b3d866f4dfb1d4ff (diff) |
drbd: Print common state changes of all volumes as connection state changes
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 | 159 |
1 files changed, 58 insertions, 101 deletions
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c index 2a170bf7cc29..164a7f821c78 100644 --- a/drivers/block/drbd/drbd_state.c +++ b/drivers/block/drbd/drbd_state.c | |||
@@ -350,29 +350,29 @@ void print_st_err(struct drbd_conf *mdev, union drbd_state os, | |||
350 | print_st(mdev, "wanted", ns); | 350 | print_st(mdev, "wanted", ns); |
351 | } | 351 | } |
352 | 352 | ||
353 | static void print_state_change(struct drbd_conf *mdev, union drbd_state os, union drbd_state ns, | 353 | static long print_state_change(char *pb, union drbd_state os, union drbd_state ns, |
354 | enum chg_state_flags flags) | 354 | enum chg_state_flags flags) |
355 | { | 355 | { |
356 | char *pbp, pb[300]; | 356 | char *pbp; |
357 | pbp = pb; | 357 | pbp = pb; |
358 | *pbp = 0; | 358 | *pbp = 0; |
359 | if (ns.role != os.role) | 359 | if (ns.role != os.role && flags & CS_DC_ROLE) |
360 | pbp += sprintf(pbp, "role( %s -> %s ) ", | 360 | pbp += sprintf(pbp, "role( %s -> %s ) ", |
361 | drbd_role_str(os.role), | 361 | drbd_role_str(os.role), |
362 | drbd_role_str(ns.role)); | 362 | drbd_role_str(ns.role)); |
363 | if (ns.peer != os.peer) | 363 | if (ns.peer != os.peer && flags & CS_DC_PEER) |
364 | pbp += sprintf(pbp, "peer( %s -> %s ) ", | 364 | pbp += sprintf(pbp, "peer( %s -> %s ) ", |
365 | drbd_role_str(os.peer), | 365 | drbd_role_str(os.peer), |
366 | drbd_role_str(ns.peer)); | 366 | drbd_role_str(ns.peer)); |
367 | if (ns.conn != os.conn && !(flags & CS_NO_CSTATE_CHG)) | 367 | if (ns.conn != os.conn && flags & CS_DC_CONN) |
368 | pbp += sprintf(pbp, "conn( %s -> %s ) ", | 368 | pbp += sprintf(pbp, "conn( %s -> %s ) ", |
369 | drbd_conn_str(os.conn), | 369 | drbd_conn_str(os.conn), |
370 | drbd_conn_str(ns.conn)); | 370 | drbd_conn_str(ns.conn)); |
371 | if (ns.disk != os.disk) | 371 | if (ns.disk != os.disk && flags & CS_DC_DISK) |
372 | pbp += sprintf(pbp, "disk( %s -> %s ) ", | 372 | pbp += sprintf(pbp, "disk( %s -> %s ) ", |
373 | drbd_disk_str(os.disk), | 373 | drbd_disk_str(os.disk), |
374 | drbd_disk_str(ns.disk)); | 374 | drbd_disk_str(ns.disk)); |
375 | if (ns.pdsk != os.pdsk) | 375 | if (ns.pdsk != os.pdsk && flags & CS_DC_PDSK) |
376 | pbp += sprintf(pbp, "pdsk( %s -> %s ) ", | 376 | pbp += sprintf(pbp, "pdsk( %s -> %s ) ", |
377 | drbd_disk_str(os.pdsk), | 377 | drbd_disk_str(os.pdsk), |
378 | drbd_disk_str(ns.pdsk)); | 378 | drbd_disk_str(ns.pdsk)); |
@@ -392,10 +392,29 @@ static void print_state_change(struct drbd_conf *mdev, union drbd_state os, unio | |||
392 | pbp += sprintf(pbp, "user_isp( %d -> %d ) ", | 392 | pbp += sprintf(pbp, "user_isp( %d -> %d ) ", |
393 | os.user_isp, | 393 | os.user_isp, |
394 | ns.user_isp); | 394 | ns.user_isp); |
395 | if (pbp != pb) | 395 | |
396 | return pbp - pb; | ||
397 | } | ||
398 | |||
399 | static void drbd_pr_state_change(struct drbd_conf *mdev, union drbd_state os, union drbd_state ns, | ||
400 | enum chg_state_flags flags) | ||
401 | { | ||
402 | char pb[300]; | ||
403 | |||
404 | if (print_state_change(pb, os, ns, flags ^ CS_DC_MASK)) | ||
396 | dev_info(DEV, "%s\n", pb); | 405 | dev_info(DEV, "%s\n", pb); |
397 | } | 406 | } |
398 | 407 | ||
408 | static void conn_pr_state_change(struct drbd_tconn *tconn, union drbd_state os, union drbd_state ns, | ||
409 | enum chg_state_flags flags) | ||
410 | { | ||
411 | char pb[300]; | ||
412 | |||
413 | if (print_state_change(pb, os, ns, flags)) | ||
414 | conn_info(tconn, "%s\n", pb); | ||
415 | } | ||
416 | |||
417 | |||
399 | /** | 418 | /** |
400 | * is_valid_state() - Returns an SS_ error code if ns is not valid | 419 | * is_valid_state() - Returns an SS_ error code if ns is not valid |
401 | * @mdev: DRBD device. | 420 | * @mdev: DRBD device. |
@@ -827,7 +846,7 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns, | |||
827 | if (warn_sync_abort) | 846 | if (warn_sync_abort) |
828 | dev_warn(DEV, "%s aborted.\n", warn_sync_abort); | 847 | dev_warn(DEV, "%s aborted.\n", warn_sync_abort); |
829 | 848 | ||
830 | print_state_change(mdev, os, ns, flags); | 849 | drbd_pr_state_change(mdev, os, ns, flags); |
831 | 850 | ||
832 | /* if we are going -> D_FAILED or D_DISKLESS, grab one extra reference | 851 | /* if we are going -> D_FAILED or D_DISKLESS, grab one extra reference |
833 | * on the ldev here, to be sure the transition -> D_DISKLESS resp. | 852 | * on the ldev here, to be sure the transition -> D_DISKLESS resp. |
@@ -1364,98 +1383,41 @@ static int w_after_conn_state_ch(struct drbd_work *w, int unused) | |||
1364 | return 0; | 1383 | return 0; |
1365 | } | 1384 | } |
1366 | 1385 | ||
1367 | static void print_conn_state_change(struct drbd_tconn *tconn, enum drbd_conns oc, enum drbd_conns nc) | 1386 | void conn_old_common_state(struct drbd_tconn *tconn, union drbd_state *pcs, enum chg_state_flags *pf) |
1368 | { | ||
1369 | char *pbp, pb[300]; | ||
1370 | pbp = pb; | ||
1371 | *pbp = 0; | ||
1372 | if (nc != oc) | ||
1373 | pbp += sprintf(pbp, "conn( %s -> %s ) ", | ||
1374 | drbd_conn_str(oc), | ||
1375 | drbd_conn_str(nc)); | ||
1376 | |||
1377 | conn_info(tconn, "%s\n", pb); | ||
1378 | } | ||
1379 | |||
1380 | enum sp_state { | ||
1381 | OC_UNINITIALIZED, | ||
1382 | OC_CONSISTENT, | ||
1383 | OC_INCONSISTENT, | ||
1384 | } oc_state; | ||
1385 | |||
1386 | static void common_state_part(enum sp_state *sps, int *sp, int nsp) | ||
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 | { | 1387 | { |
1404 | union drbd_state css = {}; /* common state state */ | 1388 | enum chg_state_flags flags = ~0; |
1405 | union drbd_state os, cs = {}; /* old_state, common_state */ | 1389 | 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; | 1390 | struct drbd_conf *mdev; |
1410 | int vnr; | 1391 | int vnr, first_vol = 1; |
1411 | 1392 | ||
1412 | idr_for_each_entry(&tconn->volumes, mdev, vnr) { | 1393 | idr_for_each_entry(&tconn->volumes, mdev, vnr) { |
1413 | os = mdev->state; | 1394 | os = mdev->state; |
1414 | 1395 | ||
1415 | sps = css.role; | 1396 | if (first_vol) { |
1416 | sp = cs.role; | 1397 | cs = os; |
1417 | common_state_part(&sps, &sp, os.role); | 1398 | first_vol = 0; |
1418 | css.role = sps; | 1399 | continue; |
1419 | cs.role = sp; | 1400 | } |
1420 | 1401 | ||
1421 | sps = css.peer; | 1402 | if (cs.role != os.role) |
1422 | sp = cs.peer; | 1403 | flags &= ~CS_DC_ROLE; |
1423 | common_state_part(&sps, &sp, os.peer); | 1404 | |
1424 | css.peer = sps; | 1405 | if (cs.peer != os.peer) |
1425 | cs.peer = sp; | 1406 | flags &= ~CS_DC_PEER; |
1426 | 1407 | ||
1427 | sps = css.conn; | 1408 | if (cs.conn != os.conn) |
1428 | sp = cs.conn; | 1409 | flags &= ~CS_DC_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 | 1410 | ||
1446 | if (css.role == OC_CONSISTENT) | 1411 | if (cs.disk != os.disk) |
1447 | mask.role = R_MASK; | 1412 | flags &= ~CS_DC_DISK; |
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 | 1413 | ||
1414 | if (cs.pdsk != os.pdsk) | ||
1415 | flags &= ~CS_DC_PDSK; | ||
1416 | } | ||
1417 | |||
1418 | *pf |= CS_DC_MASK; | ||
1419 | *pf &= flags; | ||
1457 | *pcs = cs; | 1420 | *pcs = cs; |
1458 | *pmask = mask; | ||
1459 | } | 1421 | } |
1460 | 1422 | ||
1461 | static enum drbd_state_rv | 1423 | static enum drbd_state_rv |
@@ -1541,7 +1503,7 @@ _conn_rq_cond(struct drbd_tconn *tconn, union drbd_state mask, union drbd_state | |||
1541 | rv = tconn->cstate != C_WF_REPORT_PARAMS ? SS_CW_NO_NEED : SS_UNKNOWN_ERROR; | 1503 | rv = tconn->cstate != C_WF_REPORT_PARAMS ? SS_CW_NO_NEED : SS_UNKNOWN_ERROR; |
1542 | 1504 | ||
1543 | if (rv == SS_UNKNOWN_ERROR) | 1505 | if (rv == SS_UNKNOWN_ERROR) |
1544 | rv = conn_is_valid_transition(tconn, mask, val, CS_NO_CSTATE_CHG); | 1506 | rv = conn_is_valid_transition(tconn, mask, val, 0); |
1545 | 1507 | ||
1546 | if (rv == SS_SUCCESS) | 1508 | if (rv == SS_SUCCESS) |
1547 | rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */ | 1509 | rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */ |
@@ -1583,7 +1545,7 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_ | |||
1583 | enum drbd_state_rv rv = SS_SUCCESS; | 1545 | enum drbd_state_rv rv = SS_SUCCESS; |
1584 | struct after_conn_state_chg_work *acscw; | 1546 | struct after_conn_state_chg_work *acscw; |
1585 | enum drbd_conns oc = tconn->cstate; | 1547 | enum drbd_conns oc = tconn->cstate; |
1586 | union drbd_state ms, os_val, os_mask; | 1548 | union drbd_state ms, os; |
1587 | 1549 | ||
1588 | rv = is_valid_conn_transition(oc, val.conn); | 1550 | rv = is_valid_conn_transition(oc, val.conn); |
1589 | if (rv < SS_SUCCESS) | 1551 | if (rv < SS_SUCCESS) |
@@ -1600,19 +1562,14 @@ _conn_request_state(struct drbd_tconn *tconn, union drbd_state mask, union drbd_ | |||
1600 | goto abort; | 1562 | goto abort; |
1601 | } | 1563 | } |
1602 | 1564 | ||
1603 | conn_old_common_state(tconn, &os_val, &os_mask); | 1565 | conn_old_common_state(tconn, &os, &flags); |
1604 | if (os_mask.conn == C_MASK) { | ||
1605 | oc = os_val.conn; | ||
1606 | print_conn_state_change(tconn, oc, val.conn); | ||
1607 | flags |= CS_NO_CSTATE_CHG; | ||
1608 | } | ||
1609 | |||
1610 | ms = conn_set_state(tconn, mask, val, flags); | 1566 | ms = conn_set_state(tconn, mask, val, flags); |
1611 | ms.conn = val.conn; | 1567 | ms.conn = val.conn; |
1568 | conn_pr_state_change(tconn, os, ms, flags); | ||
1612 | 1569 | ||
1613 | acscw = kmalloc(sizeof(*acscw), GFP_ATOMIC); | 1570 | acscw = kmalloc(sizeof(*acscw), GFP_ATOMIC); |
1614 | if (acscw) { | 1571 | if (acscw) { |
1615 | acscw->oc = oc; | 1572 | acscw->oc = os.conn; |
1616 | acscw->nms = ms; | 1573 | acscw->nms = ms; |
1617 | acscw->flags = flags; | 1574 | acscw->flags = flags; |
1618 | acscw->w.cb = w_after_conn_state_ch; | 1575 | acscw->w.cb = w_after_conn_state_ch; |