Skip to contentSkip to conversation

raid5: avoid find discard stripe

PATCH In review Shaohua Li 1 participant 1 message Oct 19, 2013 MD RAID

lore
Share & tools
lore

Shaohua Li

author
#0 lore raw

PATCH 2/2 raid5: avoid find discard stripe

SCSI discard will damage discard stripe bio setting, eg, some fields are changed. If the stripe is reused very soon, we have wrong bios setting. We remove discard stripe from hash list, so next time the strip will be fully initialized.

Suite for backport to 3.7+. Of course, the 'conf->hash_locks + sh->hash_lock_index' should be replaced to '&conf->device_lock' for old kernel.

---
 drivers/md/raid5.c |    9 +++++++++
 1 file changed, 9 insertions(+)
drivers/md/raid5.c +9 -0
Index: linux/drivers/md/raid5.c
===================================================================
@@ -3035,6 +3035,7 @@ static void handle_stripe_clean_event(st
 		}
 	if (!discard_pending &&
 	    test_bit(R5_Discard, &sh->dev[sh->pd_idx].flags)) {
+		unsigned long flags;
 		clear_bit(R5_Discard, &sh->dev[sh->pd_idx].flags);
 		clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags);
 		if (sh->qd_idx >= 0) {
@@ -3043,6 +3044,14 @@ static void handle_stripe_clean_event(st
 		}
 		/* now that discard is done we can proceed with any sync */
 		clear_bit(STRIPE_DISCARD, &sh->state);
+		/*
+		 * SCSI discard will change some bio fields and the stripe has
+		 * no updated data, so remove it from hash list and the stripe
+		 * will be reinitialized
+		 */
+		spin_lock_irqsave(conf->hash_locks + sh->hash_lock_index, flags);
+		remove_hash(sh);
+		spin_unlock_irqrestore(conf->hash_locks + sh->hash_lock_index, flags);
 		if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state))
 			set_bit(STRIPE_HANDLE, &sh->state);