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

📄 lvm-snap.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * kernel/lvm-snap.c * * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE *                    Heinz Mauelshagen, Sistina Software (persistent snapshots) * * LVM snapshot driver is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. *  * LVM snapshot driver is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with GNU CC; see the file COPYING.  If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA.  * *//* * Changelog * *    05/07/2000 - implemented persistent snapshot support *    23/11/2000 - used cpu_to_le64 rather than my own macro *    25/01/2001 - Put LockPage back in *    01/02/2001 - A dropped snapshot is now set as inactive *    12/03/2001 - lvm_pv_get_number changes: *                 o made it static *                 o renamed it to _pv_get_number *                 o pv number is returned in new uint * arg *                 o -1 returned on error *                 lvm_snapshot_fill_COW_table has a return value too. * */#include <linux/kernel.h>#include <linux/module.h>#include <linux/vmalloc.h>#include <linux/blkdev.h>#include <linux/smp_lock.h>#include <linux/types.h>#include <linux/iobuf.h>#include <linux/lvm.h>#include "lvm-internal.h"static char *lvm_snap_version __attribute__ ((unused)) =   "LVM "LVM_RELEASE_NAME" snapshot code ("LVM_RELEASE_DATE")\n";extern const char *const lvm_name;extern int lvm_blocksizes[];void lvm_snapshot_release(lv_t *);static int _write_COW_table_block(vg_t *vg, lv_t *lv, int idx,                                 const char **reason);static void _disable_snapshot(vg_t *vg, lv_t *lv);static int _pv_get_number(vg_t * vg, kdev_t rdev, uint *pvn) {	uint p;	for(p = 0; p < vg->pv_max; p++) {		if(vg->pv[p] == NULL)			continue;		if(vg->pv[p]->pv_dev == rdev)			break;	} 	if(p >= vg->pv_max) {		/* bad news, the snapshot COW table is probably corrupt */		printk(KERN_ERR		       "%s -- _pv_get_number failed for rdev = %u\n",		       lvm_name, rdev);		return -1;	}	*pvn = vg->pv[p]->pv_number;	return 0;}#define hashfn(dev,block,mask,chunk_size) \	((HASHDEV(dev)^((block)/(chunk_size))) & (mask))static inline lv_block_exception_t *lvm_find_exception_table(kdev_t org_dev, unsigned long org_start, lv_t * lv){	struct list_head * hash_table = lv->lv_snapshot_hash_table, * next;	unsigned long mask = lv->lv_snapshot_hash_mask;	int chunk_size = lv->lv_chunk_size;	lv_block_exception_t * ret;	int i = 0;	hash_table = &hash_table[hashfn(org_dev, org_start, mask, chunk_size)];	ret = NULL;	for (next = hash_table->next; next != hash_table; next = next->next)	{		lv_block_exception_t * exception;		exception = list_entry(next, lv_block_exception_t, hash);		if (exception->rsector_org == org_start &&		    exception->rdev_org == org_dev)		{			if (i)			{				/* fun, isn't it? :) */				list_del(next);				list_add(next, hash_table);			}			ret = exception;			break;		}		i++;	}	return ret;}inline void lvm_hash_link(lv_block_exception_t * exception,			  kdev_t org_dev, unsigned long org_start,			  lv_t * lv){	struct list_head * hash_table = lv->lv_snapshot_hash_table;	unsigned long mask = lv->lv_snapshot_hash_mask;	int chunk_size = lv->lv_chunk_size;	hash_table = &hash_table[hashfn(org_dev, org_start, mask, chunk_size)];	list_add(&exception->hash, hash_table);}int lvm_snapshot_remap_block(kdev_t * org_dev, unsigned long * org_sector,			     unsigned long pe_start, lv_t * lv){	int ret;	unsigned long pe_off, pe_adjustment, __org_start;	kdev_t __org_dev;	int chunk_size = lv->lv_chunk_size;	lv_block_exception_t * exception;	pe_off = pe_start % chunk_size;	pe_adjustment = (*org_sector-pe_off) % chunk_size;	__org_start = *org_sector - pe_adjustment;	__org_dev = *org_dev;	ret = 0;	exception = lvm_find_exception_table(__org_dev, __org_start, lv);	if (exception)	{		*org_dev = exception->rdev_new;		*org_sector = exception->rsector_new + pe_adjustment;		ret = 1;	}	return ret;}void lvm_drop_snapshot(vg_t *vg, lv_t *lv_snap, const char *reason){	kdev_t last_dev;	int i;	/* no exception storage space available for this snapshot	   or error on this snapshot --> release it */	invalidate_buffers(lv_snap->lv_dev);       /* wipe the snapshot since it's inconsistent now */       _disable_snapshot(vg, lv_snap);	for (i = last_dev = 0; i < lv_snap->lv_remap_ptr; i++) {		if ( lv_snap->lv_block_exception[i].rdev_new != last_dev) {			last_dev = lv_snap->lv_block_exception[i].rdev_new;			invalidate_buffers(last_dev);		}	}	lvm_snapshot_release(lv_snap);	lv_snap->lv_status &= ~LV_ACTIVE;	printk(KERN_INFO	       "%s -- giving up to snapshot %s on %s: %s\n",	       lvm_name, lv_snap->lv_snapshot_org->lv_name, lv_snap->lv_name,	       reason);}static inline int lvm_snapshot_prepare_blocks(unsigned long *blocks,					      unsigned long start,					      int nr_sectors,					      int blocksize){	int i, sectors_per_block, nr_blocks;	sectors_per_block = blocksize / SECTOR_SIZE;	if(start & (sectors_per_block - 1))		return 0;	nr_blocks = nr_sectors / sectors_per_block;	start /= sectors_per_block;	for (i = 0; i < nr_blocks; i++)		blocks[i] = start++;	return 1;}inline int lvm_get_blksize(kdev_t dev){	int correct_size = BLOCK_SIZE, i, major;	major = MAJOR(dev);	if (blksize_size[major])	{		i = blksize_size[major][MINOR(dev)];		if (i)			correct_size = i;	}	return correct_size;}#ifdef DEBUG_SNAPSHOTstatic inline void invalidate_snap_cache(unsigned long start, unsigned long nr,					 kdev_t dev){	struct buffer_head * bh;	int sectors_per_block, i, blksize, minor;	minor = MINOR(dev);	blksize = lvm_blocksizes[minor];	sectors_per_block = blksize >> 9;	nr /= sectors_per_block;	start /= sectors_per_block;	for (i = 0; i < nr; i++)	{		bh = get_hash_table(dev, start++, blksize);		if (bh)			bforget(bh);	}}#endifint lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap){       uint pvn;       int id = 0, is = lv_snap->lv_remap_ptr;       ulong blksize_snap;       lv_COW_table_disk_t * lv_COW_table = (lv_COW_table_disk_t *)               page_address(lv_snap->lv_COW_table_iobuf->maplist[0]);       if (is == 0)               return 0;	is--;        blksize_snap =               lvm_get_blksize(lv_snap->lv_block_exception[is].rdev_new);        is -= is % (blksize_snap / sizeof(lv_COW_table_disk_t));	memset(lv_COW_table, 0, blksize_snap);	for ( ; is < lv_snap->lv_remap_ptr; is++, id++) {		/* store new COW_table entry */               lv_block_exception_t *be = lv_snap->lv_block_exception + is;               if(_pv_get_number(vg, be->rdev_org, &pvn))                       goto bad;               lv_COW_table[id].pv_org_number = cpu_to_le64(pvn);               lv_COW_table[id].pv_org_rsector = cpu_to_le64(be->rsector_org);               if(_pv_get_number(vg, be->rdev_new, &pvn))                       goto bad;               lv_COW_table[id].pv_snap_number = cpu_to_le64(pvn);               lv_COW_table[id].pv_snap_rsector =                       cpu_to_le64(be->rsector_new);	}       return 0; bad:       printk(KERN_ERR "%s -- lvm_snapshot_fill_COW_page failed", lvm_name);       return -1;}/* * writes a COW exception table sector to disk (HM) */int lvm_write_COW_table_block(vg_t * vg, lv_t *lv_snap){	int r;	const char *err;	if((r = _write_COW_table_block(vg, lv_snap,				       lv_snap->lv_remap_ptr - 1, &err)))		lvm_drop_snapshot(vg, lv_snap, err);	return r;}/* * copy on write handler for one snapshot logical volume * * read the original blocks and store it/them on the new one(s). * if there is no exception storage space free any longer --> release snapshot. * * this routine gets called for each _first_ write to a physical chunk. */int lvm_snapshot_COW(kdev_t org_phys_dev,		     unsigned long org_phys_sector,		     unsigned long org_pe_start,		     unsigned long org_virt_sector,		     vg_t *vg, lv_t* lv_snap){	const char * reason;	unsigned long org_start, snap_start, snap_phys_dev, virt_start, pe_off;	int idx = lv_snap->lv_remap_ptr, chunk_size = lv_snap->lv_chunk_size;	struct kiobuf * iobuf;	int blksize_snap, blksize_org, min_blksize, max_blksize;	int max_sectors, nr_sectors;	/* check if we are out of snapshot space */	if (idx >= lv_snap->lv_remap_end)		goto fail_out_of_space;	/* calculate physical boundaries of source chunk */	pe_off = org_pe_start % chunk_size;	org_start = org_phys_sector - ((org_phys_sector-pe_off) % chunk_size);	virt_start = org_virt_sector - (org_phys_sector - org_start);	/* calculate physical boundaries of destination chunk */	snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new;	snap_start = lv_snap->lv_block_exception[idx].rsector_new;#ifdef DEBUG_SNAPSHOT	printk(KERN_INFO	       "%s -- COW: "	       "org %s faulting %lu start %lu, snap %s start %lu, "	       "size %d, pe_start %lu pe_off %lu, virt_sec %lu\n",	       lvm_name,	       kdevname(org_phys_dev), org_phys_sector, org_start,	       kdevname(snap_phys_dev), snap_start,	       chunk_size,

⌨️ 快捷键说明

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