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

📄 md.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (!rdev) {		MD_BUG();		return -EINVAL;	}	if (rdev->faulty) {		printk(KERN_WARNING "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(KERN_WARNING "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);	SET_SB(size);	SET_SB(nr_disks);	SET_SB(raid_disks);	SET_SB(md_minor);	SET_SB(not_persistent);	SET_SB(state);	SET_SB(active_disks);	SET_SB(working_disks);	SET_SB(failed_disks);	SET_SB(spare_disks);	SET_SB(layout);	SET_SB(chunk_size);	mddev->sb->md_magic = MD_SB_MAGIC;	/*	 * Generate a 128 bit UUID	 */	get_random_bytes(&mddev->sb->set_uuid0, 4);	get_random_bytes(&mddev->sb->set_uuid1, 4);	get_random_bytes(&mddev->sb->set_uuid2, 4);	get_random_bytes(&mddev->sb->set_uuid3, 4);	return 0;}#undef SET_SBstatic int set_disk_info(mddev_t * mddev, void * arg){	printk(KERN_INFO "md: not yet");	return -EINVAL;}static int clear_array(mddev_t * mddev){	printk(KERN_INFO "md: not yet");	return -EINVAL;}static int write_raid_info(mddev_t * mddev){	printk(KERN_INFO "md: not yet");	return -EINVAL;}static int protect_array(mddev_t * mddev){	printk(KERN_INFO "md: not yet");	return -EINVAL;}static int unprotect_array(mddev_t * mddev){	printk(KERN_INFO "md: not yet");	return -EINVAL;}static int set_disk_faulty(mddev_t *mddev, kdev_t dev){	int ret;	ret = md_error(mddev, dev);	return ret;}static int md_ioctl(struct inode *inode, struct file *file,			unsigned int cmd, unsigned long arg){	unsigned int minor;	int err = 0;	struct hd_geometry *loc = (struct hd_geometry *) arg;	mddev_t *mddev = NULL;	kdev_t dev;	if (!md_capable_admin())		return -EACCES;	dev = inode->i_rdev;	minor = MINOR(dev);	if (minor >= MAX_MD_DEVS) {		MD_BUG();		return -EINVAL;	}	/*	 * Commands dealing with the RAID driver but not any	 * particular array:	 */	switch (cmd)	{		case RAID_VERSION:			err = get_version((void *)arg);			goto done;		case PRINT_RAID_DEBUG:			err = 0;			md_print_devices();			goto done_unlock;#ifndef MODULE		case RAID_AUTORUN:			err = 0;			autostart_arrays();			goto done;#endif		case BLKGETSIZE:	/* Return device size */			if (!arg) {				err = -EINVAL;				MD_BUG();				goto abort;			}			err = md_put_user(md_hd_struct[minor].nr_sects,						(unsigned long *) arg);			goto done;		case BLKGETSIZE64:	/* Return device size */			err = md_put_user((u64)md_hd_struct[minor].nr_sects << 9,						(u64 *) arg);			goto done;		case BLKRAGET:		case BLKRASET:		case BLKFLSBUF:		case BLKBSZGET:		case BLKBSZSET:			err = blk_ioctl (dev, cmd, arg);			goto abort;		default:;	}	/*	 * Commands creating/starting a new array:	 */	mddev = kdev_to_mddev(dev);	switch (cmd)	{		case SET_ARRAY_INFO:		case START_ARRAY:			if (mddev) {				printk(KERN_WARNING "md: array md%d already exists!\n",								mdidx(mddev));				err = -EEXIST;				goto abort;			}		default:;	}	switch (cmd)	{		case SET_ARRAY_INFO:			mddev = alloc_mddev(dev);			if (!mddev) {				err = -ENOMEM;				goto abort;			}			atomic_inc(&mddev->active);			/*			 * alloc_mddev() should possibly self-lock.			 */			err = lock_mddev(mddev);			if (err) {				printk(KERN_WARNING "md: ioctl, reason %d, cmd %d\n",				       err, cmd);				goto abort;			}			if (mddev->sb) {				printk(KERN_WARNING "md: array md%d already has a superblock!\n",					mdidx(mddev));				err = -EBUSY;				goto abort_unlock;			}			if (arg) {				mdu_array_info_t info;				if (md_copy_from_user(&info, (void*)arg, sizeof(info))) {					err = -EFAULT;					goto abort_unlock;				}				err = set_array_info(mddev, &info);				if (err) {					printk(KERN_WARNING "md: couldnt set array info. %d\n", err);					goto abort_unlock;				}			}			goto done_unlock;		case START_ARRAY:			/*			 * possibly make it lock the array ...			 */			err = autostart_array((kdev_t)arg, dev);			if (err) {				printk(KERN_WARNING "md: autostart %s failed!\n",					partition_name((kdev_t)arg));				goto abort;			}			goto done;		default:;	}	/*	 * Commands querying/configuring an existing array:	 */	if (!mddev) {		err = -ENODEV;		goto abort;	}	err = lock_mddev(mddev);	if (err) {		printk(KERN_INFO "md: ioctl lock interrupted, reason %d, cmd %d\n",err, cmd);		goto abort;	}	/* if we don't have a superblock yet, only ADD_NEW_DISK or STOP_ARRAY is allowed */	if (!mddev->sb && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY && cmd != RUN_ARRAY) {		err = -ENODEV;		goto abort_unlock;	}	/*	 * Commands even a read-only array can execute:	 */	switch (cmd)	{		case GET_ARRAY_INFO:			err = get_array_info(mddev, (void *)arg);			goto done_unlock;		case GET_DISK_INFO:			err = get_disk_info(mddev, (void *)arg);			goto done_unlock;		case RESTART_ARRAY_RW:			err = restart_array(mddev);			goto done_unlock;		case STOP_ARRAY:			if (!(err = do_md_stop (mddev, 0)))				mddev = NULL;			goto done_unlock;		case STOP_ARRAY_RO:			err = do_md_stop (mddev, 1);			goto done_unlock;	/*	 * We have a problem here : there is no easy way to give a CHS	 * virtual geometry. We currently pretend that we have a 2 heads	 * 4 sectors (with a BIG number of cylinders...). This drives	 * dosfs just mad... ;-)	 */		case HDIO_GETGEO:			if (!loc) {				err = -EINVAL;				goto abort_unlock;			}			err = md_put_user (2, (char *) &loc->heads);			if (err)				goto abort_unlock;			err = md_put_user (4, (char *) &loc->sectors);			if (err)				goto abort_unlock;			err = md_put_user (md_hd_struct[mdidx(mddev)].nr_sects/8,						(short *) &loc->cylinders);			if (err)				goto abort_unlock;			err = md_put_user (md_hd_struct[minor].start_sect,						(long *) &loc->start);			goto done_unlock;	}	/*	 * The remaining ioctls are changing the state of the	 * superblock, so we do not allow read-only arrays	 * here:	 */	if (mddev->ro) {		err = -EROFS;		goto abort_unlock;	}	switch (cmd)	{		case CLEAR_ARRAY:			err = clear_array(mddev);			goto done_unlock;		case ADD_NEW_DISK:		{			mdu_disk_info_t info;			if (md_copy_from_user(&info, (void*)arg, sizeof(info)))				err = -EFAULT;			else				err = add_new_disk(mddev, &info);			goto done_unlock;		}		case HOT_GENERATE_ERROR:			err = hot_generate_error(mddev, (kdev_t)arg);			goto done_unlock;		case HOT_REMOVE_DISK:			err = hot_remove_disk(mddev, (kdev_t)arg);			goto done_unlock;		case HOT_ADD_DISK:			err = hot_add_disk(mddev, (kdev_t)arg);			goto done_unlock;		case SET_DISK_INFO:			err = set_disk_info(mddev, (void *)arg);			goto done_unlock;		case WRITE_RAID_INFO:			err = write_raid_info(mddev);			goto done_unlock;		case UNPROTECT_ARRAY:			err = unprotect_array(mddev);			goto done_unlock;		case PROTECT_ARRAY:			err = protect_array(mddev);			goto done_unlock;		case SET_DISK_FAULTY:			err = set_disk_faulty(mddev, (kdev_t)arg);			goto done_unlock;		case RUN_ARRAY:		{/* The data is never used....			mdu_param_t param;			err = md_copy_from_user(&param, (mdu_param_t *)arg,							 sizeof(param));			if (err)				goto abort_unlock;*/			err = do_md_run (mddev);			/*			 * we have to clean up the mess if			 * the array cannot be run for some			 * reason ...			 */			if (err) {				mddev->sb_dirty = 0;				if (!do_md_stop (mddev, 0))					mddev = NULL;			}			goto done_unlock;		}		default:			printk(KERN_WARNING "md: %s(pid %d) used obsolete MD ioctl, "			       "upgrade your software to use new ictls.\n",			       current->comm, current->pid);			err = -EINVAL;			goto abort_unlock;	}done_unlock:abort_unlock:	if (mddev)		unlock_mddev(mddev);	return err;done:	if (err)		MD_BUG();abort:	return err;}static int md_open(struct inode *inode, struct file *file){	/*	 * Always succeed, but increment the usage count	 */	mddev_t *mddev = kdev_to_mddev(inode->i_rdev);	if (mddev)		atomic_inc(&mddev->active);	return (0);}static int md_release(struct inode *inode, struct file * file){	mddev_t *mddev = kdev_to_mddev(inode->i_rdev);	if (mddev)		atomic_dec(&mddev->active);	return 0;}static struct block_device_operations md_fops={	owner:		THIS_MODULE,	open:		md_open,	release:	md_release,	ioctl:		md_ioctl,};int md_thread(void * arg){	mdk_thread_t *thread = arg;	md_lock_kernel();	/*	 * Detach thread	 */	daemonize();	sprintf(current->comm, thread->name);	md_init_signals();	md_flush_signals();	thread->tsk = current;	/*	 * md_thread is a 'system-thread', it's priority should be very	 * high. We avoid resource deadlocks individually in each	 * raid personality. (RAID5 does preallocation) We also use RR and	 * the very same RT priority as kswapd, thus we will never get	 * into a priority inversion deadlock.	 *	 * we definitely have to have equal or higher priority than	 * bdflush, otherwise bdflush will deadlock if there are too	 * many dirty RAID5 blocks.	 */	current->policy = SCHED_OTHER;	current->nice = -20;	md_unlock_kernel();	complete(thread->event);	while (thread->run) {		void (*run)(void *data);		DECLARE_WAITQUEUE(wait, current);		add_wait_queue(&thread->wqueue, &wait);		set_task_state(current, TASK_INTERRUPTIBLE);		if (!test_bit(THREAD_WAKEUP, &thread->flags)) {			dprintk("md: thread %p went to sleep.\n", thread);			schedule();			dprintk("md: thread %p woke up.\n", thread);		}		current->state = TASK_RUNNING;		remove_wait_queue(&thread->wqueue, &wait);		clear_bit(THREAD_WAKEUP, &thread->flags);		run = thread->run;		if (run) {			run(thread->data);			run_task_queue(&tq_disk);		}		if (md_signal_pending(current))			md_flush_signals();	}	complete(thread->event);	return 0;}void md_wakeup_thread(mdk_thread_t *thread){	dprintk("md: waking up MD thread %p.\n", thread);	set_bit(THREAD_WAKEUP, &thread->flags);	wake_up(&thread->wqueue);}mdk_thread_t *md_register_thread(void (*run) (void *),						void *data, const char *name){	mdk_thread_t *thread;	int ret;	struct completion event;	thread = (mdk_thread_t *) kmalloc				(sizeof(mdk_thread_t), GFP_KERNEL);	if (!thread)		return NULL;	memset(thread, 0, sizeof(mdk_thread_t));	md_init_waitqueue_head(&thread->wqueue);	init_completion(&event);	thread->event = &event;	thread->run = run;	thread->data = data;	thread->name = name;	ret = kernel_thread(md_thread, thread, 0);	if (ret < 0) {		kfree(thread);		return NULL;	}	wait_for_completion(&event);	return thread;}void md_interrupt_thread(mdk_thread_t *thread){	if (!thread->tsk) {		MD_BUG()

⌨️ 快捷键说明

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