让Windows的KVM虚拟机能识别宿主机Linux上未进行分区的硬盘
让Windows的KVM虚拟机能识别宿主机Linux上未进行分区的硬盘
Joshua今天学习Linux的储存相关知识的时候,意外翻到了个很有意思的求助问题:求助者其有个30TB大的未分区的硬盘,本来是给Linux用的。这时他想让在这个Linux系统上的KVM虚拟机的Windows也能识别这个盘,但却不知道如何操作。
不过作者自己倒是折腾出来了,还写了个博客。巧了!这种问题我也不会,然而这种问题,又是在各种奇怪需求中可能会邂逅的问题,遇到了吧,还不好立马找到资料,于是翻译了下原文,给自己留个底。
原文:Heinous uses for Device Mapper (jiphex.github.io)
正文:
最近我遇到一个奇怪的情况,然而这个情况却让我领会到了Linux Device Mapper
有趣性。虽然这可能永远不会用于生产环境,但是新奇的展示了Linux在块设备上到底是有多灵活。
总结一下在ServerFault(译者注:这个linux - Can Windows read an unpartitioned NTFS volume? (Single large partition) - Server Fault)的贴文,问题是这样的:
-
你有一个十分大的
Linux logical voloume
,但是它没有分区,只是直接放置了一个文件系统。 -
你要想把这个块设备作为一个磁盘给在同一机器上运行的应用,然而这个应用因为某些原因并不能解析没有分区过的卷(比如,Windows KVM 虚拟机)
-
并且,你已经用这个
Linux logical voloume
存了不少数据了,你可不想再从头拷贝了。
在理想情况下,Windows
应该能够识别卷的大小,当然这个卷里面是有文件系统的(译者注:ext4 or ntfs那些),并且能够像一个普通的硬盘一样来读取,但是现实却不是这样的。
你有一个十分大的Linux logical voloume
,但是它没有分区,只是直接放置了一个文件系统。
你要想把这个块设备作为一个磁盘给在同一机器上运行的应用,然而这个应用因为某些原因并不能解析没有分区过的卷(比如,Windows KVM 虚拟机)
并且,你已经用这个Linux logical voloume
存了不少数据了,你可不想再从头拷贝了。 所以呢显然的解决方案是:希望提供一个分区表(译者注:比较老的规范是mbr,较新是gpt)来解决这个问题
然而不幸的是,块设备自己有内在的顺序,并且我们如今常用的两个分区表格式(译者注:就指mbr和gpt)需要一个存在卷开头位置的分区表头(用来描述磁盘上分区布局的几KB信息)(译者注:我们知道卷这种存储设备内部都是一个个储存块,数据是按照一定顺序放进储存块中的,前面的储存块一旦被使用记录了数据,就没法再使用了。我们在给卷做文件系统的时候,文件系统一般都会在当前卷的头部写入文件系统需要的头部信息,因此我们现在想把分区头也写在开头,会发现已经被文件系统的头占用了)
在Linux中,仅仅在LVM卷的开头添加空间是不可能的,你可以通过在卷的末尾添加空间来扩展卷,但这并不是特别有用。你可以从末尾开始遍历设备,将所有数据向后移动N个扇区,以便在开始时腾出空间。但这对于大量数据来说,实际上是不可行的。
幸运的是,Linux为我们提供了 Device Mapper, 这是一个被LVM本身、kpartx和Linux多路径驱动程序等软件所使用的框架。我们可以操纵Device Mapper
来达到我们的目的,神奇地来创建虚拟块设备。
在这样的情况下,我们的需求可太微不足道了:
-
我们需要在卷的开头有一些空间来储存分区表
-
在同一卷上,我们需要显示我们试图访问的实际数据
实际上要实现上面的需求,在实践上来说也不算太难(假设 /dev/vgstuff/data
就是包含了我们数据的逻辑卷)
[root@server]# dd if=/dev/zero of=/root/gpt.bin bs=68K count=1 |
(译者注:我来注释一波这些命令)
# dd命令:用来从指定文件中读取内容复制到指定文件中。那么下面这行就是从/dev/zero |
这将在/dev/mapper/compositedevice中创建一个复合块设备(名称可以是你想要的任何名称,而不仅仅是’ compositedevice '),其中应该包含前68K的空白文件,然后是逻辑卷。
只要底层卷是可读可写的,文件就应该是可读可写的。您可以使用dmsetup remove
删除它,并使用dmsetup info
或dmsetup status
查看详细信息。错误可用dmesg
查看。
你现在所需要做的就是在文件开始的区域内创建一个分区表,我使用testdisk
完成了这一点,它能够通过卷本身搜索文件系统头部,并创建一个与磁盘上的实际数据匹配的分区表。写完这个,导出/dev/mapper设备,就完成了!
其实也可以不使用测试盘,而是执行以下操作:
-
创建一个与目标卷大小相同(或略大)的稀疏文件。
-
使用
parted
创建一个分区标签,并添加一个分区,该分区的开始和结束位置与最终卷所在的位置相同(包括由GPT表引起的偏移)。 -
导出这个分区表(在parted中备份或计算出它的大小并使用dd),并将其直接写入gpt.bin文件。
在我的例子中,由于所讨论的卷的大小(译者注:高达30TB),我不得不使用GPT分区表,但是使用MBR分区表就更容易了。MBR不是创建任意大的分区表文件(在上面的例子中是68K),而是总是512字节长,所以您可以利用这一点(只要您的卷本身<4TB)。