Re: [BUG 2.6.32] md/raid1: barrier disabling does not work correctly in all cases

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jan 20, 2011 at 3:25 PM, NeilBrown <neilb@xxxxxxx> wrote:

> Nonetheless, I think the correct fix is to add a special case for retrying a
> zero-length.
>
> Something like this maybe?

Close, but no cigar...

Attached is a modified patch, which does the extra necessary work
(bitmap_endwrite, md_write_end) on the bio before failing it.

Does this look correct? It seems to work.

Thanks again Neil.

--
Paul
--- linux-2.6.32-71.el6.x86_64/drivers/md/raid1.c.PRISTINE	2011-01-14 14:51:56.959809669 -0500
+++ linux-2.6.32-71.el6.x86_64/drivers/md/raid1.c	2011-01-26 08:44:20.176936238 -0500
@@ -236,14 +236,18 @@ static void raid_end_bio_io(r1bio_t *r1_
 
 	/* if nobody has done the final endio yet, do it now */
 	if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
+		int err = 0;
 		PRINTK(KERN_DEBUG "raid1: sync end %s on sectors %llu-%llu\n",
 			(bio_data_dir(bio) == WRITE) ? "write" : "read",
 			(unsigned long long) bio->bi_sector,
 			(unsigned long long) bio->bi_sector +
 				(bio->bi_size >> 9) - 1);
 
-		bio_endio(bio,
-			test_bit(R1BIO_Uptodate, &r1_bio->state) ? 0 : -EIO);
+		if (test_bit(R1BIO_BarrierRetry, &r1_bio->state))
+			err = -EOPNOTSUPP;
+		else if (!test_bit(R1BIO_Uptodate, &r1_bio->state))
+			err = -EIO;
+		bio_endio(bio, err);
 	}
 	free_r1bio(r1_bio);
 }
@@ -1623,6 +1627,18 @@ static void raid1d(mddev_t *mddev)
 			 */
 			int i;
 			const bool do_sync = bio_rw_flagged(r1_bio->master_bio, BIO_RW_SYNCIO);
+			if (r1_bio->master_bio->bi_size == 0) {
+				/* cannot retry empty barriers, just fail */
+				bitmap_endwrite(r1_bio->mddev->bitmap,
+					r1_bio->sector,
+					r1_bio->sectors,
+					!test_bit(R1BIO_Degraded, &r1_bio->state),
+					test_bit(R1BIO_BehindIO, &r1_bio->state));
+				md_write_end(r1_bio->mddev);
+
+				raid_end_bio_io(r1_bio);
+				continue;
+			}
 			clear_bit(R1BIO_BarrierRetry, &r1_bio->state);
 			clear_bit(R1BIO_Barrier, &r1_bio->state);
 			for (i=0; i < conf->raid_disks; i++)
@@ -2139,7 +2155,7 @@ static int stop(mddev_t *mddev)
 	/* wait for behind writes to complete */
 	while (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
 		behind_wait++;
-		printk(KERN_INFO "raid1: behind writes in progress on device %s, waiting to stop (%d)\n", mdname(mddev), behind_wait);
+		printk(KERN_INFO "raid1: behind writes (%d) in progress on device %s, waiting to stop (%d)\n", atomic_read(&bitmap->behind_writes), mdname(mddev), behind_wait);
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule_timeout(HZ); /* wait a second */
 		/* need to kick something here to make sure I/O goes? */

[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux