⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 md.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		printk("do_md_run() returned %d\n", err);		/*		 * prevent the writeback of an unrunnable array		 */		mddev->sb_dirty = 0;		do_md_stop (mddev, 0);	}}/* * lets try to run arrays based on all disks that have arrived * until now. (those are in the ->pending list) * * the method: pick the first pending disk, collect all disks with * the same UUID, remove all from the pending list and put them into * the 'same_array' list. Then order this list based on superblock * update time (freshest comes first), kick out 'old' disks and * compare superblocks. If everything's fine then run it. * * If "unit" is allocated, then bump its reference count */static void autorun_devices (kdev_t countdev){	struct md_list_head candidates;	struct md_list_head *tmp;	mdk_rdev_t *rdev0, *rdev;	mddev_t *mddev;	kdev_t md_kdev;	printk("autorun ...\n");	while (pending_raid_disks.next != &pending_raid_disks) {		rdev0 = md_list_entry(pending_raid_disks.next,					 mdk_rdev_t, pending);		printk("considering %s ...\n", partition_name(rdev0->dev));		MD_INIT_LIST_HEAD(&candidates);		ITERATE_RDEV_PENDING(rdev,tmp) {			if (uuid_equal(rdev0, rdev)) {				if (!sb_equal(rdev0->sb, rdev->sb)) {					printk("%s has same UUID as %s, but superblocks differ ...\n", partition_name(rdev->dev), partition_name(rdev0->dev));					continue;				}				printk("  adding %s ...\n", partition_name(rdev->dev));				md_list_del(&rdev->pending);				md_list_add(&rdev->pending, &candidates);			}		}		/*		 * now we have a set of devices, with all of them having		 * mostly sane superblocks. It's time to allocate the		 * mddev.		 */		md_kdev = MKDEV(MD_MAJOR, rdev0->sb->md_minor);		mddev = kdev_to_mddev(md_kdev);		if (mddev) {			printk("md%d already running, cannot run %s\n",				 mdidx(mddev), partition_name(rdev0->dev));			ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp)				export_rdev(rdev);			continue;		}		mddev = alloc_mddev(md_kdev); 		if (mddev == NULL) { 			printk("md: cannot allocate memory for md drive.\n"); 			break; 		} 		if (md_kdev == countdev) 			atomic_inc(&mddev->active);		printk("created md%d\n", mdidx(mddev));		ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp) {			bind_rdev_to_array(rdev, mddev);			md_list_del(&rdev->pending);			MD_INIT_LIST_HEAD(&rdev->pending);		}		autorun_array(mddev);	}	printk("... autorun DONE.\n");}/* * import RAID devices based on one partition * if possible, the array gets run as well. */#define BAD_VERSION KERN_ERR \"md: %s has RAID superblock version 0.%d, autodetect needs v0.90 or higher\n"#define OUT_OF_MEM KERN_ALERT \"md: out of memory.\n"#define NO_DEVICE KERN_ERR \"md: disabled device %s\n"#define AUTOADD_FAILED KERN_ERR \"md: auto-adding devices to md%d FAILED (error %d).\n"#define AUTOADD_FAILED_USED KERN_ERR \"md: cannot auto-add device %s to md%d, already used.\n"#define AUTORUN_FAILED KERN_ERR \"md: auto-running md%d FAILED (error %d).\n"#define MDDEV_BUSY KERN_ERR \"md: cannot auto-add to md%d, already running.\n"#define AUTOADDING KERN_INFO \"md: auto-adding devices to md%d, based on %s's superblock.\n"#define AUTORUNNING KERN_INFO \"md: auto-running md%d.\n"static int autostart_array (kdev_t startdev, kdev_t countdev){	int err = -EINVAL, i;	mdp_super_t *sb = NULL;	mdk_rdev_t *start_rdev = NULL, *rdev;	if (md_import_device(startdev, 1)) {		printk("could not import %s!\n", partition_name(startdev));		goto abort;	}	start_rdev = find_rdev_all(startdev);	if (!start_rdev) {		MD_BUG();		goto abort;	}	if (start_rdev->faulty) {		printk("can not autostart based on faulty %s!\n",						partition_name(startdev));		goto abort;	}	md_list_add(&start_rdev->pending, &pending_raid_disks);	sb = start_rdev->sb;	err = detect_old_array(sb);	if (err) {		printk("array version is too old to be autostarted, use raidtools 0.90 mkraid --upgrade\nto upgrade the array without data loss!\n");		goto abort;	}	for (i = 0; i < MD_SB_DISKS; i++) {		mdp_disk_t *desc;		kdev_t dev;		desc = sb->disks + i;		dev = MKDEV(desc->major, desc->minor);		if (dev == MKDEV(0,0))			continue;		if (dev == startdev)			continue;		if (md_import_device(dev, 1)) {			printk("could not import %s, trying to run array nevertheless.\n", partition_name(dev));			continue;		}		rdev = find_rdev_all(dev);		if (!rdev) {			MD_BUG();			goto abort;		}		md_list_add(&rdev->pending, &pending_raid_disks);	}	/*	 * possibly return codes	 */	autorun_devices(countdev);	return 0;abort:	if (start_rdev)		export_rdev(start_rdev);	return err;}#undef BAD_VERSION#undef OUT_OF_MEM#undef NO_DEVICE#undef AUTOADD_FAILED_USED#undef AUTOADD_FAILED#undef AUTORUN_FAILED#undef AUTOADDING#undef AUTORUNNINGstruct {	int set;	int noautodetect;} raid_setup_args md__initdata = { 0, 0 };void md_setup_drive(void) md__init;/* * Searches all registered partitions for autorun RAID arrays * at boot time. */#ifdef CONFIG_AUTODETECT_RAIDstatic int detected_devices[128] md__initdata = { 0, };static int dev_cnt=0;void md_autodetect_dev(kdev_t dev){	if (dev_cnt >= 0 && dev_cnt < 127)		detected_devices[dev_cnt++] = dev;}#endifint md__init md_run_setup(void){#ifdef CONFIG_AUTODETECT_RAID	mdk_rdev_t *rdev;	int i;	if (raid_setup_args.noautodetect)		printk(KERN_INFO "skipping autodetection of RAID arrays\n");	else {		printk(KERN_INFO "autodetecting RAID arrays\n");		for (i=0; i<dev_cnt; i++) {			kdev_t dev = detected_devices[i];			if (md_import_device(dev,1)) {				printk(KERN_ALERT "could not import %s!\n",				       partition_name(dev));				continue;			}			/*			 * Sanity checks:			 */			rdev = find_rdev_all(dev);			if (!rdev) {				MD_BUG();				continue;			}			if (rdev->faulty) {				MD_BUG();				continue;			}			md_list_add(&rdev->pending, &pending_raid_disks);		}		autorun_devices(-1);	}	dev_cnt = -1; /* make sure further calls to md_autodetect_dev are ignored */#endif#ifdef CONFIG_MD_BOOT	md_setup_drive();#endif	return 0;}static int get_version (void * arg){	mdu_version_t ver;	ver.major = MD_MAJOR_VERSION;	ver.minor = MD_MINOR_VERSION;	ver.patchlevel = MD_PATCHLEVEL_VERSION;	if (md_copy_to_user(arg, &ver, sizeof(ver)))		return -EFAULT;	return 0;}#define SET_FROM_SB(x) info.x = mddev->sb->xstatic int get_array_info (mddev_t * mddev, void * arg){	mdu_array_info_t info;	if (!mddev->sb)		return -EINVAL;	SET_FROM_SB(major_version);	SET_FROM_SB(minor_version);	SET_FROM_SB(patch_version);	SET_FROM_SB(ctime);	SET_FROM_SB(level);	SET_FROM_SB(size);	SET_FROM_SB(nr_disks);	SET_FROM_SB(raid_disks);	SET_FROM_SB(md_minor);	SET_FROM_SB(not_persistent);	SET_FROM_SB(utime);	SET_FROM_SB(state);	SET_FROM_SB(active_disks);	SET_FROM_SB(working_disks);	SET_FROM_SB(failed_disks);	SET_FROM_SB(spare_disks);	SET_FROM_SB(layout);	SET_FROM_SB(chunk_size);	if (md_copy_to_user(arg, &info, sizeof(info)))		return -EFAULT;	return 0;}#undef SET_FROM_SB#define SET_FROM_SB(x) info.x = mddev->sb->disks[nr].xstatic int get_disk_info (mddev_t * mddev, void * arg){	mdu_disk_info_t info;	unsigned int nr;	if (!mddev->sb)		return -EINVAL;	if (md_copy_from_user(&info, arg, sizeof(info)))		return -EFAULT;	nr = info.number;	if (nr >= mddev->sb->nr_disks)		return -EINVAL;	SET_FROM_SB(major);	SET_FROM_SB(minor);	SET_FROM_SB(raid_disk);	SET_FROM_SB(state);	if (md_copy_to_user(arg, &info, sizeof(info)))		return -EFAULT;	return 0;}#undef SET_FROM_SB#define SET_SB(x) mddev->sb->disks[nr].x = info->xstatic int add_new_disk (mddev_t * mddev, mdu_disk_info_t *info){	int err, size, persistent;	mdk_rdev_t *rdev;	unsigned int nr;	kdev_t dev;	dev = MKDEV(info->major,info->minor);	if (find_rdev_all(dev)) {		printk("device %s already used in a RAID array!\n",				partition_name(dev));		return -EBUSY;	}	if (!mddev->sb) {		/* expecting a device which has a superblock */		err = md_import_device(dev, 1);		if (err) {			printk("md error, md_import_device returned %d\n", err);			return -EINVAL;		}		rdev = find_rdev_all(dev);		if (!rdev) {			MD_BUG();			return -EINVAL;		}		if (mddev->nb_dev) {			mdk_rdev_t *rdev0 = md_list_entry(mddev->disks.next,							  mdk_rdev_t, same_set);			if (!uuid_equal(rdev0, rdev)) {				printk("md: %s has different UUID to %s\n", partition_name(rdev->dev), partition_name(rdev0->dev));				export_rdev(rdev);				return -EINVAL;			}			if (!sb_equal(rdev0->sb, rdev->sb)) {				printk("md: %s has same UUID but different superblock to %s\n", partition_name(rdev->dev), partition_name(rdev0->dev));				export_rdev(rdev);				return -EINVAL;			}		}		bind_rdev_to_array(rdev, mddev);		return 0;	}	nr = info->number;	if (nr >= mddev->sb->nr_disks)		return -EINVAL;	SET_SB(number);	SET_SB(major);	SET_SB(minor);	SET_SB(raid_disk);	SET_SB(state);	if ((info->state & (1<<MD_DISK_FAULTY))==0) {		err = md_import_device (dev, 0);		if (err) {			printk("md: error, md_import_device() returned %d\n", err);			return -EINVAL;		}		rdev = find_rdev_all(dev);		if (!rdev) {			MD_BUG();			return -EINVAL;		}		rdev->old_dev = dev;		rdev->desc_nr = info->number;		bind_rdev_to_array(rdev, mddev);		persistent = !mddev->sb->not_persistent;		if (!persistent)			printk("nonpersistent superblock ...\n");		if (!mddev->sb->chunk_size)			printk("no chunksize?\n");		size = calc_dev_size(dev, mddev, persistent);		rdev->sb_offset = calc_dev_sboffset(dev, mddev, persistent);		if (!mddev->sb->size || (mddev->sb->size > size))			mddev->sb->size = size;	}	/*	 * sync all other superblocks with the main superblock	 */	sync_sbs(mddev);	return 0;}#undef SET_SBstatic int hot_remove_disk (mddev_t * mddev, kdev_t dev){	int err;	mdk_rdev_t *rdev;	mdp_disk_t *disk;	if (!mddev->pers)		return -ENODEV;	printk("trying to remove %s from md%d ... \n",		partition_name(dev), mdidx(mddev));	if (!mddev->pers->diskop) {		printk("md%d: personality does not support diskops!\n",								 mdidx(mddev));		return -EINVAL;	}	rdev = find_rdev(mddev, dev);	if (!rdev)		return -ENXIO;	if (rdev->desc_nr == -1) {		MD_BUG();		return -EINVAL;	}	disk = &mddev->sb->disks[rdev->desc_nr];	if (disk_active(disk))		goto busy;	if (disk_removed(disk)) {		MD_BUG();		return -EINVAL;	}		err = mddev->pers->diskop(mddev, &disk, DISKOP_HOT_REMOVE_DISK);	if (err == -EBUSY)		goto busy;	if (err) {		MD_BUG();		return -EINVAL;	}	remove_descriptor(disk, mddev->sb);	kick_rdev_from_array(rdev);	mddev->sb_dirty = 1;	md_update_sb(mddev);	return 0;busy:	printk("cannot remove active disk %s from md%d ... \n",		partition_name(dev), mdidx(mddev));	return -EBUSY;}static int hot_add_disk (mddev_t * mddev, kdev_t dev){	int i, err, persistent;	unsigned int size;	mdk_rdev_t *rdev;	mdp_disk_t *disk;	if (!mddev->pers)		return -ENODEV;	printk("trying to hot-add %s to md%d ... \n",		partition_name(dev), mdidx(mddev));	if (!mddev->pers->diskop) {		printk("md%d: personality does not support diskops!\n",								 mdidx(mddev));		return -EINVAL;	}	persistent = !mddev->sb->not_persistent;	size = calc_dev_size(dev, mddev, persistent);	if (size < mddev->sb->size) {		printk("md%d: disk size %d blocks < array size %d\n",				mdidx(mddev), size, mddev->sb->size);		return -ENOSPC;	}	rdev = find_rdev(mddev, dev);	if (rdev)		return -EBUSY;	err = md_import_device (dev, 0);	if (err) {		printk("md: error, md_import_device() returned %d\n", err);		return -EINVAL;	}	rdev = find_rdev_all(dev);	if (!rdev) {		MD_BUG();		return -EINVAL;	}	if (rdev->faulty) {		printk("md: can not hot-add faulty %s disk to md%d!\n",				partition_name(dev), mdidx(mddev));		err = -EINVAL;		goto abort_export;	}	bind_rdev_to_array(rdev, mddev);	/*	 * The rest should better be atomic, we can have disk failures	 * noticed in interrupt contexts ...	 */	rdev->old_dev = dev;	rdev->size = size;	rdev->sb_offset = calc_dev_sboffset(dev, mddev, persistent);	disk = mddev->sb->disks + mddev->sb->raid_disks;	for (i = mddev->sb->raid_disks; i < MD_SB_DISKS; i++) {		disk = mddev->sb->disks + i;		if (!disk->major && !disk->minor)			break;		if (disk_removed(disk))			break;	}	if (i == MD_SB_DISKS) {		printk("md%d: can not hot-add to full array!\n", mdidx(mddev));		err = -EBUSY;		goto abort_unbind_export;	}	if (disk_removed(disk)) {		/*		 * reuse slot		 */		if (disk->number != i) {			MD_BUG();			err = -EINVAL;			goto abort_unbind_export;		}	} else {		disk->number = i;	}	disk->raid_disk = disk->number;	disk->major = MAJOR(dev);	disk->minor = MINOR(dev);	if (mddev->pers->diskop(mddev, &disk, DISKOP_HOT_ADD_DISK)) {		MD_BUG();		err = -EINVAL;		goto abort_unbind_export;	}	mark_disk_spare(disk);	mddev->sb->nr_disks++;	mddev->sb->spare_disks++;	mddev->sb->working_disks++;	mddev->sb_dirty = 1;	md_update_sb(mddev);	/*	 * Kick recovery, maybe this spare has to be added to the	 * array immediately.	 */	md_recover_arrays();	return 0;abort_unbind_export:	unbind_rdev_from_array(rdev);abort_export:	export_rdev(rdev);	return err;}#define SET_SB(x) mddev->sb->x = info->xstatic int set_array_info (mddev_t * mddev, mdu_array_info_t *info){	if (alloc_array_sb(mddev))		return -ENOMEM;	mddev->sb->major_version = MD_MAJOR_VERSION;	mddev->sb->minor_version = MD_MINOR_VERSION;	mddev->sb->patch_version = MD_PATCHLEVEL_VERSION;	mddev->sb->ctime = CURRENT_TIME;	SET_SB(level);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -