summaryrefslogtreecommitdiff
path: root/drivers/md/md.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c252
1 files changed, 121 insertions, 131 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 309b3af906ad..8273ac5eef06 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1021,8 +1021,6 @@ EXPORT_SYMBOL_GPL(sync_page_io);
static int read_disk_sb(struct md_rdev *rdev, int size)
{
- char b[BDEVNAME_SIZE];
-
if (rdev->sb_loaded)
return 0;
@@ -1032,8 +1030,8 @@ static int read_disk_sb(struct md_rdev *rdev, int size)
return 0;
fail:
- pr_err("md: disabled device %s, could not read superblock.\n",
- bdevname(rdev->bdev,b));
+ pr_err("md: disabled device %pg, could not read superblock.\n",
+ rdev->bdev);
return -EINVAL;
}
@@ -1179,7 +1177,6 @@ EXPORT_SYMBOL(md_check_no_bitmap);
*/
static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_version)
{
- char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
mdp_super_t *sb;
int ret;
bool spare_disk = true;
@@ -1198,19 +1195,19 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor
ret = -EINVAL;
- bdevname(rdev->bdev, b);
sb = page_address(rdev->sb_page);
if (sb->md_magic != MD_SB_MAGIC) {
- pr_warn("md: invalid raid superblock magic on %s\n", b);
+ pr_warn("md: invalid raid superblock magic on %pg\n",
+ rdev->bdev);
goto abort;
}
if (sb->major_version != 0 ||
sb->minor_version < 90 ||
sb->minor_version > 91) {
- pr_warn("Bad version number %d.%d on %s\n",
- sb->major_version, sb->minor_version, b);
+ pr_warn("Bad version number %d.%d on %pg\n",
+ sb->major_version, sb->minor_version, rdev->bdev);
goto abort;
}
@@ -1218,7 +1215,7 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor
goto abort;
if (md_csum_fold(calc_sb_csum(sb)) != md_csum_fold(sb->sb_csum)) {
- pr_warn("md: invalid superblock checksum on %s\n", b);
+ pr_warn("md: invalid superblock checksum on %pg\n", rdev->bdev);
goto abort;
}
@@ -1250,13 +1247,13 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor
__u64 ev1, ev2;
mdp_super_t *refsb = page_address(refdev->sb_page);
if (!md_uuid_equal(refsb, sb)) {
- pr_warn("md: %s has different UUID to %s\n",
- b, bdevname(refdev->bdev,b2));
+ pr_warn("md: %pg has different UUID to %pg\n",
+ rdev->bdev, refdev->bdev);
goto abort;
}
if (!md_sb_equal(refsb, sb)) {
- pr_warn("md: %s has same UUID but different superblock to %s\n",
- b, bdevname(refdev->bdev, b2));
+ pr_warn("md: %pg has same UUID but different superblock to %pg\n",
+ rdev->bdev, refdev->bdev);
goto abort;
}
ev1 = md_event(sb);
@@ -1620,7 +1617,6 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
int ret;
sector_t sb_start;
sector_t sectors;
- char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
int bmask;
bool spare_disk = true;
@@ -1664,13 +1660,13 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
return -EINVAL;
if (calc_sb_1_csum(sb) != sb->sb_csum) {
- pr_warn("md: invalid superblock checksum on %s\n",
- bdevname(rdev->bdev,b));
+ pr_warn("md: invalid superblock checksum on %pg\n",
+ rdev->bdev);
return -EINVAL;
}
if (le64_to_cpu(sb->data_size) < 10) {
- pr_warn("md: data_size too small on %s\n",
- bdevname(rdev->bdev,b));
+ pr_warn("md: data_size too small on %pg\n",
+ rdev->bdev);
return -EINVAL;
}
if (sb->pad0 ||
@@ -1776,9 +1772,9 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
sb->level != refsb->level ||
sb->layout != refsb->layout ||
sb->chunksize != refsb->chunksize) {
- pr_warn("md: %s has strangely different superblock to %s\n",
- bdevname(rdev->bdev,b),
- bdevname(refdev->bdev,b2));
+ pr_warn("md: %pg has strangely different superblock to %pg\n",
+ rdev->bdev,
+ refdev->bdev);
return -EINVAL;
}
ev1 = le64_to_cpu(sb->events);
@@ -2365,7 +2361,6 @@ EXPORT_SYMBOL(md_integrity_register);
int md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
{
struct blk_integrity *bi_mddev;
- char name[BDEVNAME_SIZE];
if (!mddev->gendisk)
return 0;
@@ -2376,8 +2371,8 @@ int md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
return 0;
if (blk_integrity_compare(mddev->gendisk, rdev->bdev->bd_disk) != 0) {
- pr_err("%s: incompatible integrity profile for %s\n",
- mdname(mddev), bdevname(rdev->bdev, name));
+ pr_err("%s: incompatible integrity profile for %pg\n",
+ mdname(mddev), rdev->bdev);
return -ENXIO;
}
@@ -2486,11 +2481,9 @@ static void rdev_delayed_delete(struct work_struct *ws)
static void unbind_rdev_from_array(struct md_rdev *rdev)
{
- char b[BDEVNAME_SIZE];
-
bd_unlink_disk_holder(rdev->bdev, rdev->mddev->gendisk);
list_del_rcu(&rdev->same_set);
- pr_debug("md: unbind<%s>\n", bdevname(rdev->bdev,b));
+ pr_debug("md: unbind<%pg>\n", rdev->bdev);
mddev_destroy_serial_pool(rdev->mddev, rdev, false);
rdev->mddev = NULL;
sysfs_remove_link(&rdev->kobj, "block");
@@ -2543,9 +2536,7 @@ void md_autodetect_dev(dev_t dev);
static void export_rdev(struct md_rdev *rdev)
{
- char b[BDEVNAME_SIZE];
-
- pr_debug("md: export_rdev(%s)\n", bdevname(rdev->bdev,b));
+ pr_debug("md: export_rdev(%pg)\n", rdev->bdev);
md_rdev_clear(rdev);
#ifndef MODULE
if (test_bit(AutoDetected, &rdev->flags))
@@ -2627,14 +2618,16 @@ static void sync_sbs(struct mddev *mddev, int nospares)
static bool does_sb_need_changing(struct mddev *mddev)
{
- struct md_rdev *rdev;
+ struct md_rdev *rdev = NULL, *iter;
struct mdp_superblock_1 *sb;
int role;
/* Find a good rdev */
- rdev_for_each(rdev, mddev)
- if ((rdev->raid_disk >= 0) && !test_bit(Faulty, &rdev->flags))
+ rdev_for_each(iter, mddev)
+ if ((iter->raid_disk >= 0) && !test_bit(Faulty, &iter->flags)) {
+ rdev = iter;
break;
+ }
/* No good device found. */
if (!rdev)
@@ -2645,11 +2638,11 @@ static bool does_sb_need_changing(struct mddev *mddev)
rdev_for_each(rdev, mddev) {
role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
/* Device activated? */
- if (role == 0xffff && rdev->raid_disk >=0 &&
+ if (role == MD_DISK_ROLE_SPARE && rdev->raid_disk >= 0 &&
!test_bit(Faulty, &rdev->flags))
return true;
/* Device turned faulty? */
- if (test_bit(Faulty, &rdev->flags) && (role < 0xfffd))
+ if (test_bit(Faulty, &rdev->flags) && (role < MD_DISK_ROLE_MAX))
return true;
}
@@ -2801,8 +2794,6 @@ repeat:
rewrite:
md_bitmap_update_sb(mddev->bitmap);
rdev_for_each(rdev, mddev) {
- char b[BDEVNAME_SIZE];
-
if (rdev->sb_loaded != 1)
continue; /* no noise on spare devices */
@@ -2810,8 +2801,8 @@ rewrite:
md_super_write(mddev,rdev,
rdev->sb_start, rdev->sb_size,
rdev->sb_page);
- pr_debug("md: (write) %s's sb offset: %llu\n",
- bdevname(rdev->bdev, b),
+ pr_debug("md: (write) %pg's sb offset: %llu\n",
+ rdev->bdev,
(unsigned long long)rdev->sb_start);
rdev->sb_events = mddev->events;
if (rdev->badblocks.size) {
@@ -2823,8 +2814,8 @@ rewrite:
}
} else
- pr_debug("md: %s (skipping faulty)\n",
- bdevname(rdev->bdev, b));
+ pr_debug("md: %pg (skipping faulty)\n",
+ rdev->bdev);
if (mddev->level == LEVEL_MULTIPATH)
/* only need to write one superblock... */
@@ -2984,10 +2975,11 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
if (cmd_match(buf, "faulty") && rdev->mddev->pers) {
md_error(rdev->mddev, rdev);
- if (test_bit(Faulty, &rdev->flags))
- err = 0;
- else
+
+ if (test_bit(MD_BROKEN, &rdev->mddev->flags))
err = -EBUSY;
+ else
+ err = 0;
} else if (cmd_match(buf, "remove")) {
if (rdev->mddev->pers) {
clear_bit(Blocked, &rdev->flags);
@@ -3698,7 +3690,6 @@ EXPORT_SYMBOL_GPL(md_rdev_init);
*/
static struct md_rdev *md_import_device(dev_t newdev, int super_format, int super_minor)
{
- char b[BDEVNAME_SIZE];
int err;
struct md_rdev *rdev;
sector_t size;
@@ -3722,8 +3713,8 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
size = bdev_nr_bytes(rdev->bdev) >> BLOCK_SIZE_BITS;
if (!size) {
- pr_warn("md: %s has zero or unknown size, marking faulty!\n",
- bdevname(rdev->bdev,b));
+ pr_warn("md: %pg has zero or unknown size, marking faulty!\n",
+ rdev->bdev);
err = -EINVAL;
goto abort_free;
}
@@ -3732,14 +3723,14 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
err = super_types[super_format].
load_super(rdev, NULL, super_minor);
if (err == -EINVAL) {
- pr_warn("md: %s does not have a valid v%d.%d superblock, not importing!\n",
- bdevname(rdev->bdev,b),
+ pr_warn("md: %pg does not have a valid v%d.%d superblock, not importing!\n",
+ rdev->bdev,
super_format, super_minor);
goto abort_free;
}
if (err < 0) {
- pr_warn("md: could not read %s's sb, not importing!\n",
- bdevname(rdev->bdev,b));
+ pr_warn("md: could not read %pg's sb, not importing!\n",
+ rdev->bdev);
goto abort_free;
}
}
@@ -3762,7 +3753,6 @@ static int analyze_sbs(struct mddev *mddev)
{
int i;
struct md_rdev *rdev, *freshest, *tmp;
- char b[BDEVNAME_SIZE];
freshest = NULL;
rdev_for_each_safe(rdev, tmp, mddev)
@@ -3774,8 +3764,8 @@ static int analyze_sbs(struct mddev *mddev)
case 0:
break;
default:
- pr_warn("md: fatal superblock inconsistency in %s -- removing from array\n",
- bdevname(rdev->bdev,b));
+ pr_warn("md: fatal superblock inconsistency in %pg -- removing from array\n",
+ rdev->bdev);
md_kick_rdev_from_array(rdev);
}
@@ -3793,8 +3783,8 @@ static int analyze_sbs(struct mddev *mddev)
if (mddev->max_disks &&
(rdev->desc_nr >= mddev->max_disks ||
i > mddev->max_disks)) {
- pr_warn("md: %s: %s: only %d devices permitted\n",
- mdname(mddev), bdevname(rdev->bdev, b),
+ pr_warn("md: %s: %pg: only %d devices permitted\n",
+ mdname(mddev), rdev->bdev,
mddev->max_disks);
md_kick_rdev_from_array(rdev);
continue;
@@ -3802,8 +3792,8 @@ static int analyze_sbs(struct mddev *mddev)
if (rdev != freshest) {
if (super_types[mddev->major_version].
validate_super(mddev, rdev)) {
- pr_warn("md: kicking non-fresh %s from array!\n",
- bdevname(rdev->bdev,b));
+ pr_warn("md: kicking non-fresh %pg from array!\n",
+ rdev->bdev);
md_kick_rdev_from_array(rdev);
continue;
}
@@ -4028,7 +4018,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
oldpriv = mddev->private;
mddev->pers = pers;
mddev->private = priv;
- strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
+ strscpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
mddev->level = mddev->new_level;
mddev->layout = mddev->new_layout;
mddev->chunk_sectors = mddev->new_chunk_sectors;
@@ -4353,10 +4343,9 @@ __ATTR_PREALLOC(resync_start, S_IRUGO|S_IWUSR,
* like active, but no writes have been seen for a while (100msec).
*
* broken
- * RAID0/LINEAR-only: same as clean, but array is missing a member.
- * It's useful because RAID0/LINEAR mounted-arrays aren't stopped
- * when a member is gone, so this state will at least alert the
- * user that something is wrong.
+* Array is failed. It's useful because mounted-arrays aren't stopped
+* when array is failed, so this state will at least alert the user that
+* something is wrong.
*/
enum array_state { clear, inactive, suspended, readonly, read_auto, clean, active,
write_pending, active_idle, broken, bad_word};
@@ -4842,7 +4831,7 @@ action_store(struct mddev *mddev, const char *page, size_t len)
flush_workqueue(md_misc_wq);
if (mddev->sync_thread) {
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
- md_reap_sync_thread(mddev);
+ md_reap_sync_thread(mddev, true);
}
mddev_unlock(mddev);
}
@@ -5596,8 +5585,6 @@ static void md_free(struct kobject *ko)
bioset_exit(&mddev->bio_set);
bioset_exit(&mddev->sync_set);
- if (mddev->level != 1 && mddev->level != 10)
- bioset_exit(&mddev->io_acct_set);
kfree(mddev);
}
@@ -5763,7 +5750,7 @@ static int add_named_array(const char *val, const struct kernel_param *kp)
len--;
if (len >= DISK_NAME_LEN)
return -E2BIG;
- strlcpy(buf, val, len+1);
+ strscpy(buf, val, len+1);
if (strncmp(buf, "md_", 3) == 0)
return md_alloc(0, buf);
if (strncmp(buf, "md", 2) == 0 &&
@@ -5896,7 +5883,7 @@ int md_run(struct mddev *mddev)
mddev->level = pers->level;
mddev->new_level = pers->level;
}
- strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
+ strscpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
if (mddev->reshape_position != MaxSector &&
pers->start_reshape == NULL) {
@@ -5910,7 +5897,6 @@ int md_run(struct mddev *mddev)
/* Warn if this is a potentially silly
* configuration.
*/
- char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
struct md_rdev *rdev2;
int warned = 0;
@@ -5919,10 +5905,10 @@ int md_run(struct mddev *mddev)
if (rdev < rdev2 &&
rdev->bdev->bd_disk ==
rdev2->bdev->bd_disk) {
- pr_warn("%s: WARNING: %s appears to be on the same physical disk as %s.\n",
+ pr_warn("%s: WARNING: %pg appears to be on the same physical disk as %pg.\n",
mdname(mddev),
- bdevname(rdev->bdev,b),
- bdevname(rdev2->bdev,b2));
+ rdev->bdev,
+ rdev2->bdev);
warned = 1;
}
}
@@ -5991,8 +5977,7 @@ int md_run(struct mddev *mddev)
bool nonrot = true;
rdev_for_each(rdev, mddev) {
- if (rdev->raid_disk >= 0 &&
- !blk_queue_nonrot(bdev_get_queue(rdev->bdev))) {
+ if (rdev->raid_disk >= 0 && !bdev_nonrot(rdev->bdev)) {
nonrot = false;
break;
}
@@ -6212,7 +6197,7 @@ static void __md_stop_writes(struct mddev *mddev)
flush_workqueue(md_misc_wq);
if (mddev->sync_thread) {
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
- md_reap_sync_thread(mddev);
+ md_reap_sync_thread(mddev, true);
}
del_timer_sync(&mddev->safemode_timer);
@@ -6284,8 +6269,6 @@ void md_stop(struct mddev *mddev)
__md_stop(mddev);
bioset_exit(&mddev->bio_set);
bioset_exit(&mddev->sync_set);
- if (mddev->level != 1 && mddev->level != 10)
- bioset_exit(&mddev->io_acct_set);
}
EXPORT_SYMBOL_GPL(md_stop);
@@ -6451,8 +6434,7 @@ static void autorun_array(struct mddev *mddev)
pr_info("md: running: ");
rdev_for_each(rdev, mddev) {
- char b[BDEVNAME_SIZE];
- pr_cont("<%s>", bdevname(rdev->bdev,b));
+ pr_cont("<%pg>", rdev->bdev);
}
pr_cont("\n");
@@ -6479,7 +6461,6 @@ static void autorun_devices(int part)
{
struct md_rdev *rdev0, *rdev, *tmp;
struct mddev *mddev;
- char b[BDEVNAME_SIZE];
pr_info("md: autorun ...\n");
while (!list_empty(&pending_raid_disks)) {
@@ -6489,12 +6470,12 @@ static void autorun_devices(int part)
rdev0 = list_entry(pending_raid_disks.next,
struct md_rdev, same_set);
- pr_debug("md: considering %s ...\n", bdevname(rdev0->bdev,b));
+ pr_debug("md: considering %pg ...\n", rdev0->bdev);
INIT_LIST_HEAD(&candidates);
rdev_for_each_list(rdev, tmp, &pending_raid_disks)
if (super_90_load(rdev, rdev0, 0) >= 0) {
- pr_debug("md: adding %s ...\n",
- bdevname(rdev->bdev,b));
+ pr_debug("md: adding %pg ...\n",
+ rdev->bdev);
list_move(&rdev->same_set, &candidates);
}
/*
@@ -6511,8 +6492,8 @@ static void autorun_devices(int part)
unit = MINOR(dev);
}
if (rdev0->preferred_minor != unit) {
- pr_warn("md: unit number in %s is bad: %d\n",
- bdevname(rdev0->bdev, b), rdev0->preferred_minor);
+ pr_warn("md: unit number in %pg is bad: %d\n",
+ rdev0->bdev, rdev0->preferred_minor);
break;
}
@@ -6525,8 +6506,8 @@ static void autorun_devices(int part)
pr_warn("md: %s locked, cannot run\n", mdname(mddev));
else if (mddev->raid_disks || mddev->major_version
|| !list_empty(&mddev->disks)) {
- pr_warn("md: %s already running, cannot run %s\n",
- mdname(mddev), bdevname(rdev0->bdev,b));
+ pr_warn("md: %s already running, cannot run %pg\n",
+ mdname(mddev), rdev0->bdev);
mddev_unlock(mddev);
} else {
pr_debug("md: created %s\n", mdname(mddev));
@@ -6700,7 +6681,6 @@ static int get_disk_info(struct mddev *mddev, void __user * arg)
int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
{
- char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
struct md_rdev *rdev;
dev_t dev = MKDEV(info->major,info->minor);
@@ -6730,9 +6710,9 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
err = super_types[mddev->major_version]
.load_super(rdev, rdev0, mddev->minor_version);
if (err < 0) {
- pr_warn("md: %s has different UUID to %s\n",
- bdevname(rdev->bdev,b),
- bdevname(rdev0->bdev,b2));
+ pr_warn("md: %pg has different UUID to %pg\n",
+ rdev->bdev,
+ rdev0->bdev);
export_rdev(rdev);
return -EINVAL;
}
@@ -6907,7 +6887,6 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
static int hot_remove_disk(struct mddev *mddev, dev_t dev)
{
- char b[BDEVNAME_SIZE];
struct md_rdev *rdev;
if (!mddev->pers)
@@ -6942,14 +6921,13 @@ kick_rdev:
return 0;
busy:
- pr_debug("md: cannot remove active disk %s from %s ...\n",
- bdevname(rdev->bdev,b), mdname(mddev));
+ pr_debug("md: cannot remove active disk %pg from %s ...\n",
+ rdev->bdev, mdname(mddev));
return -EBUSY;
}
static int hot_add_disk(struct mddev *mddev, dev_t dev)
{
- char b[BDEVNAME_SIZE];
int err;
struct md_rdev *rdev;
@@ -6982,8 +6960,8 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
rdev->sectors = rdev->sb_start;
if (test_bit(Faulty, &rdev->flags)) {
- pr_warn("md: can not hot-add faulty %s disk to %s!\n",
- bdevname(rdev->bdev,b), mdname(mddev));
+ pr_warn("md: can not hot-add faulty %pg disk to %s!\n",
+ rdev->bdev, mdname(mddev));
err = -EINVAL;
goto abort_export;
}
@@ -7010,8 +6988,8 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
* disable on the whole MD.
*/
if (!blk_queue_nowait(bdev_get_queue(rdev->bdev))) {
- pr_info("%s: Disabling nowait because %s does not support nowait\n",
- mdname(mddev), bdevname(rdev->bdev, b));
+ pr_info("%s: Disabling nowait because %pg does not support nowait\n",
+ mdname(mddev), rdev->bdev);
blk_queue_flag_clear(QUEUE_FLAG_NOWAIT, mddev->queue);
}
/*
@@ -7444,7 +7422,7 @@ static int set_disk_faulty(struct mddev *mddev, dev_t dev)
err = -ENODEV;
else {
md_error(mddev, rdev);
- if (!test_bit(Faulty, &rdev->flags))
+ if (test_bit(MD_BROKEN, &mddev->flags))
err = -EBUSY;
}
rcu_read_unlock();
@@ -7962,17 +7940,22 @@ EXPORT_SYMBOL(md_register_thread);
void md_unregister_thread(struct md_thread **threadp)
{
- struct md_thread *thread = *threadp;
- if (!thread)
- return;
- pr_debug("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk));
- /* Locking ensures that mddev_unlock does not wake_up a
+ struct md_thread *thread;
+
+ /*
+ * Locking ensures that mddev_unlock does not wake_up a
* non-existent thread
*/
spin_lock(&pers_lock);
+ thread = *threadp;
+ if (!thread) {
+ spin_unlock(&pers_lock);
+ return;
+ }
*threadp = NULL;
spin_unlock(&pers_lock);
+ pr_debug("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk));
kthread_stop(thread->tsk);
kfree(thread);
}
@@ -7985,13 +7968,16 @@ void md_error(struct mddev *mddev, struct md_rdev *rdev)
if (!mddev->pers || !mddev->pers->error_handler)
return;
- mddev->pers->error_handler(mddev,rdev);
- if (mddev->degraded)
+ mddev->pers->error_handler(mddev, rdev);
+
+ if (mddev->degraded && !test_bit(MD_BROKEN, &mddev->flags))
set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
sysfs_notify_dirent_safe(rdev->sysfs_state);
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
- set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
- md_wakeup_thread(mddev->thread);
+ if (!test_bit(MD_BROKEN, &mddev->flags)) {
+ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+ md_wakeup_thread(mddev->thread);
+ }
if (mddev->event_work.func)
queue_work(md_misc_wq, &mddev->event_work);
md_new_event();
@@ -8008,10 +7994,8 @@ static void status_unused(struct seq_file *seq)
seq_printf(seq, "unused devices: ");
list_for_each_entry(rdev, &pending_raid_disks, same_set) {
- char b[BDEVNAME_SIZE];
i++;
- seq_printf(seq, "%s ",
- bdevname(rdev->bdev,b));
+ seq_printf(seq, "%pg ", rdev->bdev);
}
if (!i)
seq_printf(seq, "<none>");
@@ -8251,9 +8235,8 @@ static int md_seq_show(struct seq_file *seq, void *v)
sectors = 0;
rcu_read_lock();
rdev_for_each_rcu(rdev, mddev) {
- char b[BDEVNAME_SIZE];
- seq_printf(seq, " %s[%d]",
- bdevname(rdev->bdev,b), rdev->desc_nr);
+ seq_printf(seq, " %pg[%d]", rdev->bdev, rdev->desc_nr);
+
if (test_bit(WriteMostly, &rdev->flags))
seq_printf(seq, "(W)");
if (test_bit(Journal, &rdev->flags))
@@ -8585,7 +8568,7 @@ void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,
{
struct bio *discard_bio = NULL;
- if (__blkdev_issue_discard(rdev->bdev, start, size, GFP_NOIO, 0,
+ if (__blkdev_issue_discard(rdev->bdev, start, size, GFP_NOIO,
&discard_bio) || !discard_bio)
return;
@@ -9320,7 +9303,7 @@ void md_check_recovery(struct mddev *mddev)
* ->spare_active and clear saved_raid_disk
*/
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
- md_reap_sync_thread(mddev);
+ md_reap_sync_thread(mddev, true);
clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
clear_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags);
@@ -9355,7 +9338,7 @@ void md_check_recovery(struct mddev *mddev)
goto unlock;
}
if (mddev->sync_thread) {
- md_reap_sync_thread(mddev);
+ md_reap_sync_thread(mddev, true);
goto unlock;
}
/* Set RUNNING before clearing NEEDED to avoid
@@ -9428,14 +9411,18 @@ void md_check_recovery(struct mddev *mddev)
}
EXPORT_SYMBOL(md_check_recovery);
-void md_reap_sync_thread(struct mddev *mddev)
+void md_reap_sync_thread(struct mddev *mddev, bool reconfig_mutex_held)
{
struct md_rdev *rdev;
sector_t old_dev_sectors = mddev->dev_sectors;
bool is_reshaped = false;
+ if (reconfig_mutex_held)
+ mddev_unlock(mddev);
/* resync has finished, collect result */
md_unregister_thread(&mddev->sync_thread);
+ if (reconfig_mutex_held)
+ mddev_lock_nointr(mddev);
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
mddev->degraded != mddev->raid_disks) {
@@ -9648,7 +9635,6 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev)
struct mdp_superblock_1 *sb = page_address(rdev->sb_page);
struct md_rdev *rdev2, *tmp;
int role, ret;
- char b[BDEVNAME_SIZE];
/*
* If size is changed in another node then we need to
@@ -9671,8 +9657,9 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev)
role = le16_to_cpu(sb->dev_roles[rdev2->desc_nr]);
if (test_bit(Candidate, &rdev2->flags)) {
- if (role == 0xfffe) {
- pr_info("md: Removing Candidate device %s because add failed\n", bdevname(rdev2->bdev,b));
+ if (role == MD_DISK_ROLE_FAULTY) {
+ pr_info("md: Removing Candidate device %pg because add failed\n",
+ rdev2->bdev);
md_kick_rdev_from_array(rdev2);
continue;
}
@@ -9684,13 +9671,13 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev)
/*
* got activated except reshape is happening.
*/
- if (rdev2->raid_disk == -1 && role != 0xffff &&
+ if (rdev2->raid_disk == -1 && role != MD_DISK_ROLE_SPARE &&
!(le32_to_cpu(sb->feature_map) &
MD_FEATURE_RESHAPE_ACTIVE)) {
rdev2->saved_raid_disk = role;
ret = remove_and_add_spares(mddev, rdev2);
- pr_info("Activated spare: %s\n",
- bdevname(rdev2->bdev,b));
+ pr_info("Activated spare: %pg\n",
+ rdev2->bdev);
/* wakeup mddev->thread here, so array could
* perform resync with the new activated disk */
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
@@ -9701,7 +9688,8 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev)
* as faulty. The recovery is performed by the
* one who initiated the error.
*/
- if ((role == 0xfffe) || (role == 0xfffd)) {
+ if (role == MD_DISK_ROLE_FAULTY ||
+ role == MD_DISK_ROLE_JOURNAL) {
md_error(mddev, rdev2);
clear_bit(Blocked, &rdev2->flags);
}
@@ -9791,16 +9779,18 @@ static int read_rdev(struct mddev *mddev, struct md_rdev *rdev)
void md_reload_sb(struct mddev *mddev, int nr)
{
- struct md_rdev *rdev;
+ struct md_rdev *rdev = NULL, *iter;
int err;
/* Find the rdev */
- rdev_for_each_rcu(rdev, mddev) {
- if (rdev->desc_nr == nr)
+ rdev_for_each_rcu(iter, mddev) {
+ if (iter->desc_nr == nr) {
+ rdev = iter;
break;
+ }
}
- if (!rdev || rdev->desc_nr != nr) {
+ if (!rdev) {
pr_warn("%s: %d Could not find rdev with nr %d\n", __func__, __LINE__, nr);
return;
}