aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2010-03-02 20:25:33 -0500
committerPhilipp Reisner <philipp.reisner@linbit.com>2010-03-11 10:02:45 -0500
commit4589d7f829951c1713ef5a4ad1a9bb563da329b5 (patch)
tree96a1ef3be7118a0a0dbf6b18f609486323f062c5 /drivers/block
parent676396d545350a70d922605ec23c2ed26124334a (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.c4
-rw-r--r--drivers/block/drbd/drbd_receiver.c3
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)
3173void drbd_free_sock(struct drbd_conf *mdev) 3173void 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);