<?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>Ext4 on inetshell</title><link>https://inet.sh/en/tags/ext4/</link><description>Recent content in Ext4 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/ext4/index.xml" rel="self" type="application/rss+xml"/><item><title>Grow a Linux VM disk online: rescan, growpart, pvresize, lvextend and xfs_growfs</title><link>https://inet.sh/en/posts/linux/grow-linux-vm-disk-online/</link><pubDate>Sat, 26 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/en/posts/linux/grow-linux-vm-disk-online/</guid><description>You already enlarged the virtual disk on Proxmox, VMware or the cloud and inside the VM nothing changed. The four steps with no reboot: make the kernel see the new size (virtio-blk on its own; SCSI with a rescan), growpart for the partition, pvresize + lvextend -r if there is LVM, and resize2fs or xfs_growfs. With the usual errors: NOCHANGE, locale, partition that is not the last one.</description><content:encoded><![CDATA[<h2 id="tldr">TL;DR</h2>
<p>With the disk already enlarged on the hypervisor side (<code>qm resize 100 scsi0 +50G</code> on Proxmox, <em>Edit disk</em> on VMware, your cloud console):</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><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</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"><span class="c1"># 1. Make the kernel see the new size (virtio-scsi/SATA; virtio-blk detects it alone)</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="m">1</span> &gt; /sys/class/block/sda/device/rescan
</span></span><span class="line"><span class="cl">lsblk /dev/sda
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 2. Enlarge the partition (package cloud-guest-utils on Debian/Ubuntu, cloud-utils-growpart on RHEL)</span>
</span></span><span class="line"><span class="cl">growpart /dev/sda <span class="m">3</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 3a. With LVM: PV, LV and filesystem</span>
</span></span><span class="line"><span class="cl">pvresize /dev/sda3
</span></span><span class="line"><span class="cl">lvextend -r -l +100%FREE /dev/ubuntu-vg/ubuntu-lv      <span class="c1"># -r: resize2fs or xfs_growfs depending on the fs</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 3b. Without LVM</span>
</span></span><span class="line"><span class="cl">resize2fs /dev/sda3        <span class="c1"># ext4</span>
</span></span><span class="line"><span class="cl">xfs_growfs /               <span class="c1"># xfs: takes the mount point</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>No reboot. <code>df -h /</code> confirms.</p>
<h2 id="before-starting">Before starting</h2>
<ul>
<li><strong>Snapshot or backup on the hypervisor.</strong> Growing is safe; picking the wrong partition is not.</li>
<li><strong>Look at the layout</strong>: <code>lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS</code>. It shows the partition number, whether LVM sits underneath, and which filesystem you are dealing with.</li>
<li><strong>Names</strong>: virtio-blk is <code>/dev/vda</code>; virtio-scsi and SATA, <code>/dev/sda</code>; NVMe, <code>/dev/nvme0n1</code> with partitions <code>p1</code>, <code>p2</code>… (<code>growpart /dev/nvme0n1 1</code>).</li>
<li><strong>Sometimes the space is already there</strong>: Ubuntu Server creates the LV using only part of the VG. If <code>vgs</code> shows a large <code>VFree</code>, jump straight to <code>lvextend</code>.</li>
</ul>
<h2 id="1-make-the-kernel-see-the-new-disk">1. Make the kernel see the new disk</h2>
<table>
  <thead>
      <tr>
          <th>Bus</th>
          <th>What to do</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>virtio-blk (<code>vda</code>)</td>
          <td>Nothing: <code>dmesg | tail</code> shows <code>[vda] new size: …</code></td>
      </tr>
      <tr>
          <td>virtio-scsi, SATA, IDE (<code>sda</code>)</td>
          <td><code>echo 1 &gt; /sys/class/block/sda/device/rescan</code></td>
      </tr>
      <tr>
          <td>New disk (not grown)</td>
          <td><code>echo &quot;- - -&quot; &gt; /sys/class/scsi_host/host0/scan</code></td>
      </tr>
      <tr>
          <td>NVMe in the cloud</td>
          <td>Usually shows up on its own within a minute; if not, <code>echo 1 &gt; /sys/class/nvme/nvme0/rescan_controller</code></td>
      </tr>
  </tbody>
</table>
<p><code>lsblk</code> must show the new size on the disk before moving on; otherwise <code>growpart</code> will say <code>NOCHANGE</code>.</p>
<h2 id="2-growpart">2. growpart</h2>
<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">growpart /dev/sda <span class="m">3</span>
</span></span><span class="line"><span class="cl"><span class="c1"># CHANGED: partition=3 start=4198400 old: size=… end=… new: size=… end=…</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>growpart</code> stretches the partition to the end of the disk, moves the GPT backup header, and tells the kernel about the new table even with the partition mounted (it uses <code>partx --update</code>). It only works on the <strong>last</strong> partition; if a swap partition sits behind the root, remove it first (<code>swapoff</code>, delete it with <code>fdisk</code>, recreate it at the end).</p>
<p>Without <code>growpart</code>: <code>parted /dev/sda resizepart 3 100%</code> does the same with a confirmation prompt.</p>
<h2 id="3a-lvm">3a. LVM</h2>
<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">pvresize /dev/sda3                                  <span class="c1"># the PV fills the now-larger partition</span>
</span></span><span class="line"><span class="cl">vgs                                                 <span class="c1"># VFree &gt; 0</span>
</span></span><span class="line"><span class="cl">lvextend -r -l +100%FREE /dev/ubuntu-vg/ubuntu-lv   <span class="c1"># all the space</span>
</span></span><span class="line"><span class="cl">lvextend -r -L +20G /dev/ubuntu-vg/ubuntu-lv        <span class="c1"># or only part of it</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>-r</code> calls <code>resize2fs</code> or <code>xfs_growfs</code> depending on what lives in the LV. Without <code>-r</code>, do it yourself: <code>resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv</code> or <code>xfs_growfs /</code>.</p>
<h2 id="3b-without-lvm">3b. Without LVM</h2>
<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></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">resize2fs /dev/sda3                 <span class="c1"># ext4: online</span>
</span></span><span class="line"><span class="cl">xfs_growfs /                        <span class="c1"># xfs: online, on the mount point</span>
</span></span><span class="line"><span class="cl">btrfs filesystem resize max /       <span class="c1"># btrfs</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="raspberry-pi-and-sd-cards">Raspberry Pi and SD cards</h2>
<p>Same script with other names (Fedora ARM image with LVM):</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">growpart /dev/mmcblk0 <span class="m">3</span>
</span></span><span class="line"><span class="cl">pvresize /dev/mmcblk0p3
</span></span><span class="line"><span class="cl">lvextend -l +100%FREE /dev/fedora/root
</span></span><span class="line"><span class="cl">xfs_growfs -d /
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="traps">Traps</h2>
<ul>
<li><strong><code>growpart: NOCHANGE</code></strong>: the kernel has not seen the new size yet. Back to step 1.</li>
<li><strong><code>growpart</code> fails in a non-English locale</strong> (it parses <code>sfdisk</code> output): <code>LC_ALL=C growpart /dev/sda 3</code>.</li>
<li><strong><code>GPT PMBR size mismatch</code></strong> in <code>fdisk -l</code> after growing the disk: the GPT backup header stayed where the old disk ended. <code>growpart</code> moves it; if you did it by hand, <code>sgdisk -e /dev/sda</code>.</li>
<li><strong>The partition is not the last one.</strong> Swap or <code>/home</code> behind the root: either move those, or add a new disk and join it to the VG (<code>pvcreate /dev/sdb &amp;&amp; vgextend ubuntu-vg /dev/sdb</code>), which in LVM is faster than reordering partitions.</li>
<li><strong>Shrinking is another story</strong>: ext4 only unmounted; XFS never. Think about it before handing out 2 TB &ldquo;just in case&rdquo;.</li>
<li><strong>Windows</strong> grows from <em>Disk Management → Extend Volume</em>; none of this applies.</li>
</ul>
<h2 id="see-also">See also</h2>
<ul>
<li><a href="/en/posts/proxmox/cloud-image-templates/">cloud-init templates on Proxmox</a>: the host-side <code>qm resize</code> lives there.</li>
<li><a href="/en/posts/linux/lvm-activate-volume-group-after-power-failure/">LVM: the volume group will not activate</a>, in case step 3 gets weird.</li>
<li><a href="/en/posts/k3s/migrate-data/">Move k3s data to another disk</a>, the alternative when what fills up is one specific service.</li>
</ul>
]]></content:encoded></item></channel></rss>