On Thu, Sep 28, 2017 at 09:57:41AM +0800, Guoqing Jiang wrote:
>
>
> On 09/28/2017 06:13 AM, Liu Bo wrote:
> > MD's rdev_set_badblocks() expects that badblocks_set() returns 1 if
> > badblocks are disabled, otherwise, rdev_set_badblocks() will record
> > superblock changes and return success in that case and md will fail to
> > report an IO error which it should.
> >
> > This bug has existed since badblocks were introduced in commit
> > 9e0e252a048b ("badblocks: Add core badblock management code").
>
> I don't think we need to change it since it originally was return 0 in
> original
> commit.
The difference is that the original md_set_badblocks() returns 0 for
both "being disabled" and "no room", while now badblocks_set() returns
1 for "no room" as a failure but 0 for "being disabled".
thanks,
-liubo
>
> commit 2230dfe4ccc3add340dc6d437965b2de1d269fde
> Author: NeilBrown <[email protected]>
> Date: Thu Jul 28 11:31:46 2011 +1000
>
> md: beginnings of bad block management.
>
> This the first step in allowing md to track bad-blocks per-device so
> that we can fail individual blocks rather than the whole device.
>
> This patch just adds a data structure for recording bad blocks, with
> routines to add, remove, search the list.
>
> Signed-off-by: NeilBrown <[email protected]>
> Reviewed-by: Namhyung Kim <[email protected]>
> +static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors,
> + int acknowledged)
> +{
> + u64 *p;
> + int lo, hi;
> + int rv = 1;
> +
> + if (bb->shift < 0)
> + /* badblocks are disabled */
> + return 0;
>
> After a quick glance, I guess we need to fix it inside md, since below
> change
> seems not correct in fc974ee2bffdde47d1e4b220cf326952cc2c4794.
>
> @@ -8734,114 +8485,19 @@ int rdev_set_badblocks(struct md_rdev *rdev,
> sector_t s, int sectors,
> s += rdev->new_data_offset;
> else
> s += rdev->data_offset;
> - rv = md_set_badblocks(&rdev->badblocks,
> - s, sectors, 0);
> - if (rv) {
> + rv = badblocks_set(&rdev->badblocks, s, sectors, 0);
> + if (rv == 0) {
>
>
> So we need to correct it like:
>
> diff --git a/drivers/md/md.c b/drivers/md/md.c
> index 0ff1bbf..245fe52 100644
> --- a/drivers/md/md.c
> +++ b/drivers/md/md.c
> @@ -8905,7 +8905,7 @@ int rdev_set_badblocks(struct md_rdev *rdev, sector_t
> s, int sectors,
> else
> s += rdev->data_offset;
> rv = badblocks_set(&rdev->badblocks, s, sectors, 0);
> - if (rv == 0) {
> + if (rv) {
>
> Thanks,
> Guoqing