19
19
#include <linux/idr.h>
20
20
#include <linux/hdreg.h>
21
21
#include <linux/delay.h>
22
+ #include <linux/wait.h>
22
23
23
24
#include <trace/events/block.h>
24
25
@@ -117,6 +118,7 @@ EXPORT_SYMBOL_GPL(dm_get_rq_mapinfo);
117
118
#define DMF_NOFLUSH_SUSPENDING 5
118
119
#define DMF_MERGE_IS_OPTIONAL 6
119
120
#define DMF_DEFERRED_REMOVE 7
121
+ #define DMF_SUSPENDED_INTERNALLY 8
120
122
121
123
/*
122
124
* A dummy definition to make RCU happy.
@@ -2718,36 +2720,18 @@ static void unlock_fs(struct mapped_device *md)
2718
2720
}
2719
2721
2720
2722
/*
2721
- * We need to be able to change a mapping table under a mounted
2722
- * filesystem. For example we might want to move some data in
2723
- * the background. Before the table can be swapped with
2724
- * dm_bind_table, dm_suspend must be called to flush any in
2725
- * flight bios and ensure that any further io gets deferred.
2726
- */
2727
- /*
2728
- * Suspend mechanism in request-based dm.
2729
- *
2730
- * 1. Flush all I/Os by lock_fs() if needed.
2731
- * 2. Stop dispatching any I/O by stopping the request_queue.
2732
- * 3. Wait for all in-flight I/Os to be completed or requeued.
2723
+ * If __dm_suspend returns 0, the device is completely quiescent
2724
+ * now. There is no request-processing activity. All new requests
2725
+ * are being added to md->deferred list.
2733
2726
*
2734
- * To abort suspend, start the request_queue.
2727
+ * Caller must hold md->suspend_lock
2735
2728
*/
2736
- int dm_suspend (struct mapped_device * md , unsigned suspend_flags )
2729
+ static int __dm_suspend (struct mapped_device * md , struct dm_table * map ,
2730
+ unsigned suspend_flags , int interruptible )
2737
2731
{
2738
- struct dm_table * map = NULL ;
2739
- int r = 0 ;
2740
- int do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG ? 1 : 0 ;
2741
- int noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG ? 1 : 0 ;
2742
-
2743
- mutex_lock (& md -> suspend_lock );
2744
-
2745
- if (dm_suspended_md (md )) {
2746
- r = - EINVAL ;
2747
- goto out_unlock ;
2748
- }
2749
-
2750
- map = rcu_dereference (md -> map );
2732
+ bool do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG ;
2733
+ bool noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG ;
2734
+ int r ;
2751
2735
2752
2736
/*
2753
2737
* DMF_NOFLUSH_SUSPENDING must be set before presuspend.
@@ -2772,7 +2756,7 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
2772
2756
r = lock_fs (md );
2773
2757
if (r ) {
2774
2758
dm_table_presuspend_undo_targets (map );
2775
- goto out_unlock ;
2759
+ return r ;
2776
2760
}
2777
2761
}
2778
2762
@@ -2806,7 +2790,7 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
2806
2790
* We call dm_wait_for_completion to wait for all existing requests
2807
2791
* to finish.
2808
2792
*/
2809
- r = dm_wait_for_completion (md , TASK_INTERRUPTIBLE );
2793
+ r = dm_wait_for_completion (md , interruptible );
2810
2794
2811
2795
if (noflush )
2812
2796
clear_bit (DMF_NOFLUSH_SUSPENDING , & md -> flags );
@@ -2822,14 +2806,55 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
2822
2806
2823
2807
unlock_fs (md );
2824
2808
dm_table_presuspend_undo_targets (map );
2825
- goto out_unlock ; /* pushback list is already flushed, so skip flush */
2809
+ /* pushback list is already flushed, so skip flush */
2826
2810
}
2827
2811
2828
- /*
2829
- * If dm_wait_for_completion returned 0, the device is completely
2830
- * quiescent now. There is no request-processing activity. All new
2831
- * requests are being added to md->deferred list.
2832
- */
2812
+ return r ;
2813
+ }
2814
+
2815
+ /*
2816
+ * We need to be able to change a mapping table under a mounted
2817
+ * filesystem. For example we might want to move some data in
2818
+ * the background. Before the table can be swapped with
2819
+ * dm_bind_table, dm_suspend must be called to flush any in
2820
+ * flight bios and ensure that any further io gets deferred.
2821
+ */
2822
+ /*
2823
+ * Suspend mechanism in request-based dm.
2824
+ *
2825
+ * 1. Flush all I/Os by lock_fs() if needed.
2826
+ * 2. Stop dispatching any I/O by stopping the request_queue.
2827
+ * 3. Wait for all in-flight I/Os to be completed or requeued.
2828
+ *
2829
+ * To abort suspend, start the request_queue.
2830
+ */
2831
+ int dm_suspend (struct mapped_device * md , unsigned suspend_flags )
2832
+ {
2833
+ struct dm_table * map = NULL ;
2834
+ int r = 0 ;
2835
+
2836
+ retry :
2837
+ mutex_lock_nested (& md -> suspend_lock , SINGLE_DEPTH_NESTING );
2838
+
2839
+ if (dm_suspended_md (md )) {
2840
+ r = - EINVAL ;
2841
+ goto out_unlock ;
2842
+ }
2843
+
2844
+ if (dm_suspended_internally_md (md )) {
2845
+ /* already internally suspended, wait for internal resume */
2846
+ mutex_unlock (& md -> suspend_lock );
2847
+ r = wait_on_bit (& md -> flags , DMF_SUSPENDED_INTERNALLY , TASK_INTERRUPTIBLE );
2848
+ if (r )
2849
+ return r ;
2850
+ goto retry ;
2851
+ }
2852
+
2853
+ map = rcu_dereference (md -> map );
2854
+
2855
+ r = __dm_suspend (md , map , suspend_flags , TASK_INTERRUPTIBLE );
2856
+ if (r )
2857
+ goto out_unlock ;
2833
2858
2834
2859
set_bit (DMF_SUSPENDED , & md -> flags );
2835
2860
@@ -2840,35 +2865,57 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
2840
2865
return r ;
2841
2866
}
2842
2867
2868
+ static int __dm_resume (struct mapped_device * md , struct dm_table * map )
2869
+ {
2870
+ if (map ) {
2871
+ int r = dm_table_resume_targets (map );
2872
+ if (r )
2873
+ return r ;
2874
+ }
2875
+
2876
+ dm_queue_flush (md );
2877
+
2878
+ /*
2879
+ * Flushing deferred I/Os must be done after targets are resumed
2880
+ * so that mapping of targets can work correctly.
2881
+ * Request-based dm is queueing the deferred I/Os in its request_queue.
2882
+ */
2883
+ if (dm_request_based (md ))
2884
+ start_queue (md -> queue );
2885
+
2886
+ unlock_fs (md );
2887
+
2888
+ return 0 ;
2889
+ }
2890
+
2843
2891
int dm_resume (struct mapped_device * md )
2844
2892
{
2845
2893
int r = - EINVAL ;
2846
2894
struct dm_table * map = NULL ;
2847
2895
2848
- mutex_lock (& md -> suspend_lock );
2896
+ retry :
2897
+ mutex_lock_nested (& md -> suspend_lock , SINGLE_DEPTH_NESTING );
2898
+
2849
2899
if (!dm_suspended_md (md ))
2850
2900
goto out ;
2851
2901
2902
+ if (dm_suspended_internally_md (md )) {
2903
+ /* already internally suspended, wait for internal resume */
2904
+ mutex_unlock (& md -> suspend_lock );
2905
+ r = wait_on_bit (& md -> flags , DMF_SUSPENDED_INTERNALLY , TASK_INTERRUPTIBLE );
2906
+ if (r )
2907
+ return r ;
2908
+ goto retry ;
2909
+ }
2910
+
2852
2911
map = rcu_dereference (md -> map );
2853
2912
if (!map || !dm_table_get_size (map ))
2854
2913
goto out ;
2855
2914
2856
- r = dm_table_resume_targets ( map );
2915
+ r = __dm_resume ( md , map );
2857
2916
if (r )
2858
2917
goto out ;
2859
2918
2860
- dm_queue_flush (md );
2861
-
2862
- /*
2863
- * Flushing deferred I/Os must be done after targets are resumed
2864
- * so that mapping of targets can work correctly.
2865
- * Request-based dm is queueing the deferred I/Os in its request_queue.
2866
- */
2867
- if (dm_request_based (md ))
2868
- start_queue (md -> queue );
2869
-
2870
- unlock_fs (md );
2871
-
2872
2919
clear_bit (DMF_SUSPENDED , & md -> flags );
2873
2920
2874
2921
r = 0 ;
@@ -2882,15 +2929,80 @@ int dm_resume(struct mapped_device *md)
2882
2929
* Internal suspend/resume works like userspace-driven suspend. It waits
2883
2930
* until all bios finish and prevents issuing new bios to the target drivers.
2884
2931
* It may be used only from the kernel.
2885
- *
2886
- * Internal suspend holds md->suspend_lock, which prevents interaction with
2887
- * userspace-driven suspend.
2888
2932
*/
2889
2933
2890
- void dm_internal_suspend (struct mapped_device * md )
2934
+ static void __dm_internal_suspend (struct mapped_device * md , unsigned suspend_flags )
2891
2935
{
2892
- mutex_lock (& md -> suspend_lock );
2936
+ struct dm_table * map = NULL ;
2937
+
2938
+ if (dm_suspended_internally_md (md ))
2939
+ return ; /* nested internal suspend */
2940
+
2941
+ if (dm_suspended_md (md )) {
2942
+ set_bit (DMF_SUSPENDED_INTERNALLY , & md -> flags );
2943
+ return ; /* nest suspend */
2944
+ }
2945
+
2946
+ map = rcu_dereference (md -> map );
2947
+
2948
+ /*
2949
+ * Using TASK_UNINTERRUPTIBLE because only NOFLUSH internal suspend is
2950
+ * supported. Properly supporting a TASK_INTERRUPTIBLE internal suspend
2951
+ * would require changing .presuspend to return an error -- avoid this
2952
+ * until there is a need for more elaborate variants of internal suspend.
2953
+ */
2954
+ (void ) __dm_suspend (md , map , suspend_flags , TASK_UNINTERRUPTIBLE );
2955
+
2956
+ set_bit (DMF_SUSPENDED_INTERNALLY , & md -> flags );
2957
+
2958
+ dm_table_postsuspend_targets (map );
2959
+ }
2960
+
2961
+ static void __dm_internal_resume (struct mapped_device * md )
2962
+ {
2963
+ if (!dm_suspended_internally_md (md ))
2964
+ return ; /* resume from nested internal suspend */
2965
+
2893
2966
if (dm_suspended_md (md ))
2967
+ goto done ; /* resume from nested suspend */
2968
+
2969
+ /*
2970
+ * NOTE: existing callers don't need to call dm_table_resume_targets
2971
+ * (which may fail -- so best to avoid it for now by passing NULL map)
2972
+ */
2973
+ (void ) __dm_resume (md , NULL );
2974
+
2975
+ done :
2976
+ clear_bit (DMF_SUSPENDED_INTERNALLY , & md -> flags );
2977
+ smp_mb__after_atomic ();
2978
+ wake_up_bit (& md -> flags , DMF_SUSPENDED_INTERNALLY );
2979
+ }
2980
+
2981
+ void dm_internal_suspend_noflush (struct mapped_device * md )
2982
+ {
2983
+ mutex_lock (& md -> suspend_lock );
2984
+ __dm_internal_suspend (md , DM_SUSPEND_NOFLUSH_FLAG );
2985
+ mutex_unlock (& md -> suspend_lock );
2986
+ }
2987
+ EXPORT_SYMBOL_GPL (dm_internal_suspend_noflush );
2988
+
2989
+ void dm_internal_resume (struct mapped_device * md )
2990
+ {
2991
+ mutex_lock (& md -> suspend_lock );
2992
+ __dm_internal_resume (md );
2993
+ mutex_unlock (& md -> suspend_lock );
2994
+ }
2995
+ EXPORT_SYMBOL_GPL (dm_internal_resume );
2996
+
2997
+ /*
2998
+ * Fast variants of internal suspend/resume hold md->suspend_lock,
2999
+ * which prevents interaction with userspace-driven suspend.
3000
+ */
3001
+
3002
+ void dm_internal_suspend_fast (struct mapped_device * md )
3003
+ {
3004
+ mutex_lock (& md -> suspend_lock );
3005
+ if (dm_suspended_md (md ) || dm_suspended_internally_md (md ))
2894
3006
return ;
2895
3007
2896
3008
set_bit (DMF_BLOCK_IO_FOR_SUSPEND , & md -> flags );
@@ -2899,9 +3011,9 @@ void dm_internal_suspend(struct mapped_device *md)
2899
3011
dm_wait_for_completion (md , TASK_UNINTERRUPTIBLE );
2900
3012
}
2901
3013
2902
- void dm_internal_resume (struct mapped_device * md )
3014
+ void dm_internal_resume_fast (struct mapped_device * md )
2903
3015
{
2904
- if (dm_suspended_md (md ))
3016
+ if (dm_suspended_md (md ) || dm_suspended_internally_md ( md ) )
2905
3017
goto done ;
2906
3018
2907
3019
dm_queue_flush (md );
@@ -2987,6 +3099,11 @@ int dm_suspended_md(struct mapped_device *md)
2987
3099
return test_bit (DMF_SUSPENDED , & md -> flags );
2988
3100
}
2989
3101
3102
+ int dm_suspended_internally_md (struct mapped_device * md )
3103
+ {
3104
+ return test_bit (DMF_SUSPENDED_INTERNALLY , & md -> flags );
3105
+ }
3106
+
2990
3107
int dm_test_deferred_remove_flag (struct mapped_device * md )
2991
3108
{
2992
3109
return test_bit (DMF_DEFERRED_REMOVE , & md -> flags );
0 commit comments