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

📄 lvm.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (vg_ptr->lv_max > ABS_MAX_LV) {		printk(KERN_WARNING		"%s -- Can't activate VG: ABS_MAX_LV too small for %u\n",		       lvm_name, vg_ptr->lv_max);		kfree(vg_ptr);		vg_ptr = NULL;		return -EPERM;	}	/* get the physical volume structures */	vg_ptr->pv_act = vg_ptr->pv_cur = 0;	for (p = 0; p < vg_ptr->pv_max; p++) {		/* user space address */		if ((pvp = vg_ptr->pv[p]) != NULL) {			ret = lvm_do_pv_create(pvp, vg_ptr, p);			if ( ret != 0) {				lvm_do_vg_remove(minor);				return ret;			}		}	}	size = vg_ptr->lv_max * sizeof(lv_t *);	if ((snap_lv_ptr = vmalloc ( size)) == NULL) {		printk(KERN_CRIT		       "%s -- VG_CREATE: vmalloc error snapshot LVs at line %d\n",		       lvm_name, __LINE__);		lvm_do_vg_remove(minor);		return -EFAULT;	}	memset(snap_lv_ptr, 0, size);	/* get the logical volume structures */	vg_ptr->lv_cur = 0;	for (l = 0; l < vg_ptr->lv_max; l++) {		/* user space address */		if ((lvp = vg_ptr->lv[l]) != NULL) {			if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0) {				lvm_do_vg_remove(minor);				return -EFAULT;			}			if ( lv.lv_access & LV_SNAPSHOT) {				snap_lv_ptr[ls] = lvp;				vg_ptr->lv[l] = NULL;				ls++;				continue;			}			vg_ptr->lv[l] = NULL;			/* only create original logical volumes for now */			if (lvm_do_lv_create(minor, lv.lv_name, &lv) != 0) {				lvm_do_vg_remove(minor);				return -EFAULT;			}		}	}	/* Second path to correct snapshot logical volumes which are not	   in place during first path above */	for (l = 0; l < ls; l++) {		lvp = snap_lv_ptr[l];		if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0) {			lvm_do_vg_remove(minor);			return -EFAULT;		}		if (lvm_do_lv_create(minor, lv.lv_name, &lv) != 0) {			lvm_do_vg_remove(minor);			return -EFAULT;		}	}#ifdef	CONFIG_DEVFS_FS	vg_devfs_handle[vg_ptr->vg_number] = devfs_mk_dir(0, vg_ptr->vg_name, NULL);	ch_devfs_handle[vg_ptr->vg_number] = devfs_register(		vg_devfs_handle[vg_ptr->vg_number] , "group",		DEVFS_FL_DEFAULT, LVM_CHAR_MAJOR, vg_ptr->vg_number,		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,		&lvm_chr_fops, NULL);#endif#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS	lvm_do_create_proc_entry_of_vg ( vg_ptr);#endif	vfree(snap_lv_ptr);	vg_count++;	MOD_INC_USE_COUNT;	/* let's go active */	vg_ptr->vg_status |= VG_ACTIVE;	return 0;} /* lvm_do_vg_create() *//* * character device support function VGDA extend */static int lvm_do_vg_extend(vg_t *vg_ptr, void *arg){	int ret = 0;	uint p;	pv_t *pv_ptr;	if (vg_ptr == NULL) return -ENXIO;	if (vg_ptr->pv_cur < vg_ptr->pv_max) {		for (p = 0; p < vg_ptr->pv_max; p++) {			if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) {				ret = lvm_do_pv_create(arg, vg_ptr, p);				lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr);				if ( ret != 0) return ret;					/* We don't need the PE list				   in kernel space like LVs pe_t list */				pv_ptr->pe = NULL;				vg_ptr->pv_cur++;				vg_ptr->pv_act++;				vg_ptr->pe_total +=				    pv_ptr->pe_total;#ifdef LVM_GET_INODE				/* insert a dummy inode for fs_may_mount */				pv_ptr->inode = lvm_get_inode(pv_ptr->pv_dev);#endif				return 0;			}		}	}return -EPERM;} /* lvm_do_vg_extend() *//* * character device support function VGDA reduce */static int lvm_do_vg_reduce(vg_t *vg_ptr, void *arg) {	uint p;	pv_t *pv_ptr;	if (vg_ptr == NULL) return -ENXIO;	if (copy_from_user(pv_name, arg, sizeof(pv_name)) != 0)		return -EFAULT;	for (p = 0; p < vg_ptr->pv_max; p++) {		pv_ptr = vg_ptr->pv[p];		if (pv_ptr != NULL &&		    strcmp(pv_ptr->pv_name,			       pv_name) == 0) {			if (pv_ptr->lv_cur > 0) return -EPERM;			vg_ptr->pe_total -=			    pv_ptr->pe_total;			vg_ptr->pv_cur--;			vg_ptr->pv_act--;			lvm_do_pv_remove(vg_ptr, p);			/* Make PV pointer array contiguous */			for (; p < vg_ptr->pv_max - 1; p++)				vg_ptr->pv[p] = vg_ptr->pv[p + 1];			vg_ptr->pv[p + 1] = NULL;			return 0;		}	}	return -ENXIO;} /* lvm_do_vg_reduce *//* * character device support function VG rename */static int lvm_do_vg_rename(vg_t *vg_ptr, void *arg){	int l = 0, p = 0, len = 0;	char vg_name[NAME_LEN] = { 0,};	char lv_name[NAME_LEN] = { 0,};	char *ptr = NULL;	lv_t *lv_ptr = NULL;	pv_t *pv_ptr = NULL;	if (copy_from_user(vg_name, arg, sizeof(vg_name)) != 0)		return -EFAULT;#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS	lvm_do_remove_proc_entry_of_vg ( vg_ptr);#endif	strncpy ( vg_ptr->vg_name, vg_name, sizeof ( vg_name)-1);	for ( l = 0; l < vg_ptr->lv_max; l++)	{		if ((lv_ptr = vg_ptr->lv[l]) == NULL) continue;		strncpy(lv_ptr->vg_name, vg_name, sizeof ( vg_name));		ptr = strrchr(lv_ptr->lv_name, '/');		if (ptr == NULL) ptr = lv_ptr->lv_name;		strncpy(lv_name, ptr, sizeof ( lv_name));		len = sizeof(LVM_DIR_PREFIX);		strcpy(lv_ptr->lv_name, LVM_DIR_PREFIX);		strncat(lv_ptr->lv_name, vg_name, NAME_LEN - len);		len += strlen ( vg_name);		strncat(lv_ptr->lv_name, lv_name, NAME_LEN - len);	}	for ( p = 0; p < vg_ptr->pv_max; p++)	{		if ( (pv_ptr = vg_ptr->pv[p]) == NULL) continue;		strncpy(pv_ptr->vg_name, vg_name, NAME_LEN);	}#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS	lvm_do_create_proc_entry_of_vg ( vg_ptr);#endif	return 0;} /* lvm_do_vg_rename *//* * character device support function VGDA remove */static int lvm_do_vg_remove(int minor){	int i;	vg_t *vg_ptr = vg[VG_CHR(minor)];	pv_t *pv_ptr;	if (vg_ptr == NULL) return -ENXIO;#ifdef LVM_TOTAL_RESET	if (vg_ptr->lv_open > 0 && lvm_reset_spindown == 0)#else	if (vg_ptr->lv_open > 0)#endif		return -EPERM;	/* let's go inactive */	vg_ptr->vg_status &= ~VG_ACTIVE;	/* free LVs */	/* first free snapshot logical volumes */	for (i = 0; i < vg_ptr->lv_max; i++) {		if (vg_ptr->lv[i] != NULL &&		    vg_ptr->lv[i]->lv_access & LV_SNAPSHOT) {			lvm_do_lv_remove(minor, NULL, i);			current->state = TASK_UNINTERRUPTIBLE;			schedule_timeout(1);		}	}	/* then free the rest of the LVs */	for (i = 0; i < vg_ptr->lv_max; i++) {		if (vg_ptr->lv[i] != NULL) {			lvm_do_lv_remove(minor, NULL, i);			current->state = TASK_UNINTERRUPTIBLE;			schedule_timeout(1);		}	}	/* free PVs */	for (i = 0; i < vg_ptr->pv_max; i++) {		if ((pv_ptr = vg_ptr->pv[i]) != NULL) {#ifdef DEBUG_KFREE			printk(KERN_DEBUG			       "%s -- kfree %d\n", lvm_name, __LINE__);#endif			lvm_do_pv_remove(vg_ptr, i);		}	}#ifdef	CONFIG_DEVFS_FS	devfs_unregister (ch_devfs_handle[vg_ptr->vg_number]);	devfs_unregister (vg_devfs_handle[vg_ptr->vg_number]);#endif#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS	lvm_do_remove_proc_entry_of_vg ( vg_ptr);#endif#ifdef DEBUG_KFREE	printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);#endif	kfree(vg_ptr);	vg[VG_CHR(minor)] = NULL;	vg_count--;	MOD_DEC_USE_COUNT;	return 0;} /* lvm_do_vg_remove() *//* * character device support function physical volume create */static int lvm_do_pv_create(pv_t *pvp, vg_t *vg_ptr, ulong p) {	pv_t *pv_ptr = NULL;	pv_ptr = vg_ptr->pv[p] = kmalloc(sizeof(pv_t),GFP_KERNEL);	if (pv_ptr == NULL) {		printk(KERN_CRIT		       "%s -- VG_CREATE: kmalloc error PV at line %d\n",		       lvm_name, __LINE__);		return -ENOMEM;	}	if (copy_from_user(pv_ptr, pvp, sizeof(pv_t)) != 0) {		return -EFAULT;	}	/* We don't need the PE list	   in kernel space as with LVs pe_t list (see below) */	pv_ptr->pe = NULL;	pv_ptr->pe_allocated = 0;	pv_ptr->pv_status = PV_ACTIVE;	vg_ptr->pv_act++;	vg_ptr->pv_cur++;#ifdef LVM_GET_INODE	/* insert a dummy inode for fs_may_mount */	pv_ptr->inode = lvm_get_inode(pv_ptr->pv_dev);#endif	return 0;} /* lvm_do_pv_create() *//* * character device support function physical volume create */static int lvm_do_pv_remove(vg_t *vg_ptr, ulong p) {	pv_t *pv_ptr = vg_ptr->pv[p];#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS	lvm_do_remove_proc_entry_of_pv ( vg_ptr, pv_ptr);#endif	vg_ptr->pe_total -=	    pv_ptr->pe_total;	vg_ptr->pv_cur--;	vg_ptr->pv_act--;#ifdef LVM_GET_INODE	lvm_clear_inode(pv_ptr->inode);#endif	kfree(pv_ptr);	vg_ptr->pv[p] = NULL;	return 0;}/* * character device support function logical volume create */static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv){	int e, ret, l, le, l_new, p, size;	ulong lv_status_save;	lv_block_exception_t *lvbe = lv->lv_block_exception;	vg_t *vg_ptr = vg[VG_CHR(minor)];	lv_t *lv_ptr = NULL;	if ((pep = lv->lv_current_pe) == NULL) return -EINVAL;	if (lv->lv_chunk_size > LVM_SNAPSHOT_MAX_CHUNK)		return -EINVAL;	for (l = 0; l < vg_ptr->lv_max; l++) {		if (vg_ptr->lv[l] != NULL &&		    strcmp(vg_ptr->lv[l]->lv_name, lv_name) == 0)			return -EEXIST;	}	/* in case of lv_remove(), lv_create() pair */	l_new = -1;	if (vg_ptr->lv[lv->lv_number] == NULL)		l_new = lv->lv_number;	else {		for (l = 0; l < vg_ptr->lv_max; l++) {			if (vg_ptr->lv[l] == NULL)				if (l_new == -1) l_new = l;		}	}	if (l_new == -1) return -EPERM;	else             l = l_new;	if ((lv_ptr = kmalloc(sizeof(lv_t),GFP_KERNEL)) == NULL) {;		printk(KERN_CRIT "%s -- LV_CREATE: kmalloc error LV at line %d\n",		       lvm_name, __LINE__);		return -ENOMEM;	}	/* copy preloaded LV */	memcpy((char *) lv_ptr, (char *) lv, sizeof(lv_t));	lv_status_save = lv_ptr->lv_status;	lv_ptr->lv_status &= ~LV_ACTIVE;	lv_ptr->lv_snapshot_org = \	lv_ptr->lv_snapshot_prev = \	lv_ptr->lv_snapshot_next = NULL;	lv_ptr->lv_block_exception = NULL;	lv_ptr->lv_iobuf = NULL;	lv_ptr->lv_snapshot_hash_table = NULL;	lv_ptr->lv_snapshot_hash_table_size = 0;	lv_ptr->lv_snapshot_hash_mask = 0;	lv_ptr->lv_COW_table_page = NULL;	init_MUTEX(&lv_ptr->lv_snapshot_sem);	lv_ptr->lv_snapshot_use_rate = 0;	vg_ptr->lv[l] = lv_ptr;	/* get the PE structures from user space if this	   is no snapshot logical volume */	if (!(lv_ptr->lv_access & LV_SNAPSHOT)) {		size = lv_ptr->lv_allocated_le * sizeof(pe_t);		if ((lv_ptr->lv_current_pe = vmalloc(size)) == NULL) {			printk(KERN_CRIT			       "%s -- LV_CREATE: vmalloc error LV_CURRENT_PE of %d Byte "			       "at line %d\n",			       lvm_name, size, __LINE__);#ifdef DEBUG_KFREE			printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);#endif			kfree(lv_ptr);			vg[VG_CHR(minor)]->lv[l] = NULL;			return -ENOMEM;		}		if (copy_from_user(lv_ptr->lv_current_pe, pep, size)) {			vfree(lv_ptr->lv_current_pe);			kfree(lv_ptr);			vg_ptr->lv[l] = NULL;			return -EFAULT;		}		/* correct the PE count in PVs */		for (le = 0; le < lv_ptr->lv_allocated_le; le++) {			vg_ptr->pe_allocated++;			for (p = 0; p < vg_ptr->pv_cur; p++) {				if (vg_ptr->pv[p]->pv_dev ==				    lv_ptr->lv_current_pe[le].dev)					vg_ptr->pv[p]->pe_allocated++;			}		}	} else {		/* Get snapshot exception data and block list */		if (lvbe != NULL) {			lv_ptr->lv_snapshot_org =			    vg_ptr->lv[LV_BLK(lv_ptr->lv_snapshot_minor)];			if (lv_ptr->lv_snapshot_org != NULL) {				size = lv_ptr->lv_remap_end * sizeof(lv_block_exception_t);				if ((lv_ptr->lv_block_exception = vmalloc(size)) == NULL) {					printk(KERN_CRIT					       "%s -- lvm_do_lv_create: vmalloc error LV_BLOCK_EXCEPTION "					       "of %d byte at line %d\n",					       lvm_name, size, __LINE__);#ifdef DEBUG_KFREE					printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);#endif					kfree(lv_ptr);					vg_ptr->lv[l] = NULL;					return -ENOMEM;				}				if (copy_from_user(lv_ptr->lv_block_exception, lvbe, size)) {					vfree(lv_ptr->lv_block_exception);					kfree(lv_ptr);					vg[VG_CHR(minor)]->lv[l] = NULL;					return -EFAULT;				}				/* point to the original logical volume */				lv_ptr = lv_ptr->lv_snapshot_org;				lv_ptr->lv_snapshot_minor = 0;				lv_ptr->lv_snapshot_org = lv_ptr;				lv_ptr->lv_snapshot_prev = NULL;				/* walk thrugh the snapshot list */				while (lv_ptr->lv_snapshot_next != NULL)					lv_ptr = lv_ptr->lv_snapshot_next;				/* now lv_ptr points to the last existing snapshot in the chain */				vg_ptr->lv[l]->lv_snapshot_prev = lv_ptr;				/* our new one now back points to the previous last in the chain				   which can be the original logical volume */				lv_ptr = vg_ptr->lv[l];				/* now lv_ptr points to our new last snapshot logical volume */				lv_ptr->lv_snapshot_org = lv_ptr->lv_snapshot_prev->lv_snapshot_org;				lv_ptr->lv_snapshot_next = NULL;				lv_ptr->l

⌨️ 快捷键说明

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