Commit f3ddcd6b authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] raid ->diskop() splitup

	* ->diskop() split into individual methods; prototypes cleaned
up.  In particular, handling of hot_add_disk() gets mdk_rdev_t * of
the component we are adding as an argument instead of playing the games
with major/minor.  Code cleaned up.
parent 480f4106
...@@ -1741,8 +1741,7 @@ static int do_md_stop(mddev_t * mddev, int ro) ...@@ -1741,8 +1741,7 @@ static int do_md_stop(mddev_t * mddev, int ro)
md_unregister_thread(mddev->sync_thread); md_unregister_thread(mddev->sync_thread);
mddev->sync_thread = NULL; mddev->sync_thread = NULL;
if (mddev->spare) { if (mddev->spare) {
mddev->pers->diskop(mddev, &mddev->spare, mddev->pers->spare_inactive(mddev);
DISKOP_SPARE_INACTIVE);
mddev->spare = NULL; mddev->spare = NULL;
} }
} }
...@@ -2250,7 +2249,7 @@ static int hot_remove_disk(mddev_t * mddev, kdev_t dev) ...@@ -2250,7 +2249,7 @@ static int hot_remove_disk(mddev_t * mddev, kdev_t dev)
printk(KERN_INFO "md: trying to remove %s from md%d ... \n", printk(KERN_INFO "md: trying to remove %s from md%d ... \n",
partition_name(dev), mdidx(mddev)); partition_name(dev), mdidx(mddev));
if (!mddev->pers->diskop) { if (!mddev->pers->hot_remove_disk) {
printk(KERN_WARNING "md%d: personality does not support diskops!\n", printk(KERN_WARNING "md%d: personality does not support diskops!\n",
mdidx(mddev)); mdidx(mddev));
return -EINVAL; return -EINVAL;
...@@ -2274,7 +2273,7 @@ static int hot_remove_disk(mddev_t * mddev, kdev_t dev) ...@@ -2274,7 +2273,7 @@ static int hot_remove_disk(mddev_t * mddev, kdev_t dev)
return -EINVAL; return -EINVAL;
} }
err = mddev->pers->diskop(mddev, &disk, DISKOP_HOT_REMOVE_DISK); err = mddev->pers->hot_remove_disk(mddev, disk->number);
if (err == -EBUSY) { if (err == -EBUSY) {
MD_BUG(); MD_BUG();
goto busy; goto busy;
...@@ -2308,7 +2307,7 @@ static int hot_add_disk(mddev_t * mddev, kdev_t dev) ...@@ -2308,7 +2307,7 @@ static int hot_add_disk(mddev_t * mddev, kdev_t dev)
printk(KERN_INFO "md: trying to hot-add %s to md%d ... \n", printk(KERN_INFO "md: trying to hot-add %s to md%d ... \n",
partition_name(dev), mdidx(mddev)); partition_name(dev), mdidx(mddev));
if (!mddev->pers->diskop) { if (!mddev->pers->hot_add_disk) {
printk(KERN_WARNING "md%d: personality does not support diskops!\n", printk(KERN_WARNING "md%d: personality does not support diskops!\n",
mdidx(mddev)); mdidx(mddev));
return -EINVAL; return -EINVAL;
...@@ -2388,7 +2387,7 @@ static int hot_add_disk(mddev_t * mddev, kdev_t dev) ...@@ -2388,7 +2387,7 @@ static int hot_add_disk(mddev_t * mddev, kdev_t dev)
disk->major = major(dev); disk->major = major(dev);
disk->minor = minor(dev); disk->minor = minor(dev);
if (mddev->pers->diskop(mddev, &disk, DISKOP_HOT_ADD_DISK)) { if (mddev->pers->hot_add_disk(mddev, disk, rdev)) {
MD_BUG(); MD_BUG();
err = -EINVAL; err = -EINVAL;
goto abort_unbind_export; goto abort_unbind_export;
...@@ -3370,7 +3369,7 @@ void md_do_recovery(void *data) ...@@ -3370,7 +3369,7 @@ void md_do_recovery(void *data)
ITERATE_MDDEV(mddev,tmp) if (mddev_lock(mddev)==0) { ITERATE_MDDEV(mddev,tmp) if (mddev_lock(mddev)==0) {
sb = mddev->sb; sb = mddev->sb;
if (!sb || !mddev->pers || !mddev->pers->diskop || mddev->ro) if (!sb || !mddev->pers || mddev->ro)
goto unlock; goto unlock;
if (mddev->recovery_running > 0) if (mddev->recovery_running > 0)
/* resync/recovery still happening */ /* resync/recovery still happening */
...@@ -3384,16 +3383,19 @@ void md_do_recovery(void *data) ...@@ -3384,16 +3383,19 @@ void md_do_recovery(void *data)
* If we were doing a reconstruction, * If we were doing a reconstruction,
* we need to retrieve the spare * we need to retrieve the spare
*/ */
if (!mddev->pers->spare_inactive)
goto unlock;
if (mddev->spare) { if (mddev->spare) {
mddev->pers->diskop(mddev, &mddev->spare, mddev->pers->spare_inactive(mddev);
DISKOP_SPARE_INACTIVE);
mddev->spare = NULL; mddev->spare = NULL;
} }
} else { } else {
if (!mddev->pers->spare_active)
goto unlock;
/* success...*/ /* success...*/
if (mddev->spare) { if (mddev->spare) {
mddev->pers->diskop(mddev, &mddev->spare, mddev->pers->spare_active(mddev,
DISKOP_SPARE_ACTIVE); &mddev->spare);
mark_disk_sync(mddev->spare); mark_disk_sync(mddev->spare);
mark_disk_active(mddev->spare); mark_disk_active(mddev->spare);
sb->active_disks++; sb->active_disks++;
...@@ -3432,12 +3434,13 @@ void md_do_recovery(void *data) ...@@ -3432,12 +3434,13 @@ void md_do_recovery(void *data)
if (!mddev->sync_thread) { if (!mddev->sync_thread) {
printk(KERN_ERR "md%d: could not start resync thread...\n", mdidx(mddev)); printk(KERN_ERR "md%d: could not start resync thread...\n", mdidx(mddev));
if (mddev->spare) if (mddev->spare)
mddev->pers->diskop(mddev, &mddev->spare, DISKOP_SPARE_INACTIVE); mddev->pers->spare_inactive(mddev);
mddev->spare = NULL; mddev->spare = NULL;
mddev->recovery_running = 0; mddev->recovery_running = 0;
} else { } else {
if (mddev->spare) if (mddev->spare)
mddev->pers->diskop(mddev, &mddev->spare, DISKOP_SPARE_WRITE); mddev->pers->spare_write(mddev,
mddev->spare->number);
mddev->recovery_running = 1; mddev->recovery_running = 1;
md_wakeup_thread(mddev->sync_thread); md_wakeup_thread(mddev->sync_thread);
} }
......
...@@ -55,9 +55,8 @@ static mdk_personality_t multipath_personality; ...@@ -55,9 +55,8 @@ static mdk_personality_t multipath_personality;
static spinlock_t retry_list_lock = SPIN_LOCK_UNLOCKED; static spinlock_t retry_list_lock = SPIN_LOCK_UNLOCKED;
struct multipath_bh *multipath_retry_list = NULL, **multipath_retry_tail; struct multipath_bh *multipath_retry_list = NULL, **multipath_retry_tail;
static int multipath_diskop(mddev_t *mddev, mdp_disk_t **d, int state); static int multipath_spare_write(mddev_t *, int);
static int multipath_spare_active(mddev_t *mddev, mdp_disk_t **d);
static struct multipath_bh *multipath_alloc_mpbh(multipath_conf_t *conf) static struct multipath_bh *multipath_alloc_mpbh(multipath_conf_t *conf)
{ {
...@@ -366,11 +365,11 @@ static int multipath_error (mddev_t *mddev, struct block_device *bdev) ...@@ -366,11 +365,11 @@ static int multipath_error (mddev_t *mddev, struct block_device *bdev)
spare = get_spare(mddev); spare = get_spare(mddev);
if (spare) { if (spare) {
err = multipath_diskop(mddev, &spare, DISKOP_SPARE_WRITE); err = multipath_spare_write(mddev, spare->number);
printk("got DISKOP_SPARE_WRITE err: %d. (spare_faulty(): %d)\n", err, disk_faulty(spare)); printk("got DISKOP_SPARE_WRITE err: %d. (spare_faulty(): %d)\n", err, disk_faulty(spare));
} }
if (!err && !disk_faulty(spare)) { if (!err && !disk_faulty(spare)) {
multipath_diskop(mddev, &spare, DISKOP_SPARE_ACTIVE); multipath_spare_active(mddev, &spare);
mark_disk_sync(spare); mark_disk_sync(spare);
mark_disk_active(spare); mark_disk_active(spare);
sb->active_disks++; sb->active_disks++;
...@@ -410,255 +409,238 @@ static void print_multipath_conf (multipath_conf_t *conf) ...@@ -410,255 +409,238 @@ static void print_multipath_conf (multipath_conf_t *conf)
} }
} }
static int multipath_diskop(mddev_t *mddev, mdp_disk_t **d, int state) /*
* Find the spare disk ... (can only be in the 'high' area of the array)
*/
static struct multipath_info *find_spare(mddev_t *mddev, int number)
{ {
int err = 0;
int i, failed_disk=-1, spare_disk=-1, removed_disk=-1, added_disk=-1;
multipath_conf_t *conf = mddev->private; multipath_conf_t *conf = mddev->private;
struct multipath_info *tmp, *sdisk, *fdisk, *rdisk, *adisk; int i;
mdp_super_t *sb = mddev->sb; for (i = conf->raid_disks; i < MD_SB_DISKS; i++) {
mdp_disk_t *failed_desc, *spare_desc, *added_desc; struct multipath_info *p = conf->multipaths + i;
mdk_rdev_t *spare_rdev, *failed_rdev; if (p->spare && p->number == number)
struct block_device *bdev; return p;
}
return NULL;
}
static int multipath_spare_inactive(mddev_t *mddev)
{
multipath_conf_t *conf = mddev->private;
struct multipath_info *p;
int err = 0;
print_multipath_conf(conf); print_multipath_conf(conf);
spin_lock_irq(&conf->device_lock); spin_lock_irq(&conf->device_lock);
/* p = find_spare(mddev, mddev->spare->number);
* find the disk ... if (p) {
*/ p->operational = 0;
switch (state) { } else {
MD_BUG();
case DISKOP_SPARE_ACTIVE: err = 1;
}
spin_unlock_irq(&conf->device_lock);
/* print_multipath_conf(conf);
* Find the failed disk within the MULTIPATH configuration ... return err;
* (this can only be in the first conf->working_disks part) }
*/
for (i = 0; i < conf->raid_disks; i++) {
tmp = conf->multipaths + i;
if ((!tmp->operational && !tmp->spare) ||
!tmp->used_slot) {
failed_disk = i;
break;
}
}
/*
* When we activate a spare disk we _must_ have a disk in
* the lower (active) part of the array to replace.
*/
if ((failed_disk == -1) || (failed_disk >= conf->raid_disks)) {
MD_BUG();
err = 1;
goto abort;
}
/* fall through */
case DISKOP_SPARE_WRITE: static int multipath_spare_write(mddev_t *mddev, int number)
case DISKOP_SPARE_INACTIVE: {
multipath_conf_t *conf = mddev->private;
struct multipath_info *p;
int err = 0;
/* print_multipath_conf(conf);
* Find the spare disk ... (can only be in the 'high' spin_lock_irq(&conf->device_lock);
* area of the array) p = find_spare(mddev, number);
*/ if (p) {
for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { p->operational = 1;
tmp = conf->multipaths + i; } else {
if (tmp->spare && tmp->number == (*d)->number) { MD_BUG();
spare_disk = i; err = 1;
break; }
} spin_unlock_irq(&conf->device_lock);
}
if (spare_disk == -1) {
MD_BUG();
err = 1;
goto abort;
}
break;
case DISKOP_HOT_REMOVE_DISK:
for (i = 0; i < MD_SB_DISKS; i++) {
tmp = conf->multipaths + i;
if (tmp->used_slot && (tmp->number == (*d)->number)) {
if (tmp->operational) {
printk(KERN_ERR "hot-remove-disk, slot %d is identified to be the requested disk (number %d), but is still operational!\n", i, (*d)->number);
err = -EBUSY;
goto abort;
}
removed_disk = i;
break;
}
}
if (removed_disk == -1) {
MD_BUG();
err = 1;
goto abort;
}
break;
case DISKOP_HOT_ADD_DISK: print_multipath_conf(conf);
return err;
}
for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { static int multipath_spare_active(mddev_t *mddev, mdp_disk_t **d)
tmp = conf->multipaths + i; {
if (!tmp->used_slot) { int err = 0;
added_disk = i; int i, failed_disk=-1, spare_disk=-1;
break; multipath_conf_t *conf = mddev->private;
} struct multipath_info *tmp, *sdisk, *fdisk;
} mdp_super_t *sb = mddev->sb;
if (added_disk == -1) { mdp_disk_t *failed_desc, *spare_desc;
MD_BUG(); mdk_rdev_t *spare_rdev, *failed_rdev;
err = 1;
goto abort;
}
break;
}
switch (state) { print_multipath_conf(conf);
spin_lock_irq(&conf->device_lock);
/* /*
* Switch the spare disk to write-only mode: * Find the failed disk within the MULTIPATH configuration ...
* (this can only be in the first conf->working_disks part)
*/ */
case DISKOP_SPARE_WRITE: for (i = 0; i < conf->raid_disks; i++) {
sdisk = conf->multipaths + spare_disk; tmp = conf->multipaths + i;
sdisk->operational = 1; if ((!tmp->operational && !tmp->spare) ||
break; !tmp->used_slot) {
failed_disk = i;
break;
}
}
/* /*
* Deactivate a spare disk: * When we activate a spare disk we _must_ have a disk in
* the lower (active) part of the array to replace.
*/ */
case DISKOP_SPARE_INACTIVE: if (failed_disk == -1) {
sdisk = conf->multipaths + spare_disk; MD_BUG();
sdisk->operational = 0; err = 1;
break; goto abort;
}
/* /*
* Activate (mark read-write) the (now sync) spare disk, * Find the spare disk ... (can only be in the 'high'
* which means we switch it's 'raid position' (->raid_disk) * area of the array)
* with the failed disk. (only the first 'conf->nr_disks'
* slots are used for 'real' disks and we must preserve this
* property)
*/ */
case DISKOP_SPARE_ACTIVE: for (i = conf->raid_disks; i < MD_SB_DISKS; i++) {
sdisk = conf->multipaths + spare_disk; tmp = conf->multipaths + i;
fdisk = conf->multipaths + failed_disk; if (tmp->spare && tmp->number == (*d)->number) {
spare_disk = i;
spare_desc = &sb->disks[sdisk->number]; break;
failed_desc = &sb->disks[fdisk->number];
if (spare_desc != *d) {
MD_BUG();
err = 1;
goto abort;
} }
}
if (spare_disk == -1) {
MD_BUG();
err = 1;
goto abort;
}
if (spare_desc->raid_disk != sdisk->raid_disk) { sdisk = conf->multipaths + spare_disk;
MD_BUG(); fdisk = conf->multipaths + failed_disk;
err = 1;
goto abort;
}
if (sdisk->raid_disk != spare_disk) {
MD_BUG();
err = 1;
goto abort;
}
if (failed_desc->raid_disk != fdisk->raid_disk) { spare_desc = &sb->disks[sdisk->number];
MD_BUG(); failed_desc = &sb->disks[fdisk->number];
err = 1;
goto abort;
}
if (fdisk->raid_disk != failed_disk) { if (spare_desc != *d || spare_desc->raid_disk != sdisk->raid_disk ||
MD_BUG(); sdisk->raid_disk != spare_disk || fdisk->raid_disk != failed_disk ||
err = 1; failed_desc->raid_disk != fdisk->raid_disk) {
goto abort; MD_BUG();
} err = 1;
goto abort;
}
/* /*
* do the switch finally * do the switch finally
*/ */
spare_rdev = find_rdev_nr(mddev, spare_desc->number); spare_rdev = find_rdev_nr(mddev, spare_desc->number);
failed_rdev = find_rdev_nr(mddev, failed_desc->number); failed_rdev = find_rdev_nr(mddev, failed_desc->number);
xchg_values(spare_rdev->desc_nr, failed_rdev->desc_nr); xchg_values(spare_rdev->desc_nr, failed_rdev->desc_nr);
spare_rdev->alias_device = 0; spare_rdev->alias_device = 0;
failed_rdev->alias_device = 1; failed_rdev->alias_device = 1;
xchg_values(*spare_desc, *failed_desc); xchg_values(*spare_desc, *failed_desc);
xchg_values(*fdisk, *sdisk); xchg_values(*fdisk, *sdisk);
/* /*
* (careful, 'failed' and 'spare' are switched from now on) * (careful, 'failed' and 'spare' are switched from now on)
* *
* we want to preserve linear numbering and we want to * we want to preserve linear numbering and we want to
* give the proper raid_disk number to the now activated * give the proper raid_disk number to the now activated
* disk. (this means we switch back these values) * disk. (this means we switch back these values)
*/ */
xchg_values(spare_desc->raid_disk, failed_desc->raid_disk);
xchg_values(sdisk->raid_disk, fdisk->raid_disk);
xchg_values(spare_desc->number, failed_desc->number);
xchg_values(sdisk->number, fdisk->number);
*d = failed_desc; xchg_values(spare_desc->raid_disk, failed_desc->raid_disk);
xchg_values(sdisk->raid_disk, fdisk->raid_disk);
xchg_values(spare_desc->number, failed_desc->number);
xchg_values(sdisk->number, fdisk->number);
if (!sdisk->bdev) *d = failed_desc;
sdisk->used_slot = 0;
/*
* this really activates the spare.
*/
fdisk->spare = 0;
/* if (!sdisk->bdev)
* if we activate a spare, we definitely replace a sdisk->used_slot = 0;
* non-operational disk slot in the 'low' area of /*
* the disk array. * this really activates the spare.
*/ */
fdisk->spare = 0;
conf->working_disks++; /*
* if we activate a spare, we definitely replace a
* non-operational disk slot in the 'low' area of
* the disk array.
*/
break; conf->working_disks++;
abort:
spin_unlock_irq(&conf->device_lock);
case DISKOP_HOT_REMOVE_DISK: print_multipath_conf(conf);
rdisk = conf->multipaths + removed_disk; return err;
}
if (rdisk->spare && (removed_disk < conf->raid_disks)) { static int multipath_add_disk(mddev_t *mddev, mdp_disk_t *added_desc,
MD_BUG(); mdk_rdev_t *rdev)
err = 1; {
goto abort; multipath_conf_t *conf = mddev->private;
} int err = 1;
bdev = rdisk->bdev; int i;
rdisk->dev = NODEV;
rdisk->bdev = NULL; print_multipath_conf(conf);
rdisk->used_slot = 0; spin_lock_irq(&conf->device_lock);
conf->nr_disks--; for (i = conf->raid_disks; i < MD_SB_DISKS; i++) {
bdput(bdev); struct multipath_info *p = conf->multipaths + i;
break; if (!p->used_slot) {
if (added_desc->number != i)
case DISKOP_HOT_ADD_DISK: break;
adisk = conf->multipaths + added_disk; p->number = added_desc->number;
added_desc = *d; p->raid_disk = added_desc->raid_disk;
p->dev = rdev->dev;
if (added_disk != added_desc->number) { p->bdev = rdev->bdev;
MD_BUG(); p->operational = 0;
err = 1; p->spare = 1;
goto abort; p->used_slot = 1;
conf->nr_disks++;
err = 0;
break;
} }
}
if (err)
MD_BUG();
spin_unlock_irq(&conf->device_lock);
adisk->number = added_desc->number; print_multipath_conf(conf);
adisk->raid_disk = added_desc->raid_disk; return err;
adisk->dev = mk_kdev(added_desc->major,added_desc->minor); }
/* it will be held open by rdev */
adisk->bdev = bdget(kdev_t_to_nr(adisk->dev));
adisk->operational = 0; static int multipath_remove_disk(mddev_t *mddev, int number)
adisk->spare = 1; {
adisk->used_slot = 1; multipath_conf_t *conf = mddev->private;
conf->nr_disks++; int err = 1;
int i;
break; print_multipath_conf(conf);
spin_lock_irq(&conf->device_lock);
default: for (i = 0; i < MD_SB_DISKS; i++) {
MD_BUG(); struct multipath_info *p = conf->multipaths + i;
err = 1; if (p->used_slot && (p->number == number)) {
goto abort; if (p->operational) {
printk(KERN_ERR "hot-remove-disk, slot %d is identified to be the requested disk (number %d), but is still operational!\n", i, number);
err = -EBUSY;
goto abort;
}
if (p->spare && i < conf->raid_disks)
break;
p->dev = NODEV;
p->bdev = NULL;
p->used_slot = 0;
conf->nr_disks--;
err = 0;
break;
}
} }
if (err)
MD_BUG();
abort: abort:
spin_unlock_irq(&conf->device_lock); spin_unlock_irq(&conf->device_lock);
...@@ -666,7 +648,6 @@ static int multipath_diskop(mddev_t *mddev, mdp_disk_t **d, int state) ...@@ -666,7 +648,6 @@ static int multipath_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
return err; return err;
} }
#define IO_ERROR KERN_ALERT \ #define IO_ERROR KERN_ALERT \
"multipath: %s: unrecoverable IO read error for block %lu\n" "multipath: %s: unrecoverable IO read error for block %lu\n"
...@@ -1074,7 +1055,11 @@ static mdk_personality_t multipath_personality= ...@@ -1074,7 +1055,11 @@ static mdk_personality_t multipath_personality=
stop: multipath_stop, stop: multipath_stop,
status: multipath_status, status: multipath_status,
error_handler: multipath_error, error_handler: multipath_error,
diskop: multipath_diskop, hot_add_disk: multipath_add_disk,
hot_remove_disk:multipath_remove_disk,
spare_inactive: multipath_spare_inactive,
spare_active: multipath_spare_active,
spare_write: multipath_spare_write,
}; };
static int __init multipath_init (void) static int __init multipath_init (void)
......
...@@ -658,263 +658,244 @@ static void close_sync(conf_t *conf) ...@@ -658,263 +658,244 @@ static void close_sync(conf_t *conf)
conf->r1buf_pool = NULL; conf->r1buf_pool = NULL;
} }
static int diskop(mddev_t *mddev, mdp_disk_t **d, int state) static mirror_info_t *find_spare(mddev_t *mddev, int number)
{
conf_t *conf = mddev->private;
int i;
for (i = conf->raid_disks; i < MD_SB_DISKS; i++) {
mirror_info_t *p = conf->mirrors + i;
if (p->spare && p->number == number)
return p;
}
return NULL;
}
static int raid1_spare_active(mddev_t *mddev, mdp_disk_t **d)
{ {
int err = 0; int err = 0;
int i, failed_disk = -1, spare_disk = -1, removed_disk = -1, added_disk = -1; int i, failed_disk = -1, spare_disk = -1;
conf_t *conf = mddev->private; conf_t *conf = mddev->private;
mirror_info_t *tmp, *sdisk, *fdisk, *rdisk, *adisk; mirror_info_t *tmp, *sdisk, *fdisk;
mdp_super_t *sb = mddev->sb; mdp_super_t *sb = mddev->sb;
mdp_disk_t *failed_desc, *spare_desc, *added_desc; mdp_disk_t *failed_desc, *spare_desc;
mdk_rdev_t *spare_rdev, *failed_rdev; mdk_rdev_t *spare_rdev, *failed_rdev;
struct block_device *bdev;
print_conf(conf); print_conf(conf);
spin_lock_irq(&conf->device_lock); spin_lock_irq(&conf->device_lock);
/* /*
* find the disk ... * Find the failed disk within the RAID1 configuration ...
* (this can only be in the first conf->working_disks part)
*/ */
switch (state) { for (i = 0; i < conf->raid_disks; i++) {
tmp = conf->mirrors + i;
case DISKOP_SPARE_ACTIVE: if ((!tmp->operational && !tmp->spare) ||
!tmp->used_slot) {
/* failed_disk = i;
* Find the failed disk within the RAID1 configuration ... break;
* (this can only be in the first conf->working_disks part)
*/
for (i = 0; i < conf->raid_disks; i++) {
tmp = conf->mirrors + i;
if ((!tmp->operational && !tmp->spare) ||
!tmp->used_slot) {
failed_disk = i;
break;
}
} }
/* }
* When we activate a spare disk we _must_ have a disk in /*
* the lower (active) part of the array to replace. * When we activate a spare disk we _must_ have a disk in
*/ * the lower (active) part of the array to replace.
if ((failed_disk == -1) || (failed_disk >= conf->raid_disks)) { */
MD_BUG(); if (failed_disk == -1) {
err = 1; MD_BUG();
goto abort; err = 1;
goto abort;
}
/*
* Find the spare disk ... (can only be in the 'high'
* area of the array)
*/
for (i = conf->raid_disks; i < MD_SB_DISKS; i++) {
tmp = conf->mirrors + i;
if (tmp->spare && tmp->number == (*d)->number) {
spare_disk = i;
break;
} }
/* fall through */ }
if (spare_disk == -1) {
case DISKOP_SPARE_WRITE: MD_BUG();
case DISKOP_SPARE_INACTIVE: err = 1;
goto abort;
}
/* sdisk = conf->mirrors + spare_disk;
* Find the spare disk ... (can only be in the 'high' fdisk = conf->mirrors + failed_disk;
* area of the array)
*/
for (i = conf->raid_disks; i < MD_SB_DISKS; i++) {
tmp = conf->mirrors + i;
if (tmp->spare && tmp->number == (*d)->number) {
spare_disk = i;
break;
}
}
if (spare_disk == -1) {
MD_BUG();
err = 1;
goto abort;
}
break;
case DISKOP_HOT_REMOVE_DISK:
for (i = 0; i < MD_SB_DISKS; i++) {
tmp = conf->mirrors + i;
if (tmp->used_slot && (tmp->number == (*d)->number)) {
if (tmp->operational) {
err = -EBUSY;
goto abort;
}
removed_disk = i;
break;
}
}
if (removed_disk == -1) {
MD_BUG();
err = 1;
goto abort;
}
break;
case DISKOP_HOT_ADD_DISK: spare_desc = &sb->disks[sdisk->number];
failed_desc = &sb->disks[fdisk->number];
for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { if (spare_desc != *d || spare_desc->raid_disk != sdisk->raid_disk ||
tmp = conf->mirrors + i; sdisk->raid_disk != spare_disk || fdisk->raid_disk != failed_disk ||
if (!tmp->used_slot) { failed_desc->raid_disk != fdisk->raid_disk) {
added_disk = i; MD_BUG();
break; err = 1;
} goto abort;
}
if (added_disk == -1) {
MD_BUG();
err = 1;
goto abort;
}
break;
} }
switch (state) {
/*
* Switch the spare disk to write-only mode:
*/
case DISKOP_SPARE_WRITE:
sdisk = conf->mirrors + spare_disk;
sdisk->operational = 1;
sdisk->write_only = 1;
break;
/* /*
* Deactivate a spare disk: * do the switch finally
*/ */
case DISKOP_SPARE_INACTIVE: spare_rdev = find_rdev_nr(mddev, spare_desc->number);
sdisk = conf->mirrors + spare_disk; failed_rdev = find_rdev_nr(mddev, failed_desc->number);
sdisk->operational = 0;
sdisk->write_only = 0;
break;
/* /*
* Activate (mark read-write) the (now sync) spare disk, * There must be a spare_rdev, but there may not be a
* which means we switch it's 'raid position' (->raid_disk) * failed_rdev. That slot might be empty...
* with the failed disk. (only the first 'conf->nr_disks'
* slots are used for 'real' disks and we must preserve this
* property)
*/ */
case DISKOP_SPARE_ACTIVE: spare_rdev->desc_nr = failed_desc->number;
sdisk = conf->mirrors + spare_disk; if (failed_rdev)
fdisk = conf->mirrors + failed_disk; failed_rdev->desc_nr = spare_desc->number;
spare_desc = &sb->disks[sdisk->number];
failed_desc = &sb->disks[fdisk->number];
if (spare_desc != *d) {
MD_BUG();
err = 1;
goto abort;
}
if (spare_desc->raid_disk != sdisk->raid_disk) { xchg_values(*spare_desc, *failed_desc);
MD_BUG(); xchg_values(*fdisk, *sdisk);
err = 1;
goto abort;
}
if (sdisk->raid_disk != spare_disk) {
MD_BUG();
err = 1;
goto abort;
}
if (failed_desc->raid_disk != fdisk->raid_disk) { /*
MD_BUG(); * (careful, 'failed' and 'spare' are switched from now on)
err = 1; *
goto abort; * we want to preserve linear numbering and we want to
} * give the proper raid_disk number to the now activated
* disk. (this means we switch back these values)
if (fdisk->raid_disk != failed_disk) { */
MD_BUG(); xchg_values(spare_desc->raid_disk, failed_desc->raid_disk);
err = 1; xchg_values(sdisk->raid_disk, fdisk->raid_disk);
goto abort; xchg_values(spare_desc->number, failed_desc->number);
} xchg_values(sdisk->number, fdisk->number);
/* *d = failed_desc;
* do the switch finally
*/
spare_rdev = find_rdev_nr(mddev, spare_desc->number);
failed_rdev = find_rdev_nr(mddev, failed_desc->number);
/* if (!sdisk->bdev)
* There must be a spare_rdev, but there may not be a sdisk->used_slot = 0;
* failed_rdev. That slot might be empty... /*
*/ * this really activates the spare.
spare_rdev->desc_nr = failed_desc->number; */
if (failed_rdev) fdisk->spare = 0;
failed_rdev->desc_nr = spare_desc->number; fdisk->write_only = 0;
xchg_values(*spare_desc, *failed_desc); /*
xchg_values(*fdisk, *sdisk); * if we activate a spare, we definitely replace a
* non-operational disk slot in the 'low' area of
* the disk array.
*/
/* conf->working_disks++;
* (careful, 'failed' and 'spare' are switched from now on) abort:
* spin_unlock_irq(&conf->device_lock);
* we want to preserve linear numbering and we want to
* give the proper raid_disk number to the now activated
* disk. (this means we switch back these values)
*/
xchg_values(spare_desc->raid_disk, failed_desc->raid_disk);
xchg_values(sdisk->raid_disk, fdisk->raid_disk);
xchg_values(spare_desc->number, failed_desc->number);
xchg_values(sdisk->number, fdisk->number);
*d = failed_desc; print_conf(conf);
return err;
}
if (!sdisk->bdev) static int raid1_spare_inactive(mddev_t *mddev)
sdisk->used_slot = 0; {
/* conf_t *conf = mddev->private;
* this really activates the spare. mirror_info_t *p;
*/ int err = 0;
fdisk->spare = 0;
fdisk->write_only = 0;
/* print_conf(conf);
* if we activate a spare, we definitely replace a spin_lock_irq(&conf->device_lock);
* non-operational disk slot in the 'low' area of p = find_spare(mddev, mddev->spare->number);
* the disk array. if (p) {
*/ p->operational = 0;
p->write_only = 0;
} else {
MD_BUG();
err = 1;
}
spin_unlock_irq(&conf->device_lock);
print_conf(conf);
return err;
}
conf->working_disks++; static int raid1_spare_write(mddev_t *mddev, int number)
{
conf_t *conf = mddev->private;
mirror_info_t *p;
int err = 0;
break; print_conf(conf);
spin_lock_irq(&conf->device_lock);
p = find_spare(mddev, number);
if (p) {
p->operational = 1;
p->write_only = 1;
} else {
MD_BUG();
err = 1;
}
spin_unlock_irq(&conf->device_lock);
print_conf(conf);
return err;
}
case DISKOP_HOT_REMOVE_DISK: static int raid1_add_disk(mddev_t *mddev, mdp_disk_t *added_desc,
rdisk = conf->mirrors + removed_disk; mdk_rdev_t *rdev)
{
conf_t *conf = mddev->private;
int err = 1;
int i;
if (rdisk->spare && (removed_disk < conf->raid_disks)) { print_conf(conf);
MD_BUG(); spin_lock_irq(&conf->device_lock);
err = 1; /*
goto abort; * find the disk ...
} */
bdev = rdisk->bdev; for (i = conf->raid_disks; i < MD_SB_DISKS; i++) {
rdisk->dev = NODEV; mirror_info_t *p = conf->mirrors + i;
rdisk->bdev = NULL; if (!p->used_slot) {
rdisk->used_slot = 0; if (added_desc->number != i)
conf->nr_disks--; break;
bdput(bdev); p->number = added_desc->number;
break; p->raid_disk = added_desc->raid_disk;
p->dev = rdev->dev;
case DISKOP_HOT_ADD_DISK: /* it will be held open by rdev */
adisk = conf->mirrors + added_disk; p->bdev = rdev->bdev;
added_desc = *d; p->operational = 0;
p->write_only = 0;
if (added_disk != added_desc->number) { p->spare = 1;
MD_BUG(); p->used_slot = 1;
err = 1; p->head_position = 0;
goto abort; conf->nr_disks++;
err = 0;
break;
} }
}
if (err)
MD_BUG();
spin_unlock_irq(&conf->device_lock);
adisk->number = added_desc->number; print_conf(conf);
adisk->raid_disk = added_desc->raid_disk; return err;
adisk->dev = mk_kdev(added_desc->major, added_desc->minor); }
/* it will be held open by rdev */
adisk->bdev = bdget(kdev_t_to_nr(adisk->dev));
adisk->operational = 0;
adisk->write_only = 0;
adisk->spare = 1;
adisk->used_slot = 1;
adisk->head_position = 0;
conf->nr_disks++;
break; static int raid1_remove_disk(mddev_t *mddev, int number)
{
conf_t *conf = mddev->private;
int err = 1;
int i;
default: print_conf(conf);
MD_BUG(); spin_lock_irq(&conf->device_lock);
err = 1; for (i = 0; i < MD_SB_DISKS; i++) {
goto abort; mirror_info_t *p = conf->mirrors + i;
if (p->used_slot && (p->number == number)) {
if (p->operational) {
err = -EBUSY;
goto abort;
}
if (p->spare && (i < conf->raid_disks))
break;
p->dev = NODEV;
p->bdev = NULL;
p->used_slot = 0;
conf->nr_disks--;
err = 0;
break;
}
} }
if (err)
MD_BUG();
abort: abort:
spin_unlock_irq(&conf->device_lock); spin_unlock_irq(&conf->device_lock);
...@@ -922,7 +903,6 @@ static int diskop(mddev_t *mddev, mdp_disk_t **d, int state) ...@@ -922,7 +903,6 @@ static int diskop(mddev_t *mddev, mdp_disk_t **d, int state)
return err; return err;
} }
#define IO_ERROR KERN_ALERT \ #define IO_ERROR KERN_ALERT \
"raid1: %s: unrecoverable I/O read error for block %lu\n" "raid1: %s: unrecoverable I/O read error for block %lu\n"
...@@ -1495,7 +1475,11 @@ static mdk_personality_t raid1_personality = ...@@ -1495,7 +1475,11 @@ static mdk_personality_t raid1_personality =
stop: stop, stop: stop,
status: status, status: status,
error_handler: error, error_handler: error,
diskop: diskop, hot_add_disk: raid1_add_disk,
hot_remove_disk:raid1_remove_disk,
spare_write: raid1_spare_write,
spare_inactive: raid1_spare_inactive,
spare_active: raid1_spare_active,
sync_request: sync_request sync_request: sync_request
}; };
......
...@@ -1694,276 +1694,242 @@ static void print_raid5_conf (raid5_conf_t *conf) ...@@ -1694,276 +1694,242 @@ static void print_raid5_conf (raid5_conf_t *conf)
} }
} }
static int diskop(mddev_t *mddev, mdp_disk_t **d, int state) static struct disk_info *find_spare(mddev_t *mddev, int number)
{
raid5_conf_t *conf = mddev->private;
int i;
for (i = conf->raid_disks; i < MD_SB_DISKS; i++) {
struct disk_info *p = conf->disks + i;
if (p->spare && p->number == number)
return p;
}
return NULL;
}
static int raid5_spare_active(mddev_t *mddev, mdp_disk_t **d)
{ {
int err = 0; int err = 0;
int i, failed_disk=-1, spare_disk=-1, removed_disk=-1, added_disk=-1; int i, failed_disk=-1, spare_disk=-1;
raid5_conf_t *conf = mddev->private; raid5_conf_t *conf = mddev->private;
struct disk_info *tmp, *sdisk, *fdisk, *rdisk, *adisk; struct disk_info *tmp, *sdisk, *fdisk;
mdp_super_t *sb = mddev->sb; mdp_super_t *sb = mddev->sb;
mdp_disk_t *failed_desc, *spare_desc, *added_desc; mdp_disk_t *failed_desc, *spare_desc;
mdk_rdev_t *spare_rdev, *failed_rdev; mdk_rdev_t *spare_rdev, *failed_rdev;
print_raid5_conf(conf); print_raid5_conf(conf);
spin_lock_irq(&conf->device_lock); spin_lock_irq(&conf->device_lock);
for (i = 0; i < conf->raid_disks; i++) {
tmp = conf->disks + i;
if ((!tmp->operational && !tmp->spare) ||
!tmp->used_slot) {
failed_disk = i;
break;
}
}
if (failed_disk == -1) {
MD_BUG();
err = 1;
goto abort;
}
/* /*
* find the disk ... * Find the spare disk ... (can only be in the 'high'
* area of the array)
*/ */
switch (state) { for (i = conf->raid_disks; i < MD_SB_DISKS; i++) {
tmp = conf->disks + i;
case DISKOP_SPARE_ACTIVE: if (tmp->spare && tmp->number == (*d)->number) {
spare_disk = i;
/* break;
* Find the failed disk within the RAID5 configuration ...
* (this can only be in the first conf->raid_disks part)
*/
for (i = 0; i < conf->raid_disks; i++) {
tmp = conf->disks + i;
if ((!tmp->operational && !tmp->spare) ||
!tmp->used_slot) {
failed_disk = i;
break;
}
}
/*
* When we activate a spare disk we _must_ have a disk in
* the lower (active) part of the array to replace.
*/
if ((failed_disk == -1) || (failed_disk >= conf->raid_disks)) {
MD_BUG();
err = 1;
goto abort;
}
/* fall through */
case DISKOP_SPARE_WRITE:
case DISKOP_SPARE_INACTIVE:
/*
* Find the spare disk ... (can only be in the 'high'
* area of the array)
*/
for (i = conf->raid_disks; i < MD_SB_DISKS; i++) {
tmp = conf->disks + i;
if (tmp->spare && tmp->number == (*d)->number) {
spare_disk = i;
break;
}
}
if (spare_disk == -1) {
MD_BUG();
err = 1;
goto abort;
} }
break; }
if (spare_disk == -1) {
case DISKOP_HOT_REMOVE_DISK: MD_BUG();
err = 1;
goto abort;
}
for (i = 0; i < MD_SB_DISKS; i++) { if (!conf->spare) {
tmp = conf->disks + i; MD_BUG();
if (tmp->used_slot && (tmp->number == (*d)->number)) { err = 1;
if (tmp->operational) { goto abort;
err = -EBUSY; }
goto abort; sdisk = conf->disks + spare_disk;
} fdisk = conf->disks + failed_disk;
removed_disk = i;
break;
}
}
if (removed_disk == -1) {
MD_BUG();
err = 1;
goto abort;
}
break;
case DISKOP_HOT_ADD_DISK: spare_desc = &sb->disks[sdisk->number];
failed_desc = &sb->disks[fdisk->number];
for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { if (spare_desc != *d || spare_desc->raid_disk != sdisk->raid_disk ||
tmp = conf->disks + i; sdisk->raid_disk != spare_disk || fdisk->raid_disk != failed_disk ||
if (!tmp->used_slot) { failed_desc->raid_disk != fdisk->raid_disk) {
added_disk = i; MD_BUG();
break; err = 1;
} goto abort;
}
if (added_disk == -1) {
MD_BUG();
err = 1;
goto abort;
}
break;
} }
switch (state) {
/* /*
* Switch the spare disk to write-only mode: * do the switch finally
*/ */
case DISKOP_SPARE_WRITE: spare_rdev = find_rdev_nr(mddev, spare_desc->number);
if (conf->spare) { failed_rdev = find_rdev_nr(mddev, failed_desc->number);
MD_BUG();
err = 1; /* There must be a spare_rdev, but there may not be a
goto abort; * failed_rdev. That slot might be empty...
}
sdisk = conf->disks + spare_disk;
sdisk->operational = 1;
sdisk->write_only = 1;
conf->spare = sdisk;
break;
/*
* Deactivate a spare disk:
*/ */
case DISKOP_SPARE_INACTIVE: spare_rdev->desc_nr = failed_desc->number;
sdisk = conf->disks + spare_disk; if (failed_rdev)
sdisk->operational = 0; failed_rdev->desc_nr = spare_desc->number;
sdisk->write_only = 0;
/* xchg_values(*spare_desc, *failed_desc);
* Was the spare being resynced? xchg_values(*fdisk, *sdisk);
*/
if (conf->spare == sdisk)
conf->spare = NULL;
break;
/* /*
* Activate (mark read-write) the (now sync) spare disk, * (careful, 'failed' and 'spare' are switched from now on)
* which means we switch it's 'raid position' (->raid_disk) *
* with the failed disk. (only the first 'conf->raid_disks' * we want to preserve linear numbering and we want to
* slots are used for 'real' disks and we must preserve this * give the proper raid_disk number to the now activated
* property) * disk. (this means we switch back these values)
*/ */
case DISKOP_SPARE_ACTIVE:
if (!conf->spare) {
MD_BUG();
err = 1;
goto abort;
}
sdisk = conf->disks + spare_disk;
fdisk = conf->disks + failed_disk;
spare_desc = &sb->disks[sdisk->number]; xchg_values(spare_desc->raid_disk, failed_desc->raid_disk);
failed_desc = &sb->disks[fdisk->number]; xchg_values(sdisk->raid_disk, fdisk->raid_disk);
xchg_values(spare_desc->number, failed_desc->number);
xchg_values(sdisk->number, fdisk->number);
if (spare_desc != *d) { *d = failed_desc;
MD_BUG();
err = 1;
goto abort;
}
if (spare_desc->raid_disk != sdisk->raid_disk) { if (!sdisk->bdev)
MD_BUG(); sdisk->used_slot = 0;
err = 1;
goto abort;
}
if (sdisk->raid_disk != spare_disk) {
MD_BUG();
err = 1;
goto abort;
}
if (failed_desc->raid_disk != fdisk->raid_disk) { /*
MD_BUG(); * this really activates the spare.
err = 1; */
goto abort; fdisk->spare = 0;
} fdisk->write_only = 0;
if (fdisk->raid_disk != failed_disk) {
MD_BUG();
err = 1;
goto abort;
}
/*
* do the switch finally
*/
spare_rdev = find_rdev_nr(mddev, spare_desc->number);
failed_rdev = find_rdev_nr(mddev, failed_desc->number);
/* There must be a spare_rdev, but there may not be a
* failed_rdev. That slot might be empty...
*/
spare_rdev->desc_nr = failed_desc->number;
if (failed_rdev)
failed_rdev->desc_nr = spare_desc->number;
xchg_values(*spare_desc, *failed_desc);
xchg_values(*fdisk, *sdisk);
/* /*
* (careful, 'failed' and 'spare' are switched from now on) * if we activate a spare, we definitely replace a
* * non-operational disk slot in the 'low' area of
* we want to preserve linear numbering and we want to * the disk array.
* give the proper raid_disk number to the now activated */
* disk. (this means we switch back these values) conf->failed_disks--;
*/ conf->working_disks++;
conf->spare = NULL;
xchg_values(spare_desc->raid_disk, failed_desc->raid_disk); abort:
xchg_values(sdisk->raid_disk, fdisk->raid_disk); spin_unlock_irq(&conf->device_lock);
xchg_values(spare_desc->number, failed_desc->number); print_raid5_conf(conf);
xchg_values(sdisk->number, fdisk->number); return err;
}
*d = failed_desc; static int raid5_spare_inactive(mddev_t *mddev)
{
raid5_conf_t *conf = mddev->private;
struct disk_info *p;
int err = 0;
if (!sdisk->bdev) print_raid5_conf(conf);
sdisk->used_slot = 0; spin_lock_irq(&conf->device_lock);
p = find_spare(mddev, mddev->spare->number);
if (p) {
p->operational = 0;
p->write_only = 0;
if (conf->spare == p)
conf->spare = NULL;
} else {
MD_BUG();
err = 1;
}
spin_unlock_irq(&conf->device_lock);
print_raid5_conf(conf);
return err;
}
/* static int raid5_spare_write(mddev_t *mddev, int number)
* this really activates the spare. {
*/ raid5_conf_t *conf = mddev->private;
fdisk->spare = 0; struct disk_info *p;
fdisk->write_only = 0; int err = 0;
/* print_raid5_conf(conf);
* if we activate a spare, we definitely replace a spin_lock_irq(&conf->device_lock);
* non-operational disk slot in the 'low' area of p = find_spare(mddev, number);
* the disk array. if (p && !conf->spare) {
*/ p->operational = 1;
conf->failed_disks--; p->write_only = 1;
conf->working_disks++; conf->spare = p;
conf->spare = NULL; } else {
MD_BUG();
err = 1;
}
spin_unlock_irq(&conf->device_lock);
print_raid5_conf(conf);
return err;
}
break; static int raid5_remove_disk(mddev_t *mddev, int number)
{
raid5_conf_t *conf = mddev->private;
int err = 1;
int i;
case DISKOP_HOT_REMOVE_DISK: print_raid5_conf(conf);
rdisk = conf->disks + removed_disk; spin_lock_irq(&conf->device_lock);
if (rdisk->spare && (removed_disk < conf->raid_disks)) { for (i = 0; i < MD_SB_DISKS; i++) {
MD_BUG(); struct disk_info *p = conf->disks + i;
err = 1; if (p->used_slot && p->number == number) {
goto abort; if (p->operational) {
err = -EBUSY;
goto abort;
}
if (p->spare && i < conf->raid_disks)
break;
p->bdev = NULL;
p->used_slot = 0;
err = 0;
break;
} }
rdisk->bdev = NULL; }
rdisk->used_slot = 0; if (err)
MD_BUG();
abort:
spin_unlock_irq(&conf->device_lock);
print_raid5_conf(conf);
return err;
}
break; static int raid5_add_disk(mddev_t *mddev, mdp_disk_t *added_desc,
mdk_rdev_t *rdev)
{
raid5_conf_t *conf = mddev->private;
int err = 1;
int i;
case DISKOP_HOT_ADD_DISK: print_raid5_conf(conf);
adisk = conf->disks + added_disk; spin_lock_irq(&conf->device_lock);
added_desc = *d; /*
* find the disk ...
*/
if (added_disk != added_desc->number) { for (i = conf->raid_disks; i < MD_SB_DISKS; i++) {
MD_BUG(); struct disk_info *p = conf->disks + i;
err = 1; if (!p->used_slot) {
goto abort; if (added_desc->number != i)
break;
p->number = added_desc->number;
p->raid_disk = added_desc->raid_disk;
/* it will be held open by rdev */
p->bdev = rdev->bdev;
p->operational = 0;
p->write_only = 0;
p->spare = 1;
p->used_slot = 1;
err = 0;
break;
} }
adisk->number = added_desc->number;
adisk->raid_disk = added_desc->raid_disk;
/* it will be held open by rdev */
adisk->bdev = bdget(MKDEV(added_desc->major,added_desc->minor));
adisk->operational = 0;
adisk->write_only = 0;
adisk->spare = 1;
adisk->used_slot = 1;
break;
default:
MD_BUG();
err = 1;
goto abort;
} }
abort: if (err)
MD_BUG();
spin_unlock_irq(&conf->device_lock); spin_unlock_irq(&conf->device_lock);
print_raid5_conf(conf); print_raid5_conf(conf);
return err; return err;
...@@ -1977,7 +1943,11 @@ static mdk_personality_t raid5_personality= ...@@ -1977,7 +1943,11 @@ static mdk_personality_t raid5_personality=
stop: stop, stop: stop,
status: status, status: status,
error_handler: error, error_handler: error,
diskop: diskop, hot_add_disk: raid5_add_disk,
hot_remove_disk:raid5_remove_disk,
spare_write: raid5_spare_write,
spare_inactive: raid5_spare_inactive,
spare_active: raid5_spare_active,
sync_request: sync_request sync_request: sync_request
}; };
......
...@@ -13,14 +13,9 @@ ...@@ -13,14 +13,9 @@
* Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl} * Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
*/ */
#include <linux/config.h> #include <linux/init.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/init.h>
#include <linux/raid/md.h>
#include <linux/buffer_head.h> /* for invalidate_bdev() */ #include <linux/buffer_head.h> /* for invalidate_bdev() */
#include "check.h" #include "check.h"
......
...@@ -160,16 +160,6 @@ struct mdk_rdev_s ...@@ -160,16 +160,6 @@ struct mdk_rdev_s
int desc_nr; /* descriptor index in the superblock */ int desc_nr; /* descriptor index in the superblock */
}; };
/*
* disk operations in a working array:
*/
#define DISKOP_SPARE_INACTIVE 0
#define DISKOP_SPARE_WRITE 1
#define DISKOP_SPARE_ACTIVE 2
#define DISKOP_HOT_REMOVE_DISK 3
#define DISKOP_HOT_ADD_DISK 4
typedef struct mdk_personality_s mdk_personality_t; typedef struct mdk_personality_s mdk_personality_t;
struct mddev_s struct mddev_s
...@@ -214,18 +204,11 @@ struct mdk_personality_s ...@@ -214,18 +204,11 @@ struct mdk_personality_s
int (*stop)(mddev_t *mddev); int (*stop)(mddev_t *mddev);
int (*status)(char *page, mddev_t *mddev); int (*status)(char *page, mddev_t *mddev);
int (*error_handler)(mddev_t *mddev, struct block_device *bdev); int (*error_handler)(mddev_t *mddev, struct block_device *bdev);
int (*hot_add_disk) (mddev_t *mddev, mdp_disk_t *descriptor, mdk_rdev_t *rdev);
/* int (*hot_remove_disk) (mddev_t *mddev, int number);
* Some personalities (RAID-1, RAID-5) can have disks hot-added and int (*spare_write) (mddev_t *mddev, int number);
* hot-removed. Hot removal is different from failure. (failure marks int (*spare_inactive) (mddev_t *mddev);
* a disk inactive, but the disk is still part of the array) The interface int (*spare_active) (mddev_t *mddev, mdp_disk_t **descriptor);
* to such operations is the 'pers->diskop()' function, can be NULL.
*
* the diskop function can change the pointer pointing to the incoming
* descriptor, but must do so very carefully. (currently only
* SPARE_ACTIVE expects such a change)
*/
int (*diskop) (mddev_t *mddev, mdp_disk_t **descriptor, int state);
int (*sync_request)(mddev_t *mddev, sector_t sector_nr, int go_faster); int (*sync_request)(mddev_t *mddev, sector_t sector_nr, int go_faster);
}; };
......
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