一、varyoffvg varyoffvg脚本实际上是对lvaryoffvg命令的封装,以varyoffvg datavg为例,脚本主体流程如下:
二、lvaryoffvg lvaryoffvg是二进制可执行文件,看看它调用了哪些库文件。 dump -Tv /usr/sbin/lvaryoffvg ........... [27] 0x00000000 undef IMP DS EXTref liblvm.a(shr.o) lvm_varyoffvg ............ 感觉lvm_varyoffvg这个函数是lvaryoffvg命令的核心。这是个公开的函数,在/usr/include/lvm.h头文件中有定义。 struct varyoffvg { struct unique_id vg_id; /* volume group id */ long lvs_only; /* flag to varyoff only logical volumes */ }; extern int lvm_varyoffvg(struct varyoffvg *varyoffvg); 我们可以写一个自己的命令来替代lvaryoffvg,并且让varyoffvg调用我们提供的命令。 #include <sys/types.h> #include <lvm.h> struct varyoffvg { struct unique_id vg_id; long lvs_only; }; extern int lvm_varyoffvg(struct varyoffvg *varyoffvg); __ulong32_t str2hex(char *str) { __ulong32_t value=0; unsigned int i,j; for(i=0;i<8;i++) { j=0; if(str>='0'&&str<='9') { j=str-'0'; } else if(str>='a'&&str<='f') { j=str-'a'+0xa; } else if(str>='A'&&str<='F') { j=str-'A'+0xA; } j=(j<<((7-i)*4)); value|=j; } return value; } int main(int argc,char *argv[]) { int result=0; struct varyoffvg Varyoffvg; char *cmd=argv[0]; if(argc!=2) { printf("usage:%s vgid/n",cmd); exit(-1); } Varyoffvg.vg_id.word4=str2hex(argv[1]+24); Varyoffvg.vg_id.word3=str2hex(argv[1]+16); Varyoffvg.vg_id.word2=str2hex(argv[1]+8); Varyoffvg.vg_id.word1=str2hex(argv[1]+0); Varyoffvg.lvs_only=0; result=lvm_varyoffvg(&Varyoffvg); return result; } ü 编译这个程序,得到my_lvaryoffvg文件,假设为/tmp/my_lvaryoffvg,权限为750。 ü 创建testvg,并且varyon。为了简单起见,可以不用创建LV和FS ü 编辑/usr/sbin/varyoffvg脚本,将lvaryoffvg -g $VGID $SFLAG替换为/tmp/my_lvaryoffvg $VGID ü 执行varyoffvg testvg,发现testvg被成功varyoff ü 编辑/usr/sbin/varyoffvg脚本,改回原来的命令。 三、putlvodm putlvodm具有很多参数,可以参考lvm cmds from a to z中的介绍,我们现在只关心和锁住卷组有关的内容。首先看一下它调用了哪些库文件 #dump -Tv /usr/sbin/putlvodm | grep lock [40] 0x00000000 undef IMP DS EXTref liblvm.a(shr.o) lvm_cfglock [41] 0x00000000 undef IMP DS EXTref liblvm.a(shr.o) lvm_free_cfg_lock [42] 0x00000000 undef IMP DS EXTref liblvm.a(shr.o) lvm_get_cfg_lock [43] 0x00000000 undef IMP DS EXTref liblvm.a(shr.o) lvm_free_sync_lock [44] 0x00000000 undef IMP DS EXTref liblvm.a(shr.o) lvm_get_sync_lock [47] 0x00000000 undef IMP DS EXTref liblvm.a(shr.o) lvm_cfglock_query [55] 0x00000000 undef IMP DS EXTref libodm.a(shr.o) odm_unlock [56] 0x00000000 undef IMP DS EXTref libodm.a(shr.o) odm_lock 看上去有两种锁,一种是和LVM相关的,另一种是和ODM相关。接下来再看一下putlvodm -k的效果。首先执行putlvodm -k <vgid>,然后在其他窗口中执行lsvg <vgname>。我们发现lsvg命令被hang住,过一段时间产生0516-1201报错,提示我们用chvg -u解锁。我们执行putlvodm -K <vgid>,则很快lsvg命令就恢复执行。有此可见putlvodm和lsvg争夺相同的锁。那么看看lsvg命令调用了哪些库文件 #dump -Tv /usr/sbin/lsvg | grep lock [4] 0x00000000 undef IMP RW EXTref libc.a(shr.o) _libc_lock_funcs [6] 0x00000000 undef IMP DS EXTref libc.a(shr.o) _rec_mutex_unlock [11] 0x00000000 undef IMP DS EXTref libc.a(shr.o) _rec_mutex_lock [66] 0x00000000 undef IMP DS EXTref liblvm.a(shr.o) lvm_cfglock 和putlvodm的相比较,我们发现两个都调用了lvm_cfglock。看来就是这个子例程给vg上了锁。不过这个是未公开的子例程,我们无法直接调用。接下来看看通过kdb能观察到什么。 (0)> ttid 2dac3 SLOT NAME STATE TID PRI RQ CPUID CL WCHAN pvthread+016D00 730 lsvg SLEEP 02DAC3 03C 0 0 35DEBE98 NAME................ lsvg WTYPE............... WEVENT ...............state :00000003 ...............wtype :00000001 ...............flags :00000000 ..............flags2 :00000000 2dac3是lsvg的线程ID。显然这个线程正处于sleep状态,原因应该是等待某个event。这个event的地址是0x35DEBE98,并且这个地址还会改变。(有哪位高人能通过这个地址还原event的信息?或者我理解有误,这个并不是event的地址?) 四、总结 varyoffvg的流程就是首先给VG加锁,然后调用lvaryoffvg命令执行实际操作,最后解锁。lvaryoffvg是对子例程lvm_varyoffvg的封装,我们用自己的实现替换掉lvaryoffvg命令后varyoffvg仍然可以正常工作。putlvodm执行加锁和解锁。在加锁后涉及VG的操作都hang住,包括lsvg命令,在解锁后才能继续运行。 chvg -u命令也可以为VG解锁。chvg是个脚本,可以发现-u参数最终也调用putlvodm。 |
varyoffvg命令的流程和理解
最新推荐文章于 2021-07-31 23:13:36 发布