LinuxXIII · Disks and Block DevicesRescan and resize
Rescanning and growing block devices - when the kernel still sees the old size
What you'll learn
- Name every layer between an array LUN and a mounted filesystem, and which command refreshes each
- Rescan a SCSI device or host bus without disturbing running I/O
- Choose between partprobe, partx -u and blockdev --rereadpt for re-reading a partition table
- Move a GPT backup header after a disk grows
- Recognise the resize operations that are irreversible and the dry runs that precede them
Prerequisites
Verified against Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL 9.x · Rocky Linux 9.x · AlmaLinux 9.x · Linux kernel 6.1 LTS / 6.6 LTS · systemd 255+ · OpenSSH 8.7p1 (RHEL 9) / 9.6p1 (Ubuntu 24.04) · nftables 1.0.x · chrony 4.x · Pacemaker 2.1.x · Corosync 3.1.x · 2026-08-11
The storage team grew the LUN from 2 TB to 4 TB an hour ago and
sent you the ticket. lsblk still says 2 TB. Nothing is broken
and nothing needs a reboot - the kernel simply caches a device’s
capacity and its partition table, and neither is re-read
spontaneously.
The work is a chain of layers, each of which has to be told separately, and each of which will happily report success while the layer above it is still stale.
The chain
| Layer | Refreshed by | Read back with |
|---|---|---|
| SCSI device capacity | echo 1 > /sys/block/sdb/device/rescan | blockdev --getsize64 /dev/sdb |
| Multipath map | sudo multipathd resize map mpatha | multipath -ll |
| Partition table | sudo partx -u /dev/sdb | lsblk /dev/sdb |
| Partition size | sudo growpart /dev/sdb 1 | lsblk /dev/sdb1 |
| LVM physical volume | sudo pvresize /dev/sdb1 | sudo pvs -o pv_name,pv_size,pv_free |
| Logical volume | sudo lvextend -L +1T vg0/data | sudo lvs |
| Filesystem | sudo xfs_growfs /srv/data or resize2fs | df -h /srv/data |
Every step is additive and none of them destroys data - with two exceptions marked below, which is why the exceptions get the attention.
Step 1: make the kernel re-read the capacity
$ blockdev --getsize64 /dev/sdb; cat /sys/block/sdb/size2199023255552
4294967296Illustrative output
$ echo 1 | sudo tee /sys/block/sdb/device/rescan1$ sudo dmesg -T | tail -3[Tue Aug 11 14:22:07 2026] sd 6:0:0:1: [sdb] 8589934592 512-byte logical blocks: (4.40 TB/4.00 TiB)
[Tue Aug 11 14:22:07 2026] sd 6:0:0:1: [sdb] 4096-byte physical blocks
[Tue Aug 11 14:22:07 2026] sdb: detected capacity change from 2199023255552 to 4398046511104Illustrative output
For a new LUN that does not yet have a device node, the
device-level rescan has nothing to act on. Scan the host bus
instead, or use the sg3_utils wrapper that walks every host:
for h in /sys/class/scsi_host/host*/scan; do
echo '- - -' | sudo tee "$h" > /dev/null
done
# the packaged equivalent, which also handles removals
sudo rescan-scsi-bus.sh
The three dashes are channel target lun, each wildcarded.
Scanning a bus is safe but not free: on a large fabric it
produces a burst of discovery I/O, so do it once rather than in
a loop.
Step 2: re-read the partition table
Three commands do overlapping things, and choosing the wrong one is how a resize turns into an outage.
| Command | Mechanism | With partitions in use |
|---|---|---|
blockdev --rereadpt | BLKRRPART ioctl - drops and re-adds every partition | Fails with EBUSY |
partprobe | Tries BLKRRPART, falls back to per-partition updates | Usually works, sometimes silently partial |
partx -u | BLKPG ioctl per partition - updates in place | Works |
$ sudo partx -u /dev/sdbStep 3: the GPT backup header is now in the middle of the disk
GPT stores a primary header at the start of the disk and a backup header in the last sector. Grow the disk and the backup is suddenly thousands of sectors short of the end, where nothing looks for it.
$ sudo sgdisk --verify /dev/sdbCaution: invalid backup GPT header, but valid main header; regenerating
backup header from main header.
Warning! Main and backup partition tables differ! Use the 'c' and 'e' options
on the recovery & transformation menu to examine the two tables.
Problem: The secondary header's self-pointer indicates that it doesn't reside
at the end of the disk. If you've added a disk to a RAID array, use the 'e'
option on the experts' menu to adjust the secondary header's and partition
table's locations.
Identified 1 problems!Illustrative output
$ sudo sgdisk --move-second-header /dev/sdbWarning: The kernel is still using the old partition table.
The new table will be used at the next reboot or after you
run partprobe(8) or partx(8)
The operation has completed successfully.Step 4: grow the partition
$ sudo growpart --dry-run /dev/sdb 1CHANGE: partition=1 start=2048 old: size=4294965248 end=4294967296 new: size=8589932544 end=8589934592
# === old sfdisk -d ===
label: gpt
/dev/sdb1 : start=2048, size=4294965248, type=E6D6D379-F507-44C2-A23C-238F2A3DF928
# === new sfdisk -d ===
label: gpt
/dev/sdb1 : start=2048, size=8589932544, type=E6D6D379-F507-44C2-A23C-238F2A3DF928Illustrative output
Drop --dry-run to apply it. growpart rewrites the partition
entry in place, keeping the start sector, and then asks the
kernel to update. The alternative - deleting the partition in
fdisk and recreating it larger - works only if you recreate it
at exactly the same start sector, and is how filesystems get
orphaned by people who were sure they remembered the number.
Step 5 onwards: PV, LV, filesystem
- sudo pvresize /dev/sdb1 - the PV metadata records its own size and does not follow the partition automatically. Confirm with sudo pvs -o pv_name,pv_size,pv_free.
- sudo lvextend -r -L +2T vg0/data - the -r flag is equivalent to --fs resize and calls the filesystem-specific resize command in the same step, which removes the window where the LV is larger than the filesystem and nobody has noticed.
- df -h /srv/data - the only check that matters to the person who filed the ticket.
xfs_growfs /srv/data and resize2fs /dev/vg0/data are the
manual forms if you prefer to do the two steps separately. Both
grow online. Both are additive.
Knowledge check
Knowledge check · 4 questions
Q1. A LUN was grown on the array. After echoing 1 to /sys/block/sdb/device/rescan, blockdev --getsize64 /dev/sdb shows the new size but /dev/mapper/mpatha still shows the old one. What is missing?
Q2. When blockdev --rereadpt fails with EBUSY because a partition is mounted, the correct fix is to unmount the filesystem so the command can complete.
Q3. Which of the following are safe, non-destructive steps in a device-growth procedure? Select all that apply.
Q4. sgdisk --verify on a recently grown disk reports that the secondary header does not reside at the end of the disk. What is the actual risk?
Passing score: 75%. Answers are checked in this browser.