>On Tue, 6 Nov 2012 18:36:33 +0800 majianpeng <majianpeng@xxxxxxxxx> wrote: > >> >On Tue, 6 Nov 2012 17:13:00 +0800 majianpeng <majianpeng@xxxxxxxxx> wrote: >> > >> >> If read_seqretry returned true and bbp was changed, it will write >> >> invalid address which can cause some serious problem. >> >> >> >> This bug was introduced by commit v3.0-rc7-130-g2699b67. >> >> So fix is suitable for 3.0.y thru 3.6.y. >> >> >> >> Reported-by: zhuwenfeng@xxxxxxxxxxx >> >> Tested-by: zhuwenfeng@xxxxxxxxxxx >> >> Cc: stable@xxxxxxxxxxxxxxx >> >> Signed-off-by: Jianpeng Ma <majianpeng@xxxxxxxxx> >> >> --- >> >> drivers/md/md.c | 4 ++-- >> >> 1 file changed, 2 insertions(+), 2 deletions(-) >> >> >> >> diff --git a/drivers/md/md.c b/drivers/md/md.c >> >> index 9ab768a..d63aa78 100644 >> >> --- a/drivers/md/md.c >> >> +++ b/drivers/md/md.c >> >> @@ -1805,15 +1805,15 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev) >> >> md_error(mddev, rdev); >> >> else { >> >> struct badblocks *bb = &rdev->badblocks; >> >> - u64 *bbp = (u64 *)page_address(rdev->bb_page); >> >> u64 *p = bb->page; >> >> sb->feature_map |= cpu_to_le32(MD_FEATURE_BAD_BLOCKS); >> >> if (bb->changed) { >> >> unsigned seq; >> >> + u64 *bbp; >> >> >> >> retry: >> >> + bbp = (u64 *)page_address(rdev->bb_page); >> >> seq = read_seqbegin(&bb->lock); >> >> - >> >> memset(bbp, 0xff, PAGE_SIZE); >> >> >> >> for (i = 0 ; i < bb->count ; i++) { >> > >> > >> >No. >> >The contents of the page might change, but it is always the same page, so it >> >always has the same address, so "bbp" is guaranteed to be stable. >> > >> >NeilBrown >> > >> Is my understand wrong? >> >u64 *bbp = (u64 *)page_address(rdev->bb_page); >> > u64 *p = bb->page; >> > sb->feature_map |= cpu_to_le32(MD_FEATURE_BAD_BLOCKS); >> > if (bb->changed) { >> > unsigned seq; >> >> >retry: >> > seq = read_seqbegin(&bb->lock); >> >> > memset(bbp, 0xff, PAGE_SIZE); >> >> > for (i = 0 ; i < bb->count ; i++) { >> > u64 internal_bb = *p++; >> > u64 store_bb = ((BB_OFFSET(internal_bb) << 10) >> > | BB_LEN(internal_bb)); >> > *bbp++ = cpu_to_le64(store_bb); >> I think bbp will be changed. Is ok? > > My patch missed one parameter: >> > u64 internal_bb = *p++; So the code should be: diff --git a/drivers/md/md.c b/drivers/md/md.c index 9ab768a..1f86c48 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1817,10 +1817,10 @@ retry: memset(bbp, 0xff, PAGE_SIZE); for (i = 0 ; i < bb->count ; i++) { - u64 internal_bb = *p++; + u64 internal_bb = p[i]; u64 store_bb = ((BB_OFFSET(internal_bb) << 10) | BB_LEN(internal_bb)); - *bbp++ = cpu_to_le64(store_bb); + bbp[i] = cpu_to_le64(store_bb); } bb->changed = 0; if (read_seqretry(&bb->lock, seq)) I think this is your first wanted!?韬{.n?????%??檩??w?{.n???{炳盯w???塄}?财??j:+v??????2??璀??摺?囤??z夸z罐?+?????w棹f