1818
1919#define MIN_CELLS 1024
2020
21- struct dm_bio_prison {
21+ struct prison_region {
2222 spinlock_t lock ;
23- struct rb_root cells ;
23+ struct rb_root cell ;
24+ } ____cacheline_aligned_in_smp ;
25+
26+ struct dm_bio_prison {
2427 mempool_t cell_pool ;
28+ unsigned int num_locks ;
29+ struct prison_region regions [];
2530};
2631
2732static struct kmem_cache * _cell_cache ;
@@ -34,22 +39,27 @@ static struct kmem_cache *_cell_cache;
3439 */
3540struct dm_bio_prison * dm_bio_prison_create (void )
3641{
37- struct dm_bio_prison * prison = kzalloc (sizeof (* prison ), GFP_KERNEL );
3842 int ret ;
43+ unsigned int i , num_locks ;
44+ struct dm_bio_prison * prison ;
3945
46+ num_locks = dm_num_hash_locks ();
47+ prison = kzalloc (struct_size (prison , regions , num_locks ), GFP_KERNEL );
4048 if (!prison )
4149 return NULL ;
50+ prison -> num_locks = num_locks ;
4251
43- spin_lock_init (& prison -> lock );
52+ for (i = 0 ; i < prison -> num_locks ; i ++ ) {
53+ spin_lock_init (& prison -> regions [i ].lock );
54+ prison -> regions [i ].cell = RB_ROOT ;
55+ }
4456
4557 ret = mempool_init_slab_pool (& prison -> cell_pool , MIN_CELLS , _cell_cache );
4658 if (ret ) {
4759 kfree (prison );
4860 return NULL ;
4961 }
5062
51- prison -> cells = RB_ROOT ;
52-
5363 return prison ;
5464}
5565EXPORT_SYMBOL_GPL (dm_bio_prison_create );
@@ -107,14 +117,32 @@ static int cmp_keys(struct dm_cell_key *lhs,
107117 return 0 ;
108118}
109119
110- static int __bio_detain (struct dm_bio_prison * prison ,
120+ static inline unsigned int lock_nr (struct dm_cell_key * key , unsigned int num_locks )
121+ {
122+ return dm_hash_locks_index ((key -> block_begin >> BIO_PRISON_MAX_RANGE_SHIFT ),
123+ num_locks );
124+ }
125+
126+ bool dm_cell_key_has_valid_range (struct dm_cell_key * key )
127+ {
128+ if (WARN_ON_ONCE (key -> block_end - key -> block_begin > BIO_PRISON_MAX_RANGE ))
129+ return false;
130+ if (WARN_ON_ONCE ((key -> block_begin >> BIO_PRISON_MAX_RANGE_SHIFT ) !=
131+ (key -> block_end - 1 ) >> BIO_PRISON_MAX_RANGE_SHIFT ))
132+ return false;
133+
134+ return true;
135+ }
136+ EXPORT_SYMBOL (dm_cell_key_has_valid_range );
137+
138+ static int __bio_detain (struct rb_root * root ,
111139 struct dm_cell_key * key ,
112140 struct bio * inmate ,
113141 struct dm_bio_prison_cell * cell_prealloc ,
114142 struct dm_bio_prison_cell * * cell_result )
115143{
116144 int r ;
117- struct rb_node * * new = & prison -> cells . rb_node , * parent = NULL ;
145+ struct rb_node * * new = & root -> rb_node , * parent = NULL ;
118146
119147 while (* new ) {
120148 struct dm_bio_prison_cell * cell =
@@ -139,7 +167,7 @@ static int __bio_detain(struct dm_bio_prison *prison,
139167 * cell_result = cell_prealloc ;
140168
141169 rb_link_node (& cell_prealloc -> node , parent , new );
142- rb_insert_color (& cell_prealloc -> node , & prison -> cells );
170+ rb_insert_color (& cell_prealloc -> node , root );
143171
144172 return 0 ;
145173}
@@ -151,10 +179,11 @@ static int bio_detain(struct dm_bio_prison *prison,
151179 struct dm_bio_prison_cell * * cell_result )
152180{
153181 int r ;
182+ unsigned l = lock_nr (key , prison -> num_locks );
154183
155- spin_lock_irq (& prison -> lock );
156- r = __bio_detain (prison , key , inmate , cell_prealloc , cell_result );
157- spin_unlock_irq (& prison -> lock );
184+ spin_lock_irq (& prison -> regions [ l ]. lock );
185+ r = __bio_detain (& prison -> regions [ l ]. cell , key , inmate , cell_prealloc , cell_result );
186+ spin_unlock_irq (& prison -> regions [ l ]. lock );
158187
159188 return r ;
160189}
@@ -181,11 +210,11 @@ EXPORT_SYMBOL_GPL(dm_get_cell);
181210/*
182211 * @inmates must have been initialised prior to this call
183212 */
184- static void __cell_release (struct dm_bio_prison * prison ,
213+ static void __cell_release (struct rb_root * root ,
185214 struct dm_bio_prison_cell * cell ,
186215 struct bio_list * inmates )
187216{
188- rb_erase (& cell -> node , & prison -> cells );
217+ rb_erase (& cell -> node , root );
189218
190219 if (inmates ) {
191220 if (cell -> holder )
@@ -198,32 +227,35 @@ void dm_cell_release(struct dm_bio_prison *prison,
198227 struct dm_bio_prison_cell * cell ,
199228 struct bio_list * bios )
200229{
201- spin_lock_irq (& prison -> lock );
202- __cell_release (prison , cell , bios );
203- spin_unlock_irq (& prison -> lock );
230+ unsigned l = lock_nr (& cell -> key , prison -> num_locks );
231+
232+ spin_lock_irq (& prison -> regions [l ].lock );
233+ __cell_release (& prison -> regions [l ].cell , cell , bios );
234+ spin_unlock_irq (& prison -> regions [l ].lock );
204235}
205236EXPORT_SYMBOL_GPL (dm_cell_release );
206237
207238/*
208239 * Sometimes we don't want the holder, just the additional bios.
209240 */
210- static void __cell_release_no_holder (struct dm_bio_prison * prison ,
241+ static void __cell_release_no_holder (struct rb_root * root ,
211242 struct dm_bio_prison_cell * cell ,
212243 struct bio_list * inmates )
213244{
214- rb_erase (& cell -> node , & prison -> cells );
245+ rb_erase (& cell -> node , root );
215246 bio_list_merge (inmates , & cell -> bios );
216247}
217248
218249void dm_cell_release_no_holder (struct dm_bio_prison * prison ,
219250 struct dm_bio_prison_cell * cell ,
220251 struct bio_list * inmates )
221252{
253+ unsigned l = lock_nr (& cell -> key , prison -> num_locks );
222254 unsigned long flags ;
223255
224- spin_lock_irqsave (& prison -> lock , flags );
225- __cell_release_no_holder (prison , cell , inmates );
226- spin_unlock_irqrestore (& prison -> lock , flags );
256+ spin_lock_irqsave (& prison -> regions [ l ]. lock , flags );
257+ __cell_release_no_holder (& prison -> regions [ l ]. cell , cell , inmates );
258+ spin_unlock_irqrestore (& prison -> regions [ l ]. lock , flags );
227259}
228260EXPORT_SYMBOL_GPL (dm_cell_release_no_holder );
229261
@@ -248,18 +280,19 @@ void dm_cell_visit_release(struct dm_bio_prison *prison,
248280 void * context ,
249281 struct dm_bio_prison_cell * cell )
250282{
251- spin_lock_irq (& prison -> lock );
283+ unsigned l = lock_nr (& cell -> key , prison -> num_locks );
284+ spin_lock_irq (& prison -> regions [l ].lock );
252285 visit_fn (context , cell );
253- rb_erase (& cell -> node , & prison -> cells );
254- spin_unlock_irq (& prison -> lock );
286+ rb_erase (& cell -> node , & prison -> regions [ l ]. cell );
287+ spin_unlock_irq (& prison -> regions [ l ]. lock );
255288}
256289EXPORT_SYMBOL_GPL (dm_cell_visit_release );
257290
258- static int __promote_or_release (struct dm_bio_prison * prison ,
291+ static int __promote_or_release (struct rb_root * root ,
259292 struct dm_bio_prison_cell * cell )
260293{
261294 if (bio_list_empty (& cell -> bios )) {
262- rb_erase (& cell -> node , & prison -> cells );
295+ rb_erase (& cell -> node , root );
263296 return 1 ;
264297 }
265298
@@ -271,10 +304,11 @@ int dm_cell_promote_or_release(struct dm_bio_prison *prison,
271304 struct dm_bio_prison_cell * cell )
272305{
273306 int r ;
307+ unsigned l = lock_nr (& cell -> key , prison -> num_locks );
274308
275- spin_lock_irq (& prison -> lock );
276- r = __promote_or_release (prison , cell );
277- spin_unlock_irq (& prison -> lock );
309+ spin_lock_irq (& prison -> regions [ l ]. lock );
310+ r = __promote_or_release (& prison -> regions [ l ]. cell , cell );
311+ spin_unlock_irq (& prison -> regions [ l ]. lock );
278312
279313 return r ;
280314}
0 commit comments