我对LVM快照的理解是:如果源在块上发生更改,则块将首先复制(在更改之前)到快照。 然后该块就像通常那样在原点上被改变。
从理论上说,当一个快照首次创build时,它不应该包含任何内容。 然后当原点发生变化时,这些块将开始填充快照。
但是,如果出于testing目的,我创build一个小的1G LV,我把一些文件放在上面; 然后我创build一个200MB的快照。 正如预期的那样,lvs显示了200M的LSize和snap的1G。 但是,当我安装快照卷,df显示它的大小为1G。 当我检查它的内容时,我发现它包含原始卷中的所有内容,即使原始文件没有被更改。
为什么是这样? 我假设“安装”命令有一些逻辑来做一个比较之间的原始LV和快照LV? 有人可以解释这是如何工作的。 如果我查看每个卷上的文件的inode编号(原点和捕捉),它们是不同的(因为每个文件系统都是自己独特的文件系统),但是我假设有一些“指针”用来引用原点上未改变的块。
沿着这一脉络,我假设如果我将快照逻辑卷本身复制到另一个位置,我将得到原始文件的一个子集 – 只有那些已经改变的文件。 …但是,如果我第一次挂载快照文件系统,然后做一个文件系统级副本(cp),我会得到原始的一切,就像创build快照时一样。 对?
LVM快照通过在快照卷中保存已更改块的列表及其内容,同时传递所有请求以将未更改的数据读取到底层块设备。 所有这些智能都内置在LVM中,在内核中, mount
并不知道它。 就用户空间而言,有两个块设备可用,两个都是相同的大小(在你的例子中是1G)。 事实上,一个LVM原始卷,另一个是快照,除了dm(设备映射器)系统中必须处理的那些位之外,其他任何人都不关心这个事实。
快照的大小为200MB,这是快照在存储接口和溢出数据块之前可以存储的已更改数据量。
如果您复制快照卷,无论是作为块设备还是通过复制快照卷中的文件,无论采用哪种方式,都可以获得完整的内容。
所有这一切都伴随着一个警告:你可以进入shapshot LV中的元数据,做一些“时髦”的事情,比如高效的设备级rsync。 我提到这一点是因为我写了lvmsync来完成这个工作,听起来好像你可能会在这种function之后,从你的问题的口气。
快照是LVM子系统的一部分,数据块是文件系统下的抽象层。
快照是原始卷的完整副本,因此在安装时也将具有相同的大小。 两者都是1 GB。
除了快照做一些欺骗的事实,所以你实际上不必完全复制整个1 GB。 事实上,在拍摄快照的时候没有任何东西被复制 ,这就是为什么它非常快,为什么它最初几乎没有任何空间。
相反,快照仅在原始数据被修改时才开始复制数据( 写入时复制 )。 但是只有“即将被修改”的原始数据(块)才被复制,而没有其他的东西。 快照的200 MB空间是您为这些副本保留的空间量。 换句话说,您可以在快照中跟踪200 MB的修改值。
诀窍是快照是作为指向原始数据块的指针集合而开始的。 原始卷中的每一个改变都会触发原始数据块到COW表的一个副本(缓慢填充你为此设置的200 MB)并相应地更新指针。 当读取快照时,遵循这些指针,通过跟随其中的指针返回来自其原始卷的未修改的数据,或者在COW表中跟随指针到复制的块。