Skip to content

Commit af209e0

Browse files
committed
Merge branch 'for-linus' of git://neil.brown.name/md
* 'for-linus' of git://neil.brown.name/md: md: raid5 crash during degradation md/raid5: never wait for bad-block acks on failed device. md: ensure new badblocks are handled promptly. md: bad blocks shouldn't cause a Blocked status on a Faulty device. md: take a reference to mddev during sysfs access. md: refine interpretation of "hold_active == UNTIL_IOCTL". md/lock: ensure updates to page_attrs are properly locked.
2 parents 53523d5 + 5d8c71f commit af209e0

File tree

3 files changed

+32
-7
lines changed

3 files changed

+32
-7
lines changed

drivers/md/bitmap.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,10 +1106,12 @@ void bitmap_write_all(struct bitmap *bitmap)
11061106
*/
11071107
int i;
11081108

1109+
spin_lock_irq(&bitmap->lock);
11091110
for (i = 0; i < bitmap->file_pages; i++)
11101111
set_page_attr(bitmap, bitmap->filemap[i],
11111112
BITMAP_PAGE_NEEDWRITE);
11121113
bitmap->allclean = 0;
1114+
spin_unlock_irq(&bitmap->lock);
11131115
}
11141116

11151117
static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc)
@@ -1605,7 +1607,9 @@ void bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e)
16051607
for (chunk = s; chunk <= e; chunk++) {
16061608
sector_t sec = (sector_t)chunk << CHUNK_BLOCK_SHIFT(bitmap);
16071609
bitmap_set_memory_bits(bitmap, sec, 1);
1610+
spin_lock_irq(&bitmap->lock);
16081611
bitmap_file_set_bit(bitmap, sec);
1612+
spin_unlock_irq(&bitmap->lock);
16091613
if (sec < bitmap->mddev->recovery_cp)
16101614
/* We are asserting that the array is dirty,
16111615
* so move the recovery_cp address back so

drivers/md/md.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ static void mddev_put(struct mddev *mddev)
570570
mddev->ctime == 0 && !mddev->hold_active) {
571571
/* Array is not configured at all, and not held active,
572572
* so destroy it */
573-
list_del(&mddev->all_mddevs);
573+
list_del_init(&mddev->all_mddevs);
574574
bs = mddev->bio_set;
575575
mddev->bio_set = NULL;
576576
if (mddev->gendisk) {
@@ -2546,7 +2546,8 @@ state_show(struct md_rdev *rdev, char *page)
25462546
sep = ",";
25472547
}
25482548
if (test_bit(Blocked, &rdev->flags) ||
2549-
rdev->badblocks.unacked_exist) {
2549+
(rdev->badblocks.unacked_exist
2550+
&& !test_bit(Faulty, &rdev->flags))) {
25502551
len += sprintf(page+len, "%sblocked", sep);
25512552
sep = ",";
25522553
}
@@ -3788,6 +3789,8 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
37883789
if (err)
37893790
return err;
37903791
else {
3792+
if (mddev->hold_active == UNTIL_IOCTL)
3793+
mddev->hold_active = 0;
37913794
sysfs_notify_dirent_safe(mddev->sysfs_state);
37923795
return len;
37933796
}
@@ -4487,11 +4490,20 @@ md_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
44874490

44884491
if (!entry->show)
44894492
return -EIO;
4493+
spin_lock(&all_mddevs_lock);
4494+
if (list_empty(&mddev->all_mddevs)) {
4495+
spin_unlock(&all_mddevs_lock);
4496+
return -EBUSY;
4497+
}
4498+
mddev_get(mddev);
4499+
spin_unlock(&all_mddevs_lock);
4500+
44904501
rv = mddev_lock(mddev);
44914502
if (!rv) {
44924503
rv = entry->show(mddev, page);
44934504
mddev_unlock(mddev);
44944505
}
4506+
mddev_put(mddev);
44954507
return rv;
44964508
}
44974509

@@ -4507,13 +4519,19 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
45074519
return -EIO;
45084520
if (!capable(CAP_SYS_ADMIN))
45094521
return -EACCES;
4522+
spin_lock(&all_mddevs_lock);
4523+
if (list_empty(&mddev->all_mddevs)) {
4524+
spin_unlock(&all_mddevs_lock);
4525+
return -EBUSY;
4526+
}
4527+
mddev_get(mddev);
4528+
spin_unlock(&all_mddevs_lock);
45104529
rv = mddev_lock(mddev);
4511-
if (mddev->hold_active == UNTIL_IOCTL)
4512-
mddev->hold_active = 0;
45134530
if (!rv) {
45144531
rv = entry->store(mddev, page, length);
45154532
mddev_unlock(mddev);
45164533
}
4534+
mddev_put(mddev);
45174535
return rv;
45184536
}
45194537

@@ -7840,6 +7858,7 @@ int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
78407858
s + rdev->data_offset, sectors, acknowledged);
78417859
if (rv) {
78427860
/* Make sure they get written out promptly */
7861+
sysfs_notify_dirent_safe(rdev->sysfs_state);
78437862
set_bit(MD_CHANGE_CLEAN, &rdev->mddev->flags);
78447863
md_wakeup_thread(rdev->mddev->thread);
78457864
}

drivers/md/raid5.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3036,6 +3036,8 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
30363036
if (dev->written)
30373037
s->written++;
30383038
rdev = rcu_dereference(conf->disks[i].rdev);
3039+
if (rdev && test_bit(Faulty, &rdev->flags))
3040+
rdev = NULL;
30393041
if (rdev) {
30403042
is_bad = is_badblock(rdev, sh->sector, STRIPE_SECTORS,
30413043
&first_bad, &bad_sectors);
@@ -3063,20 +3065,20 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
30633065
}
30643066
} else if (test_bit(In_sync, &rdev->flags))
30653067
set_bit(R5_Insync, &dev->flags);
3066-
else if (!test_bit(Faulty, &rdev->flags)) {
3068+
else {
30673069
/* in sync if before recovery_offset */
30683070
if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
30693071
set_bit(R5_Insync, &dev->flags);
30703072
}
3071-
if (test_bit(R5_WriteError, &dev->flags)) {
3073+
if (rdev && test_bit(R5_WriteError, &dev->flags)) {
30723074
clear_bit(R5_Insync, &dev->flags);
30733075
if (!test_bit(Faulty, &rdev->flags)) {
30743076
s->handle_bad_blocks = 1;
30753077
atomic_inc(&rdev->nr_pending);
30763078
} else
30773079
clear_bit(R5_WriteError, &dev->flags);
30783080
}
3079-
if (test_bit(R5_MadeGood, &dev->flags)) {
3081+
if (rdev && test_bit(R5_MadeGood, &dev->flags)) {
30803082
if (!test_bit(Faulty, &rdev->flags)) {
30813083
s->handle_bad_blocks = 1;
30823084
atomic_inc(&rdev->nr_pending);

0 commit comments

Comments
 (0)