📄 raid5.c
字号:
const char * name = "raid5d"; conf->thread = md_register_thread(raid5d, conf, name); if (!conf->thread) { printk(KERN_ERR "raid5: couldn't allocate thread for md%d\n", mdidx(mddev)); goto abort; } } memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + conf->raid_disks * ((sizeof(struct buffer_head) + PAGE_SIZE))) / 1024; if (grow_stripes(conf, conf->max_nr_stripes, GFP_KERNEL)) { printk(KERN_ERR "raid5: couldn't allocate %dkB for buffers\n", memory); shrink_stripes(conf, conf->max_nr_stripes); goto abort; } else printk(KERN_INFO "raid5: allocated %dkB for md%d\n", memory, mdidx(mddev)); /* * Regenerate the "device is in sync with the raid set" bit for * each device. */ for (i = 0; i < MD_SB_DISKS ; i++) { mark_disk_nonsync(sb->disks + i); for (j = 0; j < sb->raid_disks; j++) { if (!conf->disks[j].operational) continue; if (sb->disks[i].number == conf->disks[j].number) mark_disk_sync(sb->disks + i); } } sb->active_disks = conf->working_disks; if (sb->active_disks == sb->raid_disks) printk("raid5: raid level %d set md%d active with %d out of %d devices, algorithm %d\n", conf->level, mdidx(mddev), sb->active_disks, sb->raid_disks, conf->algorithm); else printk(KERN_ALERT "raid5: raid level %d set md%d active with %d out of %d devices, algorithm %d\n", conf->level, mdidx(mddev), sb->active_disks, sb->raid_disks, conf->algorithm); if (!start_recovery && !(sb->state & (1 << MD_SB_CLEAN))) { const char * name = "raid5syncd"; conf->resync_thread = md_register_thread(raid5syncd, conf,name); if (!conf->resync_thread) { printk(KERN_ERR "raid5: couldn't allocate thread for md%d\n", mdidx(mddev)); goto abort; } printk("raid5: raid set md%d not clean; reconstructing parity\n", mdidx(mddev)); conf->resync_parity = 1; md_wakeup_thread(conf->resync_thread); } print_raid5_conf(conf); if (start_recovery) md_recover_arrays(); print_raid5_conf(conf); /* Ok, everything is just fine now */ return (0);abort: if (conf) { print_raid5_conf(conf); if (conf->stripe_hashtbl) free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); kfree(conf); } mddev->private = NULL; printk(KERN_ALERT "raid5: failed to run raid set md%d\n", mdidx(mddev)); MOD_DEC_USE_COUNT; return -EIO;}static int raid5_stop_resync (mddev_t *mddev){ raid5_conf_t *conf = mddev_to_conf(mddev); mdk_thread_t *thread = conf->resync_thread; if (thread) { if (conf->resync_parity) { conf->resync_parity = 2; md_interrupt_thread(thread); printk(KERN_INFO "raid5: parity resync was not fully finished, restarting next time.\n"); return 1; } return 0; } return 0;}static int raid5_restart_resync (mddev_t *mddev){ raid5_conf_t *conf = mddev_to_conf(mddev); if (conf->resync_parity) { if (!conf->resync_thread) { MD_BUG(); return 0; } printk("raid5: waking up raid5resync.\n"); conf->resync_parity = 1; md_wakeup_thread(conf->resync_thread); return 1; } else printk("raid5: no restart-resync needed.\n"); return 0;}static int raid5_stop (mddev_t *mddev){ raid5_conf_t *conf = (raid5_conf_t *) mddev->private; if (conf->resync_thread) md_unregister_thread(conf->resync_thread); md_unregister_thread(conf->thread); shrink_stripes(conf, conf->max_nr_stripes); free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); kfree(conf); mddev->private = NULL; MOD_DEC_USE_COUNT; return 0;}#if RAID5_DEBUGstatic void print_sh (struct stripe_head *sh){ int i; printk("sh %lu, size %d, pd_idx %d, state %ld.\n", sh->sector, sh->size, sh->pd_idx, sh->state); printk("sh %lu, count %d.\n", sh->sector, atomic_read(&sh->count)); printk("sh %lu, ", sh->sector); for (i = 0; i < MD_SB_DISKS; i++) { if (sh->bh_cache[i]) printk("(cache%d: %p %ld) ", i, sh->bh_cache[i], sh->bh_cache[i]->b_state); } printk("\n");}static void printall (raid5_conf_t *conf){ struct stripe_head *sh; int i; md_spin_lock_irq(&conf->device_lock); for (i = 0; i < NR_HASH; i++) { sh = conf->stripe_hashtbl[i]; for (; sh; sh = sh->hash_next) { if (sh->raid_conf != conf) continue; print_sh(sh); } } md_spin_unlock_irq(&conf->device_lock); PRINTK("--- raid5d inactive\n");}#endifstatic int raid5_status (char *page, mddev_t *mddev){ raid5_conf_t *conf = (raid5_conf_t *) mddev->private; mdp_super_t *sb = mddev->sb; int sz = 0, i; sz += sprintf (page+sz, " level %d, %dk chunk, algorithm %d", sb->level, sb->chunk_size >> 10, sb->layout); sz += sprintf (page+sz, " [%d/%d] [", conf->raid_disks, conf->working_disks); for (i = 0; i < conf->raid_disks; i++) sz += sprintf (page+sz, "%s", conf->disks[i].operational ? "U" : "_"); sz += sprintf (page+sz, "]");#if RAID5_DEBUG#define D(x) \ sz += sprintf (page+sz, "<"#x":%d>", atomic_read(&conf->x)) printall(conf);#endif return sz;}static void print_raid5_conf (raid5_conf_t *conf){ int i; struct disk_info *tmp; printk("RAID5 conf printout:\n"); if (!conf) { printk("(conf==NULL)\n"); return; } printk(" --- rd:%d wd:%d fd:%d\n", conf->raid_disks, conf->working_disks, conf->failed_disks);#if RAID5_DEBUG for (i = 0; i < MD_SB_DISKS; i++) {#else for (i = 0; i < conf->working_disks+conf->failed_disks; i++) {#endif tmp = conf->disks + i; printk(" disk %d, s:%d, o:%d, n:%d rd:%d us:%d dev:%s\n", i, tmp->spare,tmp->operational, tmp->number,tmp->raid_disk,tmp->used_slot, partition_name(tmp->dev)); }}static int raid5_diskop(mddev_t *mddev, mdp_disk_t **d, int state){ int err = 0; int i, failed_disk=-1, spare_disk=-1, removed_disk=-1, added_disk=-1; raid5_conf_t *conf = mddev->private; struct disk_info *tmp, *sdisk, *fdisk, *rdisk, *adisk; mdp_super_t *sb = mddev->sb; mdp_disk_t *failed_desc, *spare_desc, *added_desc; mdk_rdev_t *spare_rdev, *failed_rdev; print_raid5_conf(conf); md_spin_lock_irq(&conf->device_lock); /* * find the disk ... */ switch (state) { case DISKOP_SPARE_ACTIVE: /* * 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; case DISKOP_HOT_REMOVE_DISK: for (i = 0; i < MD_SB_DISKS; i++) { tmp = conf->disks + 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: for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { tmp = conf->disks + i; if (!tmp->used_slot) { added_disk = i; break; } } 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: if (conf->spare) { MD_BUG(); err = 1; goto abort; } sdisk = conf->disks + spare_disk; sdisk->operational = 1; sdisk->write_only = 1; conf->spare = sdisk; break; /* * Deactivate a spare disk: */ case DISKOP_SPARE_INACTIVE: sdisk = conf->disks + spare_disk; sdisk->operational = 0; sdisk->write_only = 0; /* * Was the spare being resynced? */ if (conf->spare == sdisk) conf->spare = NULL; break; /* * Activate (mark read-write) the (now sync) spare disk, * which means we switch it's 'raid position' (->raid_disk) * with the failed disk. (only the first 'conf->raid_disks' * slots are used for 'real' disks and we must preserve this * property) */ 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]; failed_desc = &sb->disks[fdisk->number]; if (spare_desc != *d) { MD_BUG(); err = 1; goto abort; } if (spare_desc->raid_disk != sdisk->raid_disk) { MD_BUG(); 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(); err = 1; goto abort; } 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) * * 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; if (sdisk->dev == MKDEV(0,0)) sdisk->used_slot = 0; /* * this really activates the spare. */ fdisk->spare = 0; fdisk->write_only = 0; /* * if we activate a spare, we definitely replace a * non-operational disk slot in the 'low' area of * the disk array. */ conf->failed_disks--; conf->working_disks++; conf->spare = NULL; break; case DISKOP_HOT_REMOVE_DISK: rdisk = conf->disks + removed_disk; if (rdisk->spare && (removed_disk < conf->raid_disks)) { MD_BUG(); err = 1; goto abort; } rdisk->dev = MKDEV(0,0); rdisk->used_slot = 0; break; case DISKOP_HOT_ADD_DISK: adisk = conf->disks + added_disk; added_desc = *d; if (added_disk != added_desc->number) { MD_BUG(); err = 1; goto abort; } adisk->number = added_desc->number; adisk->raid_disk = added_desc->raid_disk; adisk->dev = 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: md_spin_unlock_irq(&conf->device_lock); print_raid5_conf(conf); return err;}static mdk_personality_t raid5_personality={ name: "raid5", make_request: raid5_make_request, run: raid5_run, stop: raid5_stop, status: raid5_status, error_handler: raid5_error, diskop: raid5_diskop, stop_resync: raid5_stop_resync, restart_resync: raid5_restart_resync, sync_request: raid5_sync_request};static int md__init raid5_init (void){ return register_md_personality (RAID5, &raid5_personality);}static void raid5_exit (void){ unregister_md_personality (RAID5);}module_init(raid5_init);module_exit(raid5_exit);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -