diff mbox series

[2/3] dm bufio: Split main logic out of dm_bufio_client creation/destroy

Message ID 20221111121029.3985561-3-chengzhihao1@huawei.com (mailing list archive)
State Accepted, archived
Delegated to: Mike Snitzer
Headers show
Series dm thin: Fix ABBA deadlock between shrink_slab and dm_pool_abort_metadata | expand

Commit Message

Zhihao Cheng Nov. 11, 2022, 12:10 p.m. UTC
Split main logic excepts shrinker register/unregister out of
dm_bufio_client creation/destroy, the extracted code is wrapped
into new helpers __do_init and __do_destroy.
This commit is prepare to support dm_bufio_client resetting.

Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
---
 drivers/md/dm-bufio.c    | 144 +++++++++++++++++++++++++++------------
 include/linux/dm-bufio.h |   4 +-
 2 files changed, 101 insertions(+), 47 deletions(-)

Comments

Zhihao Cheng Nov. 29, 2022, 7:04 a.m. UTC | #1
在 2022/11/11 20:10, Zhihao Cheng 写道:
Hi Mike,
I found patch 1/3 has been applied to mainline, any thoughts for patch 
2/3 and 3/3? Thanks.

> Split main logic excepts shrinker register/unregister out of
> dm_bufio_client creation/destroy, the extracted code is wrapped
> into new helpers __do_init and __do_destroy.
> This commit is prepare to support dm_bufio_client resetting.
> 
> Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
> ---
>   drivers/md/dm-bufio.c    | 144 +++++++++++++++++++++++++++------------
>   include/linux/dm-bufio.h |   4 +-
>   2 files changed, 101 insertions(+), 47 deletions(-)
> 

--
dm-devel mailing list
dm-devel@redhat.com
https://listman.redhat.com/mailman/listinfo/dm-devel
diff mbox series

Patch

diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index bb786c39545e..5859d69d6944 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -1731,31 +1731,17 @@  static unsigned long dm_bufio_shrink_count(struct shrinker *shrink, struct shrin
 	return count;
 }
 
-/*
- * Create the buffering interface
- */
-struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsigned block_size,
-					       unsigned reserved_buffers, unsigned aux_size,
-					       void (*alloc_callback)(struct dm_buffer *),
-					       void (*write_callback)(struct dm_buffer *),
-					       unsigned int flags)
-{
-	int r;
-	struct dm_bufio_client *c;
-	unsigned i;
+static int __do_init(struct dm_bufio_client *c, struct block_device *bdev,
+		     unsigned int block_size, unsigned int reserved_buffers,
+		     unsigned int aux_size,
+		     void (*alloc_callback)(struct dm_buffer *),
+		     void (*write_callback)(struct dm_buffer *),
+		     unsigned int flags)
+{
+	int r = 0;
+	unsigned int i;
 	char slab_name[27];
 
-	if (!block_size || block_size & ((1 << SECTOR_SHIFT) - 1)) {
-		DMERR("%s: block size not specified or is not multiple of 512b", __func__);
-		r = -EINVAL;
-		goto bad_client;
-	}
-
-	c = kzalloc(sizeof(*c), GFP_KERNEL);
-	if (!c) {
-		r = -ENOMEM;
-		goto bad_client;
-	}
 	c->buffer_tree = RB_ROOT;
 
 	c->bdev = bdev;
@@ -1829,6 +1815,63 @@  struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
 	INIT_WORK(&c->shrink_work, shrink_work);
 	atomic_long_set(&c->need_shrink, 0);
 
+	return 0;
+
+bad:
+	while (!list_empty(&c->reserved_buffers)) {
+		struct dm_buffer *b = list_entry(c->reserved_buffers.next,
+						 struct dm_buffer, lru_list);
+		list_del(&b->lru_list);
+		free_buffer(b);
+	}
+	kmem_cache_destroy(c->slab_cache);
+	c->slab_cache = NULL;
+	kmem_cache_destroy(c->slab_buffer);
+	c->slab_buffer = NULL;
+	dm_io_client_destroy(c->dm_io);
+bad_dm_io:
+	c->dm_io = NULL;
+	mutex_destroy(&c->lock);
+	c->need_reserved_buffers = 0;
+	if (c->no_sleep) {
+		static_branch_dec(&no_sleep_enabled);
+		c->no_sleep = false;
+	}
+	return r;
+}
+
+/*
+ * Create the buffering interface
+ */
+struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev,
+					       unsigned int block_size,
+					       unsigned int reserved_buffers,
+					       unsigned int aux_size,
+					       void (*alloc_callback)(struct dm_buffer *),
+					       void (*write_callback)(struct dm_buffer *),
+					       unsigned int flags)
+{
+	int r;
+	struct dm_bufio_client *c;
+	char slab_name[27];
+
+	if (!block_size || block_size & ((1 << SECTOR_SHIFT) - 1)) {
+		DMERR("%s: block size not specified or is not multiple of 512b", __func__);
+		r = -EINVAL;
+		goto bad_client;
+	}
+
+	c = kzalloc(sizeof(*c), GFP_KERNEL);
+	if (!c) {
+		r = -ENOMEM;
+		goto bad_client;
+	}
+
+	r = __do_init(c, bdev, block_size, reserved_buffers, aux_size,
+		      alloc_callback, write_callback, flags);
+	if (r)
+		goto bad_do_init;
+
 	c->shrinker.count_objects = dm_bufio_shrink_count;
 	c->shrinker.scan_objects = dm_bufio_shrink_scan;
 	c->shrinker.seeks = 1;
@@ -1856,36 +1899,19 @@  struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
 	kmem_cache_destroy(c->slab_cache);
 	kmem_cache_destroy(c->slab_buffer);
 	dm_io_client_destroy(c->dm_io);
-bad_dm_io:
 	mutex_destroy(&c->lock);
 	if (c->no_sleep)
 		static_branch_dec(&no_sleep_enabled);
+bad_do_init:
 	kfree(c);
 bad_client:
 	return ERR_PTR(r);
 }
 EXPORT_SYMBOL_GPL(dm_bufio_client_create);
 
-/*
- * Free the buffering interface.
- * It is required that there are no references on any buffers.
- */
-void dm_bufio_client_destroy(struct dm_bufio_client *c)
+static void __do_destroy(struct dm_bufio_client *c)
 {
-	unsigned i;
-
-	drop_buffers(c);
-
-	unregister_shrinker(&c->shrinker);
-	flush_work(&c->shrink_work);
-
-	mutex_lock(&dm_bufio_clients_lock);
-
-	list_del(&c->client_list);
-	dm_bufio_client_count--;
-	__cache_size_refresh();
-
-	mutex_unlock(&dm_bufio_clients_lock);
+	unsigned int i;
 
 	BUG_ON(!RB_EMPTY_ROOT(&c->buffer_tree));
 	BUG_ON(c->need_reserved_buffers);
@@ -1905,11 +1931,39 @@  void dm_bufio_client_destroy(struct dm_bufio_client *c)
 		BUG_ON(c->n_buffers[i]);
 
 	kmem_cache_destroy(c->slab_cache);
+	c->slab_cache = NULL;
 	kmem_cache_destroy(c->slab_buffer);
-	dm_io_client_destroy(c->dm_io);
+	c->slab_buffer = NULL;
+	if (c->dm_io) {
+		dm_io_client_destroy(c->dm_io);
+		c->dm_io = NULL;
+	}
 	mutex_destroy(&c->lock);
-	if (c->no_sleep)
+	if (c->no_sleep) {
 		static_branch_dec(&no_sleep_enabled);
+		c->no_sleep = false;
+	}
+}
+
+/*
+ * Free the buffering interface.
+ * It is required that there are no references on any buffers.
+ */
+void dm_bufio_client_destroy(struct dm_bufio_client *c)
+{
+	drop_buffers(c);
+
+	unregister_shrinker(&c->shrinker);
+	flush_work(&c->shrink_work);
+
+	mutex_lock(&dm_bufio_clients_lock);
+	list_del(&c->client_list);
+	dm_bufio_client_count--;
+	__cache_size_refresh();
+	mutex_unlock(&dm_bufio_clients_lock);
+
+	__do_destroy(c);
+
 	kfree(c);
 }
 EXPORT_SYMBOL_GPL(dm_bufio_client_destroy);
diff --git a/include/linux/dm-bufio.h b/include/linux/dm-bufio.h
index 15d9e15ca830..ee4f19c170ab 100644
--- a/include/linux/dm-bufio.h
+++ b/include/linux/dm-bufio.h
@@ -26,8 +26,8 @@  struct dm_buffer;
  * Create a buffered IO cache on a given device
  */
 struct dm_bufio_client *
-dm_bufio_client_create(struct block_device *bdev, unsigned block_size,
-		       unsigned reserved_buffers, unsigned aux_size,
+dm_bufio_client_create(struct block_device *bdev, unsigned int block_size,
+		       unsigned int reserved_buffers, unsigned int aux_size,
 		       void (*alloc_callback)(struct dm_buffer *),
 		       void (*write_callback)(struct dm_buffer *),
 		       unsigned int flags);