提交 d0962936 编写于 作者: N NeilBrown

md: fix clearing of the 'changed' flags for the bad blocks list.

In super_1_sync (the first hunk) we need to clear 'changed' before
checking read_seqretry(), otherwise we might race with other code
adding a bad block and so won't retry later.

In md_update_sb (the second hunk), in the case where there is no
metadata (neither persistent nor external), we treat any bad blocks as
an error.  However we need to clear the 'changed' flag before calling
md_ack_all_badblocks, else it won't do anything.

This patch is suitable for -stable release 3.0 and later.

Cc: stable@vger.kernel.org
Signed-off-by: NNeilBrown <neilb@suse.de>
上级 61a0d80c
...@@ -1805,13 +1805,13 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev) ...@@ -1805,13 +1805,13 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
| BB_LEN(internal_bb)); | BB_LEN(internal_bb));
*bbp++ = cpu_to_le64(store_bb); *bbp++ = cpu_to_le64(store_bb);
} }
bb->changed = 0;
if (read_seqretry(&bb->lock, seq)) if (read_seqretry(&bb->lock, seq))
goto retry; goto retry;
bb->sector = (rdev->sb_start + bb->sector = (rdev->sb_start +
(int)le32_to_cpu(sb->bblog_offset)); (int)le32_to_cpu(sb->bblog_offset));
bb->size = le16_to_cpu(sb->bblog_size); bb->size = le16_to_cpu(sb->bblog_size);
bb->changed = 0;
} }
} }
...@@ -2366,6 +2366,7 @@ static void md_update_sb(struct mddev * mddev, int force_change) ...@@ -2366,6 +2366,7 @@ static void md_update_sb(struct mddev * mddev, int force_change)
clear_bit(MD_CHANGE_PENDING, &mddev->flags); clear_bit(MD_CHANGE_PENDING, &mddev->flags);
rdev_for_each(rdev, mddev) { rdev_for_each(rdev, mddev) {
if (rdev->badblocks.changed) { if (rdev->badblocks.changed) {
rdev->badblocks.changed = 0;
md_ack_all_badblocks(&rdev->badblocks); md_ack_all_badblocks(&rdev->badblocks);
md_error(mddev, rdev); md_error(mddev, rdev);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册