<?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>Raid on inetshell</title><link>https://inet.sh/en/tags/raid/</link><description>Recent content in Raid on inetshell</description><generator>Hugo</generator><language>en</language><lastBuildDate>Fri, 25 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://inet.sh/en/tags/raid/index.xml" rel="self" type="application/rss+xml"/><item><title>mdadm: add a disk and grow a RAID 5 (reshape) without losing data</title><link>https://inet.sh/en/posts/linux/mdadm-add-disk-grow-raid5/</link><pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/en/posts/linux/mdadm-add-disk-grow-raid5/</guid><description>Expand an mdadm RAID 5 with one more disk: mdadm --add, mdadm --grow --raid-devices with --backup-file on another disk, watch the reshape in /proc/mdstat, speed it up with speed_limit_min, then grow the filesystem with resize2fs or xfs_growfs. With what to check first and what cannot be undone.</description><content:encoded><![CDATA[<h2 id="tldr">TL;DR</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><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">mdadm --add /dev/md0 /dev/sdd
</span></span><span class="line"><span class="cl">mdadm --grow /dev/md0 --raid-devices<span class="o">=</span><span class="m">4</span> --backup-file<span class="o">=</span>/root/md0-grow.bak   <span class="c1"># on ANOTHER disk, never the array</span>
</span></span><span class="line"><span class="cl">cat /proc/mdstat                            <span class="c1"># reshape = [====&gt;....] 23.4% ... finish=310min</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># once it finishes:</span>
</span></span><span class="line"><span class="cl">resize2fs /dev/md0                          <span class="c1"># ext4, online</span>
</span></span><span class="line"><span class="cl">xfs_growfs /mnt/vol1                        <span class="c1"># xfs, mounted</span>
</span></span><span class="line"><span class="cl">rm /root/md0-grow.bak
</span></span></code></pre></td></tr></table>
</div>
</div><p>From 3 disks to 4 in a RAID 5: usable capacity goes from 2 to 3 disks&rsquo; worth. The reshape rewrites every stripe and takes <strong>hours or days</strong> depending on size; the array stays in service meanwhile.</p>
<h2 id="before-touching-anything">Before touching anything</h2>
<ol>
<li>
<p><strong>Backup.</strong> The reshape is md&rsquo;s most delicate operation: it rewrites all the data with the array in production. If something is going to break, it is here.</p>
</li>
<li>
<p><strong>Healthy array.</strong> <code>mdadm --detail /dev/md0</code> must say <code>State : clean</code> with no <code>degraded</code>, <code>recovering</code>, or <code>resyncing</code>. Never <code>--grow</code> a degraded array.</p>
</li>
<li>
<p><strong>Healthy disks.</strong> <code>smartctl -H /dev/sdX</code> on every member. A disk dying halfway through a RAID 5 reshape is total loss.</p>
</li>
<li>
<p><strong>New disk the same size or bigger.</strong> If the array uses partitions instead of whole disks, copy the table from an existing disk to the new one:</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">sfdisk -d /dev/sda <span class="p">|</span> sfdisk /dev/sdd            <span class="c1"># MBR</span>
</span></span><span class="line"><span class="cl">sgdisk -R /dev/sdd /dev/sda <span class="o">&amp;&amp;</span> sgdisk -G /dev/sdd   <span class="c1"># GPT (-G regenerates the GUIDs)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>and add <code>/dev/sdd1</code> instead of <code>/dev/sdd</code>.</p>
</li>
</ol>
<h2 id="step-by-step">Step by step</h2>
<p><strong>1. Add the disk.</strong> It comes in as a <em>spare</em>:</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">mdadm --add /dev/md0 /dev/sdd
</span></span><span class="line"><span class="cl">mdadm --detail /dev/md0 <span class="p">|</span> tail -6       <span class="c1"># ... 3 8 48 - spare /dev/sdd</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>2. Grow the array.</strong> This is what starts the reshape:</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></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">mdadm --grow /dev/md0 --raid-devices<span class="o">=</span><span class="m">4</span> --backup-file<span class="o">=</span>/root/md0-grow.bak
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>--backup-file</code> keeps a copy of the stripes being rewritten during the critical section of the reshape. It must live on a disk <strong>that is not part of the array</strong> and not on <code>tmpfs</code>. On arrays with 1.2 metadata and free space before the data area mdadm sometimes reports it does not need it; providing it does no harm.</p>
<p><strong>3. Watch.</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></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">watch -n <span class="m">30</span> cat /proc/mdstat
</span></span></code></pre></td></tr></table>
</div>
</div><p>By default md throttles itself so it does not kill performance (<code>speed_limit_min</code> = 1000 KB/s under load). If the array is not serving anyone, raise it:</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">sysctl -w dev.raid.speed_limit_min<span class="o">=</span><span class="m">200000</span>
</span></span><span class="line"><span class="cl">sysctl -w dev.raid.speed_limit_max<span class="o">=</span><span class="m">500000</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>4. Grow the filesystem.</strong> Once <code>/proc/mdstat</code> no longer shows <code>reshape</code>, <code>mdadm --detail</code> reports <code>Raid Devices : 4</code> and a bigger <code>Array Size</code>. The filesystem still occupies the old size:</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">resize2fs /dev/md0            <span class="c1"># ext2/3/4, works mounted</span>
</span></span><span class="line"><span class="cl">xfs_growfs /mnt/vol1          <span class="c1"># xfs, takes the mount point, mounted</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>5. Clean up.</strong> Delete the backup file. <code>/etc/mdadm/mdadm.conf</code> does not change: the <code>ARRAY</code> line identifies the array by UUID, not by disk count. If <code>/</code> lives on the array, regenerate the initramfs to be safe (<code>update-initramfs -u</code> on Debian/Ubuntu, <code>dracut -f</code> on RHEL/Fedora).</p>
<h2 id="traps">Traps</h2>
<ul>
<li><strong>It cannot be undone.</strong> Once the reshape starts it only finishes forward. You can reboot the machine (it resumes on assembly) but not cancel it.</li>
<li><strong>Power loss halfway.</strong> If the array does not assemble at boot, <code>mdadm --assemble /dev/md0 --backup-file=/root/md0-grow.bak /dev/sd[abcd]</code>; that is where the backup file earns its name.</li>
<li><strong>Bitmap.</strong> If mdadm refuses because of the <em>write-intent bitmap</em>, remove it first and put it back when done: <code>mdadm --grow --bitmap=none /dev/md0</code> … <code>mdadm --grow --bitmap=internal /dev/md0</code>.</li>
<li><strong>Changing the chunk</strong> (<code>mdadm --grow --chunk=128 /dev/md0</code>) is also a full reshape, same rules.</li>
<li><strong>Big disks in RAID 5</strong> are a gamble: with 4 × 8 TB disks, the rebuild after a failure runs for days with no redundancy. The same <code>--grow</code> can move you to RAID 6: <code>mdadm --grow /dev/md0 --level=6 --raid-devices=5 --backup-file=…</code>.</li>
<li><strong>Whole disks vs partitions.</strong> Mixing <code>/dev/sdd</code> with <code>/dev/sda1</code> works but confuses later; follow whatever pattern the array already has.</li>
</ul>
<p>References: <a href="https://raid.wiki.kernel.org/index.php/Growing">Growing</a> on the Linux RAID Wiki and <code>man 8 mdadm</code> (<em>GROW MODE</em> section).</p>
]]></content:encoded></item></channel></rss>