aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/raid5-cache.c79
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
218static void r5l_wake_reclaim(struct r5l_log *log, sector_t space);
219static void __r5l_set_io_unit_state(struct r5l_io_unit *io, 218static 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
249static 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
432static 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
526static 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
550void r5l_stripe_write_finished(struct stripe_head *sh) 550void 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
564static void r5l_log_flush_endio(struct bio *bio) 561static void r5l_log_flush_endio(struct bio *bio)