From 2cd259a77de561d49c1ff939a239095749e65ee7 Mon Sep 17 00:00:00 2001 From: Mariusz Dabrowski Date: Thu, 19 Apr 2018 19:28:10 +0200 Subject: raid5: copy write hint from origin bio to stripe Store write hint from original bio in stripe head so it can be assigned to bio sent to each RAID device. Signed-off-by: Mariusz Dabrowski Reviewed-by: Artur Paszkiewicz Reviewed-by: Pawel Baldysiak Signed-off-by: Shaohua Li --- drivers/md/raid5.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/md/raid5.c') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index be117d0a65a8..1e1515c817ff 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1139,6 +1139,9 @@ again: bi->bi_io_vec[0].bv_len = STRIPE_SIZE; bi->bi_io_vec[0].bv_offset = 0; bi->bi_iter.bi_size = STRIPE_SIZE; + bi->bi_write_hint = sh->dev[i].write_hint; + if (!rrdev) + sh->dev[i].write_hint = RWF_WRITE_LIFE_NOT_SET; /* * If this is discard request, set bi_vcnt 0. We don't * want to confuse SCSI because SCSI will replace payload @@ -1190,6 +1193,8 @@ again: rbi->bi_io_vec[0].bv_len = STRIPE_SIZE; rbi->bi_io_vec[0].bv_offset = 0; rbi->bi_iter.bi_size = STRIPE_SIZE; + rbi->bi_write_hint = sh->dev[i].write_hint; + sh->dev[i].write_hint = RWF_WRITE_LIFE_NOT_SET; /* * If this is discard request, set bi_vcnt 0. We don't * want to confuse SCSI because SCSI will replace payload @@ -3204,6 +3209,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, (unsigned long long)sh->sector); spin_lock_irq(&sh->stripe_lock); + sh->dev[dd_idx].write_hint = bi->bi_write_hint; /* Don't allow new IO added to stripes in batch list */ if (sh->batch_head) goto overlap; -- cgit v1.2.3 From 448ec638c6bcf36923db695b6188373b933e7ddc Mon Sep 17 00:00:00 2001 From: Amy Chiang Date: Wed, 16 May 2018 18:59:35 +0800 Subject: md/raid5: Assigning NULL to sh->batch_head before testing bit R5_Overlap of a stripe In add_stripe_bio(), if the stripe_head is in batch list, the incoming bio is regarded as overlapping, and the bit R5_Overlap on this stripe_head is set. break_stripe_batch_list() checks bit R5_Overlap on each stripe_head first then assigns NULL to sh->batch_head. If break_stripe_batch_list() checks bit R5_Overlap on stripe_head A after add_stripe_bio() finds stripe_head A is in batch list and before add_stripe_bio() sets bit R5_Overlapt of stripe_head A, break_stripe_batch_list() would not know there's a process in wait_for_overlap and needs to call wake_up(). There's a huge chance a process never returns from schedule() if add_stripe_bio() is called from raid5_make_request(). In break_stripe_batch_list(), assigning NULL to sh->batch_head should be done before it checks bit R5_Overlap of a stripe_head. Signed-off-by: Amy Chiang Signed-off-by: Shaohua Li --- drivers/md/raid5.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/md/raid5.c') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 1e1515c817ff..d034a20a12be 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4620,15 +4620,15 @@ static void break_stripe_batch_list(struct stripe_head *head_sh, sh->check_state = head_sh->check_state; sh->reconstruct_state = head_sh->reconstruct_state; + spin_lock_irq(&sh->stripe_lock); + sh->batch_head = NULL; + spin_unlock_irq(&sh->stripe_lock); for (i = 0; i < sh->disks; i++) { if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) do_wakeup = 1; sh->dev[i].flags = head_sh->dev[i].flags & (~((1 << R5_WriteError) | (1 << R5_Overlap))); } - spin_lock_irq(&sh->stripe_lock); - sh->batch_head = NULL; - spin_unlock_irq(&sh->stripe_lock); if (handle_flags == 0 || sh->state & handle_flags) set_bit(STRIPE_HANDLE, &sh->state); -- cgit v1.2.3