diff options
-rw-r--r-- | drivers/md/raid5-cache.c | 79 |
1 files changed, 38 insertions, 41 deletions
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index 496f8e2578cc..6479f15a5434 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c | |||
@@ -215,46 +215,12 @@ static void r5l_compress_stripe_end_list(struct r5l_log *log) | |||
215 | list_add_tail(&last->log_sibling, &log->stripe_end_ios); | 215 | list_add_tail(&last->log_sibling, &log->stripe_end_ios); |
216 | } | 216 | } |
217 | 217 | ||
218 | static void r5l_wake_reclaim(struct r5l_log *log, sector_t space); | ||
219 | static void __r5l_set_io_unit_state(struct r5l_io_unit *io, | 218 | static void __r5l_set_io_unit_state(struct r5l_io_unit *io, |
220 | enum r5l_io_unit_state state) | 219 | enum r5l_io_unit_state state) |
221 | { | 220 | { |
222 | struct r5l_log *log = io->log; | ||
223 | |||
224 | if (WARN_ON(io->state >= state)) | 221 | if (WARN_ON(io->state >= state)) |
225 | return; | 222 | return; |
226 | io->state = state; | 223 | io->state = state; |
227 | if (state == IO_UNIT_IO_END) | ||
228 | r5l_move_io_unit_list(&log->running_ios, &log->io_end_ios, | ||
229 | IO_UNIT_IO_END); | ||
230 | if (state == IO_UNIT_STRIPE_END) { | ||
231 | struct r5l_io_unit *last; | ||
232 | sector_t reclaimable_space; | ||
233 | |||
234 | r5l_move_io_unit_list(&log->flushed_ios, &log->stripe_end_ios, | ||
235 | IO_UNIT_STRIPE_END); | ||
236 | |||
237 | last = list_last_entry(&log->stripe_end_ios, | ||
238 | struct r5l_io_unit, log_sibling); | ||
239 | reclaimable_space = r5l_ring_distance(log, log->last_checkpoint, | ||
240 | last->log_end); | ||
241 | if (reclaimable_space >= log->max_free_space) | ||
242 | r5l_wake_reclaim(log, 0); | ||
243 | |||
244 | r5l_compress_stripe_end_list(log); | ||
245 | wake_up(&log->iounit_wait); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | static void r5l_set_io_unit_state(struct r5l_io_unit *io, | ||
250 | enum r5l_io_unit_state state) | ||
251 | { | ||
252 | struct r5l_log *log = io->log; | ||
253 | unsigned long flags; | ||
254 | |||
255 | spin_lock_irqsave(&log->io_list_lock, flags); | ||
256 | __r5l_set_io_unit_state(io, state); | ||
257 | spin_unlock_irqrestore(&log->io_list_lock, flags); | ||
258 | } | 224 | } |
259 | 225 | ||
260 | /* XXX: totally ignores I/O errors */ | 226 | /* XXX: totally ignores I/O errors */ |
@@ -262,13 +228,19 @@ static void r5l_log_endio(struct bio *bio) | |||
262 | { | 228 | { |
263 | struct r5l_io_unit *io = bio->bi_private; | 229 | struct r5l_io_unit *io = bio->bi_private; |
264 | struct r5l_log *log = io->log; | 230 | struct r5l_log *log = io->log; |
231 | unsigned long flags; | ||
265 | 232 | ||
266 | bio_put(bio); | 233 | bio_put(bio); |
267 | 234 | ||
268 | if (!atomic_dec_and_test(&io->pending_io)) | 235 | if (!atomic_dec_and_test(&io->pending_io)) |
269 | return; | 236 | return; |
270 | 237 | ||
271 | r5l_set_io_unit_state(io, IO_UNIT_IO_END); | 238 | spin_lock_irqsave(&log->io_list_lock, flags); |
239 | __r5l_set_io_unit_state(io, IO_UNIT_IO_END); | ||
240 | r5l_move_io_unit_list(&log->running_ios, &log->io_end_ios, | ||
241 | IO_UNIT_IO_END); | ||
242 | spin_unlock_irqrestore(&log->io_list_lock, flags); | ||
243 | |||
272 | md_wakeup_thread(log->rdev->mddev->thread); | 244 | md_wakeup_thread(log->rdev->mddev->thread); |
273 | } | 245 | } |
274 | 246 | ||
@@ -277,6 +249,7 @@ static void r5l_submit_current_io(struct r5l_log *log) | |||
277 | struct r5l_io_unit *io = log->current_io; | 249 | struct r5l_io_unit *io = log->current_io; |
278 | struct r5l_meta_block *block; | 250 | struct r5l_meta_block *block; |
279 | struct bio *bio; | 251 | struct bio *bio; |
252 | unsigned long flags; | ||
280 | u32 crc; | 253 | u32 crc; |
281 | 254 | ||
282 | if (!io) | 255 | if (!io) |
@@ -288,7 +261,9 @@ static void r5l_submit_current_io(struct r5l_log *log) | |||
288 | block->checksum = cpu_to_le32(crc); | 261 | block->checksum = cpu_to_le32(crc); |
289 | 262 | ||
290 | log->current_io = NULL; | 263 | log->current_io = NULL; |
291 | r5l_set_io_unit_state(io, IO_UNIT_IO_START); | 264 | spin_lock_irqsave(&log->io_list_lock, flags); |
265 | __r5l_set_io_unit_state(io, IO_UNIT_IO_START); | ||
266 | spin_unlock_irqrestore(&log->io_list_lock, flags); | ||
292 | 267 | ||
293 | while ((bio = bio_list_pop(&io->bios))) { | 268 | while ((bio = bio_list_pop(&io->bios))) { |
294 | /* all IO must start from rdev->data_offset */ | 269 | /* all IO must start from rdev->data_offset */ |
@@ -454,6 +429,7 @@ static void r5l_log_stripe(struct r5l_log *log, struct stripe_head *sh, | |||
454 | sh->log_io = io; | 429 | sh->log_io = io; |
455 | } | 430 | } |
456 | 431 | ||
432 | static void r5l_wake_reclaim(struct r5l_log *log, sector_t space); | ||
457 | /* | 433 | /* |
458 | * running in raid5d, where reclaim could wait for raid5d too (when it flushes | 434 | * running in raid5d, where reclaim could wait for raid5d too (when it flushes |
459 | * data from log to raid disks), so we shouldn't wait for reclaim here | 435 | * data from log to raid disks), so we shouldn't wait for reclaim here |
@@ -547,18 +523,39 @@ static void r5l_run_no_space_stripes(struct r5l_log *log) | |||
547 | spin_unlock(&log->no_space_stripes_lock); | 523 | spin_unlock(&log->no_space_stripes_lock); |
548 | } | 524 | } |
549 | 525 | ||
526 | static void __r5l_stripe_write_finished(struct r5l_io_unit *io) | ||
527 | { | ||
528 | struct r5l_log *log = io->log; | ||
529 | struct r5l_io_unit *last; | ||
530 | sector_t reclaimable_space; | ||
531 | unsigned long flags; | ||
532 | |||
533 | spin_lock_irqsave(&log->io_list_lock, flags); | ||
534 | __r5l_set_io_unit_state(io, IO_UNIT_STRIPE_END); | ||
535 | r5l_move_io_unit_list(&log->flushed_ios, &log->stripe_end_ios, | ||
536 | IO_UNIT_STRIPE_END); | ||
537 | |||
538 | last = list_last_entry(&log->stripe_end_ios, | ||
539 | struct r5l_io_unit, log_sibling); | ||
540 | reclaimable_space = r5l_ring_distance(log, log->last_checkpoint, | ||
541 | last->log_end); | ||
542 | if (reclaimable_space >= log->max_free_space) | ||
543 | r5l_wake_reclaim(log, 0); | ||
544 | |||
545 | r5l_compress_stripe_end_list(log); | ||
546 | spin_unlock_irqrestore(&log->io_list_lock, flags); | ||
547 | wake_up(&log->iounit_wait); | ||
548 | } | ||
549 | |||
550 | void r5l_stripe_write_finished(struct stripe_head *sh) | 550 | void r5l_stripe_write_finished(struct stripe_head *sh) |
551 | { | 551 | { |
552 | struct r5l_io_unit *io; | 552 | struct r5l_io_unit *io; |
553 | 553 | ||
554 | /* Don't support stripe batch */ | ||
555 | io = sh->log_io; | 554 | io = sh->log_io; |
556 | if (!io) | ||
557 | return; | ||
558 | sh->log_io = NULL; | 555 | sh->log_io = NULL; |
559 | 556 | ||
560 | if (atomic_dec_and_test(&io->pending_stripe)) | 557 | if (io && atomic_dec_and_test(&io->pending_stripe)) |
561 | r5l_set_io_unit_state(io, IO_UNIT_STRIPE_END); | 558 | __r5l_stripe_write_finished(io); |
562 | } | 559 | } |
563 | 560 | ||
564 | static void r5l_log_flush_endio(struct bio *bio) | 561 | static void r5l_log_flush_endio(struct bio *bio) |