Partitioning

A disk arrives from the factory as one undifferentiated run of sectors. Before a filesystem can live on it, something has to write down where each one begins and ends. That is a partition table, and on Peios the tool that writes one is part.

part manages GPT and nothing else. That is not an omission waiting to be filled: Peios boots through UEFI with no bootloader and no boot manager, so the MBR layout it would otherwise support has nothing to do on a Peios system.

The shape of the tool #

If you have used Windows, part occupies the slot diskpart occupies — but it is not the same shape, and the difference is deliberate.

diskpartpart
how you use itan interactive shell: select disk 0, then act on itone command, one device, one job
what it coverspartitions, formatting, drive letters, dynamic disksthe partition table

Everything else diskpart bundles already has a home here: mke2fs and mkfs.vfat make filesystems, mount mounts them, and Peios has no drive letters. And a select-then-act model is a hazard in a script, which is what usually calls part — a command that acts on "whatever was selected earlier" is one stray line away from acting on the wrong disk.

Listing disks #

Run part list with no arguments to see every disk on the machine:

# part list
DEVICE             SIZE  CONTENTS
/dev/vda           8.0G  gpt, 2 partitions
  vda1             512M  esp    EFI system partition
  vda2             7.5G  linux  Peios root
/dev/vdb           8.0G  no partition table

This is the view to start from, because it answers the question that precedes every other one: which disk did you mean? The partition names are the ones the kernel actually created — vda1 on a virtio or SATA disk, nvme0n1p1 on an NVMe one — so they are what you can pass straight to mkfs or to the installer.

The structure here comes from the kernel, not from reading a partition table, so a disk carrying a format part cannot manage still shows its partitions. A disk it cannot read at all is still listed, with ? for its contents — the disk you cannot read is exactly the one worth knowing about.

Name a disk to see it in full:

# part list /dev/vda
/dev/vda: 16777216 sectors of 512 bytes (8.0G)
Label:     gpt
Disk GUID: DE942295-427C-411D-8023-B689D8BEE907
Usable:    34 .. 16777182

  #         START           END        SIZE  TYPE      NAME
  1          2048       1050623        512M  esp       EFI system partition
  2       1050624      16777182        7.5G  linux     Peios root

Free (aligned): 0B  in 0 extent(s), largest 0B

Free (aligned) counts space a new partition could actually occupy, which is not the same as unallocated sectors — the run below the first alignment boundary can never hold one. Reporting raw free space would promise room that add would then refuse to use.

part verify checks the same table's structure: both checksums, the two headers agreeing with each other, no overlaps, everything aligned and inside the usable range.

Creating a table #

# part create /dev/vda --yes
/dev/vda: wrote a new GPT (DE942295-427C-411D-8023-B689D8BEE907)

# part add /dev/vda --size 512M --type esp   --name "EFI system partition" --yes
/dev/vda: partition 1 at 2048..1050623 (512M)

# part add /dev/vda --size max  --type linux --name "Peios root" --yes
/dev/vda: partition 2 at 1050624..16777182 (7.5G)

add puts each partition in the first free run that fits, aligned to 1 MiB. --size max takes the largest free run rather than merely the last one, so it still does the obvious thing on a disk with a gap in the middle.

part del /dev/vda 2 --yes removes a partition by number. It frees the space and the slot; it does not touch the data that was in it.

Sizes are sectors unless you say otherwise #

--size takes K, M, G, T — powers of 1024 — or max. A bare number is a sector count, not bytes. --size 2048 is 1 MiB on a 512-byte-sector disk, and you can write 2048s to say so explicitly. Reading it as bytes would silently produce a partition a thousand times smaller than intended.

Types #

--type takes a short alias or a raw GUID:

AliasMeaning
espEFI system partition
linuxLinux filesystem data
swapLinux swap
msdataMicrosoft basic data

The list is short on purpose. Every type GUID in circulation would be a catalogue to keep current, and since a raw GUID is always accepted, nothing is unreachable for want of an alias.

Names #

Up to 36 UTF-16 code units — fewer if you use characters outside the Basic Multilingual Plane, which cost two units each. A longer name is refused rather than shortened. A partition name is how you identify the thing you are about to format, and a tool that quietly truncates it makes the label on your screen disagree with the label on the disk.

What it will not do #

part is the one tool on the system whose mistakes cannot be undone, so it is deliberately hard to point at the wrong thing.

It requires --yes. There is no interactive "are you sure": the usual caller is a script, and a prompt nobody can answer is worse than no prompt at all.

It refuses a partition. Naming /dev/vda1 where you meant /dev/vda would write a GPT inside a partition — a table that looks valid to anything reading that partition directly, and is invisible to everything else.

# part create /dev/vda1 --yes
part: /dev/vda1 is a partition, not a whole disk; did you mean /dev/vda?

It refuses a disk with anything mounted on it. Not just the disk itself — any partition of it.

It refuses a table it did not create. This is the important one:

# part create /dev/vdb --yes
part: this disk carries an MBR (dos) partition table, which part cannot manage;
      pass --force to replace it — every partition on it will be lost

part list says what it found, not merely that it found no GPT — because "no GPT" is ambiguous between a blank disk and a disk holding somebody's data, and those deserve opposite treatment:

What is thereWhat part says
an MBR"an MBR (dos) partition table, which part cannot manage"
an Apple, BSD, Sun or SGI labelnames it
a GPT whose header is corrupt"the table may be damaged"
a filesystem written straight to the disk"a <type> filesystem … with no partition table"
genuinely nothing"no partition table"

--force is the way through, and it is a second confirmation, separate from --yes. --yes means "I mean this destructive operation"; --force means "and I know it destroys a table that was already there". Requiring both is proportionate for an operation with no undo.

Alignment, and why 1 MiB #

Every partition starts on a 1 MiB boundary — 2048 sectors on a 512-byte-sector disk, 256 on a 4096-byte one. The number is not arbitrary: 1 MiB divides every erase block and RAID stripe width in practical use, so an aligned partition never straddles one. A misaligned filesystem pays a read-modify-write cycle on every boundary-crossing write, for the life of the filesystem.

part reads the logical sector size from the kernel rather than assuming it, so a 4Kn disk gets a correct table rather than one whose every structure is in the wrong place.

Exit status #

CodeMeaning
0success
1usage error, or the operation failed
2could not read or write the device
3refused by a safety check

3 is separated from 1 on purpose. A refusal is part working correctly, not malfunctioning, and a script should treat "this disk is not what you said it was" differently from "partitioning broke". peios-install relies on exactly this distinction.

Where to go next #

To put a filesystem on what you just created, read Formatting with security descriptors and mke2fs.

To have the installer do all of this for you, read Installing to diskpeios-install --whole-disk runs exactly the three commands above before it formats anything.

Edit this page