@@ -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);
@@ -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);
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(-)