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

📄 lvm.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
						     lvm_name, __LINE__);				}			}			sz_last = sz;		}	}	MOD_DEC_USE_COUNT;	if (pos > sz - 1) {		lock_kernel();		vfree(buf);		unlock_kernel();		buf = NULL;		return 0;	}	*start = &buf[pos];	if (sz - pos < count)		return sz - pos;	else		return count;} /* lvm_proc_get_global_info() */#endif /* #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS *//* * provide VG information */int lvm_proc_read_vg_info(char *page, char **start, off_t off,			  int count, int *eof, void *data) {	int sz = 0;	vg_t *vg = data;	sz += sprintf ( page+sz, "name:         %s\n", vg->vg_name);	sz += sprintf ( page+sz, "size:         %u\n",		        vg->pe_total * vg->pe_size / 2);	sz += sprintf ( page+sz, "access:       %u\n", vg->vg_access);	sz += sprintf ( page+sz, "status:       %u\n", vg->vg_status);	sz += sprintf ( page+sz, "number:       %u\n", vg->vg_number);	sz += sprintf ( page+sz, "LV max:       %u\n", vg->lv_max);	sz += sprintf ( page+sz, "LV current:   %u\n", vg->lv_cur);	sz += sprintf ( page+sz, "LV open:      %u\n", vg->lv_open);	sz += sprintf ( page+sz, "PV max:       %u\n", vg->pv_max);	sz += sprintf ( page+sz, "PV current:   %u\n", vg->pv_cur);	sz += sprintf ( page+sz, "PV active:    %u\n", vg->pv_act);	sz += sprintf ( page+sz, "PE size:      %u\n", vg->pe_size / 2);	sz += sprintf ( page+sz, "PE total:     %u\n", vg->pe_total);	sz += sprintf ( page+sz, "PE allocated: %u\n", vg->pe_allocated);	sz += sprintf ( page+sz, "uuid:         %s\n", vg->vg_uuid);	return sz;}/* * provide LV information */int lvm_proc_read_lv_info(char *page, char **start, off_t off,			  int count, int *eof, void *data) {	int sz = 0;	lv_t *lv = data;	sz += sprintf ( page+sz, "name:         %s\n", lv->lv_name);	sz += sprintf ( page+sz, "size:         %u\n", lv->lv_size);	sz += sprintf ( page+sz, "access:       %u\n", lv->lv_access);	sz += sprintf ( page+sz, "status:       %u\n", lv->lv_status);	sz += sprintf ( page+sz, "number:       %u\n", lv->lv_number);	sz += sprintf ( page+sz, "open:         %u\n", lv->lv_open);	sz += sprintf ( page+sz, "allocation:   %u\n", lv->lv_allocation);	sz += sprintf ( page+sz, "device:       %02u:%02u\n",                        MAJOR(lv->lv_dev), MINOR(lv->lv_dev));	return sz;}/* * provide PV information */int lvm_proc_read_pv_info(char *page, char **start, off_t off,			  int count, int *eof, void *data) {	int sz = 0;	pv_t *pv = data;	sz += sprintf ( page+sz, "name:         %s\n", pv->pv_name);	sz += sprintf ( page+sz, "size:         %u\n", pv->pv_size);	sz += sprintf ( page+sz, "status:       %u\n", pv->pv_status);	sz += sprintf ( page+sz, "number:       %u\n", pv->pv_number);	sz += sprintf ( page+sz, "allocatable:  %u\n", pv->pv_allocatable);	sz += sprintf ( page+sz, "LV current:   %u\n", pv->lv_cur);	sz += sprintf ( page+sz, "PE size:      %u\n", pv->pe_size / 2);	sz += sprintf ( page+sz, "PE total:     %u\n", pv->pe_total);	sz += sprintf ( page+sz, "PE allocated: %u\n", pv->pe_allocated);	sz += sprintf ( page+sz, "device:       %02u:%02u\n",                        MAJOR(pv->pv_dev), MINOR(pv->pv_dev));	sz += sprintf ( page+sz, "uuid:         %s\n", pv->pv_uuid);	return sz;}/* * block device support function for /usr/src/linux/drivers/block/ll_rw_blk.c * (see init_module/lvm_init) */static int lvm_map(struct buffer_head *bh, int rw){	int minor = MINOR(bh->b_dev);	int ret = 0;	ulong index;	ulong pe_start;	ulong size = bh->b_size >> 9;	ulong rsector_tmp = bh->b_blocknr * size;	ulong rsector_sav;	kdev_t rdev_tmp = bh->b_dev;	kdev_t rdev_sav;	vg_t *vg_this = vg[VG_BLK(minor)];	lv_t *lv = vg_this->lv[LV_BLK(minor)];	if (!(lv->lv_status & LV_ACTIVE)) {		printk(KERN_ALERT		       "%s - lvm_map: ll_rw_blk for inactive LV %s\n",		       lvm_name, lv->lv_name);		return -1;	}	if ((rw == WRITE || rw == WRITEA) &&	    !(lv->lv_access & LV_WRITE)) {		printk(KERN_CRIT		    "%s - lvm_map: ll_rw_blk write for readonly LV %s\n",		       lvm_name, lv->lv_name);		return -1;	}#ifdef DEBUG_MAP	printk(KERN_DEBUG	       "%s - lvm_map minor:%d  *rdev: %02d:%02d  *rsector: %lu  "	       "size:%lu\n",	       lvm_name, minor,	       MAJOR(rdev_tmp),	       MINOR(rdev_tmp),	       rsector_tmp, size);#endif	if (rsector_tmp + size > lv->lv_size) {		printk(KERN_ALERT		       "%s - lvm_map access beyond end of device; *rsector: "                       "%lu or size: %lu wrong for minor: %2d\n",                       lvm_name, rsector_tmp, size, minor);		return -1;	}	rsector_sav = rsector_tmp;	rdev_sav = rdev_tmp;lvm_second_remap:	/* linear mapping */	if (lv->lv_stripes < 2) {		/* get the index */		index = rsector_tmp / vg_this->pe_size;		pe_start = lv->lv_current_pe[index].pe;		rsector_tmp = lv->lv_current_pe[index].pe +		    (rsector_tmp % vg_this->pe_size);		rdev_tmp = lv->lv_current_pe[index].dev;#ifdef DEBUG_MAP		printk(KERN_DEBUG		       "lv_current_pe[%ld].pe: %ld  rdev: %02d:%02d  rsector:%ld\n",		       index,		       lv->lv_current_pe[index].pe,		       MAJOR(rdev_tmp),		       MINOR(rdev_tmp),		       rsector_tmp);#endif		/* striped mapping */	} else {		ulong stripe_index;		ulong stripe_length;		stripe_length = vg_this->pe_size * lv->lv_stripes;		stripe_index = (rsector_tmp % stripe_length) / lv->lv_stripesize;		index = rsector_tmp / stripe_length +		    (stripe_index % lv->lv_stripes) *		    (lv->lv_allocated_le / lv->lv_stripes);		pe_start = lv->lv_current_pe[index].pe;		rsector_tmp = lv->lv_current_pe[index].pe +		    (rsector_tmp % stripe_length) -		    (stripe_index % lv->lv_stripes) * lv->lv_stripesize -		    stripe_index / lv->lv_stripes *		    (lv->lv_stripes - 1) * lv->lv_stripesize;		rdev_tmp = lv->lv_current_pe[index].dev;	}#ifdef DEBUG_MAP	printk(KERN_DEBUG	     "lv_current_pe[%ld].pe: %ld  rdev: %02d:%02d  rsector:%ld\n"	       "stripe_length: %ld  stripe_index: %ld\n",	       index,	       lv->lv_current_pe[index].pe,	       MAJOR(rdev_tmp),	       MINOR(rdev_tmp),	       rsector_tmp,	       stripe_length,	       stripe_index);#endif	/* handle physical extents on the move */	if (pe_lock_req.lock == LOCK_PE) {		if (rdev_tmp == pe_lock_req.data.pv_dev &&		    rsector_tmp >= pe_lock_req.data.pv_offset &&		    rsector_tmp < (pe_lock_req.data.pv_offset +				   vg_this->pe_size)) {			sleep_on(&lvm_map_wait);			rsector_tmp = rsector_sav;			rdev_tmp = rdev_sav;			goto lvm_second_remap;		}	}	/* statistic */	if (rw == WRITE || rw == WRITEA)		lv->lv_current_pe[index].writes++;	else		lv->lv_current_pe[index].reads++;	/* snapshot volume exception handling on physical device address base */	if (lv->lv_access & (LV_SNAPSHOT|LV_SNAPSHOT_ORG)) {		/* original logical volume */		if (lv->lv_access & LV_SNAPSHOT_ORG) {			if (rw == WRITE || rw == WRITEA)			{				lv_t *lv_ptr;				/* start with first snapshot and loop thrugh all of them */				for (lv_ptr = lv->lv_snapshot_next;				     lv_ptr != NULL;				     lv_ptr = lv_ptr->lv_snapshot_next) {					/* Check for inactive snapshot */					if (!(lv_ptr->lv_status & LV_ACTIVE)) continue;					down(&lv->lv_snapshot_org->lv_snapshot_sem);					/* do we still have exception storage for this snapshot free? */					if (lv_ptr->lv_block_exception != NULL) {						rdev_sav = rdev_tmp;						rsector_sav = rsector_tmp;						if (!lvm_snapshot_remap_block(&rdev_tmp,									      &rsector_tmp,									      pe_start,									      lv_ptr)) {							/* create a new mapping */							if (!(ret = lvm_snapshot_COW(rdev_tmp,									       	     rsector_tmp,									             pe_start,									             rsector_sav,									             lv_ptr)))								ret = lvm_write_COW_table_block(vg_this,												lv_ptr);						}						rdev_tmp = rdev_sav;						rsector_tmp = rsector_sav;					}					up(&lv->lv_snapshot_org->lv_snapshot_sem);				}			}		} else {			/* remap snapshot logical volume */			down(&lv->lv_snapshot_sem);			if (lv->lv_block_exception != NULL)				lvm_snapshot_remap_block(&rdev_tmp, &rsector_tmp, pe_start, lv);			up(&lv->lv_snapshot_sem);		}	}	bh->b_rdev = rdev_tmp;	bh->b_rsector = rsector_tmp;	return ret;} /* lvm_map() *//* * internal support functions */#ifdef LVM_HD_NAME/* * generate "hard disk" name */void lvm_hd_name(char *buf, int minor){	int len = 0;	lv_t *lv_ptr;	if (vg[VG_BLK(minor)] == NULL ||	    (lv_ptr = vg[VG_BLK(minor)]->lv[LV_BLK(minor)]) == NULL)		return;	len = strlen(lv_ptr->lv_name) - 5;	memcpy(buf, &lv_ptr->lv_name[5], len);	buf[len] = 0;	return;}#endif/* * this one never should be called... */static void lvm_dummy_device_request(request_queue_t * t){	printk(KERN_EMERG	     "%s -- oops, got lvm request for %02d:%02d [sector: %lu]\n",	       lvm_name,	       MAJOR(CURRENT->rq_dev),	       MINOR(CURRENT->rq_dev),	       CURRENT->sector);	return;}/* * make request function */static int lvm_make_request_fn(request_queue_t *q,			       int rw,			       struct buffer_head *bh){	if (lvm_map(bh, rw)<0)		return 0; /* failure, buffer_IO_error has been called, don't recurse */	else		return 1; /* all ok, mapping done, call lower level driver */}/******************************************************************** * * Character device support functions * ********************************************************************//* * character device support function logical volume manager lock */static int lvm_do_lock_lvm(void){lock_try_again:	spin_lock(&lvm_lock);	if (lock != 0 && lock != current->pid) {#ifdef DEBUG_IOCTL		printk(KERN_INFO "lvm_do_lock_lvm: %s is locked by pid %d ...\n",		       lvm_name, lock);#endif		spin_unlock(&lvm_lock);		interruptible_sleep_on(&lvm_wait);		if (current->sigpending != 0)			return -EINTR;#ifdef LVM_TOTAL_RESET		if (lvm_reset_spindown > 0)			return -EACCES;#endif		goto lock_try_again;	}	lock = current->pid;	spin_unlock(&lvm_lock);	return 0;} /* lvm_do_lock_lvm *//* * character device support function lock/unlock physical extend */static int lvm_do_pe_lock_unlock(vg_t *vg_ptr, void *arg){	uint p;	if (vg_ptr == NULL) return -ENXIO;	if (copy_from_user(&pe_lock_req, arg,			   sizeof(pe_lock_req_t)) != 0) return -EFAULT;	switch (pe_lock_req.lock) {	case LOCK_PE:		for (p = 0; p < vg_ptr->pv_max; p++) {			if (vg_ptr->pv[p] != NULL &&			    pe_lock_req.data.pv_dev ==			    vg_ptr->pv[p]->pv_dev)				break;		}		if (p == vg_ptr->pv_max) return -ENXIO;		pe_lock_req.lock = UNLOCK_PE;		fsync_dev(pe_lock_req.data.lv_dev);		pe_lock_req.lock = LOCK_PE;		break;	case UNLOCK_PE:		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;		wake_up(&lvm_map_wait);		break;	default:		return -EINVAL;	}	return 0;}/* * character device support function logical extend remap */static int lvm_do_le_remap(vg_t *vg_ptr, void *arg){	uint l, le;	lv_t *lv_ptr;	if (vg_ptr == NULL) return -ENXIO;	if (copy_from_user(&le_remap_req, arg,			   sizeof(le_remap_req_t)) != 0)		return -EFAULT;	for (l = 0; l < vg_ptr->lv_max; l++) {		lv_ptr = vg_ptr->lv[l];		if (lv_ptr != NULL &&		    strcmp(lv_ptr->lv_name,			       le_remap_req.lv_name) == 0) {			for (le = 0; le < lv_ptr->lv_allocated_le; le++) {				if (lv_ptr->lv_current_pe[le].dev ==				    le_remap_req.old_dev &&				    lv_ptr->lv_current_pe[le].pe ==				    le_remap_req.old_pe) {					lv_ptr->lv_current_pe[le].dev =					    le_remap_req.new_dev;					lv_ptr->lv_current_pe[le].pe =					    le_remap_req.new_pe;					return 0;				}			}			return -EINVAL;		}	}	return -ENXIO;} /* lvm_do_le_remap() *//* * character device support function VGDA create */int lvm_do_vg_create(int minor, void *arg){	int ret = 0;	ulong l, ls = 0, p, size;	lv_t lv;	vg_t *vg_ptr;	lv_t **snap_lv_ptr;	if (vg[VG_CHR(minor)] != NULL) return -EPERM;	if ((vg_ptr = kmalloc(sizeof(vg_t),GFP_KERNEL)) == NULL) {		printk(KERN_CRIT		       "%s -- VG_CREATE: kmalloc error VG at line %d\n",		       lvm_name, __LINE__);		return -ENOMEM;	}	/* get the volume group structure */	if (copy_from_user(vg_ptr, arg, sizeof(vg_t)) != 0) {		kfree(vg_ptr);		return -EFAULT;	}	/* we are not that active so far... */	vg_ptr->vg_status &= ~VG_ACTIVE;	vg[VG_CHR(minor)] = vg_ptr;	vg[VG_CHR(minor)]->pe_allocated = 0;	if (vg_ptr->pv_max > ABS_MAX_PV) {		printk(KERN_WARNING		       "%s -- Can't activate VG: ABS_MAX_PV too small\n",		       lvm_name);		kfree(vg_ptr);		vg[VG_CHR(minor)] = NULL;		return -EPERM;	}

⌨️ 快捷键说明

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