Commit ab17b68f authored by Philipp Reisner's avatar Philipp Reisner

drbd: Improvements in sanitize_state()

The relevant change is that the state change to C_FW_BITMAP_S should
implicitly change pdsk to C_CONSISTENT. (Think of it as C_OUTDATED, only
without the guarantee that the peer has the outdated written to its
meta data)

At that opportunity I restructured the switch statement so that it
gets evaluated every time. (Has declarative character)
Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
parent 22afd7ee
...@@ -817,6 +817,7 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state ...@@ -817,6 +817,7 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state
union drbd_state ns, const char **warn_sync_abort) union drbd_state ns, const char **warn_sync_abort)
{ {
enum drbd_fencing_p fp; enum drbd_fencing_p fp;
enum drbd_disk_state disk_min, disk_max, pdsk_min, pdsk_max;
fp = FP_DONT_CARE; fp = FP_DONT_CARE;
if (get_ldev(mdev)) { if (get_ldev(mdev)) {
...@@ -869,73 +870,106 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state ...@@ -869,73 +870,106 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state
ns.conn = C_CONNECTED; ns.conn = C_CONNECTED;
} }
if (ns.conn >= C_CONNECTED && /* Connection breaks down before we finished "Negotiating" */
((ns.disk == D_CONSISTENT || ns.disk == D_OUTDATED) || if (ns.conn < C_CONNECTED && ns.disk == D_NEGOTIATING &&
(ns.disk == D_NEGOTIATING && ns.conn == C_WF_BITMAP_T) || get_ldev_if_state(mdev, D_NEGOTIATING)) {
ns.conn >= C_AHEAD)) { if (mdev->ed_uuid == mdev->ldev->md.uuid[UI_CURRENT]) {
switch (ns.conn) { ns.disk = mdev->new_state_tmp.disk;
case C_WF_BITMAP_T: ns.pdsk = mdev->new_state_tmp.pdsk;
case C_PAUSED_SYNC_T: } else {
case C_BEHIND: dev_alert(DEV, "Connection lost while negotiating, no data!\n");
ns.disk = D_OUTDATED; ns.disk = D_DISKLESS;
break; ns.pdsk = D_UNKNOWN;
case C_CONNECTED:
case C_WF_BITMAP_S:
case C_SYNC_SOURCE:
case C_PAUSED_SYNC_S:
case C_AHEAD:
ns.disk = D_UP_TO_DATE;
break;
case C_SYNC_TARGET:
ns.disk = D_INCONSISTENT;
dev_warn(DEV, "Implicitly set disk state Inconsistent!\n");
break;
} }
if (os.disk == D_OUTDATED && ns.disk == D_UP_TO_DATE) put_ldev(mdev);
dev_warn(DEV, "Implicitly set disk from Outdated to UpToDate\n");
} }
if (ns.conn >= C_CONNECTED && /* D_CONSISTENT and D_OUTDATED vanish when we get connected */
(ns.pdsk == D_CONSISTENT || ns.pdsk == D_OUTDATED || ns.conn >= C_AHEAD)) { if (ns.conn >= C_CONNECTED && ns.conn < C_AHEAD) {
switch (ns.conn) { if (ns.disk == D_CONSISTENT || ns.disk == D_OUTDATED)
case C_CONNECTED: ns.disk = D_UP_TO_DATE;
if (ns.pdsk == D_CONSISTENT || ns.pdsk == D_OUTDATED)
ns.pdsk = D_UP_TO_DATE;
}
/* Implications of the connection stat on the disk states */
disk_min = D_DISKLESS;
disk_max = D_UP_TO_DATE;
pdsk_min = D_INCONSISTENT;
pdsk_max = D_UNKNOWN;
switch ((enum drbd_conns)ns.conn) {
case C_WF_BITMAP_T: case C_WF_BITMAP_T:
case C_PAUSED_SYNC_T: case C_PAUSED_SYNC_T:
case C_SYNC_TARGET: case C_STARTING_SYNC_T:
case C_WF_SYNC_UUID:
case C_BEHIND: case C_BEHIND:
ns.pdsk = D_UP_TO_DATE; disk_min = D_INCONSISTENT;
disk_max = D_OUTDATED;
pdsk_min = D_UP_TO_DATE;
pdsk_max = D_UP_TO_DATE;
break;
case C_VERIFY_S:
case C_VERIFY_T:
disk_min = D_UP_TO_DATE;
disk_max = D_UP_TO_DATE;
pdsk_min = D_UP_TO_DATE;
pdsk_max = D_UP_TO_DATE;
break;
case C_CONNECTED:
disk_min = D_DISKLESS;
disk_max = D_UP_TO_DATE;
pdsk_min = D_DISKLESS;
pdsk_max = D_UP_TO_DATE;
break; break;
case C_WF_BITMAP_S: case C_WF_BITMAP_S:
case C_PAUSED_SYNC_S: case C_PAUSED_SYNC_S:
case C_STARTING_SYNC_S:
case C_AHEAD: case C_AHEAD:
/* remap any consistent state to D_OUTDATED, disk_min = D_UP_TO_DATE;
* but disallow "upgrade" of not even consistent states. disk_max = D_UP_TO_DATE;
*/ pdsk_min = D_INCONSISTENT;
ns.pdsk = pdsk_max = D_CONSISTENT; /* D_OUTDATED would be nice. But explicit outdate necessary*/
(D_DISKLESS < os.pdsk && os.pdsk < D_OUTDATED) break;
? os.pdsk : D_OUTDATED; case C_SYNC_TARGET:
disk_min = D_INCONSISTENT;
disk_max = D_INCONSISTENT;
pdsk_min = D_UP_TO_DATE;
pdsk_max = D_UP_TO_DATE;
break; break;
case C_SYNC_SOURCE: case C_SYNC_SOURCE:
ns.pdsk = D_INCONSISTENT; disk_min = D_UP_TO_DATE;
dev_warn(DEV, "Implicitly set pdsk Inconsistent!\n"); disk_max = D_UP_TO_DATE;
pdsk_min = D_INCONSISTENT;
pdsk_max = D_INCONSISTENT;
break;
case C_STANDALONE:
case C_DISCONNECTING:
case C_UNCONNECTED:
case C_TIMEOUT:
case C_BROKEN_PIPE:
case C_NETWORK_FAILURE:
case C_PROTOCOL_ERROR:
case C_TEAR_DOWN:
case C_WF_CONNECTION:
case C_WF_REPORT_PARAMS:
case C_MASK:
break; break;
} }
if (os.pdsk == D_OUTDATED && ns.pdsk == D_UP_TO_DATE) if (ns.disk > disk_max)
dev_warn(DEV, "Implicitly set pdsk from Outdated to UpToDate\n"); ns.disk = disk_max;
}
/* Connection breaks down before we finished "Negotiating" */ if (ns.disk < disk_min) {
if (ns.conn < C_CONNECTED && ns.disk == D_NEGOTIATING && dev_warn(DEV, "Implicitly set disk from %s to %s\n",
get_ldev_if_state(mdev, D_NEGOTIATING)) { drbd_disk_str(ns.disk), drbd_disk_str(disk_min));
if (mdev->ed_uuid == mdev->ldev->md.uuid[UI_CURRENT]) { ns.disk = disk_min;
ns.disk = mdev->new_state_tmp.disk;
ns.pdsk = mdev->new_state_tmp.pdsk;
} else {
dev_alert(DEV, "Connection lost while negotiating, no data!\n");
ns.disk = D_DISKLESS;
ns.pdsk = D_UNKNOWN;
} }
put_ldev(mdev); if (ns.pdsk > pdsk_max)
ns.pdsk = pdsk_max;
if (ns.pdsk < pdsk_min) {
dev_warn(DEV, "Implicitly set pdsk from %s to %s\n",
drbd_disk_str(ns.pdsk), drbd_disk_str(pdsk_min));
ns.pdsk = pdsk_min;
} }
if (fp == FP_STONITH && if (fp == FP_STONITH &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment