How to Force Linux Kernel to Reread Partition Table Without Reboot (BLKRRPART vs BLKPG Deep Dive)


2 views

When modifying disk partitions on Linux systems, you've likely encountered the frustrating message:

Wrote partition table, but re-read table failed. Reboot to update table.

This occurs across various partitioning tools (cfdisk, fdisk, parted) because they all ultimately rely on the same kernel mechanisms. The core issue stems from how the Linux kernel caches partition information.

Modern Linux offers two primary methods for partition table updates:

// Traditional method used by most tools
ioctl(fd, BLKRRPART, NULL);

// Newer approach used by partprobe
ioctl(fd, BLKPG, &partition_data);

BLKRRPART attempts to reload the entire partition table but fails if any partition is in use. BLKPG offers more granular control by allowing updates to individual partitions.

Here are the most effective methods to force a partition table reload:

Method 1: partprobe (Recommended)

# Install if needed
sudo apt install parted

# Reload partition table
sudo partprobe /dev/sdX

Advantages:
- Uses BLKPG when available
- Falls back to BLKRRPART
- Handles both MBR and GPT

Method 2: blockdev Command

sudo blockdev --rereadpt /dev/sdX

Method 3: Manual BLKPG via Python

For developers needing programmatic control:

import fcntl
import struct

def refresh_partition(device, partition_num):
    BLKPG = 0x1269
    data = struct.pack('iLLLL', 
                       partition_num, 
                       0, 0, 0, 0)  # Simplified structure
    with open(device, 'rb') as f:
        fcntl.ioctl(f, BLKPG, data)

# Example usage:
refresh_partition('/dev/sda', 1)

Even with these methods, reboots may still be necessary when:
- The root filesystem partition was modified
- LVM/DM devices are involved
- Filesystems were mounted during changes
- Kernel has internal references to old partition sizes

Consider expanding a cloud instance's root disk:

# After resizing cloud volume
sudo growpart /dev/vda 1
sudo partprobe /dev/vda
sudo resize2fs /dev/vda1

The partprobe step ensures the kernel sees the new partition boundaries before filesystem resizing.

If methods fail:
1. Check dmesg for kernel messages
2. Verify no processes have open handles: lsof | grep /dev/sdX
3. Try unloading kernel modules using the device: lsmod | grep sd
4. As last resort: echo 1 > /sys/block/sdX/device/rescan


When working with disk partitioning tools like cfdisk, sfdisk, or parted, you might encounter this frustrating message:

Wrote partition table, but re-read table failed. Reboot to update table.

This occurs because the kernel fails to acknowledge the modified partition table through the standard BLKRRPART ioctl. The problem typically manifests when:

  • Any partition on the disk is currently mounted (even if you're not modifying that specific partition)
  • The disk is being actively accessed by other processes
  • There are pending I/O operations on the device

Linux provides two primary methods for partition table updates:

// Traditional method (used by cfdisk/sfdisk/hdparm -z)
ioctl(fd, BLKRRPART, NULL);

// Alternative method (used by partprobe)
struct blkpg_ioctl_arg arg;
ioctl(fd, BLKPG, &arg);

BLKPG offers more granular control as it can update individual partitions rather than requiring a full table reload. Here's how the kernel handles each approach:

// Simplified kernel pseudocode
case BLKRRPART:
    if (disk->open_partitions > 0)
        return -EBUSY;
    rescan_partitions(disk);
    break;

case BLKPG:
    if (!(partition->in_use))
        update_partition(partition);
    break;

Here are the most effective methods to force a partition table reload:

1. Using partprobe (Recommended)

# For a specific device
partprobe /dev/sdX

# For all devices
partprobe

This tool uses the BLKPG ioctl first, falling back to BLKRRPART if needed.

2. Alternative Tools

# Using hdparm
hdparm -z /dev/sdX

# Using sfdisk
sfdisk -R /dev/sdX

# Using blockdev
blockdev --rereadpt /dev/sdX

3. Manual Kernel Notification

For programmers implementing this in C:

#include <linux/fs.h>
#include <sys/ioctl.h>

int refresh_partitions(int fd) {
    // Try BLKPG first
    struct blkpg_ioctl_arg arg = {0};
    if (ioctl(fd, BLKPG, &arg) == 0)
        return 0;
    
    // Fall back to BLKRRPART
    return ioctl(fd, BLKRRPART, NULL);
}

If you still can't refresh the partition table:

  1. Check for mounted partitions: mount | grep /dev/sdX
  2. Look for processes using the device: lsof /dev/sdX*
  3. Verify no LVM/DM activity: dmsetup ls
  4. Check kernel messages: dmesg | tail -20

Remember that some virtualized environments (especially cloud instances) may require additional steps due to their storage architectures.