Browse Source

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>
Lars Ellenberg 15 years ago
parent
commit
4589d7f829
2 changed files with 4 additions and 3 deletions
  1. 4 0
      drivers/block/drbd/drbd_main.c
  2. 0 3
      drivers/block/drbd/drbd_receiver.c

+ 4 - 0
drivers/block/drbd/drbd_main.c

@@ -3173,14 +3173,18 @@ void drbd_free_bc(struct drbd_backing_dev *ldev)
 void drbd_free_sock(struct drbd_conf *mdev)
 {
 	if (mdev->data.socket) {
+		mutex_lock(&mdev->data.mutex);
 		kernel_sock_shutdown(mdev->data.socket, SHUT_RDWR);
 		sock_release(mdev->data.socket);
 		mdev->data.socket = NULL;
+		mutex_unlock(&mdev->data.mutex);
 	}
 	if (mdev->meta.socket) {
+		mutex_lock(&mdev->meta.mutex);
 		kernel_sock_shutdown(mdev->meta.socket, SHUT_RDWR);
 		sock_release(mdev->meta.socket);
 		mdev->meta.socket = NULL;
+		mutex_unlock(&mdev->meta.mutex);
 	}
 }
 

+ 0 - 3
drivers/block/drbd/drbd_receiver.c

@@ -3617,10 +3617,7 @@ static void drbd_disconnect(struct drbd_conf *mdev)
 
 	/* asender does not clean up anything. it must not interfere, either */
 	drbd_thread_stop(&mdev->asender);
-
-	mutex_lock(&mdev->data.mutex);
 	drbd_free_sock(mdev);
-	mutex_unlock(&mdev->data.mutex);
 
 	spin_lock_irq(&mdev->req_lock);
 	_drbd_wait_ee_list_empty(mdev, &mdev->active_ee);