How Linux fdisk Partitions Raw Block Devices
This article explores how the standard Linux fdisk
utility partitions raw block devices, covering its interaction with
low-level storage architectures, the mechanics of manipulating partition
tables in memory, and the process of updating the Linux kernel to
recognize new storage boundaries.
Understanding Raw Block Devices
In Linux, a raw block device is an unformatted physical or virtual
storage drive represented as a special device file in the
/dev directory, such as /dev/sda for SATA/SCSI
drives or /dev/nvme0n1 for NVMe drives. These devices
transfer data in fixed-size blocks—typically 512 bytes or 4096 bytes
(4Kn)—without any inherent logical organization, filesystems, or
partition boundaries.
The Role of Partition Tables
To segment a raw block device into discrete logical sections, a partition table must be written to its designated sectors. The two primary partition table formats are:
- Master Boot Record (MBR): Resides in the first sector (LBA 0) of the disk, supporting up to four primary partitions and disks up to 2TB.
- GUID Partition Table (GPT): Part of the UEFI specification, GPT places its header at LBA 1 (with a protective MBR at LBA 0) and maintains a backup header at the end of the disk, supporting partitions larger than 2TB and significantly more partition entries.
While historically associated strictly with MBR, modern versions of
fdisk support both MBR and GPT partition schemes.
In-Memory Partition Editing
When fdisk is launched against a device path (for
example, fdisk /dev/sdb), it opens the target device
descriptor with read and write permissions. Instead of modifying the
physical disk immediately with every user action:
- Reading Existing Tables:
fdiskreads the first few sectors of the disk to identify an existing MBR or GPT header. - In-Memory Representation: It loads the partition map into system RAM.
- Staging Changes: Operations such as creating a new
partition (
n), changing a partition type (t), or deleting an entry (d) merely alter this in-memory data structure. No persistent alterations are committed to the hardware during this interactive phase.
Committing Changes to the Block Device
When the user enters the write command (w),
fdisk translates the staged memory structures into raw
binary data formatted according to the chosen scheme (MBR or GPT).
- Writing Sectors:
fdiskwrites the calculated sector offsets, sizes, partition types, and unique identifiers directly to the appropriate sectors (e.g., LBA 0 for MBR, or LBAs 1–33 and the end of the disk for GPT). - Preserving Data Areas: Crucially,
fdiskonly touches the partition table areas. It does not overwrite the actual payload data blocks within the partitions, nor does it create filesystems.
Informing the Linux Kernel
Once the physical sectors are written, the Linux kernel must be informed of the change so it can expose the new partitions to user space:
- The
BLKRRPARTioctl:fdiskissues anioctlsystem call using theBLKRRPART(Block Reread Partition Table) request to the raw device file descriptor. - Kernel Reparsing: The kernel reads the newly updated partition tables directly from the storage controller.
- Device Node Creation: The kernel updates its
internal partition maps and emits
uevents. Theudevdaemon captures these events and dynamically creates corresponding device nodes in/dev, such as/dev/sdb1and/dev/sdb2.
If an existing partition on the block device is currently mounted or
in use, the ioctl call fails with a busy warning. In this
scenario, the disk headers are updated, but the kernel continues using
the old table until the system is rebooted or the table is manually
refreshed using tools like partx or
blockdev.