nbd: refactor device removal
authorChristoph Hellwig <hch@lst.de>
Wed, 11 Aug 2021 12:44:24 +0000 (14:44 +0200)
committerJens Axboe <axboe@kernel.dk>
Fri, 13 Aug 2021 20:17:32 +0000 (14:17 -0600)
Share common code for the synchronous and workqueue based device removal,
and remove the pointless use of refcount_dec_and_mutex_lock.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20210811124428.2368491-3-hch@lst.de
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/nbd.c

index deefb2cda9bbd86407461efcae19140593b35095..a9883fbed9247b97e69e7005d182f8bcc0a8089f 100644 (file)
@@ -259,48 +259,37 @@ static void nbd_notify_destroy_completion(struct nbd_device *nbd)
                complete(nbd->destroy_complete);
 }
 
-static void nbd_dev_remove_work(struct work_struct *work)
+static void nbd_dev_remove(struct nbd_device *nbd)
 {
-       struct nbd_device *nbd =
-               container_of(work, struct nbd_device, remove_work);
-
        nbd_del_disk(nbd);
 
-       mutex_lock(&nbd_index_mutex);
        /*
-        * Remove from idr after del_gendisk() completes,
-        * so if the same id is reused, the following
-        * add_disk() will succeed.
+        * Remove from idr after del_gendisk() completes, so if the same ID is
+        * reused, the following add_disk() will succeed.
         */
+       mutex_lock(&nbd_index_mutex);
        idr_remove(&nbd_index_idr, nbd->index);
-
        nbd_notify_destroy_completion(nbd);
        mutex_unlock(&nbd_index_mutex);
 
        kfree(nbd);
 }
 
-static void nbd_dev_remove(struct nbd_device *nbd)
+static void nbd_dev_remove_work(struct work_struct *work)
 {
-       /* Call del_gendisk() asynchrounously to prevent deadlock */
-       if (test_bit(NBD_DESTROY_ON_DISCONNECT, &nbd->flags)) {
-               queue_work(nbd_del_wq, &nbd->remove_work);
-               return;
-       }
-
-       nbd_del_disk(nbd);
-       idr_remove(&nbd_index_idr, nbd->index);
-       nbd_notify_destroy_completion(nbd);
-       kfree(nbd);
+       nbd_dev_remove(container_of(work, struct nbd_device, remove_work));
 }
 
 static void nbd_put(struct nbd_device *nbd)
 {
-       if (refcount_dec_and_mutex_lock(&nbd->refs,
-                                       &nbd_index_mutex)) {
+       if (!refcount_dec_and_test(&nbd->refs))
+               return;
+
+       /* Call del_gendisk() asynchrounously to prevent deadlock */
+       if (test_bit(NBD_DESTROY_ON_DISCONNECT, &nbd->flags))
+               queue_work(nbd_del_wq, &nbd->remove_work);
+       else
                nbd_dev_remove(nbd);
-               mutex_unlock(&nbd_index_mutex);
-       }
 }
 
 static int nbd_disconnected(struct nbd_config *config)