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.
This commit is contained in:
commit
af209e0aea
3 changed files with 32 additions and 7 deletions
|
@ -1106,10 +1106,12 @@ void bitmap_write_all(struct bitmap *bitmap)
|
|||
*/
|
||||
int i;
|
||||
|
||||
spin_lock_irq(&bitmap->lock);
|
||||
for (i = 0; i < bitmap->file_pages; i++)
|
||||
set_page_attr(bitmap, bitmap->filemap[i],
|
||||
BITMAP_PAGE_NEEDWRITE);
|
||||
bitmap->allclean = 0;
|
||||
spin_unlock_irq(&bitmap->lock);
|
||||
}
|
||||
|
||||
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)
|
|||
for (chunk = s; chunk <= e; chunk++) {
|
||||
sector_t sec = (sector_t)chunk << CHUNK_BLOCK_SHIFT(bitmap);
|
||||
bitmap_set_memory_bits(bitmap, sec, 1);
|
||||
spin_lock_irq(&bitmap->lock);
|
||||
bitmap_file_set_bit(bitmap, sec);
|
||||
spin_unlock_irq(&bitmap->lock);
|
||||
if (sec < bitmap->mddev->recovery_cp)
|
||||
/* We are asserting that the array is dirty,
|
||||
* so move the recovery_cp address back so
|
||||
|
|
|
@ -570,7 +570,7 @@ static void mddev_put(struct mddev *mddev)
|
|||
mddev->ctime == 0 && !mddev->hold_active) {
|
||||
/* Array is not configured at all, and not held active,
|
||||
* so destroy it */
|
||||
list_del(&mddev->all_mddevs);
|
||||
list_del_init(&mddev->all_mddevs);
|
||||
bs = mddev->bio_set;
|
||||
mddev->bio_set = NULL;
|
||||
if (mddev->gendisk) {
|
||||
|
@ -2546,7 +2546,8 @@ state_show(struct md_rdev *rdev, char *page)
|
|||
sep = ",";
|
||||
}
|
||||
if (test_bit(Blocked, &rdev->flags) ||
|
||||
rdev->badblocks.unacked_exist) {
|
||||
(rdev->badblocks.unacked_exist
|
||||
&& !test_bit(Faulty, &rdev->flags))) {
|
||||
len += sprintf(page+len, "%sblocked", sep);
|
||||
sep = ",";
|
||||
}
|
||||
|
@ -3788,6 +3789,8 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
|
|||
if (err)
|
||||
return err;
|
||||
else {
|
||||
if (mddev->hold_active == UNTIL_IOCTL)
|
||||
mddev->hold_active = 0;
|
||||
sysfs_notify_dirent_safe(mddev->sysfs_state);
|
||||
return len;
|
||||
}
|
||||
|
@ -4487,11 +4490,20 @@ md_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
|
|||
|
||||
if (!entry->show)
|
||||
return -EIO;
|
||||
spin_lock(&all_mddevs_lock);
|
||||
if (list_empty(&mddev->all_mddevs)) {
|
||||
spin_unlock(&all_mddevs_lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
mddev_get(mddev);
|
||||
spin_unlock(&all_mddevs_lock);
|
||||
|
||||
rv = mddev_lock(mddev);
|
||||
if (!rv) {
|
||||
rv = entry->show(mddev, page);
|
||||
mddev_unlock(mddev);
|
||||
}
|
||||
mddev_put(mddev);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -4507,13 +4519,19 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
|
|||
return -EIO;
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EACCES;
|
||||
spin_lock(&all_mddevs_lock);
|
||||
if (list_empty(&mddev->all_mddevs)) {
|
||||
spin_unlock(&all_mddevs_lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
mddev_get(mddev);
|
||||
spin_unlock(&all_mddevs_lock);
|
||||
rv = mddev_lock(mddev);
|
||||
if (mddev->hold_active == UNTIL_IOCTL)
|
||||
mddev->hold_active = 0;
|
||||
if (!rv) {
|
||||
rv = entry->store(mddev, page, length);
|
||||
mddev_unlock(mddev);
|
||||
}
|
||||
mddev_put(mddev);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -7840,6 +7858,7 @@ int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
|
|||
s + rdev->data_offset, sectors, acknowledged);
|
||||
if (rv) {
|
||||
/* Make sure they get written out promptly */
|
||||
sysfs_notify_dirent_safe(rdev->sysfs_state);
|
||||
set_bit(MD_CHANGE_CLEAN, &rdev->mddev->flags);
|
||||
md_wakeup_thread(rdev->mddev->thread);
|
||||
}
|
||||
|
|
|
@ -3036,6 +3036,8 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
|
|||
if (dev->written)
|
||||
s->written++;
|
||||
rdev = rcu_dereference(conf->disks[i].rdev);
|
||||
if (rdev && test_bit(Faulty, &rdev->flags))
|
||||
rdev = NULL;
|
||||
if (rdev) {
|
||||
is_bad = is_badblock(rdev, sh->sector, STRIPE_SECTORS,
|
||||
&first_bad, &bad_sectors);
|
||||
|
@ -3063,12 +3065,12 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
|
|||
}
|
||||
} else if (test_bit(In_sync, &rdev->flags))
|
||||
set_bit(R5_Insync, &dev->flags);
|
||||
else if (!test_bit(Faulty, &rdev->flags)) {
|
||||
else {
|
||||
/* in sync if before recovery_offset */
|
||||
if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset)
|
||||
set_bit(R5_Insync, &dev->flags);
|
||||
}
|
||||
if (test_bit(R5_WriteError, &dev->flags)) {
|
||||
if (rdev && test_bit(R5_WriteError, &dev->flags)) {
|
||||
clear_bit(R5_Insync, &dev->flags);
|
||||
if (!test_bit(Faulty, &rdev->flags)) {
|
||||
s->handle_bad_blocks = 1;
|
||||
|
@ -3076,7 +3078,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
|
|||
} else
|
||||
clear_bit(R5_WriteError, &dev->flags);
|
||||
}
|
||||
if (test_bit(R5_MadeGood, &dev->flags)) {
|
||||
if (rdev && test_bit(R5_MadeGood, &dev->flags)) {
|
||||
if (!test_bit(Faulty, &rdev->flags)) {
|
||||
s->handle_bad_blocks = 1;
|
||||
atomic_inc(&rdev->nr_pending);
|
||||
|
|
Loading…
Reference in a new issue