diff options
author | Lars Ellenberg <lars.ellenberg@linbit.com> | 2010-03-02 20:25:33 -0500 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2010-03-11 10:02:45 -0500 |
commit | 4589d7f829951c1713ef5a4ad1a9bb563da329b5 (patch) | |
tree | 96a1ef3be7118a0a0dbf6b18f609486323f062c5 /drivers/block | |
parent | 676396d545350a70d922605ec23c2ed26124334a (diff) |
drbd_disconnect: grab meta.socket mutex as well
Fixes a race and potential kernel panic if e.g. the worker was just
about to send a few P_RS_IS_IN_SYNC via the meta socket for checksum
based resync, while the receiver destroys the sockets in
drbd_disconnect.
To make sure no-one is using the meta socket,
it is not enough to stop the asender...
Grab the meta socket mutex before destroying it.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 4 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_receiver.c | 3 |
2 files changed, 4 insertions, 3 deletions
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index b2d347d18c7d..67e0fc542249 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -3173,14 +3173,18 @@ void drbd_free_bc(struct drbd_backing_dev *ldev) | |||
3173 | void drbd_free_sock(struct drbd_conf *mdev) | 3173 | void drbd_free_sock(struct drbd_conf *mdev) |
3174 | { | 3174 | { |
3175 | if (mdev->data.socket) { | 3175 | if (mdev->data.socket) { |
3176 | mutex_lock(&mdev->data.mutex); | ||
3176 | kernel_sock_shutdown(mdev->data.socket, SHUT_RDWR); | 3177 | kernel_sock_shutdown(mdev->data.socket, SHUT_RDWR); |
3177 | sock_release(mdev->data.socket); | 3178 | sock_release(mdev->data.socket); |
3178 | mdev->data.socket = NULL; | 3179 | mdev->data.socket = NULL; |
3180 | mutex_unlock(&mdev->data.mutex); | ||
3179 | } | 3181 | } |
3180 | if (mdev->meta.socket) { | 3182 | if (mdev->meta.socket) { |
3183 | mutex_lock(&mdev->meta.mutex); | ||
3181 | kernel_sock_shutdown(mdev->meta.socket, SHUT_RDWR); | 3184 | kernel_sock_shutdown(mdev->meta.socket, SHUT_RDWR); |
3182 | sock_release(mdev->meta.socket); | 3185 | sock_release(mdev->meta.socket); |
3183 | mdev->meta.socket = NULL; | 3186 | mdev->meta.socket = NULL; |
3187 | mutex_unlock(&mdev->meta.mutex); | ||
3184 | } | 3188 | } |
3185 | } | 3189 | } |
3186 | 3190 | ||
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 41f36a9cd407..d803e6c257e2 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c | |||
@@ -3617,10 +3617,7 @@ static void drbd_disconnect(struct drbd_conf *mdev) | |||
3617 | 3617 | ||
3618 | /* asender does not clean up anything. it must not interfere, either */ | 3618 | /* asender does not clean up anything. it must not interfere, either */ |
3619 | drbd_thread_stop(&mdev->asender); | 3619 | drbd_thread_stop(&mdev->asender); |
3620 | |||
3621 | mutex_lock(&mdev->data.mutex); | ||
3622 | drbd_free_sock(mdev); | 3620 | drbd_free_sock(mdev); |
3623 | mutex_unlock(&mdev->data.mutex); | ||
3624 | 3621 | ||
3625 | spin_lock_irq(&mdev->req_lock); | 3622 | spin_lock_irq(&mdev->req_lock); |
3626 | _drbd_wait_ee_list_empty(mdev, &mdev->active_ee); | 3623 | _drbd_wait_ee_list_empty(mdev, &mdev->active_ee); |