From d6b212f4b19da5301e6b6eca562e5c7a2a6e8c8d Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Wed, 8 Jun 2011 18:00:28 -0500 Subject: MD: raid5 do not set fullsync Add check to determine if a device needs full resync or if partial resync will do RAID 5 was assuming that if a device was not In_sync, it must undergo a full resync. We add a check to see if 'saved_raid_disk' is the same as 'raid_disk'. If it is, we can safely skip the full resync and rely on the bitmap for partial recovery instead. This is the legitimate purpose of 'saved_raid_disk', from md.h: int saved_raid_disk; /* role that device used to have in the * array and could again if we did a partial * resync from the bitmap */ Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/raid5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/md/raid5.c') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 346e69bfdab3..f9d2fbc64977 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4858,7 +4858,7 @@ static raid5_conf_t *setup_conf(mddev_t *mddev) printk(KERN_INFO "md/raid:%s: device %s operational as raid" " disk %d\n", mdname(mddev), bdevname(rdev->bdev, b), raid_disk); - } else + } else if (rdev->saved_raid_disk != raid_disk) /* Cannot rely on bitmap to complete recovery */ conf->fullsync = 1; } -- cgit v1.2.3 From 9b2dc8b665932a8e681a7ab3237f60475e75e161 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 13 Jun 2011 14:48:22 +0900 Subject: md/raid5: fix raid5_set_bi_hw_segments The @bio->bi_phys_segments consists of active stripes count in the lower 16 bits and processed stripes count in the upper 16 bits. So logical-OR operator should be bitwise one. This bug has been present since 2.6.27 and the fix is suitable for any -stable kernel since then. Fortunately the bad code is only used on error paths and is relatively unlikely to be hit. Cc: stable@kernel.org Signed-off-by: Namhyung Kim Signed-off-by: NeilBrown --- drivers/md/raid5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/md/raid5.c') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index f9d2fbc64977..af8a9a89e4da 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -129,7 +129,7 @@ static inline int raid5_dec_bi_hw_segments(struct bio *bio) static inline void raid5_set_bi_hw_segments(struct bio *bio, unsigned int cnt) { - bio->bi_phys_segments = raid5_bi_phys_segments(bio) || (cnt << 16); + bio->bi_phys_segments = raid5_bi_phys_segments(bio) | (cnt << 16); } /* Find first data disk in a raid6 stripe */ -- cgit v1.2.3 From b062962edb086011e94ec4d9eb3f6a6d814f2a8f Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 14 Jun 2011 14:20:19 +1000 Subject: md/raid5: fix FUA request handling in ops_run_io() Commit e9c7469bb4f5 ("md: implment REQ_FLUSH/FUA support") introduced R5_WantFUA flag and set rw to WRITE_FUA in that case. However remaining code still checks whether rw is exactly same as WRITE or not, so FUAed-write ends up with being treated as READ. Fix it. This bug has been present since 2.6.37 and the fix is suitable for any -stable kernel since then. It is not clear why this has not caused more problems. Cc: Tejun Heo Cc: stable@kernel.org Signed-off-by: Namhyung Kim Signed-off-by: NeilBrown --- 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 af8a9a89e4da..b7dcc677dda4 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -514,7 +514,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) bi = &sh->dev[i].req; bi->bi_rw = rw; - if (rw == WRITE) + if (rw & WRITE) bi->bi_end_io = raid5_end_write_request; else bi->bi_end_io = raid5_end_read_request; @@ -548,13 +548,13 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) bi->bi_io_vec[0].bv_offset = 0; bi->bi_size = STRIPE_SIZE; bi->bi_next = NULL; - if (rw == WRITE && + if ((rw & WRITE) && test_bit(R5_ReWrite, &sh->dev[i].flags)) atomic_add(STRIPE_SECTORS, &rdev->corrected_errors); generic_make_request(bi); } else { - if (rw == WRITE) + if (rw & WRITE) set_bit(STRIPE_DEGRADED, &sh->state); pr_debug("skip op %ld on disc %d for sector %llu\n", bi->bi_rw, i, (unsigned long long)sh->sector); -- cgit v1.2.3 From fcde90759a985d8bfa4391346a821cc12fc16207 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 14 Jun 2011 14:23:57 +1000 Subject: md/raid5: remove unusual use of bio_iovec_idx() In the bio_for_each_segment loop, bvl always points current bio_vec, so the same as bio_iovec_idx(, i). Let's get rid of it. Cc: Dan Williams Signed-off-by: Namhyung Kim Signed-off-by: NeilBrown --- 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 b7dcc677dda4..b72edf35ec54 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -585,7 +585,7 @@ async_copy_data(int frombio, struct bio *bio, struct page *page, init_async_submit(&submit, flags, tx, NULL, NULL, NULL); bio_for_each_segment(bvl, bio, i) { - int len = bio_iovec_idx(bio, i)->bv_len; + int len = bvl->bv_len; int clen; int b_offset = 0; @@ -601,8 +601,8 @@ async_copy_data(int frombio, struct bio *bio, struct page *page, clen = len; if (clen > 0) { - b_offset += bio_iovec_idx(bio, i)->bv_offset; - bio_page = bio_iovec_idx(bio, i)->bv_page; + b_offset += bvl->bv_offset; + bio_page = bvl->bv_page; if (frombio) tx = async_memcpy(page, bio_page, page_offset, b_offset, clen, &submit); -- cgit v1.2.3