Commit 1b114450 authored by Neil Brown's avatar Neil Brown Committed by Trond Myklebust

[PATCH] MD - when writing superblock, generate from mddev/rdev info.

when writing superblock, generate from mddev/rdev info.

Rather than relying on the superblock info being kept up-to-date,
we regenerate the superblock from mddev/rdev info before
each write.
parent d58aa811
...@@ -860,44 +860,73 @@ static int write_disk_sb(mdk_rdev_t * rdev) ...@@ -860,44 +860,73 @@ static int write_disk_sb(mdk_rdev_t * rdev)
return 1; return 1;
} }
static void set_this_disk(mddev_t *mddev, mdk_rdev_t *rdev)
{
int i, ok = 0;
mdp_disk_t *desc;
for (i = 0; i < MD_SB_DISKS; i++) {
desc = mddev->sb->disks + i;
#if 0
if (disk_faulty(desc)) {
if (mk_kdev(desc->major,desc->minor) == rdev->dev)
ok = 1;
continue;
}
#endif
if (kdev_same(mk_kdev(desc->major,desc->minor), rdev->dev)) {
rdev->sb->this_disk = *desc;
ok = 1;
break;
}
}
if (!ok) {
MD_BUG();
}
}
static int sync_sbs(mddev_t * mddev) static int sync_sbs(mddev_t * mddev)
{ {
mdk_rdev_t *rdev; mdk_rdev_t *rdev;
mdp_super_t *sb; mdp_super_t *sb;
struct list_head *tmp; struct list_head *tmp;
/* make sb->disks match mddev->disks
* 1/ zero out disks
* 2/ Add info for each disk, keeping track of highest desc_nr
* 3/ any empty disks < highest become removed
*
* disks[0] gets initialised to REMOVED because
* we cannot be sure from other fields if it has
* been initialised or not.
*/
int highest = 0;
int i;
int active=0, working=0,failed=0,spare=0,nr_disks=0;
sb = mddev->sb;
sb->disks[0].state = (1<<MD_DISK_REMOVED);
ITERATE_RDEV(mddev,rdev,tmp) {
mdp_disk_t *d = &sb->disks[rdev->desc_nr];
nr_disks++;
d->number = rdev->desc_nr;
d->major = major(rdev->dev);
d->minor = minor(rdev->dev);
d->raid_disk = rdev->raid_disk;
if (rdev->faulty) {
d->state = (1<<MD_DISK_FAULTY);
failed++;
} else if (rdev->in_sync) {
d->state = (1<<MD_DISK_ACTIVE);
d->state |= (1<<MD_DISK_SYNC);
active++;
working++;
} else {
d->state = 0;
spare++;
working++;
}
if (rdev->desc_nr > highest)
highest = rdev->desc_nr;
}
/* now set the "removed" bit on any non-trailing holes */
for (i=0; i<highest; i++) {
mdp_disk_t *d = &sb->disks[i];
if (d->state == 0 && d->number == 0) {
d->number = i;
d->raid_disk = i;
d->state = (1<<MD_DISK_REMOVED);
}
}
sb->nr_disks = nr_disks;
sb->active_disks = active;
sb->working_disks = working;
sb->failed_disks = failed;
sb->spare_disks = spare;
ITERATE_RDEV(mddev,rdev,tmp) { ITERATE_RDEV(mddev,rdev,tmp) {
if (rdev->faulty || rdev->alias_device) if (rdev->faulty || rdev->alias_device)
continue; continue;
sb = rdev->sb; sb = rdev->sb;
*sb = *mddev->sb; *sb = *mddev->sb;
set_this_disk(mddev, rdev); sb->this_disk = sb->disks[rdev->desc_nr];
sb->sb_csum = calc_sb_csum(sb); sb->sb_csum = calc_sb_csum(sb);
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment