mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-10 07:50:04 +00:00
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>
This commit is contained in:
parent
7e27d6e778
commit
dc66c74de6
@ -1236,8 +1236,6 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
|
||||
/* Last part of the attaching process ... */
|
||||
if (ns.conn >= C_CONNECTED &&
|
||||
os.disk == D_ATTACHING && ns.disk == D_NEGOTIATING) {
|
||||
kfree(mdev->p_uuid); /* We expect to receive up-to-date UUIDs soon. */
|
||||
mdev->p_uuid = NULL; /* ...to not use the old ones in the mean time */
|
||||
drbd_send_sizes(mdev, 0, 0); /* to start sync... */
|
||||
drbd_send_uuids(mdev);
|
||||
drbd_send_state(mdev);
|
||||
|
@ -1114,6 +1114,12 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
|
||||
mdev->new_state_tmp.i = ns.i;
|
||||
ns.i = os.i;
|
||||
ns.disk = D_NEGOTIATING;
|
||||
|
||||
/* We expect to receive up-to-date UUIDs soon.
|
||||
To avoid a race in receive_state, free p_uuid while
|
||||
holding req_lock. I.e. atomic with the state change */
|
||||
kfree(mdev->p_uuid);
|
||||
mdev->p_uuid = NULL;
|
||||
}
|
||||
|
||||
rv = _drbd_set_state(mdev, ns, CS_VERBOSE, NULL);
|
||||
|
@ -53,7 +53,7 @@
|
||||
|
||||
|
||||
extern const char *drbd_buildtag(void);
|
||||
#define REL_VERSION "8.3.8rc2"
|
||||
#define REL_VERSION "8.3.8"
|
||||
#define API_VERSION 88
|
||||
#define PRO_VERSION_MIN 86
|
||||
#define PRO_VERSION_MAX 94
|
||||
|
Loading…
x
Reference in New Issue
Block a user