Windows is expecting an entire disk, with partition table, as you state. Linux can deal with a block device without a partition table.
Theoretically a hypervisor could synthesize a fake partition table to do that for you, but I don’t know of any with that feature.
Couple of ways:
- Create a partition table inside the LV, then pass through the LV to the Windows VM. Windows will see it normally, but the host will need to use the partition table inside the LV. Works fine with a tool like
kpartx
to handle that for you.
Downside: The LV you already have doesn’t have free space at the start for the partition table, so you’ll need to backup the data, create a partition table inside the LV, re-create the filesystem and restore all the data.
This will probably be the easiest way if you don’t mind restoring all the data, or don’t have any data to begin with.
edit: I initially interpreted your question as having two partitions, but when you say LVM partitions I guess you mean LVs. I’ve edited the above to correct.
- Use device-mapper to create a “fake” disk with a partition table from the data partition.
Pro: Don’t need to recreate your NTFS filesystem, use it as-is.
Con: Lots of commands
Here’s the commands!
This is the partition you want to pass through to the VM:
ntfs_partition=/dev/sdx1
Calculate the size of the partition and the GPT
part_size=$(blockdev --getsize64 ${ntfs_partition})
part_size_sectors=$[part_size / 512]
gpt_size=$[1024*1024]
gpt_size_sectors=$[gpt_size / 512]
Create files for the GPT and a temporary data partition.
It needs to be GPT because you have >=2TB of data. With <2TB of data you can use a single sector for a single MBR partition.
We create a temporary data partition so that we’re not writing to the real partition when we create the partition table.
The files will be created sparse, so a 4TB file doesn’t use any space unless you actually write to it.
truncate --size=${gpt_size} ntfs.gpt.primary.img
truncate --size=${part_size} temp.img
truncate --size=${gpt_size} ntfs.gpt.secondary.img
Setup loopback devices for these (device-mapper needs block devices)
losetup /dev/loop0 ntfs.gpt.primary.img
losetup /dev/loop1 temp.img
losetup /dev/loop2 ntfs.gpt.secondary.img
Create a device-mapper table to describe the device.
This uses the linear
target to concatenate the three block devices.
read -r -d '' table <<EOF
0 ${gpt_size_sectors} linear /dev/loop0 0
${gpt_size_sectors} ${part_size_sectors} linear /dev/loop1 0
$[gpt_size_sectors + part_size_sectors] ${gpt_size_sectors} linear /dev/loop2 0
EOF
Create the device-mapper device
echo "$table" | dmsetup create ntfs.with-gpt
Create the partition table
sgdisk \
--new=1:${gpt_size_sectors}:+${part_size_sectors} \
--typecode=1:0700 \
/dev/mapper/ntfs.with-gpt
Check the partition tables looks good
sgdisk -p /dev/mapper/ntfs.with-gpt
Disk /dev/mapper/ntfs.with-gpt: 8589938688 sectors, 4.0 TiB
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): C4741A85-8972-451E-871A-BA2181D78ADF
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 8589938654
Partitions will be aligned on 2048-sector boundaries
Total free space is 4029 sectors (2.0 MiB)
Number Start (sector) End (sector) Size Code Name
1 2048 8589936639 4.0 TiB 0700
We’ve finished writing.
Remove the temporary NTFS partition used to create the partition table.
dmsetup remove /dev/mapper/ntfs.with-gpt
losetup -d /dev/loop1
losetup /dev/loop1 ntfs.img
Create a new device mapper table using the real NTFS partition
read -r -d '' table <<EOF
0 ${gpt_size_sectors} linear /dev/loop0 0
${gpt_size_sectors} ${part_size_sectors} linear ${ntfs_partition} 0
$[gpt_size_sectors + part_size_sectors] ${gpt_size_sectors} linear /dev/loop2 0
EOF
echo "$table" | dmsetup create ntfs.with-gpt
Now you have a /dev/mapper/ntfs.with-gpt
block device which you can pass to a VM which has the correct partition table.