diff options
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r-- | drivers/md/dm.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 73f28802dc7a..9b641b38b857 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -2616,6 +2616,19 @@ void dm_get(struct mapped_device *md) | |||
2616 | BUG_ON(test_bit(DMF_FREEING, &md->flags)); | 2616 | BUG_ON(test_bit(DMF_FREEING, &md->flags)); |
2617 | } | 2617 | } |
2618 | 2618 | ||
2619 | int dm_hold(struct mapped_device *md) | ||
2620 | { | ||
2621 | spin_lock(&_minor_lock); | ||
2622 | if (test_bit(DMF_FREEING, &md->flags)) { | ||
2623 | spin_unlock(&_minor_lock); | ||
2624 | return -EBUSY; | ||
2625 | } | ||
2626 | dm_get(md); | ||
2627 | spin_unlock(&_minor_lock); | ||
2628 | return 0; | ||
2629 | } | ||
2630 | EXPORT_SYMBOL_GPL(dm_hold); | ||
2631 | |||
2619 | const char *dm_device_name(struct mapped_device *md) | 2632 | const char *dm_device_name(struct mapped_device *md) |
2620 | { | 2633 | { |
2621 | return md->name; | 2634 | return md->name; |
@@ -2638,10 +2651,16 @@ static void __dm_destroy(struct mapped_device *md, bool wait) | |||
2638 | if (dm_request_based(md)) | 2651 | if (dm_request_based(md)) |
2639 | flush_kthread_worker(&md->kworker); | 2652 | flush_kthread_worker(&md->kworker); |
2640 | 2653 | ||
2654 | /* | ||
2655 | * Take suspend_lock so that presuspend and postsuspend methods | ||
2656 | * do not race with internal suspend. | ||
2657 | */ | ||
2658 | mutex_lock(&md->suspend_lock); | ||
2641 | if (!dm_suspended_md(md)) { | 2659 | if (!dm_suspended_md(md)) { |
2642 | dm_table_presuspend_targets(map); | 2660 | dm_table_presuspend_targets(map); |
2643 | dm_table_postsuspend_targets(map); | 2661 | dm_table_postsuspend_targets(map); |
2644 | } | 2662 | } |
2663 | mutex_unlock(&md->suspend_lock); | ||
2645 | 2664 | ||
2646 | /* dm_put_live_table must be before msleep, otherwise deadlock is possible */ | 2665 | /* dm_put_live_table must be before msleep, otherwise deadlock is possible */ |
2647 | dm_put_live_table(md, srcu_idx); | 2666 | dm_put_live_table(md, srcu_idx); |
@@ -3115,6 +3134,7 @@ void dm_internal_suspend_fast(struct mapped_device *md) | |||
3115 | flush_workqueue(md->wq); | 3134 | flush_workqueue(md->wq); |
3116 | dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE); | 3135 | dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE); |
3117 | } | 3136 | } |
3137 | EXPORT_SYMBOL_GPL(dm_internal_suspend_fast); | ||
3118 | 3138 | ||
3119 | void dm_internal_resume_fast(struct mapped_device *md) | 3139 | void dm_internal_resume_fast(struct mapped_device *md) |
3120 | { | 3140 | { |
@@ -3126,6 +3146,7 @@ void dm_internal_resume_fast(struct mapped_device *md) | |||
3126 | done: | 3146 | done: |
3127 | mutex_unlock(&md->suspend_lock); | 3147 | mutex_unlock(&md->suspend_lock); |
3128 | } | 3148 | } |
3149 | EXPORT_SYMBOL_GPL(dm_internal_resume_fast); | ||
3129 | 3150 | ||
3130 | /*----------------------------------------------------------------- | 3151 | /*----------------------------------------------------------------- |
3131 | * Event notification. | 3152 | * Event notification. |