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? */