aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorShaohua Li <shli@kernel.org>2012-07-19 02:01:31 -0400
committerNeilBrown <neilb@suse.de>2012-07-19 02:01:31 -0400
commit4eb788df670ef30a19b7ea15b107ea440544bc80 (patch)
tree6a99872db014f67e43312afd4a93b3bcffe64506 /drivers/md
parent58e94ae18478c08229626daece2fc108a4a23261 (diff)
raid5: reduce chance release_stripe() taking device_lock
release_stripe() is a place conf->device_lock is heavily contended. We take the lock even stripe count isn't 1, which isn't required. Signed-off-by: Shaohua Li <shli@fusionio.com> Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/raid5.c75
1 files changed, 41 insertions, 34 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 04348d76bb30..848034666342 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -190,49 +190,56 @@ static int stripe_operations_active(struct stripe_head *sh)
190 test_bit(STRIPE_COMPUTE_RUN, &sh->state); 190 test_bit(STRIPE_COMPUTE_RUN, &sh->state);
191} 191}
192 192
193static void __release_stripe(struct r5conf *conf, struct stripe_head *sh) 193static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh)
194{ 194{
195 if (atomic_dec_and_test(&sh->count)) { 195 BUG_ON(!list_empty(&sh->lru));
196 BUG_ON(!list_empty(&sh->lru)); 196 BUG_ON(atomic_read(&conf->active_stripes)==0);
197 BUG_ON(atomic_read(&conf->active_stripes)==0); 197 if (test_bit(STRIPE_HANDLE, &sh->state)) {
198 if (test_bit(STRIPE_HANDLE, &sh->state)) { 198 if (test_bit(STRIPE_DELAYED, &sh->state) &&
199 if (test_bit(STRIPE_DELAYED, &sh->state) && 199 !test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
200 !test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) 200 list_add_tail(&sh->lru, &conf->delayed_list);
201 list_add_tail(&sh->lru, &conf->delayed_list); 201 else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
202 else if (test_bit(STRIPE_BIT_DELAY, &sh->state) && 202 sh->bm_seq - conf->seq_write > 0)
203 sh->bm_seq - conf->seq_write > 0) 203 list_add_tail(&sh->lru, &conf->bitmap_list);
204 list_add_tail(&sh->lru, &conf->bitmap_list); 204 else {
205 else { 205 clear_bit(STRIPE_DELAYED, &sh->state);
206 clear_bit(STRIPE_DELAYED, &sh->state); 206 clear_bit(STRIPE_BIT_DELAY, &sh->state);
207 clear_bit(STRIPE_BIT_DELAY, &sh->state); 207 list_add_tail(&sh->lru, &conf->handle_list);
208 list_add_tail(&sh->lru, &conf->handle_list); 208 }
209 } 209 md_wakeup_thread(conf->mddev->thread);
210 md_wakeup_thread(conf->mddev->thread); 210 } else {
211 } else { 211 BUG_ON(stripe_operations_active(sh));
212 BUG_ON(stripe_operations_active(sh)); 212 if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
213 if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) 213 if (atomic_dec_return(&conf->preread_active_stripes)
214 if (atomic_dec_return(&conf->preread_active_stripes) 214 < IO_THRESHOLD)
215 < IO_THRESHOLD) 215 md_wakeup_thread(conf->mddev->thread);
216 md_wakeup_thread(conf->mddev->thread); 216 atomic_dec(&conf->active_stripes);
217 atomic_dec(&conf->active_stripes); 217 if (!test_bit(STRIPE_EXPANDING, &sh->state)) {
218 if (!test_bit(STRIPE_EXPANDING, &sh->state)) { 218 list_add_tail(&sh->lru, &conf->inactive_list);
219 list_add_tail(&sh->lru, &conf->inactive_list); 219 wake_up(&conf->wait_for_stripe);
220 wake_up(&conf->wait_for_stripe); 220 if (conf->retry_read_aligned)
221 if (conf->retry_read_aligned) 221 md_wakeup_thread(conf->mddev->thread);
222 md_wakeup_thread(conf->mddev->thread);
223 }
224 } 222 }
225 } 223 }
226} 224}
227 225
226static void __release_stripe(struct r5conf *conf, struct stripe_head *sh)
227{
228 if (atomic_dec_and_test(&sh->count))
229 do_release_stripe(conf, sh);
230}
231
228static void release_stripe(struct stripe_head *sh) 232static void release_stripe(struct stripe_head *sh)
229{ 233{
230 struct r5conf *conf = sh->raid_conf; 234 struct r5conf *conf = sh->raid_conf;
231 unsigned long flags; 235 unsigned long flags;
232 236
233 spin_lock_irqsave(&conf->device_lock, flags); 237 local_irq_save(flags);
234 __release_stripe(conf, sh); 238 if (atomic_dec_and_lock(&sh->count, &conf->device_lock)) {
235 spin_unlock_irqrestore(&conf->device_lock, flags); 239 do_release_stripe(conf, sh);
240 spin_unlock(&conf->device_lock);
241 }
242 local_irq_restore(flags);
236} 243}
237 244
238static inline void remove_hash(struct stripe_head *sh) 245static inline void remove_hash(struct stripe_head *sh)