提交 20004e24 编写于 作者: L Lars Ellenberg 提交者: Jens Axboe

drbd: bump current uuid when resuming IO with diskless peer

Scenario, starting with normal operation
 Connected Primary/Secondary UpToDate/UpToDate
 NetworkFailure Primary/Unknown UpToDate/DUnknown (frozen)
 ... more failures happen, secondary loses it's disk,
 but eventually is able to re-establish the replication link ...
 Connected Primary/Secondary UpToDate/Diskless (resumed; needs to bump uuid!)

We used to just resume/resent suspended requests,
without bumping the UUID.

Which will lead to problems later, when we want to re-attach the disk on
the peer, without first disconnecting, or if we experience additional
failures, because we now have diverging data without being able to
recognize it.

Make sure we also bump the current data generation UUID,
if we notice "peer disk unknown" -> "peer disk known bad".
Signed-off-by: NPhilipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: NLars Ellenberg <lars.ellenberg@linbit.com>
Signed-off-by: NJens Axboe <axboe@fb.com>
上级 31d64604
...@@ -1637,6 +1637,26 @@ static void broadcast_state_change(struct drbd_state_change *state_change) ...@@ -1637,6 +1637,26 @@ static void broadcast_state_change(struct drbd_state_change *state_change)
#undef REMEMBER_STATE_CHANGE #undef REMEMBER_STATE_CHANGE
} }
/* takes old and new peer disk state */
static bool lost_contact_to_peer_data(enum drbd_disk_state os, enum drbd_disk_state ns)
{
if ((os >= D_INCONSISTENT && os != D_UNKNOWN && os != D_OUTDATED)
&& (ns < D_INCONSISTENT || ns == D_UNKNOWN || ns == D_OUTDATED))
return true;
/* Scenario, starting with normal operation
* Connected Primary/Secondary UpToDate/UpToDate
* NetworkFailure Primary/Unknown UpToDate/DUnknown (frozen)
* ...
* Connected Primary/Secondary UpToDate/Diskless (resumed; needs to bump uuid!)
*/
if (os == D_UNKNOWN
&& (ns == D_DISKLESS || ns == D_FAILED || ns == D_OUTDATED))
return true;
return false;
}
/** /**
* after_state_ch() - Perform after state change actions that may sleep * after_state_ch() - Perform after state change actions that may sleep
* @device: DRBD device. * @device: DRBD device.
...@@ -1708,6 +1728,13 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os, ...@@ -1708,6 +1728,13 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os,
idr_for_each_entry(&connection->peer_devices, peer_device, vnr) idr_for_each_entry(&connection->peer_devices, peer_device, vnr)
clear_bit(NEW_CUR_UUID, &peer_device->device->flags); clear_bit(NEW_CUR_UUID, &peer_device->device->flags);
rcu_read_unlock(); rcu_read_unlock();
/* We should actively create a new uuid, _before_
* we resume/resent, if the peer is diskless
* (recovery from a multiple error scenario).
* Currently, this happens with a slight delay
* below when checking lost_contact_to_peer_data() ...
*/
_tl_restart(connection, RESEND); _tl_restart(connection, RESEND);
_conn_request_state(connection, _conn_request_state(connection,
(union drbd_state) { { .susp_fen = 1 } }, (union drbd_state) { { .susp_fen = 1 } },
...@@ -1751,12 +1778,7 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os, ...@@ -1751,12 +1778,7 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os,
BM_LOCKED_TEST_ALLOWED); BM_LOCKED_TEST_ALLOWED);
/* Lost contact to peer's copy of the data */ /* Lost contact to peer's copy of the data */
if ((os.pdsk >= D_INCONSISTENT && if (lost_contact_to_peer_data(os.pdsk, ns.pdsk)) {
os.pdsk != D_UNKNOWN &&
os.pdsk != D_OUTDATED)
&& (ns.pdsk < D_INCONSISTENT ||
ns.pdsk == D_UNKNOWN ||
ns.pdsk == D_OUTDATED)) {
if (get_ldev(device)) { if (get_ldev(device)) {
if ((ns.role == R_PRIMARY || ns.peer == R_PRIMARY) && if ((ns.role == R_PRIMARY || ns.peer == R_PRIMARY) &&
device->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) { device->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册