Skip to content

Commit

Permalink
drbd: Fixed a race between disk-attach and unexpected state changes
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Philipp Reisner committed Jun 14, 2010
1 parent 7e27d6e commit dc66c74
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 3 deletions.
2 changes: 0 additions & 2 deletions drivers/block/drbd/drbd_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions drivers/block/drbd/drbd_nl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion include/linux/drbd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit dc66c74

Please sign in to comment.