LVM是在物理层面之上的一层逻辑结构。它把下面的磁盘以PE的形式组合成一个大的VG,这个VG就是一个完整独立的空闲空间,我们可以在之上再创建各个分区,这个就是LV。LV就可以跟我们的普通磁盘分区一样的格式化挂载了。而普通磁盘首先要做成PV,以支持PE。

它带来的好处是分区大小可以动态扩展,更好的是可以做快照以实现在线备份。

而坏处是因为不是直接存储在硬件上的,而是由软件组织的, 所以数据损坏或删除以后很难找回。也正是因为这样LVM一般都是建立在RAID之上的,当然删除无法避免。

虽然说现在出现了btrfs的文件系统可以完全替代lvm,不过完全流行起来可能也是几年后的事情了。


目录:

一、介绍

二、使用

1、前提

2、准备分区

3、创建LVM。

4、动态调整大小

5、快照


环境:

系统:CentOS7.1.1503

fdisk:util-linux 2.23.2

lvm:2.02.115(2)


一、介绍

LVM: Logical Volume Manager  逻辑卷管理

物理卷:PV (Physical Volume)

卷组:VG(Volume Group)

PE: Physical Extent 物理盘区


PV:把普通磁盘做成LVM的第一步。可以是整块的磁盘,也可以是一个单独的分区,只要是块设备就可以。创建PV,会自动在PV盘中存储一些元数据,这个区域叫做header;剩余的其它区域才会被当做数据区使用,加入VG以后会被划分成无数个PE。


VG:可以将多个PV组成一个管理区域,并在各个PV上划分PE。每个VG对PE的大小可能都不相同。 所以一个PV在加入不同的VG以后也会被划分成不同的PE。LV就是在VG里面建立。


PE:LVM的基本数据存储单元。移动数据(如删除一个PV的时候)和分区都是以PE为单位的。在创建完lv以后,在lv中组织单元还是pe, 但名称换了。叫作LE(逻辑盘区)以示区分。


LV:虚拟盘,由PE组成。是一个设备,可以用来做与普通分区一样的操作。


来张图看看,这里没有磁盘和分区的区别,这些都是块设备。

wKiom1Z_VZKRbaVkAAEQVi3eYoQ319.jpg


一些要注意的:

1、LVM层面与磁盘层面的分区没有关系,LVM的组织结构在磁盘的上层。对于LVM来说磁盘的分区也是一个块设备,是一部分存储空间。

2、LVM的VG最多仅能有65534个PE,因此4M的PE, VG最多能有 4M*65534/(1024M/G)=256G。

3、LVM的数据移动是在LVM层完成的,文件系统对于LVM来说也是数据。


LVM的命名方式:

每一个LV的设备路径为/dev/dm-#,但默认的会有两种符号链接:
1、/dev/mapper/VG_NAME-LV_NAME
如:/dev/mapper/vg0-root

2、/dev/VG_NAME/LV_NAME
如:/dev/vg0/root


二、使用

1、前提

首先要确认dm模块和lvm2软件包。

在linux上面LVM的支持是由内核中的dm(device mapper)模块所实现的,用以将一个或多个底层块设备组织成一个逻辑设备。我们可以查看/sys/module目录里面有哪些模块或者直接使用lsmod来查看系统已挂载的模块。我这里lsmod的信息。

wKioL1Z_YAXgYBbvAACQ9uF92Rg063.jpg

可以看到dm_mod已经加载了,上面几个是dm的其它功能,而且dm_mod也依赖于它们。

如果没有,可能是没有默认加载,可以查看modules.dep文件中有没有。uname只是用来识别内核版本号的,那个目录就是版本号。因为朋友们可以跟我这里不一样,所以用uname -r 来自动识别。

[root@localhost 3.10.0-229.el7.x86_64]# cat /lib/modules/`uname -r`/modules.dep | grep dm-mod.ko
kernel/drivers/md/dm-mod.ko:
kernel/drivers/md/dm-bufio.ko: kernel/drivers/md/dm-mod.ko
kernel/drivers/md/dm-crypt.ko: kernel/drivers/md/dm-mod.ko
......

或者直接查看目录中有没有模块:

[root@localhost 3.10.0-229.el7.x86_64]# ls /lib/modules/`uname -r`/kernel/drivers/md

也有可能是编译内内核的。不管怎样我们拉出来溜溜就知道了。


lvm2软件包是我们用户空间用来管理LVM的。所以要有这个软件包才行。


确认有可被用作PV的分区或磁盘。

[root@localhost module]# ll /dev/sd*
brw-rw----. 1 root disk 8, 0 Dec 27 18:15 /dev/sda
brw-rw----. 1 root disk 8, 1 Dec 27 18:14 /dev/sda1
brw-rw----. 1 root disk 8, 2 Dec 27 18:14 /dev/sda2
brw-rw----. 1 root disk 8, 3 Dec 27 18:14 /dev/sda3
brw-rw----. 1 root disk 8, 4 Dec 27 18:14 /dev/sda4
brw-rw----. 1 root disk 8, 5 Dec 27 18:14 /dev/sda5

wKioL1Z_XtWSQ47jAAGRBsz6QTM969.jpg

我这里的虚拟机只有一个磁盘,但还有很多空间,所以就建几个分区用来创建PV了。如果是磁盘也不用分区,直接创建pv就可以了(如/dev/sda)。如果是分区需要把分区的标识改为linux lvm,为了让系统识别,来调用驱动。


2、准备分区

[root@localhost ~]# fdisk /dev/sda

用虚拟机分区的时候有个诡异的地方,看下面这张图:

wKiom1Z_hA_ian2DAAEv2LIJviA367.jpg

因为上面默认的起始的位置在/dev/sda5和/dev/sda4之间,所以空间非常小,这时我们只要手动的指定起始位置大于一点/dev/sda5分区结束的位置。

wKioL1Z_hPPgBBC1AADjt6M-Xak617.jpg

启始位置就会自动变成之后的可分区位置。

分区这里就不多说了。我这里的结果是。

wKiom1Z_hfXRtsUtAACkJWoYR4E153.jpg

系统在使用过程中,会保护磁盘分区表。所以在这里保存以后会发生警告。

wKiom1Z_hufhtizZAAF-b7Wga3I623.jpg

我们只要多运行几遍partx -a /dev/sda即可,或是 kpartx -af /dev/sda。这是新建分区,如果是删除分区,那就只有重启系统了。

看一下分区:

wKiom1Z_huny4nUpAACwndgdrh4627.jpg


一切完成就可以开始创建LVM了。


3、创建LVM

命令大钢:

物理卷管理命令: pv

pvcreatepvremovepvscanpvspvdisplaypvmove
创建pv移除pv扫描信息详细信息移动设备数据(先移数据,再删pv)

卷组的管理命令: vg

vgcreatevgremovevgextendvgsvgdisplayvgreducevgrename
创建vg移除VG扩容vg信息详细信息从VG中移除PV重命名

逻辑卷管理命令: lv

lvcreatelvremovelvextendlvslvdisplaylvreducelvresize
创建lv移除lv扩容lv信息详细信息缩小改容量


创建pv与相关

创建pv的参数有一大堆,但我们这里一个也用不到,所以简单的这样:

[root@localhost ~]# pvcreate /dev/sda[6-8]
  Physical volume "/dev/sda6" successfully created
  Physical volume "/dev/sda7" successfully created
  Physical volume "/dev/sda8" successfully created
[root@localhost ~]#

完成了。来查看一下相关信息:

[root@localhost ~]# pvs
  PV         VG   Fmt  Attr PSize  PFree 
  /dev/sda6       lvm2 ---  20.00g 20.00g
  /dev/sda7       lvm2 ---  30.00g 30.00g
  /dev/sda8       lvm2 ---  10.00g 10.00g
[root@localhost ~]#

有3个设备用做pv,大小有20G,30G,10G。 空闲也是这么多。还没有加任何vg。

PV这里主要记住一点,在执行vgreduce的时候一定要先执行pvmove把数据移到别的pv上面去


创建VG与相关:

一个参数,-s 指定pe大小,默认一般是4M。

vgcreate  [-s #[kKmMgGtTpPeE]] VolumeGroupName  PhysicalDevicePath [PhysicalDevicePath...]

[root@localhost ~]# vgcreate myvg /dev/sda[6-7]
  Volume group "myvg" successfully created
[root@localhost ~]#

成功创建VG,VG名称为myvg。看一下信息。

[root@localhost ~]# vgs
  VG   #PV #LV #SN Attr   VSize  VFree 
  myvg   2   0   0 wz--n- 49.99g 49.99g
[root@localhost ~]# vgs myvg
  VG   #PV #LV #SN Attr   VSize  VFree 
  myvg   2   0   0 wz--n- 49.99g 49.99g
[root@localhost ~]#

由两个PV组成,现在VG的大小为49.99G。

再查看一下pv的。

[root@localhost ~]# pvs
  PV         VG   Fmt  Attr PSize  PFree 
  /dev/sda6  myvg lvm2 a--  20.00g 20.00g
  /dev/sda7  myvg lvm2 a--  30.00g 30.00g
  /dev/sda8       lvm2 ---  10.00g 10.00g
[root@localhost ~]#

看到VG那里变成了myvg。表示加入了myvg的VG。sda8刚才没有加入。

那么把sda7也从myvg中除去。


缩减VG: 这种操作不知道什么样的情况下才会用到,这里就当闲写吧。

vgreduce  VolumeGroupName  PhysicalDevicePath [PhysicalDevicePath...]

注意:先执行pvmove。

[root@localhost ~]# pvmove /dev/sda7
  No data to move for myvg
[root@localhost ~]# vgreduce myvg /dev/sda7
  Removed "/dev/sda7" from volume group "myvg"
[root@localhost ~]#

因为pv中没有数据,所以pvmove的时候没有效果。

如果按正常情况来看,我们这里模拟一下试试看。

我这里重新在VG中加入了sda7。并且建立了一个lv,名为myroot。格式化并挂载了,而且复制了一些数据。

[root@localhost vg]# vgs
  VG   #PV #LV #SN Attr   VSize  VFree 
  myvg   2   1   0 wz--n- 49.99g 39.99g
[root@localhost vg]#

看到VFree了吧, 少了10个!!!! j_0060.gif怎么少了这么多?

[root@localhost vg]# pvs
  PV         VG   Fmt  Attr PSize  PFree 
  /dev/sda6  myvg lvm2 a--  20.00g 10.00g
  /dev/sda7  myvg lvm2 a--  30.00g 30.00g
  /dev/sda8       lvm2 ---  10.00g 10.00g
[root@localhost vg]#

看样子数据都在/dev/sda6上面。

[root@localhost vg]# pvdisplay /dev/sda6
  --- Physical volume ---
  PV Name               /dev/sda6
  VG Name               myvg
  PV Size               20.00 GiB / not usable 4.00 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              5119
  Free PE               2559
  Allocated PE          2560
  PV UUID               Pqf2l9-9ZID-dXdg-kdGX-fELt-ARoR-5hTm1H
   
[root@localhost vg]#

其实这里为什么显示空间用的这么多,我也不是很清楚,这个问题暂时不管它。我们接着来。VG空间49G,把sda6移除以后还有30G,完全可够装得下现在在sda6上的数据。

我也没有做过这种操作,暂时也不知道要注意些什么。

开工:

[root@localhost vg]# pvmove /dev/sda6
  /dev/sda6: Moved: 0.3%
  /dev/sda6: Moved: 5.0%
  /dev/sda6: Moved: 9.9%
  /dev/sda6: Moved: 14.8%
  /dev/sda6: Moved: 19.7%
  /dev/sda6: Moved: 24.1%
  /dev/sda6: Moved: 29.0%
  /dev/sda6: Moved: 34.1%
  /dev/sda6: Moved: 39.0%
  /dev/sda6: Moved: 42.6%
  /dev/sda6: Moved: 47.3%
  /dev/sda6: Moved: 52.0%
  /dev/sda6: Moved: 57.0%
  /dev/sda6: Moved: 61.6%
  /dev/sda6: Moved: 66.5%
  /dev/sda6: Moved: 71.5%
  /dev/sda6: Moved: 76.4%
  /dev/sda6: Moved: 80.9%
  /dev/sda6: Moved: 84.1%
  /dev/sda6: Moved: 88.8%
  /dev/sda6: Moved: 93.6%
  /dev/sda6: Moved: 98.5%
  /dev/sda6: Moved: 100.0%
[root@localhost vg]#

在挂载的情况下完成的,但过程中没有修改数据,朋友们有兴趣可以试试。

[root@localhost vg]# vgreduce myvg /dev/sda6
  Removed "/dev/sda6" from volume group "myvg"
[root@localhost vg]# 
[root@localhost vg]# vgs
  VG   #PV #LV #SN Attr   VSize  VFree 
  myvg   1   1   0 wz--n- 30.00g 20.00g
[root@localhost vg]#

数据只有300M,空间都去哪了? 不知道是不是因为虚拟机的问题。


扩展VG:

vgextend  VolumeGroupName  PhysicalDevicePath [PhysicalDevicePath...]

[root@localhost vg]# vgextend myvg /dev/sda[68]
  Volume group "myvg" successfully extended
[root@localhost vg]# vgs
  VG   #PV #LV #SN Attr   VSize  VFree 
  myvg   3   1   0 wz--n- 59.99g 49.99g
[root@localhost vg]# pvs
  PV         VG   Fmt  Attr PSize  PFree 
  /dev/sda6  myvg lvm2 a--  20.00g 20.00g
  /dev/sda7  myvg lvm2 a--  30.00g 20.00g
  /dev/sda8  myvg lvm2 a--  10.00g 10.00g


创建lv相关

lvcreate -L #[mMgGtT] -n NAME VolumeGroup
lvremove /dev/VG_NAME/LV_NAME

上面是创建,下面是移除。

[root@localhost vg]# lvcreate -L 20G -n myusr myvg
  Logical volume "myusr" created.
[root@localhost vg]# 
[root@localhost vg]# lvs
  LV     VG   Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  myroot myvg -wi-ao---- 10.00g                                                    
  myusr  myvg -wi-a----- 20.00g                                                    
[root@localhost vg]#

一个是我们刚才创建的,还记着否。

[root@localhost vg]# ll /dev/dm*
brw-rw----. 1 root disk  253, 0 Dec 27 23:02 /dev/dm-0
brw-rw----. 1 root disk  253, 1 Dec 27 23:15 /dev/dm-1
[root@localhost vg]# ll /dev/myvg/*
lrwxrwxrwx. 1 root root 7 Dec 27 23:02 /dev/myvg/myroot -> ../dm-0
lrwxrwxrwx. 1 root root 7 Dec 27 23:15 /dev/myvg/myusr -> ../dm-1
[root@localhost vg]#


创建文件系统

[root@localhost vg]# mke2fs -t ext4 /dev/myvg/myusr
[root@localhost vg]# mkdir /mnt/vg2
[root@localhost vg]# mount /dev/myvg/myusr /mnt/vg2
[root@localhost vg]# lvs 
  LV     VG   Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  myroot myvg -wi-ao---- 10.00g                                                    
  myusr  myvg -wi-ao---- 20.00g 
[root@localhost vg]# df -Th
.....
/dev/mapper/myvg-myroot ext4      9.8G  249M  9.0G   3% /mnt/vg
/dev/mapper/myvg-myusr  ext4       20G   45M   19G   1% /mnt/vg2


4、动态调整大小

有没有发现一个规律

在PV阶段还是以设备名来操作,如/dev/sda8。

在VG和LV阶段就是以VG或LV的名称来操作了。


动态调整大小,可变大可变小。变小这个操作我们做做实验还可以,但是在实际工作中,就不要玩命了,现在也没有这个需求。

扩展和缩小都需要两步:

1、物理边界,说白了就是我们LV的大小。

2、逻辑边界,就是我们的文件系统啦。

注意:我们的LVM就是一个动态的磁盘管理结构,跟文件系统一毛钱关系也没有。所以文件系统的变化用文件系统的命令resize2fs(只用于ext系列文件系统)。下面的e2fsck也是只用于ext系列文件系统的。


缩小逻辑卷
        # umount /dev/VG_NAME/LV_NAME
        # e2fsck -f /dev/VG_NAME/LV_NAME
        # resize2fs /dev/VG_NAME/LV_NAME #[mMgGtT]
        # lvreduce -L [-]#[mMgGtT] /dev/VG_NAME/LV_NAME
        # mount

这个必须要先卸载逻辑卷,然后强制执行磁盘检测,然后缩小文件系统边界,然后缩小物理边界。最后就可以挂载上去,看看数据有没有变化了。

我们这里就以myroot这个lv来试试:

查看一下物理总大小。

[root@localhost mnt]# lvs
  LV     VG   Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  myroot myvg -wi-ao---- 10.00g                                                    
  myusr  myvg -wi-ao---- 20.00g

总大小10G

查看一下文件系统中数据的大小。

[root@localhost mnt]# df -Th
/dev/mapper/myvg-myusr  ext4       20G   45M   19G   1% /mnt/vg2
/dev/mapper/myvg-myroot ext4      9.8G  344M  8.9G   4% /mnt/vg

数据已使用344M

查看一下所有文件的大小。

[root@localhost mnt]# du -s vg
315384    vg
[root@localhost mnt]#

现在挂载目录大小为315384,这个是以文件计算的大小,如果缩减完成以后,数值变了,估计就有数据丢了。。

我这里可能有点罗嗦了,不过却不多余。可以查看一下有没有什么异常之类的。


[root@localhost mnt]# umount vg
[root@localhost mnt]# e2fsck -f /dev/myvg/myroot 
e2fsck 1.42.9 (28-Dec-2013)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/myvg/myroot: 10860/655360 files (0.1% non-contiguous), 161978/2621440 blocks
[root@localhost mnt]# resize2fs /dev/myvg/myroot 4G
resize2fs 1.42.9 (28-Dec-2013)
Resizing the filesystem on /dev/myvg/myroot to 1048576 (4k) blocks.
The filesystem on /dev/myvg/myroot is now 1048576 blocks long.

逻辑边界缩减成功了,我这里挂载看看。

[root@localhost mnt]# mount /dev/myvg/myroot vg
[root@localhost mnt]# df -Th
.....
/dev/mapper/myvg-myusr  ext4       20G   45M   19G   1% /mnt/vg2
/dev/mapper/myvg-myroot ext4      3.9G  341M  3.3G  10% /mnt/vg

df查看的是文件系统,怎么样4G了吧。不要非说是3.9啊。

[root@localhost mnt]# du -s vg
315388    vg
[root@localhost mnt]#

呃,怎么变大了。这个操作可真不好玩,查看了一下数据,还好没有变化。

物理边界

[root@localhost mnt]# lvreduce -L 4G /dev/myvg/myroot
  WARNING: Reducing active logical volume to 4.00 GiB
  THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce myroot? [y/n]: y
  Size of logical volume myvg/myroot changed from 10.00 GiB (2560 extents) to 4.00 GiB (1024 extents).
  Logical volume myroot successfully resized
[root@localhost mnt]# mount /dev/myvg/myroot vg
[root@localhost etc]# lvs
  LV     VG   Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  myroot myvg -wi-ao----  4.00g                                                    
  myusr  myvg -wi-ao---- 20.00g                                                    
[root@localhost etc]#

变成了4G了吧。

如果物理边界缩减过度,会导致文件系统不能挂载,再重新扩展点边界就可以了。


扩展逻辑卷:

扩展逻辑卷:
    # lvextend -L [+]#[mMgGtT] /dev/VG_NAME/LV_NAME
    # resize2fs /dev/VG_NAME/LV_NAME


与缩减正好相反,这个是前扩展物理边界,再扩展逻辑边界。可在线扩展。

[root@localhost mnt]# lvextend -L 15G /dev/myvg/myroot
  Size of logical volume myvg/myroot changed from 4.00 GiB (1024 extents) to 15.00 GiB (3840 extents).
  Logical volume myroot successfully resized
[root@localhost mnt]# resize2fs /dev/myvg/myroot
resize2fs 1.42.9 (28-Dec-2013)
Filesystem at /dev/myvg/myroot is mounted on /mnt/vg; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 2
The filesystem on /dev/myvg/myroot is now 3932160 blocks long.

查看现在的大小:

[root@localhost mnt]# df -Th
.....
/dev/mapper/myvg-myroot ext4       15G  348M   14G   3% /mnt/vg
[root@localhost mnt]# lvs
  LV     VG   Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  myroot myvg -wi-ao---- 15.00g                                                    
  myusr  myvg -wi-ao---- 20.00g

15G。扩展逻辑边界的时候不用指定大小,它会自动能扩多大扩多大。


5、快照

快照:snapshot
lvcreate -L #[mMgGtT] -p r -s -n snapshot_lv_name original_lv_name

-s 指定为快照卷
-L 大小
-p 权限 [r|rw]
-n 快照卷名称

最后是源卷路径名称,因为快照卷只能与目标卷在同一个VG。所以不过指定VG。


快照卷也是一种逻辑卷, 通常设置成只读的。不能去修改数据。

快照卷的存在是为了防止inconsistent非一致性:

同一个文件前面的数据还在复制,而后面的数据却已经随着用户的访问而在不断的发生着改变,这种错位的数据是损坏的,进程不能使用。 除了一些数据库应用自带备份数据的机制外, 这里我们就要用快照了。

快照卷从建立的那一刻起,会锁定源卷1秒钟左右,来生成源卷的状态,复制目标卷的元数据信息(inode),并建立与目标卷block的映射。而在以后的过程中,LVM会实时的监控目标卷上的元数据的变化,如果目标卷上的元数据要变化,就证明目标卷元数据所指向的数据要发生变化。LVM就在变化还没有发生之前,把数据复制到快照卷中,并更新快照卷中的元数据所指向的数据为已复制过来的数据。


刚创建完快照卷的时候。图中目标盘也有元数据,只不过没有画而已。

wKioL1Z_v83gQoveAACg5UeVMOE089.jpg

现在我们通过快照卷访问的数据都在目标卷上。 而当数据A快要发生变化了:

wKioL1Z_wF_j0kLtAAChCeDx4RU034.jpg


怎么样,明白了吗,如果B要发生变化,就在之前把B也复制到快照卷中,并更新元数据的指向。

如果改变的文件有很多,超过了快照卷所能存储的大小。快照卷就会自动失效、卸载。


这样数据变化则复制到快照卷,不变化则还用目标中的数据。就实现了我们通过快照卷访问的数据一直都是创建快照卷那一刻的数据。

而快照卷的大小,就要我们自己来估算了:

我们备份目标卷的数据要多长时间,目标卷的数据修改频率。实在不行就创建成与目标卷一样大也行(只要VG空间足),


知道了原理,操作就太简单了。

我们来为myroot创建一个快照卷试试。首先看一下VG的空间是否可以容纳我们想要创建的快照的大小。

[root@localhost mnt]# vgs
  VG   #PV #LV #SN Attr   VSize  VFree 
  myvg   3   2   0 wz--n- 59.99g 24.99g

myroot里面的数据大约在400M左右。而且我们这里也没有什么大的变化。50M其实就够了。

[root@localhost mnt]# lvcreate -L 50M -p r -s -n mysnap /dev/myvg/myroot
  Rounding up size to full physical extent 52.00 MiB
  Logical volume "mysnap" created.
[root@localhost mnt]# mkdir /mnt/snap
[root@localhost mnt]# mount /dev/myvg/mysnap /mnt/snap
mount: /dev/mapper/myvg-mysnap is write-protected, mounting read-only
[root@localhost mnt]#

因为我们所创建的快照卷是只读的,所以挂载的时候提示了一下。

快照卷不要格式化, 直接挂载到一个挂载点就可以。

看一下快照卷。

wKiom1Z_wv7CjnZxAACVQUhjzqQ819.jpg

与目标卷一模一样。向目标卷加一些东西试试。

wKiom1Z_w0iBEa-DAAESaZLX4Yw063.jpg

上面的是snap的目录,下面的是目标卷的。画红线的就是刚复制进去的。

快照卷工作正常,可以备份数据了。 完成以后卸载并删除快照卷即可。


wKioL1Z_xAnBij5HAACs8WDaRPI125.jpg


至此,终于完成啦。



谢谢浏览。如果发现问题,还请指出。j_0077.gif