md: fix clearing of the 'changed' flags for the bad blocks list.
authorNeilBrown <neilb@suse.de>
Mon, 19 Mar 2012 01:46:41 +0000 (12:46 +1100)
committerNeilBrown <neilb@suse.de>
Mon, 19 Mar 2012 01:46:41 +0000 (12:46 +1100)
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: NeilBrown <neilb@suse.de>
drivers/md/md.c

index 26591cc8ee874559426eeaa83f75eee0bbf01293..21a90efb13b7e74566aa3abed7a8185b3e47b6e8 100644 (file)
@@ -1805,13 +1805,13 @@ retry:
                                                | BB_LEN(internal_bb));
                                *bbp++ = cpu_to_le64(store_bb);
                        }
+                       bb->changed = 0;
                        if (read_seqretry(&bb->lock, seq))
                                goto retry;
 
                        bb->sector = (rdev->sb_start +
                                      (int)le32_to_cpu(sb->bblog_offset));
                        bb->size = le16_to_cpu(sb->bblog_size);
-                       bb->changed = 0;
                }
        }
 
@@ -2366,6 +2366,7 @@ repeat:
                        clear_bit(MD_CHANGE_PENDING, &mddev->flags);
                        rdev_for_each(rdev, mddev) {
                                if (rdev->badblocks.changed) {
+                                       rdev->badblocks.changed = 0;
                                        md_ack_all_badblocks(&rdev->badblocks);
                                        md_error(mddev, rdev);
                                }