|
@@ -54,6 +54,8 @@ static void do_deferred_remove(struct work_struct *w);
|
|
|
|
|
|
static DECLARE_WORK(deferred_remove_work, do_deferred_remove);
|
|
static DECLARE_WORK(deferred_remove_work, do_deferred_remove);
|
|
|
|
|
|
|
|
+static struct workqueue_struct *deferred_remove_workqueue;
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* For bio-based dm.
|
|
* For bio-based dm.
|
|
* One of these is allocated per bio.
|
|
* One of these is allocated per bio.
|
|
@@ -276,16 +278,24 @@ static int __init local_init(void)
|
|
if (r)
|
|
if (r)
|
|
goto out_free_rq_tio_cache;
|
|
goto out_free_rq_tio_cache;
|
|
|
|
|
|
|
|
+ deferred_remove_workqueue = alloc_workqueue("kdmremove", WQ_UNBOUND, 1);
|
|
|
|
+ if (!deferred_remove_workqueue) {
|
|
|
|
+ r = -ENOMEM;
|
|
|
|
+ goto out_uevent_exit;
|
|
|
|
+ }
|
|
|
|
+
|
|
_major = major;
|
|
_major = major;
|
|
r = register_blkdev(_major, _name);
|
|
r = register_blkdev(_major, _name);
|
|
if (r < 0)
|
|
if (r < 0)
|
|
- goto out_uevent_exit;
|
|
|
|
|
|
+ goto out_free_workqueue;
|
|
|
|
|
|
if (!_major)
|
|
if (!_major)
|
|
_major = r;
|
|
_major = r;
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
|
|
+out_free_workqueue:
|
|
|
|
+ destroy_workqueue(deferred_remove_workqueue);
|
|
out_uevent_exit:
|
|
out_uevent_exit:
|
|
dm_uevent_exit();
|
|
dm_uevent_exit();
|
|
out_free_rq_tio_cache:
|
|
out_free_rq_tio_cache:
|
|
@@ -299,6 +309,7 @@ out_free_io_cache:
|
|
static void local_exit(void)
|
|
static void local_exit(void)
|
|
{
|
|
{
|
|
flush_scheduled_work();
|
|
flush_scheduled_work();
|
|
|
|
+ destroy_workqueue(deferred_remove_workqueue);
|
|
|
|
|
|
kmem_cache_destroy(_rq_tio_cache);
|
|
kmem_cache_destroy(_rq_tio_cache);
|
|
kmem_cache_destroy(_io_cache);
|
|
kmem_cache_destroy(_io_cache);
|
|
@@ -407,7 +418,7 @@ static void dm_blk_close(struct gendisk *disk, fmode_t mode)
|
|
|
|
|
|
if (atomic_dec_and_test(&md->open_count) &&
|
|
if (atomic_dec_and_test(&md->open_count) &&
|
|
(test_bit(DMF_DEFERRED_REMOVE, &md->flags)))
|
|
(test_bit(DMF_DEFERRED_REMOVE, &md->flags)))
|
|
- schedule_work(&deferred_remove_work);
|
|
|
|
|
|
+ queue_work(deferred_remove_workqueue, &deferred_remove_work);
|
|
|
|
|
|
dm_put(md);
|
|
dm_put(md);
|
|
|
|
|