pvcreate代码分析
- 格式:doc
- 大小:254.00 KB
- 文档页数:48
Lvm众所周知、硬盘是用于存储数据、信息的。
硬盘也是最常用的存储设备之一。
我们从市面上买回来的一块一块的这些硬盘叫做基本磁盘。
它们都是有容量的、当容量达到最大存储量时则不能再往里面写入数据。
正因为每块硬盘这个固定的容量限制了我们无法存储单个比较大的文件、或者说不能扩容。
比如说:有三个100G容量的硬盘、但是要存储一个150G的文件、显然是没法存放的。
那么是否有办法让这些单个硬盘“连接”起来形成一个更大容量的存储设备呢,而且只要有硬盘、就可以不断的把更多的硬盘“连接”起来从而实现更多更大的容量。
是否有这么一种方法的存在呢?答:是有的。
那就lvm (动态逻辑卷管理)、刚才上面说的为什么叫基本磁盘呢、是因为它是有固定的容量的,容量大小是定死了的。
而这个lvm?为什么说是动态磁盘的呢?因为通过lvm这个技术、我们可以把许许多多个硬盘“连接”起来组成一个更大容量逻辑存储设备(这里指卷组,当然真正能存储数据的是在卷组中创建的lv而不是卷组,卷组并不能直接拿来存储)而且、只要有硬盘、我们就可以组成更大的逻辑存储设备。
因此、假如我们的操作系统跑在这种动态磁盘(lv)上面、那么根本就不会出现存储空间不足的问题、因为既然操作系统是跑在动态逻辑磁盘上面、那么只要存储空间不足、我们就可以用lvm技术把新的一块硬盘加进来、让逻辑存储设备的容量更大。
那么这样的话、就可以直线无限的扩容了。
这就是lvm技术。
先理解上面这张图:1、最下面的表示存储块设备、如硬盘、(这个在虚拟机实验中、我们一般会用一个分区来模拟一个块设备)块设备必须初始化成物理卷,只有初始化成了物理卷才具备组成vg(卷组)的功能。
否则,一个块设备是无法直接跳跃、组成vg(卷组)的。
初始化命令:pvcreateEge: pvcreate /dev/sda62、pv (物理卷)一个块设备初始化之后对应一个物理卷。
3、vg (卷组)卷组是由一个或者多个pv组成的。
创建vg :Vgcreate vg01 /dev/sda{7,8,9,10}命令解释:Vg01 :卷组的名字,这个可以名字可以是任意。
sv property高级复杂用法sv property是一个用于创建或更新特定项属性值的函数。
它的语法如下:sv property [-Path] <String[]> [-Name] <String[]> [-Value]<Object[]> [[-Type] <String[]>] [[-Force]] [[-PassThru]] [[-Credential] <PSCredential>] [[-UseTransaction]][<CommonParameters>]其中,一些常用的高级复杂用法包括:1. 创建多个属性:可以通过将多个属性名称和对应的属性值传递给`-Name`和`-Value`参数来同时创建多个属性。
例如:```sv property -Path C:\Test -Name "Property1", "Property2" -Value "Value1", "Value2"```2. 更新属性类型:可以使用`-Type`参数来指定属性的类型。
例如,将属性的类型设置为字符串:```sv property -Path C:\Test -Name "Property" -Value "Value" -Type "String"```3. 使用事务功能:如果希望在特定操作中创建或更新多个属性,并希望这些属性要么全部成功要么全部失败,可以使用`-UseTransaction`参数启用事务功能。
例如:```sv property -Path C:\Test -Name "Property1", "Property2" -Value "Value1", "Value2" -UseTransaction```4. 使用凭据:可以通过`-Credential`参数传递凭据信息来使用具有适当权限的用户身份执行操作。
pvcreate命令参数pvcreate命令是LVM(逻辑卷管理)中的一个重要命令,用于创建物理卷(Physical Volume),为LVM创建逻辑卷做准备。
在本文中,我们将详细介绍pvcreate命令的参数及其用法。
1. -h 或 --help 参数该参数用于获取pvcreate命令的帮助信息,包括参数列表和简要说明。
使用该参数可以快速查阅pvcreate命令的使用方法。
2. -v 或 --verbose 参数该参数用于显示pvcreate命令的详细执行过程。
当需要查看创建物理卷的详细信息时,可以使用该参数。
3. -u 或 --uuid 参数该参数用于指定要创建的物理卷的UUID。
UUID是唯一标识符,用于确保物理卷的唯一性。
使用该参数可以自定义UUID,避免冲突。
4. -y 或 --yes 参数该参数用于在执行pvcreate命令时跳过确认提示,直接进行创建物理卷的操作。
当需要批量创建物理卷时,可以使用该参数提高效率。
5. -ff 参数该参数用于强制创建物理卷,即使设备已经包含文件系统或LVM 元数据。
使用该参数可以覆盖已有的文件系统或LVM元数据,但需谨慎操作,以免数据丢失。
6. -M 或 --metadatasize 参数该参数用于指定物理卷元数据的大小。
物理卷元数据用于存储LVM的相关信息,包括物理卷的分配情况和逻辑卷的映射关系等。
使用该参数可以调整元数据的大小,以适应不同的需求。
7. -p 或 --poolmetadata 参数该参数用于将物理卷作为元数据池来使用。
元数据池用于存储LVM的元数据,可以提高系统的性能和可靠性。
使用该参数可以将物理卷作为元数据池,为LVM提供更好的支持。
8. -R 或 --readahead 参数该参数用于指定读取物理卷的缓存大小。
读取缓存大小可以影响磁盘IO的性能,合理调整缓存大小可以提高系统的读取速度。
使用该参数可以根据需求调整读取缓存大小。
9. -Z 或 --zero 参数该参数用于在创建物理卷时填充零值。
代码中的“控制参数”通常指的是用于控制程序行为或状态的参数。
如果控制参数过多或过于复杂,可能会引起代码坏味道,即代码质量下降的迹象。
以下是一些可能导致代码坏味道的控制参数:过多的控制参数:如果一个函数或方法包含过多的控制参数,这可能会使代码难以理解和维护。
控制参数越多,代码的复杂度越高,错误的可能性也越大。
重复的控制逻辑:如果代码中存在重复的控制逻辑,这可能会导致代码重复和不必要的复杂性。
可以通过提取重复逻辑到单独的函数或方法来消除重复。
硬编码的默认值:如果默认值是硬编码在代码中的,这可能会导致不灵活的代码。
可以通过使用配置文件或环境变量来提供可配置的默认值,以提高代码的灵活性和可维护性。
敏感的控制参数:如果控制参数是敏感的,例如密码或密钥,这可能会导致安全问题。
应该避免在代码中直接存储敏感信息,而是使用安全的方式来存储和管理这些信息。
缺乏注释和控制参数说明:如果控制参数缺乏注释或说明,这可能会导致代码难以理解。
应该为每个控制参数提供清晰的注释,以帮助其他开发人员理解其用途和影响。
为了避免代码坏味道,可以通过以下方法来管理控制参数:提取公共参数:如果多个函数或方法使用相同的控制参数,可以考虑将这些参数提取到公共的变量或参数中,以便于管理和复用。
封装控制逻辑:将控制逻辑封装到单独的类或方法中,以减少其他代码的耦合度,并提高代码的可维护性。
使用配置文件或环境变量:对于可配置的控制参数,可以使用外部的配置文件或环境变量来提供值,而不是硬编码在代码中。
敏感信息加密:对于敏感的控制参数,应该使用加密的方式来存储和管理这些信息,以保护数据的机密性和完整性。
提供清晰的注释和控制参数说明:为每个控制参数提供清晰的注释和控制参数说明,以帮助其他开发人员理解其用途和影响。
LVM讲解及磁盘挂载故障LVM是 Logical Volume Manager(逻辑卷管理)的简写,它是Linux环境下对磁盘分区进⾏管理的⼀种机制,使硬盘不必使⽤分区也能被简单地重新划分⼤⼩。
⾸先我们先准备磁盘分区,模拟sdb创建3个分区,每个分区1g,并且将分区类型改为lvm,否则就⽆法向下进⾏命令(输⼊ m 获取帮助):nPartition type:p primary (0 primary, 0 extended, 4 free)e extendedSelect (default p): p分区号 (1-4,默认 1):1起始 扇区 (2048-10485759,默认为 2048):将使⽤默认值 2048Last 扇区, +扇区 or +size{K,M,G} (2048-10485759,默认为 10485759):+1G分区 1 已设置为 Linux 类型,⼤⼩设为 1 GiB命令(输⼊ m 获取帮助):p磁盘 /dev/sdb:5368 MB, 5368709120 字节,10485760 个扇区Units = 扇区 of 1 * 512 = 512 bytes扇区⼤⼩(逻辑/物理):512 字节 / 512 字节I/O ⼤⼩(最⼩/最佳):512 字节 / 512 字节磁盘标签类型:dos磁盘标识符:0xdfb97a6b设备 Boot Start End Blocks Id System/dev/sdb1 2048 2099199 1048576 83 Linux这⾥我们看到,刚分好的磁盘的ID还是83,⽂件类型还是linux,如果要使⽤lvm,则要输⼊t,在Hex代码中输⼊8e,去改变命令(输⼊ m 获取帮助):t已选择分区 1Hex 代码(输⼊ L 列出所有代码):8e已将分区“Linux”的类型更改为“Linux LVM”命令(输⼊ m 获取帮助):p磁盘 /dev/sdb:5368 MB, 5368709120 字节,10485760 个扇区Units = 扇区 of 1 * 512 = 512 bytes扇区⼤⼩(逻辑/物理):512 字节 / 512 字节I/O ⼤⼩(最⼩/最佳):512 字节 / 512 字节磁盘标签类型:dos磁盘标识符:0xdfb97a6b设备 Boot Start End Blocks Id System/dev/sdb1 2048 2099199 1048576 8e Linux LVM现在,就已经把sdb1这块磁盘改为lvm了,因为只有id为8e,system为linux lvm才可以做物理卷。
Linux系统下对硬盘分区进⾏扩容的⽅法总结硬盘快满了,加硬盘扩容,不管是独⽴的服务器,还是云空间新买的硬盘,扩容⽅式⼀样。
下⾯以阿⾥VPS为例,详细说⼀下,挂载硬盘扩容的2种⽅法。
阿⾥VPS,个⼈觉得有以下⼆个⽅⾯需要改进1,默认不是lvm,所以系统盘/dev/xvda1是不能扩容的,所以如果有⼤数据的东西,⼀开始就要考虑到扩容的问题。
数据量越⼤,操作风险越⼤。
2,不能实现⽆缝扩容,也就是说,在后台扩容⼀下,不⽤登录到VPS,进⾏调整。
⾮专业⼈⼠,扩容困难⼀,不采⽤lvm,直接将硬盘挂载到⽬录1,查看硬盘分区情况复制代码代码如下:[root@iZ94zz3wqciZ ~]# dfFilesystem 1K-blocks Used Available Use% Mounted on/dev/xvda1 20641404 14778400 4814480 76% /tmpfs 509300 0 509300 0% /dev/shm[root@iZ94zz3wqciZ ~]# fdisk -lDisk /dev/xvda: 21.5 GB, 21474836480 bytes255 heads, 63 sectors/track, 2610 cylindersUnits = cylinders of 16065 * 512 = 8225280 bytesSector size (logical/physical): 512 bytes / 512 bytesI/O size (minimum/optimal): 512 bytes / 512 bytesDisk identifier: 0x00078f9cDevice Boot Start End Blocks Id System/dev/xvda1 * 1 2611 20970496 83 Linux //id是83,⾮lvmDisk /dev/xvdb: 23.6 GB, 23622320128 bytes //新买的硬盘255 heads, 56 sectors/track, 3230 cylindersUnits = cylinders of 14280 * 512 = 7311360 bytesSector size (logical/physical): 512 bytes / 512 bytesI/O size (minimum/optimal): 512 bytes / 512 bytesDisk identifier: 0x27cc1f5a2,硬盘分区并查看分区情况复制代码代码如下:[root@iZ94zz3wqciZ ~]# fdisk -S 56 /dev/xvdb //分区WARNING: DOS-compatible mode is deprecated. It's strongly recommended toswitch off the mode (command 'c') and change display units tosectors (command 'u').Command (m for help): n //输⼊nCommand actione extendedp primary partition (1-4)p //主分区Partition number (1-4): 1 //分区号1First cylinder (1-3230, default 1):Using default value 1Last cylinder, +cylinders or +size{K,M,G} (1-3230, default 3230):Using default value 3230Command (m for help): wq //保存并退出The partition table has been altered![root@iZ94zz3wqciZ ~]# fdisk -lDisk /dev/xvda: 21.5 GB, 21474836480 bytes255 heads, 63 sectors/track, 2610 cylindersUnits = cylinders of 16065 * 512 = 8225280 bytesSector size (logical/physical): 512 bytes / 512 bytesI/O size (minimum/optimal): 512 bytes / 512 bytesDisk identifier: 0x00078f9cDevice Boot Start End Blocks Id System/dev/xvda1 * 1 2611 20970496 83 LinuxDisk /dev/xvdb: 23.6 GB, 23622320128 bytes255 heads, 56 sectors/track, 3230 cylindersUnits = cylinders of 14280 * 512 = 7311360 bytesSector size (logical/physical): 512 bytes / 512 bytesI/O size (minimum/optimal): 512 bytes / 512 bytesDisk identifier: 0x27cc1f5aDevice Boot Start End Blocks Id System/dev/xvdb1 1 3230 23062172 83 Linux //分区后3,格式化新分区xvdb1复制代码代码如下:[root@iZ94zz3wqciZ ~]# mkfs.ext4 /dev/xvdb1 //格式化分区mke2fs 1.41.12 (17-May-2010)Filesystem label=OS type: LinuxBlock size=4096 (log=2)Fragment size=4096 (log=2)Stride=0 blocks, Stripe width=0 blocks1441792 inodes, 5765543 blocks288277 blocks (5.00%) reserved for the super userFirst data block=0Maximum filesystem blocks=4294967296176 block groups32768 blocks per group, 32768 fragments per group8192 inodes per groupSuperblock backups stored on blocks:32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 4096000Writing inode tables: doneCreating journal (32768 blocks): doneWriting superblocks and filesystem accounting information: doneThis filesystem will be automatically checked every 35 mounts or180 days, whichever comes first. Use tune2fs -c or -i to override.4,创建⽬录,并挂载分区复制代码代码如下:[root@iZ94zz3wqciZ ~]# mkdir /mnt/fastdfs //挂载⽬录[root@iZ94zz3wqciZ ~]# echo "/dev/xvdb1 /mnt/fastdfs ext4 defaults 0 0" >> /etc/fstab //重启会⾃动挂载[root@iZ94zz3wqciZ ~]# mount -a //挂载所有⽬录[root@iZ94zz3wqciZ ~]# dfFilesystem 1K-blocks Used Available Use% Mounted on/dev/xvda1 20641404 14778404 4814476 76% /tmpfs 509300 0 509300 0% /dev/shm/dev/xvdb1 22694396 176064 21365516 1% /mnt/fastdfs //新的分区已挂载到这⼉,就把⼀块独⽴的硬盘加到系统当中了。
物理卷操作命令:pvcreate,pvscan,pvdisplay.卷组操作命令:vgcr。
新硬盘创建LVM系统过程。
物理卷操作命令:pvcreate,pvscan,pvdisplay.卷组操作命令:vgcreate,vgdisplay.逻辑卷操作命令:lvcreate,lvdisplay.Linx卷管理详解VG LV PV作者:吴伟龙⼀、前⾔每个Linux使⽤者在安装Linux时都会遇到这样的困境:在为系统分区时,如何精确评估和分配各个硬盘分区的容量,因为系统管理员不但要考虑到当前某个分区需要的容量,还要预见该分区以后可能需要的容量的最⼤值。
因为如果估计不准确,当遇到某个分区不够⽤时管理员可能甚⾄要备份整个系统、清除硬盘、重新对硬盘分区,然后恢复数据到新分区。
虽然现在有很多动态调整磁盘的⼯具可以使⽤,例如Partation Magic等等,但是它并不能完全解决问题,因为某个分区可能会再次被耗尽;另外⼀个⽅⾯这需要重新引导系统才能实现,对于很多关键的服务器,停机是不可接受的,⽽且对于添加新硬盘,希望⼀个能跨越多个硬盘驱动器的⽂件系统时,分区调整程序就不能解决问题。
因此完美的解决⽅法应该是在零停机前提下可以⾃如对⽂件系统的⼤⼩进⾏调整,可以⽅便实现⽂件系统跨越不同磁盘和分区。
那么我们可以通过逻辑盘卷管理(LVM,Logical Volume Manager)的⽅式来⾮常完美的实现这⼀功能。
LVM是逻辑盘卷管理(Logical Volume Manager)的简称,他是磁盘管理的另⼀种⼯具,就⽬前基本上所有操作系统均⽀持,LVM是建⽴在硬盘和分区之上的⼀个逻辑层,来提⾼磁盘分区管理的灵活性。
通过LVM系统管理员可以轻松管理磁盘分区,如:将若⼲个磁盘分区连接为⼀个整块的卷组(volume group),形成⼀个存储池。
管理员可以在卷组上随意创建逻辑卷组(logical volumes),并进⼀步在逻辑卷组上创建⽂件系统。
《探索sv property的高级复杂用法》在Verilog和SystemVerilog中,sv property是用于描述信号行为和约束的强大工具。
它可以用来定义与时序相关的性质,从而验证设计的正确性。
本文将深入研究sv property的高级复杂用法,帮助读者更深入地理解并灵活应用这一功能。
1. 介绍sv propertysv property是SystemVerilog中引入的一个重要特性,它可以用于描述设计中的性质和约束。
sv property通常包括assertion和covergroup两个部分,其中assertion用于描述设计中的性质,而covergroup用于覆盖率分析。
通过使用sv property,设计工程师可以方便地定义和验证设计中的行为和时序约束。
2. 基本的sv property语法让我们回顾一下基本的sv property语法。
一个简单的sv property 通常由property和endproperty关键字包围,中间包含对信号行为的描述。
下面是一个简单的sv property示例:```verilogproperty p1;@(posedge clk) disable iff (rst_n)(req && !ack) |-> ##[1:10] ack;endproperty```在这个示例中,我们定义了一个名为p1的sv property,描述了当req有效且ack无效时,经过1到10个时钟周期后,ack必须变为有效。
3. 高级复杂用法之sequence和eventually除了基本的sv property语法外,我们还可以使用一些高级的复杂用法来描述更复杂的时序约束。
其中,sequence和eventually是两个常用的关键字。
sequence用于描述一系列信号事件的发生顺序,而eventually用于描述某个事件最终会发生。
通过组合使用这两个关键字,可以灵活地描述各种复杂的时序约束。
逻辑卷操作相关命令逻辑卷操作相关命令逻辑卷的优势:1、在多个磁盘上条带化存储数据,提供并⾏IO能⼒2、可以建⽴磁盘镜像,提供容错功能保护数据3、扩展性好,根据需要灵活扩容存储空间逻辑卷常⽤命令:pvcreate 设备名vgcreate 卷组名物理卷名1 物理卷名2lvcreate -L ⼤⼩ -n 逻辑卷名卷组名lvextend -L +⼤⼩ /dev/卷组名/逻辑卷名扫描:pvscan vgscan lvscan建⽴:pvcreate vgcreate lvcreate显⽰:pvdisplay vgdisplay lvdisplay删除:pvremove vgremove lvremoveresize命令:resize2fs ---ext⽂件系统xfs_growfs ----xfs⽂件系统swap ---swap off lv_namemake swap lv_nameswapon lv_name⽰例⼀:缩⼩根⽬录,增⼤/usr⽬录当前:[root@mysql2 ~]# df -hFilesystem Size Used Avail Use% Mounted on/dev/mapper/vg_system-Log_root 9.8G 2.8G 6.5G 30% /tmpfs 864M 72K 863M 1% /dev/shm/dev/sda1 190M 84M 93M 48% /boot/dev/mapper/vg_data-LogVol0030G 44M 28G 1% /data/dev/mapper/vg_system-Log_tmp 2.9G 639M 2.2G 23% /tmp/dev/mapper/vg_system-LogVol02 3.9G 3.5G 144M 97% /usr计划把/data⽬录缩⼩⾄15G,把5G给/usr⾸先umountumount /dev/mapper/vg_data-LogVol00e2fsck -f /dev/mapper/vg_data-LogVol00resize2fs /dev/mapper/vg_data-LogVol00 25Glvreduce -L -5G /dev/mapper/vg_data-LogVol00lvdisplaymount /dev/mapper/vg_data-LogVol00 /data[root@mysql2 ~]# df -hFilesystem Size Used Avail Use% Mounted on/dev/mapper/vg_system-Log_root 9.8G 2.8G 6.5G 30% / tmpfs 864M 72K 863M 1% /dev/shm/dev/sda1 190M 84M 93M 48% /boot/dev/mapper/vg_system-Log_tmp 2.9G 639M 2.2G 23% /tmp /dev/mapper/vg_system-LogVol02 3.9G 3.5G 144M 97% /usr /dev/mapper/vg_data-LogVol00 25G 44M 23G 1% /data然后把我们缩⼩得到的5G给/usrlvextend -L +5G /dev/mapper/vg_system-LogVol02resize2fs /dev/mapper/vg_system-LogVol02⽰例⼆.red hat 7.9 逻辑卷,把/home⽬录缩⼩,把swap扩⼤⾸先备份/home⽬录umount /dev/mapper/rhel-homelvreduce -L 150G /dev/mapper/rhel-homemkfs.xfs -f /dev/mapper/rhel-homemount /dev/mapper/rhel-home /home把备份的/home⽬录的内容恢复回去lvextend -L +28G /dev/mapper/rhel-swapswapoff -amkswap /dev/mapper/rhel-swapswapon -va。
LVM代码分析1.探索pvcreate函数大致的执行过程1.1. p vcreate/** 代码1*/int pvcreate(struct cmd_context *cmd, int argc, char **argv){int i;int ret = ECMD_PROCESSED;struct pvcreate_params pp;struct physical_volume *pv;/* 给pp设置默认值*/pvcreate_params_set_defaults(&pp);/* 检查pvcreate需要保存到磁盘的参数,如restorefile、uuid,并传给pp结构体*/ if (!pvcreate_restore_params_validate(cmd, argc, argv, &pp)) {return EINV ALID_CMD_LINE;}/* 检查pvcreate不需要保存到磁盘的参数(见man pvcreate),并传给pp结构体*/ if (!pvcreate_params_validate(cmd, argc, argv, &pp)) {return EINV ALID_CMD_LINE;}/* 将用户输入的所有device转换成PV */for (i = 0; i < argc; i++) {if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) {log_error("Can't get lock for orphan PVs");return ECMD_FAILED;}dm_unescape_colons_and_at_signs(argv[i], NULL, NULL);/* 单独转换一个device,详见代码2 */if (!(pv = pvcreate_single(cmd, argv[i], &pp, 1))) {stack;ret = ECMD_FAILED;}unlock_vg(cmd, VG_ORPHANS);if (sigint_caught())return ret;}return ret;}1.2. p vcreate_single/** 代码2* pvcreate_single() - initialize a device with PV label and metadata area** Parameters:* - pv_name: device path to initialize* - pp: parameters to pass to pv_create; if NULL, use default values** Returns:* NULL: error* struct physical_volume * (non-NULL): handle to physical volume created*/struct physical_volume * pvcreate_single(struct cmd_context *cmd,const char *pv_name,struct pvcreate_params *pp,int write_now){struct physical_volume *pv = NULL;struct device *dev;struct dm_list mdas;struct pvcreate_params default_pp;char buffer[64] __attribute__((aligned(8)));/* 给pp设置默认值,pp保存的是pvcreate命令创建PV时的参数。
可以由用户指定,否则使用默认值*/ pvcreate_params_set_defaults(&default_pp);if (!pp) // 如果pp未定义,则使用默认的pp值pp = &default_pp;if (pp->idp) {// 如果UUID存在(比如用户指定一个UUID)if ((dev = lvmcache_device_from_pvid(cmd, pp->idp, NULL, NULL)) && // 查看此UUID是否在lvm缓存中已经存在对应的设备(dev != dev_cache_get(pv_name, cmd->filter))) { // 在缓存中查看用户输入的pv_name对应的设备if (!id_write_format((const struct id*)&pp->idp->uuid,buffer, sizeof(buffer)))goto_bad;log_error("uuid %s already in use on \"%s\"", buffer,dev_name(dev));goto bad;;}}// 上述缓存为两个hash表,在lvm启动的时候初始化if (!pvcreate_check(cmd, pv_name, pp))goto_bad;if (sigint_caught())goto_bad;if (!(dev = dev_cache_get(pv_name, cmd->filter))) {log_error("%s: Couldn't find device. Check your filters?",pv_name);goto bad;}dm_list_init(&mdas);/* pv_create函数见代码3,作用是:创建并填充pv结构体*/if (!(pv = pv_create(cmd, dev, pp->idp, pp->size,pp->data_alignment, pp->data_alignment_offset,pp->pe_start ? pp->pe_start : PV_PE_START_CALC,pp->extent_count, pp->extent_size,pp->labelsector, pp->pvmetadatacopies,pp->pvmetadatasize, pp->metadataignore))) {log_error("Failed to setup physical volume \"%s\"", pv_name);goto bad;}log_verbose("Set up physical volume for \"%s\" with %" PRIu64" available sectors", pv_name, pv_size(pv));if (write_now) {struct pv_to_create pvc;pvc.pp = pp;pvc.pv = pv;if (!_pvcreate_write(cmd, &pvc)) //将pv和pp的信息写到磁盘,详见代码4 goto bad;} else {pv->status |= UNLABELLED_PV;}return pv;bad:return NULL;}1.3. p v_create/*** 代码3* pv_create - initialize a physical volume for use with a volume group * created PV belongs to Orphan VG.** @fmt: format type* @dev: PV device to initialize* @size: size of the PV in sectors* @data_alignment: requested alignment of data* @data_alignment_offset: requested offset to aligned data * @pe_start: physical extent start* @existing_extent_count* @existing_extent_size* @pvmetadatacopies* @pvmetadatasize* @mdas** Returns:* PV handle - physical volume initialized successfully * NULL - invalid parameter or problem initializing the physical volume ** Note:* FIXME: shorten argument list and replace with explict 'set' functions */struct physical_volume *pv_create(const struct cmd_context *cmd, struct device *dev,struct id *id, uint64_t size, unsigned long data_alignment, unsigned long data_alignment_offset,uint64_t pe_start,uint32_t existing_extent_count,uint32_t existing_extent_size,uint64_t label_sector,unsigned pvmetadatacopies,uint64_t pvmetadatasize,unsigned metadataignore){const struct format_type *fmt = cmd->fmt;struct dm_pool *mem = fmt->orphan_vg->vgmem;struct physical_volume *pv = _alloc_pv(mem, dev);unsigned mda_index;struct pv_list *pvl;if (!pv)return_NULL;if (id)memcpy(&pv->id, id, sizeof(*id));else if (!id_create(&pv->id)) {log_error("Failed to create random uuid for %s.",dev_name(dev));goto bad;}if (!dev_get_size(pv->dev, &pv->size)) {log_error("%s: Couldn't get size.", pv_dev_name(pv));goto bad;}if (size) {if (size > pv->size)log_warn("WARNING: %s: Overriding real size. ""Y ou could lose data.", pv_dev_name(pv));log_verbose("%s: Pretending size is %" PRIu64 " sectors.",pv_dev_name(pv), size);pv->size = size;}if (pv->size < pv_min_size()) {log_error("%s: Size must exceed minimum of %" PRIu64 " sectors.", pv_dev_name(pv), pv_min_size());goto bad;}if (pv->size < data_alignment) {log_error("%s: Data alignment must not exceed device size.", pv_dev_name(pv));goto bad;}if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl)))) {log_error("pv_list allocation in pv_create failed");goto bad;}pvl->pv = pv;add_pvl_to_vgs(fmt->orphan_vg, pvl);fmt->orphan_vg->extent_count += pv->pe_count;fmt->orphan_vg->free_count += pv->pe_count;pv->fmt = fmt;pv->vg_name = fmt->orphan_vg_name;if (!fmt->ops->pv_initialise(fmt, label_sector, pe_start,existing_extent_count, existing_extent_size,data_alignment, data_alignment_offset, pv)) { log_error("Format-specific initialisation of physical ""volume %s failed.", pv_dev_name(pv));goto bad;}for (mda_index = 0; mda_index < pvmetadatacopies; mda_index++) { if (pv->fmt->ops->pv_add_metadata_area &&!pv->fmt->ops->pv_add_metadata_area(pv->fmt, pv,pe_start != PV_PE_START_CALC,mda_index, pvmetadatasize,metadataignore)) {log_error("Failed to add metadata area for ""new physical volume %s", pv_dev_name(pv));goto bad;}}return pv;bad:// FIXME: detach from orphan in error path//free_pv_fid(pv);//dm_pool_free(mem, pv);}1.4. _pvcreate_write/** 代码4*/static int _pvcreate_write(struct cmd_context *cmd, struct pv_to_create *pvc){int zero = pvc->pp->zero;struct physical_volume *pv = pvc->pv;struct device *dev = pv->dev;const char *pv_name = dev_name(dev);/* Wipe existing label first */if (!label_remove(pv_dev(pv))) {log_error("Failed to wipe existing label on %s", pv_name);return 0;}if (zero) {log_verbose("Zeroing start of device %s", pv_name);if (!dev_open_quiet(dev)) {log_error("%s not opened: device not zeroed", pv_name);return 0;}if (!dev_set(dev, UINT64_C(0), (size_t) 2048, 0)) {log_error("%s not wiped: aborting", pv_name);if (!dev_close(dev))stack;return 0;}if (!dev_close(dev))stack;}log_error("Writing physical volume data to disk \"%s\"",pv_name);if (!(pv_write(cmd, pv, 1))) { // 很明显,这个命令就是写磁盘用的,详见代码5 log_error("Failed to write physical volume \"%s\"", pv_name);}log_print("Physical volume \"%s\" successfully created", pv_name);return 1;}1.5. p v_write/** 代码5* 调用pv->fmt->ops->pv_write函数* 代码3中,第一句就是:const struct format_type *fmt = cmd->fmt;之后pv->fmt = fmt; * 所以找pv_write函数,需从cmd结构体下手* 另外有个蛋疼的名词:orphan,词典解释:孤儿。