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

📄 md.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	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("not yet");	return -EINVAL;}static int clear_array (mddev_t * mddev){	printk("not yet");	return -EINVAL;}static int write_raid_info (mddev_t * mddev){	printk("not yet");	return -EINVAL;}static int protect_array (mddev_t * mddev){	printk("not yet");	return -EINVAL;}static int unprotect_array (mddev_t * mddev){	printk("not yet");	return -EINVAL;}static int set_disk_faulty (mddev_t *mddev, kdev_t dev){	int ret;	fsync_dev(mddev_to_kdev(mddev));	ret = md_error(mddev_to_kdev(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)		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;		case BLKGETSIZE:   /* Return device size */			if (!arg) {				err = -EINVAL;				goto abort;			}			err = md_put_user(md_hd_struct[minor].nr_sects,						(long *) arg);			goto done;		case BLKFLSBUF:			fsync_dev(dev);			invalidate_buffers(dev);			goto done;		case BLKRASET:			if (arg > 0xff) {				err = -EINVAL;				goto abort;			}			read_ahead[MAJOR(dev)] = arg;			goto done;		case BLKRAGET:			if (!arg) {				err = -EINVAL;				goto abort;			}			err = md_put_user (read_ahead[				MAJOR(dev)], (long *) arg);			goto done;		default:	}	/*	 * Commands creating/starting a new array:	 */	mddev = kdev_to_mddev(dev);	switch (cmd)	{		case SET_ARRAY_INFO:		case START_ARRAY:			if (mddev) {				printk("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("ioctl, reason %d, cmd %d\n", err, cmd);				goto abort;			}			if (mddev->sb) {				printk("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("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("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("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_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 "%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)		printk("huh12?\n");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={	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();	up(thread->sem);	for (;;) {		DECLARE_WAITQUEUE(wait, current);		add_wait_queue(&thread->wqueue, &wait);		set_task_state(current, TASK_INTERRUPTIBLE);		if (!test_bit(THREAD_WAKEUP, &thread->flags)) {			dprintk("thread %p went to sleep.\n", thread);			schedule();			dprintk("thread %p woke up.\n", thread);		}		current->state = TASK_RUNNING;		remove_wait_queue(&thread->wqueue, &wait);		clear_bit(THREAD_WAKEUP, &thread->flags);		if (thread->run) {			thread->run(thread->data);			run_task_queue(&tq_disk);		} else			break;		if (md_signal_pending(current)) {			printk("%8s(%d) flushing signals.\n", current->comm,				current->pid);			md_flush_signals();		}	}	up(thread->sem);	return 0;}void md_wakeup_thread(mdk_thread_t *thread){	dprintk("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;	DECLARE_MUTEX_LOCKED(sem);		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);		thread->sem = &sem;	thread->run = run;	thread->data = data;	thread->name = name;	ret = kernel_thread(md_thread, thread, 0);	if (ret < 0) {		kfree(thread);		return NULL;	}	down(&sem);	return thread;}void md_interrupt_thread (mdk_thread_t *thread){	if (!thread->tsk) {		MD_BUG();		return;	}	printk("interrupting MD-thread pid %d\n", thread->tsk->pid);	send_sig(SIGKILL, thread->tsk, 1);}void md_unregister_thread (mdk_thread_t *thread){	DECLARE_MUTEX_LOCKED(sem);		thread->sem = &sem;	thread->run = NULL;	thread->name = NULL;	if (!thread->tsk) {		MD_BUG();		return;	}	md_interrupt_thread(thread);	down(&sem);}void md_recover_arrays (void){	if (!md_recovery_thread) {		MD_BUG();		return;	}	md_wakeup_thread(md_recovery_thread);}int md_error (kdev_t dev, kdev_t rdev){	mddev_t *mddev;	mdk_rdev_t * rrdev;	int rc;	mddev = kdev_to_mddev(dev);/*	printk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",MAJOR(dev),MINOR(dev),MAJOR(rdev),MINOR(rdev), __builtin_return_address(0),__builtin_return_address(1),__builtin_return_address(2),__builtin_return_address(3)); */	if (!mddev) {		MD_BUG();		return 0;	}	rrdev = find_rdev(mddev, rdev);	mark_rdev_faulty(rrdev);	/*	 * if recovery was running, stop it now.	 */	if (mddev->pers->stop_resync)		mddev->pers->stop_resync(mddev);	if (mddev->recovery_running)		md_interrupt_thread(md_recovery_thread);	if (mddev->pers->error_handler) {		rc = mddev->pers->error_handler(mddev, rdev);		md_recover_arrays();		return rc;	}	return 0;}static int status_unused (char * page){	int sz = 0, i = 0;	mdk_rdev_t *rdev;	struct md_list_head *tmp;	sz += sprintf(page + sz, "unused devices: ");	ITERATE_RDEV_ALL(rdev,tmp) {		if (!rdev->same_set.next && !rdev->same_set.prev) {			/*			 * The device is not yet used by any array.			 */			i++;			sz += sprintf(page + sz, "%s ",				partition_name(rdev->dev));		}	}	if (!i)		sz += sprintf(page + sz, "<none>");	sz += sprintf(page + sz, "\n");	return sz;}static int status_resync (char * page, mddev_t * mddev){	int sz = 0;	unsigned long max_blocks, resync, res, dt, db, rt;	resync = mddev->curr_resync - atomic_read(&mddev->recovery_active);	max_blocks = mddev->sb->size;	/*	 * Should not happen.	 */			if (!max_blocks) {		MD_BUG();		return 0;	}	res = (resync/1024)*1000/(max_blocks/1024 + 1);	{		int i, x = res/50, y = 20-x;		sz += sprintf(page + sz, "[");		for (i = 0; i < x; i++)			sz += sprintf(page + sz, "=");		sz += sprintf(page + sz, ">");		for (i = 0; i < y; i++)			sz += sprintf(page + sz, ".");		sz +=

⌨️ 快捷键说明

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