diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2010-06-02 08:31:29 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2010-06-14 06:19:41 -0400 |
commit | dc66c74de6f4238020db3e2041d4aca5c5b3e9bc (patch) | |
tree | 8df9cdd2f1672217a210e624f4613744e57450e0 /drivers/block/drbd/drbd_nl.c | |
parent | 7e27d6e778cd87b6f2415515d7127eba53fe5d02 (diff) |
drbd: Fixed a race between disk-attach and unexpected state changes
This was a very hard to trigger race condition.
If we got a state packet from the peer, after drbd_nl_disk() has
already changed the disk state to D_NEGOTIATING but
after_state_ch() was not yet run by the worker, then receive_state()
might called drbd_sync_handshake(), which in turn crashed
when accessing p_uuid.
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_nl.c')
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 632e3245d1bb..2151f18b21de 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c | |||
@@ -1114,6 +1114,12 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp | |||
1114 | mdev->new_state_tmp.i = ns.i; | 1114 | mdev->new_state_tmp.i = ns.i; |
1115 | ns.i = os.i; | 1115 | ns.i = os.i; |
1116 | ns.disk = D_NEGOTIATING; | 1116 | ns.disk = D_NEGOTIATING; |
1117 | |||
1118 | /* We expect to receive up-to-date UUIDs soon. | ||
1119 | To avoid a race in receive_state, free p_uuid while | ||
1120 | holding req_lock. I.e. atomic with the state change */ | ||
1121 | kfree(mdev->p_uuid); | ||
1122 | mdev->p_uuid = NULL; | ||
1117 | } | 1123 | } |
1118 | 1124 | ||
1119 | rv = _drbd_set_state(mdev, ns, CS_VERBOSE, NULL); | 1125 | rv = _drbd_set_state(mdev, ns, CS_VERBOSE, NULL); |