ioctl-RUN_ARRAY
RUN_ARRAY는 드디어 md 디스크를 생성하는 명령입니다. do_md_run함수가 처리합니다.
static int md_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
......
case RUN_ARRAY:
err = do_md_run(mddev);
goto unlock;
do_md_run
- call md_run()
- set disk size at mddev->gendisk
- revalidate_disk
md_alloc()
:gendisk->fops = md_fops
- disk->fops->revalidate_disk = md_revalidate
- check_disk_size_change(): print message "md100: detected capacity change from 0 to 104726528"
- throw uevent KBOJ_CHANGE for user-level event handler
md_run
do_md_run에서 첫번째로 호출하는 함수는 md_run입니다. md_run은 다음과 같은 일을 합니다.
- mddev->disks 리스트에 아무런 장치가 없으면 -EINVAL 반환
- mddev->pers, mddev->sysfs_active 값이 0이 아니면 새로 생성되는 디스크가 아니므로 -EBUSY 반환
- analyze_sbs 호출: mddev에 연결된 md_rdev 디스크들의 슈퍼블럭을 읽어서 정상적인 슈퍼블럭인지 확인
- pers = &raid1_personality
- pers->run = run() in raid1.c
- setup_conf() creates conf object
- conf->mirrors[0].rdev: pointer to md_rdev of /dev/vda
- conf->mirrors[1].rdev: pointer to md_rdev of /dev/vdb
- conf->mirrors[2,3]: for replacement, in case when vda or vdb is faulty
- conf object keeps information of raid-disks
- "md/raid1:md100: active with 2 out of 2 mirrors\n"
- md100: device file name
- 2 out of: mddev->raid_disks - mddev->degraded, if all devices are clean
- 2 mirrors: mddev->raid_disks, the number of all raid-disks
- mddev->thread = conf->thread: md100_raid1 thread
- run raid1d() function
- call md_check_recovery(): check MD_RECOVERY_NEEDED bit and do recovery or resync
- this thread is not started yet, will start after md_run() is finished
- see
do_md_run(): md_wakeup_thread(mddev->thread)
- see
- We will look into what raid1d() does in later chapter
- run raid1d() function
- mddev->private = conf
- setup_conf() creates conf object
- mddev->in_sync = 1
- mddev->pers = pers;
- mddev->ready = 1
- set
MD_RECOVORY_NEEDED
bit at mddev->recovery- comment in md.h:
NEEDED: we might need to start a resync/recover
- After creating md, md100_raid1 thread will start resync
- comment in md.h:
struct md_personality
md_run:
- mddev->level = 1
pers = find_pers(mddev->level, mddev->clevel);
raid1.c:
- raid1.ko is a module to support RAID-1
- If that module does not exist or is not loaded, find_pers would fails and md module results "md: personality for level %d is not loaded!" error.
static struct md_personality raid1_personality =
{
.name = "raid1",
.level = 1,
.owner = THIS_MODULE,
.make_request = make_request,
.run = run,
.free = raid1_free,
.status = status,
.error_handler = error,
.hot_add_disk = raid1_add_disk,
.hot_remove_disk= raid1_remove_disk,
.spare_active = raid1_spare_active,
.sync_request = sync_request,
.resize = raid1_resize,
.size = raid1_size,
.check_reshape = raid1_reshape,
.quiesce = raid1_quiesce,
.takeover = raid1_takeover,
.congested = raid1_congested,
};
static int __init raid_init(void)
{
return register_md_personality(&raid1_personality);
}