@@ -186,6 +186,7 @@ struct dm_integrity_c {
186
186
187
187
/* these variables are locked with endio_wait.lock */
188
188
struct rb_root in_progress ;
189
+ struct list_head wait_list ;
189
190
wait_queue_head_t endio_wait ;
190
191
struct workqueue_struct * wait_wq ;
191
192
@@ -233,7 +234,14 @@ struct dm_integrity_c {
233
234
struct dm_integrity_range {
234
235
sector_t logical_sector ;
235
236
unsigned n_sectors ;
236
- struct rb_node node ;
237
+ bool waiting ;
238
+ union {
239
+ struct rb_node node ;
240
+ struct {
241
+ struct task_struct * task ;
242
+ struct list_head wait_entry ;
243
+ };
244
+ };
237
245
};
238
246
239
247
struct dm_integrity_io {
@@ -867,13 +875,27 @@ static void copy_from_journal(struct dm_integrity_c *ic, unsigned section, unsig
867
875
}
868
876
}
869
877
870
- static bool add_new_range (struct dm_integrity_c * ic , struct dm_integrity_range * new_range )
878
+ static bool ranges_overlap (struct dm_integrity_range * range1 , struct dm_integrity_range * range2 )
879
+ {
880
+ return range1 -> logical_sector < range2 -> logical_sector + range2 -> n_sectors &&
881
+ range2 -> logical_sector + range2 -> n_sectors > range2 -> logical_sector ;
882
+ }
883
+
884
+ static bool add_new_range (struct dm_integrity_c * ic , struct dm_integrity_range * new_range , bool check_waiting )
871
885
{
872
886
struct rb_node * * n = & ic -> in_progress .rb_node ;
873
887
struct rb_node * parent ;
874
888
875
889
BUG_ON ((new_range -> logical_sector | new_range -> n_sectors ) & (unsigned )(ic -> sectors_per_block - 1 ));
876
890
891
+ if (likely (check_waiting )) {
892
+ struct dm_integrity_range * range ;
893
+ list_for_each_entry (range , & ic -> wait_list , wait_entry ) {
894
+ if (unlikely (ranges_overlap (range , new_range )))
895
+ return false;
896
+ }
897
+ }
898
+
877
899
parent = NULL ;
878
900
879
901
while (* n ) {
@@ -898,7 +920,22 @@ static bool add_new_range(struct dm_integrity_c *ic, struct dm_integrity_range *
898
920
static void remove_range_unlocked (struct dm_integrity_c * ic , struct dm_integrity_range * range )
899
921
{
900
922
rb_erase (& range -> node , & ic -> in_progress );
901
- wake_up_locked (& ic -> endio_wait );
923
+ while (unlikely (!list_empty (& ic -> wait_list ))) {
924
+ struct dm_integrity_range * last_range =
925
+ list_first_entry (& ic -> wait_list , struct dm_integrity_range , wait_entry );
926
+ struct task_struct * last_range_task ;
927
+ if (!ranges_overlap (range , last_range ))
928
+ break ;
929
+ last_range_task = last_range -> task ;
930
+ list_del (& last_range -> wait_entry );
931
+ if (!add_new_range (ic , last_range , false)) {
932
+ last_range -> task = last_range_task ;
933
+ list_add (& last_range -> wait_entry , & ic -> wait_list );
934
+ break ;
935
+ }
936
+ last_range -> waiting = false;
937
+ wake_up_process (last_range_task );
938
+ }
902
939
}
903
940
904
941
static void remove_range (struct dm_integrity_c * ic , struct dm_integrity_range * range )
@@ -910,6 +947,19 @@ static void remove_range(struct dm_integrity_c *ic, struct dm_integrity_range *r
910
947
spin_unlock_irqrestore (& ic -> endio_wait .lock , flags );
911
948
}
912
949
950
+ static void wait_and_add_new_range (struct dm_integrity_c * ic , struct dm_integrity_range * new_range )
951
+ {
952
+ new_range -> waiting = true;
953
+ list_add_tail (& new_range -> wait_entry , & ic -> wait_list );
954
+ new_range -> task = current ;
955
+ do {
956
+ __set_current_state (TASK_UNINTERRUPTIBLE );
957
+ spin_unlock_irq (& ic -> endio_wait .lock );
958
+ io_schedule ();
959
+ spin_lock_irq (& ic -> endio_wait .lock );
960
+ } while (unlikely (new_range -> waiting ));
961
+ }
962
+
913
963
static void init_journal_node (struct journal_node * node )
914
964
{
915
965
RB_CLEAR_NODE (& node -> node );
@@ -1658,7 +1708,7 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
1658
1708
}
1659
1709
}
1660
1710
}
1661
- if (unlikely (!add_new_range (ic , & dio -> range ))) {
1711
+ if (unlikely (!add_new_range (ic , & dio -> range , true ))) {
1662
1712
/*
1663
1713
* We must not sleep in the request routine because it could
1664
1714
* stall bios on current->bio_list.
@@ -1670,10 +1720,8 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
1670
1720
INIT_WORK (& dio -> work , integrity_bio_wait );
1671
1721
queue_work (ic -> wait_wq , & dio -> work );
1672
1722
return ;
1673
- } else {
1674
- sleep_on_endio_wait (ic );
1675
- goto retry ;
1676
1723
}
1724
+ wait_and_add_new_range (ic , & dio -> range );
1677
1725
}
1678
1726
spin_unlock_irq (& ic -> endio_wait .lock );
1679
1727
@@ -1896,8 +1944,8 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
1896
1944
io -> range .n_sectors = (k - j ) << ic -> sb -> log2_sectors_per_block ;
1897
1945
1898
1946
spin_lock_irq (& ic -> endio_wait .lock );
1899
- while (unlikely (!add_new_range (ic , & io -> range )))
1900
- sleep_on_endio_wait (ic );
1947
+ if (unlikely (!add_new_range (ic , & io -> range , true )))
1948
+ wait_and_add_new_range (ic , & io -> range );
1901
1949
1902
1950
if (likely (!from_replay )) {
1903
1951
struct journal_node * section_node = & ic -> journal_tree [i * ic -> journal_section_entries ];
@@ -2852,6 +2900,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
2852
2900
ti -> per_io_data_size = sizeof (struct dm_integrity_io );
2853
2901
2854
2902
ic -> in_progress = RB_ROOT ;
2903
+ INIT_LIST_HEAD (& ic -> wait_list );
2855
2904
init_waitqueue_head (& ic -> endio_wait );
2856
2905
bio_list_init (& ic -> flush_bio_list );
2857
2906
init_waitqueue_head (& ic -> copy_to_journal_wait );
@@ -3196,6 +3245,7 @@ static void dm_integrity_dtr(struct dm_target *ti)
3196
3245
struct dm_integrity_c * ic = ti -> private ;
3197
3246
3198
3247
BUG_ON (!RB_EMPTY_ROOT (& ic -> in_progress ));
3248
+ BUG_ON (!list_empty (& ic -> wait_list ));
3199
3249
3200
3250
if (ic -> metadata_wq )
3201
3251
destroy_workqueue (ic -> metadata_wq );
0 commit comments