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

📄 lvm.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#else	       "Driver"#endif	       " successfully initialized\n",	       lvm_version, lvm_name);	return 0;} /* init_module() / lvm_init() */#ifdef MODULE/* * Module cleanup... */void cleanup_module(void){	struct gendisk *gendisk_ptr = NULL, *gendisk_ptr_prev = NULL;#ifdef	CONFIG_DEVFS_FS	devfs_unregister (lvm_devfs_handle);#endif	if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) {		printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name);	}	if (unregister_blkdev(MAJOR_NR, lvm_name) < 0) {		printk(KERN_ERR "%s -- unregister_blkdev failed\n", lvm_name);	}	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));	gendisk_ptr = gendisk_ptr_prev = gendisk_head;	while (gendisk_ptr != NULL) {		if (gendisk_ptr == &lvm_gendisk)			break;		gendisk_ptr_prev = gendisk_ptr;		gendisk_ptr = gendisk_ptr->next;	}	/* delete our gendisk from chain */	if (gendisk_ptr == &lvm_gendisk)		gendisk_ptr_prev->next = gendisk_ptr->next;	blk_size[MAJOR_NR] = NULL;	blksize_size[MAJOR_NR] = NULL;	hardsect_size[MAJOR_NR] = NULL;#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS	remove_proc_entry(LVM_GLOBAL, lvm_proc_dir);	remove_proc_entry(LVM_VG_SUBDIR, lvm_proc_dir);	remove_proc_entry(LVM_DIR, &proc_root);#endif#ifdef LVM_HD_NAME	/* reference from linux/drivers/block/genhd.c */	lvm_hd_name_ptr = NULL;#endif	printk(KERN_INFO "%s -- Module successfully deactivated\n", lvm_name);	return;}	/* void cleanup_module() */#endif	/* #ifdef MODULE *//* * support function to initialize lvm variables */#ifdef __initfunc__initfunc(void lvm_init_vars(void))#elsevoid __init lvm_init_vars(void)#endif{	int v;	loadtime = CURRENT_TIME;	lvm_lock = lvm_snapshot_lock = SPIN_LOCK_UNLOCKED;	pe_lock_req.lock = UNLOCK_PE;	pe_lock_req.data.lv_dev = \	pe_lock_req.data.pv_dev = \	pe_lock_req.data.pv_offset = 0;	/* Initialize VG pointers */	for (v = 0; v < ABS_MAX_VG; v++) vg[v] = NULL;	/* Initialize LV -> VG association */	for (v = 0; v < ABS_MAX_LV; v++) {		/* index ABS_MAX_VG never used for real VG */		vg_lv_map[v].vg_number = ABS_MAX_VG;		vg_lv_map[v].lv_number = -1;	}	return;} /* lvm_init_vars() *//******************************************************************** * * Character device functions * ********************************************************************//* * character device open routine */static int lvm_chr_open(struct inode *inode,			struct file *file){	int minor = MINOR(inode->i_rdev);#ifdef DEBUG	printk(KERN_DEBUG	 "%s -- lvm_chr_open MINOR: %d  VG#: %d  mode: 0x%X  lock: %d\n",	       lvm_name, minor, VG_CHR(minor), file->f_mode, lock);#endif	/* super user validation */	if (!capable(CAP_SYS_ADMIN)) return -EACCES;	/* Group special file open */	if (VG_CHR(minor) > MAX_VG) return -ENXIO;	lvm_chr_open_count++;	MOD_INC_USE_COUNT;	return 0;} /* lvm_chr_open() *//* * character device i/o-control routine * * Only one changing process can do changing ioctl at one time, * others will block. * */static int lvm_chr_ioctl(struct inode *inode, struct file *file,			 uint command, ulong a){	int minor = MINOR(inode->i_rdev);	uint extendable, l, v;	void *arg = (void *) a;	lv_t lv;	vg_t* vg_ptr = vg[VG_CHR(minor)];	/* otherwise cc will complain about unused variables */	(void) lvm_lock;#ifdef DEBUG_IOCTL	printk(KERN_DEBUG	       "%s -- lvm_chr_ioctl: command: 0x%X  MINOR: %d  "	       "VG#: %d  mode: 0x%X\n",	       lvm_name, command, minor, VG_CHR(minor), file->f_mode);#endif#ifdef LVM_TOTAL_RESET	if (lvm_reset_spindown > 0) return -EACCES;#endif	/* Main command switch */	switch (command) {	case LVM_LOCK_LVM:		/* lock the LVM */		return lvm_do_lock_lvm();	case LVM_GET_IOP_VERSION:		/* check lvm version to ensure driver/tools+lib		   interoperability */		if (copy_to_user(arg, &lvm_iop_version, sizeof(ushort)) != 0)			return -EFAULT;		return 0;#ifdef LVM_TOTAL_RESET	case LVM_RESET:		/* lock reset function */		lvm_reset_spindown = 1;		for (v = 0; v < ABS_MAX_VG; v++) {			if (vg[v] != NULL) lvm_do_vg_remove(v);		}#ifdef MODULE		while (GET_USE_COUNT(&__this_module) < 1)			MOD_INC_USE_COUNT;		while (GET_USE_COUNT(&__this_module) > 1)			MOD_DEC_USE_COUNT;#endif /* MODULE */		lock = 0;	/* release lock */		wake_up_interruptible(&lvm_wait);		return 0;#endif /* LVM_TOTAL_RESET */	case LE_REMAP:		/* remap a logical extent (after moving the physical extent) */		return lvm_do_le_remap(vg_ptr,arg);	case PE_LOCK_UNLOCK:		/* lock/unlock i/o to a physical extent to move it to another		   physical volume (move's done in user space's pvmove) */		return lvm_do_pe_lock_unlock(vg_ptr,arg);	case VG_CREATE:		/* create a VGDA */		return lvm_do_vg_create(minor, arg);	case VG_EXTEND:		/* extend a volume group */		return lvm_do_vg_extend(vg_ptr, arg);	case VG_REDUCE:		/* reduce a volume group */		return lvm_do_vg_reduce(vg_ptr, arg);	case VG_RENAME:		/* rename a volume group */		return lvm_do_vg_rename(vg_ptr, arg);	case VG_REMOVE:		/* remove an inactive VGDA */		return lvm_do_vg_remove(minor);	case VG_SET_EXTENDABLE:		/* set/clear extendability flag of volume group */		if (vg_ptr == NULL) return -ENXIO;		if (copy_from_user(&extendable, arg, sizeof(extendable)) != 0)			return -EFAULT;		if (extendable == VG_EXTENDABLE ||		    extendable == ~VG_EXTENDABLE) {			if (extendable == VG_EXTENDABLE)				vg_ptr->vg_status |= VG_EXTENDABLE;			else				vg_ptr->vg_status &= ~VG_EXTENDABLE;		} else return -EINVAL;		return 0;	case VG_STATUS:		/* get volume group data (only the vg_t struct) */		if (vg_ptr == NULL) return -ENXIO;		if (copy_to_user(arg, vg_ptr, sizeof(vg_t)) != 0)			return -EFAULT;		return 0;	case VG_STATUS_GET_COUNT:		/* get volume group count */		if (copy_to_user(arg, &vg_count, sizeof(vg_count)) != 0)			return -EFAULT;		return 0;	case VG_STATUS_GET_NAMELIST:		/* get volume group count */		for (l = v = 0; v < ABS_MAX_VG; v++) {			if (vg[v] != NULL) {				if (copy_to_user(arg + l * NAME_LEN,						 vg[v]->vg_name,						 NAME_LEN) != 0)					return -EFAULT;				l++;			}		}		return 0;	case LV_CREATE:	case LV_EXTEND:	case LV_REDUCE:	case LV_REMOVE:	case LV_RENAME:		/* create, extend, reduce, remove or rename a logical volume */		if (vg_ptr == NULL) return -ENXIO;		if (copy_from_user(&lv_req, arg, sizeof(lv_req)) != 0)			return -EFAULT;		if (command != LV_REMOVE) {			if (copy_from_user(&lv, lv_req.lv, sizeof(lv_t)) != 0)				return -EFAULT;		}		switch (command) {		case LV_CREATE:			return lvm_do_lv_create(minor, lv_req.lv_name, &lv);		case LV_EXTEND:		case LV_REDUCE:			return lvm_do_lv_extend_reduce(minor, lv_req.lv_name, &lv);		case LV_REMOVE:			return lvm_do_lv_remove(minor, lv_req.lv_name, -1);		case LV_RENAME:			return lvm_do_lv_rename(vg_ptr, &lv_req, &lv);		}	case LV_STATUS_BYNAME:		/* get status of a logical volume by name */		return lvm_do_lv_status_byname(vg_ptr, arg);	case LV_STATUS_BYINDEX:		/* get status of a logical volume by index */		return lvm_do_lv_status_byindex(vg_ptr, arg);	case LV_STATUS_BYDEV:		return lvm_do_lv_status_bydev(vg_ptr, arg);	case PV_CHANGE:		/* change a physical volume */		return lvm_do_pv_change(vg_ptr,arg);	case PV_STATUS:		/* get physical volume data (pv_t structure only) */		return lvm_do_pv_status(vg_ptr,arg);	case PV_FLUSH:		/* physical volume buffer flush/invalidate */		if (copy_from_user(&pv_flush_req, arg,				   sizeof(pv_flush_req)) != 0)			return -EFAULT;		fsync_dev(pv_flush_req.pv_dev);		invalidate_buffers(pv_flush_req.pv_dev);		return 0;	default:		printk(KERN_WARNING		       "%s -- lvm_chr_ioctl: unknown command %x\n",		       lvm_name, command);		return -EINVAL;	}	return 0;} /* lvm_chr_ioctl *//* * character device close routine */static int lvm_chr_close(struct inode *inode, struct file *file){#ifdef DEBUG	int minor = MINOR(inode->i_rdev);	printk(KERN_DEBUG	     "%s -- lvm_chr_close   VG#: %d\n", lvm_name, VG_CHR(minor));#endif#ifdef LVM_TOTAL_RESET	if (lvm_reset_spindown > 0) {		lvm_reset_spindown = 0;		lvm_chr_open_count = 0;	}#endif	if (lvm_chr_open_count > 0) lvm_chr_open_count--;	if (lock == current->pid) {		lock = 0;	/* release lock */		wake_up_interruptible(&lvm_wait);	}	MOD_DEC_USE_COUNT;	return 0;} /* lvm_chr_close() *//******************************************************************** * * Block device functions * ********************************************************************//* * block device open routine */static int lvm_blk_open(struct inode *inode, struct file *file){	int minor = MINOR(inode->i_rdev);	lv_t *lv_ptr;	vg_t *vg_ptr = vg[VG_BLK(minor)];#ifdef DEBUG_LVM_BLK_OPEN	printk(KERN_DEBUG	  "%s -- lvm_blk_open MINOR: %d  VG#: %d  LV#: %d  mode: 0x%X\n",	    lvm_name, minor, VG_BLK(minor), LV_BLK(minor), file->f_mode);#endif#ifdef LVM_TOTAL_RESET	if (lvm_reset_spindown > 0)		return -EPERM;#endif	if (vg_ptr != NULL &&	    (vg_ptr->vg_status & VG_ACTIVE) &&	    (lv_ptr = vg_ptr->lv[LV_BLK(minor)]) != NULL &&	    LV_BLK(minor) >= 0 &&	    LV_BLK(minor) < vg_ptr->lv_max) {		/* Check parallel LV spindown (LV remove) */		if (lv_ptr->lv_status & LV_SPINDOWN) return -EPERM;		/* Check inactive LV and open for read/write */		if (file->f_mode & O_RDWR) {			if (!(lv_ptr->lv_status & LV_ACTIVE)) return -EPERM;			if (!(lv_ptr->lv_access & LV_WRITE))  return -EACCES;		}#ifndef BLOCK_DEVICE_OPERATIONS		file->f_op = &lvm_blk_fops;#endif                /* be sure to increment VG counter */		if (lv_ptr->lv_open == 0) vg_ptr->lv_open++;		lv_ptr->lv_open++;		MOD_INC_USE_COUNT;#ifdef DEBUG_LVM_BLK_OPEN		printk(KERN_DEBUG		       "%s -- lvm_blk_open MINOR: %d  VG#: %d  LV#: %d  size: %d\n",		       lvm_name, minor, VG_BLK(minor), LV_BLK(minor),		       lv_ptr->lv_size);#endif		return 0;	}	return -ENXIO;} /* lvm_blk_open() *//* * block device i/o-control routine */static int lvm_blk_ioctl(struct inode *inode, struct file *file,			 uint command, ulong a){	int minor = MINOR(inode->i_rdev);	vg_t *vg_ptr = vg[VG_BLK(minor)];	lv_t *lv_ptr = vg_ptr->lv[LV_BLK(minor)];	void *arg = (void *) a;	struct hd_geometry *hd = (struct hd_geometry *) a;#ifdef DEBUG_IOCTL	printk(KERN_DEBUG	       "%s -- lvm_blk_ioctl MINOR: %d  command: 0x%X  arg: %X  "	       "VG#: %dl  LV#: %d\n",	       lvm_name, minor, command, (ulong) arg,	       VG_BLK(minor), LV_BLK(minor));#endif	switch (command) {	case BLKGETSIZE:		/* return device size */#ifdef DEBUG_IOCTL		printk(KERN_DEBUG		       "%s -- lvm_blk_ioctl -- BLKGETSIZE: %u\n",		       lvm_name, lv_ptr->lv_size);#endif		if (put_user(lv_ptr->lv_size, (long *)arg))			return -EFAULT; 		break;	case BLKFLSBUF:		/* flush buffer cache */		if (!capable(CAP_SYS_ADMIN)) return -EACCES;

⌨️ 快捷键说明

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