From: NeilBrown Date: Thu, 14 Feb 2013 05:30:29 +0000 (+1100) Subject: bestmatch: improve poor matches. X-Git-Tag: v1.0~62 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=20f3c4e3aff6d4a1479974b0ff095bdfc00d4e23;p=wiggle.git bestmatch: improve poor matches. If the bestmatch doens't include all of the lines in a hunk, try to find matches between the unmatch parts of the hunk, and surrounding text in the original. This is particularly useful when some of the context is just blank lines. The best-match algorithm might ignore blank lines because they aren't big enough to justify much distance from the rest of the match. This makes tests/linux/raid1-A/merge a lot nicer. Signed-off-by: NeilBrown --- diff --git a/bestmatch.c b/bestmatch.c index e839cb0..578dc0b 100644 --- a/bestmatch.c +++ b/bestmatch.c @@ -468,6 +468,7 @@ struct csl *pdiff(struct file a, struct file b, int chunks) struct best *best = xmalloc(sizeof(struct best)*(chunks+1)); int i; struct file asmall, bsmall; + int xmin; asmall = reduce(a); bsmall = reduce(b); @@ -484,12 +485,70 @@ struct csl *pdiff(struct file a, struct file b, int chunks) free(bsmall.list); csl1 = NULL; + xmin = 0; for (i = 1; i <= chunks; i++) if (best[i].val > 0) { + /* If we there are any newlines in the hunk before + * ylo, then extend xlo back that many newlines if + * possible and diff_partial the extended regions. + */ + int lines = 0; + int ylo = best[i].ylo; + int yhi; + while (ylo > 0 && b.list[ylo-1].start[0]) { + ylo--; + lines += !!ends_line(b.list[ylo]); + } + if (lines) { + int xlo = best[i].xlo; + while (lines && xlo > xmin) { + xlo--; + lines -= !!ends_line(a.list[xlo]); + } + while (xlo > xmin && !ends_line(a.list[xlo-1])) + xlo--; + csl2 = diff_partial(a, b, + xlo, best[i].xlo, + ylo, best[i].ylo); + csl1 = csl_join(csl1, csl2); + } + + /* Now diff_partial the good bit of the hunk with the + * good match + */ csl2 = diff_partial(a, b, best[i].xlo, best[i].xhi, best[i].ylo, best[i].yhi); csl1 = csl_join(csl1, csl2); + + /* Now if there are newlines at the end of the + * hunk that weren't matched, find as many in + * original and diff_partial those bits + */ + lines = 0; + yhi = best[i].yhi; + while (yhi < b.elcnt && b.list[yhi].start[0]) { + lines += !!ends_line(b.list[yhi]); + yhi++; + } + xmin = best[i].xhi; + if (lines) { + int xhi = best[i].xhi; + int xmax = a.elcnt; + if (i < chunks) + xmax = best[i+1].xlo; + while (lines && xhi < xmax) { + lines -= !!ends_line(a.list[xhi]); + xhi++; + } + csl2 = diff_partial(a, b, + best[i].xhi, xhi, + best[i].yhi, yhi); + csl1 = csl_join(csl1, csl2); + xmin = xhi; + } + } else { + /* FIXME we just lost a hunk!! */; } if (csl1) { for (csl2 = csl1; csl2->len; csl2++) diff --git a/tests/linux/md-resync/merge b/tests/linux/md-resync/merge index b3d93fb..8118461 100644 --- a/tests/linux/md-resync/merge +++ b/tests/linux/md-resync/merge @@ -1474,11 +1474,15 @@ nomem: raid1_shrink_buffers(conf); return -ENOMEM; } + +static void end_sync_read(struct buffer_head *bh, int uptodate) ||||||| if (!sector_nr) if (init_resync(conf)) return -ENOMEM; /* + * If there is non-resync activity waiting for us then + * put in a delay to throttle resync. ======= if (sector_nr == 0) if (init_resync(conf)) @@ -1491,9 +1495,9 @@ nomem: } /* + * If there is non-resync activity waiting for us then + * put in a delay to throttle resync. >>>>>>> - -static void end_sync_read(struct buffer_head *bh, int uptodate) { struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_private); @@ -1516,11 +1520,25 @@ static void end_sync_write(struct buffer_head *bh, int uptodate) md_error (r1_bh->mddev, bh->b_dev); if (atomic_dec_and_test(&r1_bh->remaining)) { mddev_t *mddev = r1_bh->mddev; +<<<<<<< unsigned long sect = bh->b_blocknr; int size = bh->b_size; raid1_free_buf(r1_bh); sync_request_done(sect, mddev_to_conf(mddev)); md_done_sync(mddev,size>>9, uptodate); +||||||| + r1_bio->sector = sector_nr; + r1_bio->cmd = SPECIAL; + + max_sector = mddev->sb->size << 1; + if (sector_nr >= max_sector) + BUG(); + +======= + r1_bio->sector = sector_nr; + r1_bio->cmd = SPECIAL; + +>>>>>>> } } diff --git a/tests/linux/raid1-A/merge b/tests/linux/raid1-A/merge index 8361ac4..eac9718 100644 --- a/tests/linux/raid1-A/merge +++ b/tests/linux/raid1-A/merge @@ -936,12 +936,14 @@ static int make_request(mddev_t *mddev, struct bio * bio) bio_list_add(&conf->pending_bio_list, mbio); spin_unlock_irqrestore(&conf->device_lock, flags); } + r1_bio_write_done(r1_bio); ||||||| test_bit(R1BIO_BehindIO, &r1_bio->state)); spin_lock_irqsave(&conf->device_lock, flags); bio_list_merge(&conf->pending_bio_list, &bl); bio_list_init(&bl); + blk_plug_device(mddev->queue); ======= test_bit(R1BIO_BehindIO, &r1_bio->state)); spin_lock_irqsave(&conf->device_lock, flags); @@ -949,8 +951,8 @@ static int make_request(mddev_t *mddev, struct bio * bio) conf->pending_count += bl_count; bio_list_init(&bl); + blk_plug_device(mddev->queue); >>>>>>> - r1_bio_write_done(r1_bio); /* In case raid1d snuck in to freeze_array */ wake_up(&conf->wait_barrier); @@ -1954,6 +1956,16 @@ static conf_t *setup_conf(mddev_t *mddev) conf->last_used = -1; for (i = 0; i < conf->raid_disks; i++) { +||||||| + bio_list_init(&conf->flushing_bio_list); + + +======= + conf->pending_count = 0; + bio_list_init(&conf->flushing_bio_list); + + +>>>>>>> disk = conf->mirrors + i; @@ -2317,13 +2329,3 @@ MODULE_ALIAS("md-raid1"); MODULE_ALIAS("md-level-1"); module_param(max_queued, int, S_IRUGO|S_IWUSR); -||||||| - bio_list_init(&conf->flushing_bio_list); - - -======= - conf->pending_count = 0; - bio_list_init(&conf->flushing_bio_list); - - ->>>>>>>