<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Qcow2 on inetshell</title><link>https://inet.sh/en/tags/qcow2/</link><description>Recent content in Qcow2 on inetshell</description><generator>Hugo</generator><language>en</language><lastBuildDate>Sat, 26 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://inet.sh/en/tags/qcow2/index.xml" rel="self" type="application/rss+xml"/><item><title>Mount a qcow2 disk on the host with qemu-nbd (read or repair files of a powered-off VM)</title><link>https://inet.sh/en/posts/linux/mount-qcow2-qemu-nbd/</link><pubDate>Sat, 26 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/en/posts/linux/mount-qcow2-qemu-nbd/</guid><description>A qcow2 cannot be loop-mounted: qemu-nbd exposes it as a block device (/dev/nbd0) and the partitions come out of that. How to do it read-only or read-write, what happens when the VM disk carries LVM (duplicate VG names, vgimportclone), how to mount an internal snapshot, guestmount as the nbd-free alternative, and why never with the VM running.</description><content:encoded><![CDATA[<h2 id="tldr">TL;DR</h2>
<p>With the VM <strong>powered off</strong>:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">modprobe nbd <span class="nv">max_part</span><span class="o">=</span><span class="m">16</span>
</span></span><span class="line"><span class="cl">qemu-nbd --connect<span class="o">=</span>/dev/nbd0 /var/lib/vz/images/100/vm-100-disk-0.qcow2   <span class="c1"># add -r for read-only</span>
</span></span><span class="line"><span class="cl">partprobe /dev/nbd0
</span></span><span class="line"><span class="cl">lsblk /dev/nbd0                                  <span class="c1"># nbd0p1, nbd0p2…</span>
</span></span><span class="line"><span class="cl">mount /dev/nbd0p2 /mnt/vm
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ... read, copy, or repair ...</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">umount /mnt/vm
</span></span><span class="line"><span class="cl">qemu-nbd --disconnect /dev/nbd0
</span></span></code></pre></td></tr></table>
</div>
</div><p>Without the <code>--disconnect</code> the VM will not start again: QEMU finds the image locked.</p>
<h2 id="why-nbd">Why nbd</h2>
<p>A <code>.qcow2</code> is not a dump of the disk: it has a header, a cluster table, internal snapshots, and sometimes a backing file behind it. <code>losetup</code> does not understand it. <code>qemu-nbd</code> does, and publishes it as a block device through the kernel&rsquo;s NBD client; from there on it is one more disk for <code>lsblk</code>, <code>mount</code>, <code>fsck</code>, or <code>dd</code>.</p>
<p><code>max_part</code> matters: without it the kernel does not create the <code>nbd0p1</code>, <code>nbd0p2</code>… nodes. <code>partprobe</code> forces them if they do not show up after <code>--connect</code>.</p>
<h2 id="if-the-vm-disk-carries-lvm">If the VM disk carries LVM</h2>
<p>The norm on Ubuntu Server, RHEL, and Fedora: inside the partition there is a VG. Activate it, mount the LV, and when done deactivate it before disconnecting:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">vgscan
</span></span><span class="line"><span class="cl">vgchange -ay                                   <span class="c1"># activates whatever it finds on nbd0</span>
</span></span><span class="line"><span class="cl">lvs                                            <span class="c1"># ubuntu-vg/ubuntu-lv, rhel/root…</span>
</span></span><span class="line"><span class="cl">mount /dev/ubuntu-vg/ubuntu-lv /mnt/vm
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">umount /mnt/vm
</span></span><span class="line"><span class="cl">vgchange -an ubuntu-vg
</span></span><span class="line"><span class="cl">qemu-nbd --disconnect /dev/nbd0
</span></span></code></pre></td></tr></table>
</div>
</div><p>Classic trap: the host has a VG with the <strong>same name</strong> as the VM&rsquo;s (<code>ubuntu-vg</code> vs <code>ubuntu-vg</code>, <code>pve</code> vs <code>pve</code>). LVM refuses to activate two alike. The tool for that is <code>vgimportclone</code>, which renames the VG on the imported disk without touching the host&rsquo;s:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">vgimportclone -n vm100-vg /dev/nbd0p3
</span></span><span class="line"><span class="cl">vgchange -ay vm100-vg
</span></span></code></pre></td></tr></table>
</div>
</div><p>If you would rather change nothing inside the VM, <code>guestmount</code> (below) resolves the LVM on its own and does not touch the host&rsquo;s LVM.</p>
<h2 id="windows-ntfs-and-internal-snapshots">Windows, NTFS, and internal snapshots</h2>
<ul>
<li><strong>NTFS</strong>: <code>mount -t ntfs3 /dev/nbd0p3 /mnt/vm</code> (kernel 5.15+) or <code>ntfs-3g</code>. If Windows was left hibernated or with <em>Fast Startup</em>, NTFS only mounts read-only; shut it down properly from inside before writing.</li>
<li><strong>qcow2 internal snapshot</strong> (<code>qemu-img snapshot -l vm.qcow2</code>): <code>qemu-nbd -r -l before-the-change --connect=/dev/nbd0 vm.qcow2</code> mounts the state of that snapshot, read-only, without touching the current disk.</li>
<li><strong>Other formats</strong>: <code>qemu-nbd</code> also speaks vmdk, vhdx, and vdi (<code>-f vhdx</code> if it does not detect it); <code>qemu-img convert -O raw</code> is the alternative if you are going to work on the image for a long time.</li>
</ul>
<h2 id="guestmount-the-same-without-nbd-or-root">guestmount: the same without nbd or root</h2>
<p>libguestfs mounts the image over FUSE, detects partitions and LVM on its own, and does not interfere with the host:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">apt install libguestfs-tools          <span class="c1"># dnf install guestfs-tools on Fedora/RHEL</span>
</span></span><span class="line"><span class="cl">virt-filesystems --long -h --all -a vm.qcow2      <span class="c1"># what is inside</span>
</span></span><span class="line"><span class="cl">guestmount -a vm.qcow2 -i --ro /mnt/vm            <span class="c1"># -i: mount the operating system it finds</span>
</span></span><span class="line"><span class="cl">guestunmount /mnt/vm
</span></span></code></pre></td></tr></table>
</div>
</div><p>Slower than nbd for copying gigabytes, but impossible to leave half closed.</p>
<h2 id="traps">Traps</h2>
<ul>
<li><strong>Never with the VM running.</strong> Read-write you will corrupt the filesystem for sure; with <code>-r</code> you see an inconsistent state (what the guest holds in cache is not on disk). If you need to look at a live VM, take a snapshot and mount the snapshot.</li>
<li><strong>The image stays locked</strong> while <code>qemu-nbd</code> is connected: <code>qm start 100</code> fails with <code>Failed to get &quot;write&quot; lock</code>. <code>qemu-nbd -d /dev/nbd0</code> releases it; <code>ls /sys/block/nbd*/pid</code> tells which ones are still in use.</li>
<li><strong><code>--disconnect</code> with &ldquo;device busy&rdquo;</strong>: something is still mounted or a VG is active (<code>vgchange -an</code>). <code>lsof /dev/nbd0*</code> finds it.</li>
<li><strong>Proxmox with LVM-thin or ZFS</strong> needs no nbd: the VM disk is already a block device (<code>/dev/pve/vm-100-disk-0</code>, <code>/dev/zvol/rpool/data/vm-100-disk-0</code>); <code>kpartx -av</code> on it exposes the partitions. <code>qemu-nbd</code> is for qcow2 on directory and NFS storages.</li>
<li><strong>Backing files</strong>: an image with a <code>backing file</code> mounts the same; whatever you write goes to the top layer. Do not move the base while it is connected.</li>
</ul>
<p>See also: <a href="/en/posts/windows/disk2vhd-p2v-vhdx-live-machine/">convert a physical machine to VHDX</a> and <a href="/en/posts/proxmox/cloud-image-templates/">disk import on Proxmox</a>. Reference: <a href="https://www.qemu.org/docs/master/tools/qemu-nbd.html">qemu-nbd</a> in the QEMU documentation.</p>
]]></content:encoded></item></channel></rss>