📄 lvm.c.txt
字号:
any questions,send email to netxiong@263.net
相关文件:
/linux/lvm.h
/driver/md/lvm-snap.c
*************************基本数据结构*************************/
(1):static struct gendisk lvm_gendisk //可分区设备
(2):vg_t *vg[ABS_MAX_VG] //所有的VG都在放在这个数组中
**************************************************************/
**********************从block的minor映射为VG和LV的号************
typedef struct {
int vg_number;
int lv_number;
} vg_lv_map_t;
static vg_lv_map_t vg_lv_map[ABS_MAX_LV];
****************************************************************
************************lvm的初始化过程*************************
(1)
int lvm_init(void)
devfs_register_chrdev(LVM_CHAR_MAJOR,lvm_name, &lvm_chr_fops) < 0) //注册处理函数集
devfs_register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) //注册处理函数集
/*
* 生成callback结构的池结构,主要避免资源短缺对系统性能的影响
*/
lvm_callback_mempool = mempool_create(NR_LVM_CALLBACK,
lvm_callback_alloc,
lvm_callback_free, NULL);
lvm_init_fs(); //注册devfs等结构
lvm_init_vars(); //注册一些公用变量
lvm_geninit(&lvm_gendisk); //注册geninit结构,为上层系统所需的设备块大小等信息
add_gendisk(&lvm_gendisk);
/*
* 注册bh处理含数接口
*/
blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), lvm_make_request_fn);
(2)
static void __init lvm_init_vars(void)
loadtime = CURRENT_TIME; //设置装载时间
lvm_lock = lvm_snapshot_lock = SPIN_LOCK_UNLOCKED; //设置锁
…… //其它初始化
for (v = 0; v < ABS_MAX_VG; v++) vg[v] = NULL; //初始化vg数组为空
for (v = 0; v < ABS_MAX_LV; v++) {
vg_lv_map[v].vg_number = ABS_MAX_VG;
vg_lv_map[v].lv_number = -1;
}
(3)
static void __init lvm_geninit(struct gendisk *lvm_gdisk)
for (i = 0; i < MAX_LV; i++) { //对于每一个lv
lvm_gendisk.part[i].start_sect = -1;
lvm_size[i] = lvm_gendisk.part[i].nr_sects = 0;
lvm_blocksizes[i] = BLOCK_SIZE; //块设备的大小都为指定的BLOCK_SIZE。
}
blk_size[MAJOR_NR] = lvm_size; //设置块大小
blksize_size[MAJOR_NR] = lvm_blocksizes; //设置块大小
hardsect_size[MAJOR_NR] = lvm_hardsectsizes; //设置扇区大小
****************************************************************
*********************proc接口***********************************
(1)int lvm_proc_read_lv_info(char *page, char **start, off_t off,
int count, int *eof, void *data)
lv_t *lv = data;
打印出相应的lv的各种信息,例如下面的信息,其中lv是1GB
name: /dev/lvmtest/lv1 #lv->lv_name
size: 2097152 #lv->lv_size
access: 3 #lv->lv_access
status: 1 #lv->lv_status
number: 0 #lv->lv_number
open: 1 #lv->lv_open
allocation: 0 #lv->lv_allocation
device: 58:00 #MAJOR(lv->lv_dev), MINOR(lv->lv_dev)
(2)int lvm_proc_read_pv_info(char *page, char **start, off_t off,
int count, int *eof, void *data)
pv_t *pv = data
打印相应的pv的各种信息。例如下面的信息,其中pv是15.53GB
name: /dev/hda7 #pv->pv_name
size: 32563692 #pv->pv_size
status: 1 #pv->pv_status
number: 1 #pv->pv_number
allocatable: 2 #pv->pv_allocatable
LV current: 1 #pv->lv_cur
PE size: 4096 #pv->pe_size / 2
PE total: 3975 #pv->pe_total
PE allocated: 256 #pv->pe_allocated
device: 03:07 #MAJOR(pv->pv_dev), MINOR(pv->pv_dev)
uuid: 72IZRt-XG85-AelI-4OTk-v60a-osK8-aoHA5M
****************************************************************
************************映射函数*************************************
(1)
这个函数是整个lvm系统中最为重要的一个函数。首先要声明的一点是,在这个remap的过程中,计量单位都以扇区为单位。
static int lvm_map(struct buffer_head *bh, int rw)
ulong size = bh->b_size >> 9; //将bh的大小转换为扇区的大小
ulong rsector_tmp = bh->b_blocknr * size;//这个bh所处的扇区号
############################
这样计算出来的rsector_tmp应该和bh->b_rsector的数值相同
以下是屏幕洁图
xwhack,bh->b_size is 1024
xwhack,bh->b_blocknr is 1
xwhack,bh->b_rsector is 2
xwhack,vg_this->pe_size is 8192
############################
if (rsector_tmp + size > lv->lv_size) //明显开始扇区号+这个bh的扇区 //大小应该比总的扇区上届小
报错
if (线性划分) {
/*
* 计算这个扇区属于哪一个pe结构,注意这里的pe_size也是按照扇区
* 来进行计量的,如4M,则pe_size = 8192
*/
index = rsector_tmp / vg_this->pe_size;
pe_start = lv->lv_current_pe[index].pe; //得到这个bh所在块的pe的起始扇区号
rsector_map = lv->lv_current_pe[index].pe +
(rsector_org % vg_this->pe_size);//得到重新计算过后的扇区号。
rdev_map = lv->lv_current_pe[index].dev;
################################
xwhack,bh->b_size is 1024
xwhack,bh->b_blocknr is 252
xwhack,bh->b_rsector is 504
xwhack,bh->b_rdev's major is 58
xwhack,bh->b_rdev's minor is 1
xwhack,vg_this->pe_size is 8192
//rsector = 252 * 1024>>9 = 252 * 2 = 504
lvm map: lvm - lvm_map minor:1 *rdev: 58:01 *rsector: 504 size:2
lvm map: lv_current_pe[0].pe: 4352 rdev: 09:00 rsector:4856
//rsector = lv_current_pe[504 /8192] + 504 % 8192 = 4352 + 504 = 4856
################################
} else { //否则就是条纹化划分
}
/*
* 如果要进行写操作的设备正在进行move操作,就要延迟它的进行
*/
if (rw == WRITE || rw == WRITEA) {
if(_defer_extent(bh, rw, rdev_map,
rsector_map, vg_this->pe_size)) {
up_read(&lv->lv_lock);
return 0;
}
lv->lv_current_pe[index].writes++; /* statistic */
} else
lv->lv_current_pe[index].reads++; /* statistic */
if (!(lv->lv_access & (LV_SNAPSHOT|LV_SNAPSHOT_ORG))) //如果不是snap_shot或者它的源
goto out; //就可以直接返回
if (lv->lv_access & LV_SNAPSHOT) { //如果时snap_shot的写
lvm_snapshot_remap_block(&rdev_map, &rsector_map, pe_start, lv) //重新计算
} else if (rw == WRITE || rw == WRITEA) { //如果是snap_shot的源并且是写请求
lv_t *snap;
for (snap = lv->lv_snapshot_next; snap;
snap = snap->lv_snapshot_next) {
if (!(snap->lv_status & LV_ACTIVE)) //如果snap_shot的lv不是活动的
continue; //继续寻找
_remap_snapshot(rdev_map, rsector_map,pe_start, snap, vg_this);//重新映射
}
}
out:
/*
* bh相关的快照操作已经完成,可以将这个bh按照一般bh进行处理了
*/
bh->b_rdev = rdev_map; //设置dev
bh->b_rsector = rsector_map; //设置扇区号
ret = lvm_push_callback(lv, rw, bh); //
up_read(&lv->lv_lock);
return ret;
…… //错误处理
(2)
static int lvm_push_callback(lv_t *lv, int rw, struct buffer_head *bh)
callback = mempool_alloc(lvm_callback_mempool, GFP_NOIO); //分配一个callback结构
callback->lv = lv; //保存lv
callback->bh_orig = bh; //保存bh
nbh = &callback->bh_io;
…… //用bh的信息填充nbh
nbh->b_end_io = lvm_bh_callback;
nbh->b_private = callback;
down_read(&lv->lv_io_sem);
generic_make_request(rw, nbh); //将nbh写出道设备上
return 0; //返回0,告知系统不必再将bh提交给系统
(3)
static void lvm_bh_callback(struct buffer_head *bh, int uptodate)
callback = bh->b_private;
lv = callback->lv;
obh = callback->bh_orig;
mempool_free(callback, lvm_callback_mempool); //释放callback结构
if (obh->b_end_io)
obh->b_end_io(obh, uptodate); //同时将源bh释放
(4)
static inline void _remap_snapshot(kdev_t rdev, ulong rsector,
ulong pe_start, lv_t *lv, vg_t *vg)
/*
* 检查一下是否参数指定的块已经在snap_shot中了
*/
r = lvm_snapshot_remap_block(&rdev, &rsector, pe_start, lv);
if (!r) //如果还没有在snap_shot中有映射,就进入if结构
__remap_snapshot(rdev, rsector, pe_start, lv, vg); //重新进行定位和计算
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -