Partitioning disks in Linux is generally the first step before installing a system. Before we can create any files, a filesystem must exist. Similarly, we can’t make a filesystem unless there is a partition on the disk.
Partitions are used to divide raw storage space into chunks (slices). This provides the means for organization and hosting of filesystems. Besides that, partitions also help isolate filesystem faults.
In this tutorial, we’ll discuss the tools and the process of partitioning disks in Linux. First, we’ll discuss in brief about disk types and boot modes. Secondly, we’ll go through the partitioning examples, using parted and LVM partitioning. And finally, we’ll conclude with a summary of the discussed topics.
2. Disk Types and Tools
The information about how a disk is partitioned is stored on the disk. This is usually called a partition table. The entries in this table define where partitions on the disk start and end. The format of this table is sometimes regarded as the disk type.
2.1. MBR and GPT
In the MBR scheme with 32-bit entries, we can only have a maximum disk size of 2 TB. Furthermore, only four primary partitions are allowed. However, we can use an extended partition that is further divided into logical partitions to overcome this limitation.
Besides partition entries, the MBR also contains a boot loader that is written in the initial sectors of the drive.
Whereas, GPT doesn’t contain a boot loader and can have up to 128 partitions (128-bit entries). Thus, most of the modern computers come pre-configured with a GPT disk. Though, GPT does support the MBR section for backward compatibility.
2.2. BIOS and UEFI
BIOS (Basic Input Output System) is low-level software that performs hardware initialization and loads the boot loader from the MBR. Gradually BIOS is being replaced by UEFI (Unified Extensible Firmware Interface). Still, most new systems have support for both.
Instead of loading a boot loader from the MBR, UEFI uses efi images from the EFI System Partition. With UEFI and GPT, we can have large disk support.
In some Linux systems, it is possible to use BIOS boot mode with a GPT disk.
2.3. Partitioning Tools
Historically, to partition MBR disks, the fdisk tool is used. However, in new Linux systems, fdisk can also understand GPT format.
In this article, however, we’ll focus on the parted tool. The parted tool is newer and understands both GPT and MBR layouts. Moreover, it is also considered a better option for partitioning disks in Linux because of its usability in scripting and automation.
3. Using the parted Tool
We’ll use a system with multiple hard drives. Let’s now start a terminal and list available hard drives:
$ lsblk -e7 NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 100G 0 disk ├─sda1 8:1 0 512M 0 part /boot/efi ├─sda2 8:2 0 1K 0 part └─sda5 8:5 0 99,5G 0 part / sdb 8:16 0 976,6G 0 disk sdc 8:32 0 3,8T 0 disk
In total, we’ve three disks in this system. The sda drive is the Linux system drive with three partitions. But, drives sdb and sdc have no partition table.
3.1. Selecting a Device
Since sda is the system drive, we’ll use sdb and sdc for our partitioning examples.
Let’s now start the parted program and select sdb drive:
# parted GNU Parted 3.3 Using /dev/sda Welcome to GNU Parted! Type 'help' to view a list of commands. (parted)
In interactive mode, all parted commands are issued one at a time, on the (parted) prompt. Notice that parted is using /dev/sda drive by default.
Before committing any partition changes, always check if the correct drive is selected:
(parted) select /dev/sdb Using /dev/sdb (parted)
To change the target device, we use the select command. Additionally, we can also start the parted program with a specific device:
(parted) quit # parted /dev/sdb GNU Parted 3.3 Using /dev/sdb Welcome to GNU Parted! Type 'help' to view a list of commands. (parted) q #
As we can see that commands can be abbreviated. For instance, q can be used instead of quit.
3.2. Getting Partition Information
We’ll now see, how to list partition information:
# parted /dev/sda GNU Parted 3.3 Using /dev/sda Welcome to GNU Parted! Type 'help' to view a list of commands. (parted) print Model: ATA VBOX HARDDISK (scsi) Disk /dev/sda: 107GB Sector size (logical/physical): 512B/512B Partition Table: msdos Disk Flags: Number Start End Size Type File system Flags 1 1049kB 538MB 537MB primary fat32 boot 2 539MB 107GB 107GB extended 5 539MB 107GB 107GB logical ext4 (parted)
Here, we’ve used the print command to show information about the sda drive. We can see that the partition table is MBR (msdos). Furthermore, the disk size (by default) is reported in bytes.
Let’s now try some other units:
# parted /dev/sda unit s print unit chs print Model: ATA VBOX HARDDISK (scsi) Disk /dev/sda: 209715200s Sector size (logical/physical): 512B/512B Partition Table: msdos Disk Flags: Number Start End Size Type File system Flags 1 2048s 1050623s 1048576s primary fat32 boot 2 1052670s 209713151s 208660482s extended 5 1052672s 209713151s 208660480s logical ext4 Model: ATA VBOX HARDDISK (scsi) Disk /dev/sda: 411206,69,1 Sector size (logical/physical): 512B/512B BIOS cylinder,head,sector geometry: 411206,255,2. Each cylinder is 261kB. Partition Table: msdos Disk Flags: Number Start End Type File system Flags 1 4,4,0 2060,11,1 primary fat32 boot 2 2064,15,0 411202,65,1 extended 5 2064,16,0 411202,65,1 logical ext4
With the unit command, we can change the units that are used to report sizes and start/end marks. For instance, we’ve now used s (sector) and chs (cylinder-head-sector). Additionally, we can chain multiple commands in the command-line mode.
3.3. Creating Partitions
Let’s see now, how to use parted tool for the partitioning of disks:
# parted -s /dev/sdb mklabel gpt # parted -s /dev/sdb mkpart primary fat32 0% 512MiB # parted -s /dev/sdb mkpart primary linux-swap 1048576s 16GiB # parted -s /dev/sdb mkpart primary ext4 16GiB 40% # parted -s /dev/sdb mkpart primary ext4 40% 60% # parted -s /dev/sdb mkpart primary ext4 60% 100% # parted -s /dev/sdb name 1 EFI-Boot # parted -s /dev/sdb name 2 Swap # parted -s /dev/sdb name 3 root # parted -s /dev/sdb name 4 /opt # parted -s /dev/sdb name 5 /home # parted -s /dev/sdb set 1 esp on
The mklabel command sets the partition table type. And, the most usual choices are gpt and msdos (MBR). In particular, we must set this before partitioning the disk.
The -s option is useful in scripts to suppress most warnings from the parted command.
To create partitions on the selected disk, we can use the mkpart command. The syntax requires partition-type, filesystem-type, start, and end parameters.
On a GPT disk, there is no extended partition. Therefore, we can specify all partitions as primary.
Different units are allowed for start and end parameters in the mkpart command. For example, we’ve used percentages, exact sector counts, and sizes as units. Moreover, we can also mix these units in a single command invocation. We’ve also set partition names based on the intended usage.
Additionally, we’ve set the esp (EFI system partition) flag on the first partition. On a GPT disk, the esp flag is an alias to the boot flag. Generally, on a Linux system, this partition is mounted on /boot/efi. We can find more details on how to mount filesystems on Linux.
Let’s verify the changes we’ve made to the sdb drive:
# parted /dev/sdb unit GiB print Model: ATA VBOX HARDDISK (scsi) Disk /dev/sdb: 977GiB Sector size (logical/physical): 512B/512B Partition Table: gpt Disk Flags: Number Start End Size File system Name Flags 1 0,00GiB 0,50GiB 0,50GiB EFI-Boot boot, esp 2 0,50GiB 16,0GiB 15,5GiB Swap swap 3 16,0GiB 391GiB 375GiB root 4 391GiB 586GiB 195GiB /opt 5 586GiB 977GiB 391GiB /home
3.4. Modifying Partitions
Let’s go back to the terminal and make some changes in our partition scheme:
# parted -s /dev/sdb rm 5 # parted -s /dev/sdb resizepart 4 70% # parted -s /dev/sdb mkpart primary ext4 70% 100% # parted -s /dev/sdb name 5 /home
We want to extend /opt, but this will result in the overlap. Hence, we’ve removed /home to resize /opt partition.
To resize a partition, we can only change the end parameter of a partition. Using the resizepart command, we can extend or shrink a partition.
Let’s again verify our changes:
# parted /dev/sdb unit GiB print Model: ATA VBOX HARDDISK (scsi) Disk /dev/sdb: 977GiB Sector size (logical/physical): 512B/512B Partition Table: gpt Disk Flags: Number Start End Size File system Name Flags 1 0,00GiB 0,50GiB 0,50GiB EFI-Boot boot, esp 2 0,50GiB 16,0GiB 15,5GiB Swap swap 3 16,0GiB 391GiB 375GiB root 4 391GiB 684GiB 293GiB /opt 5 684GiB 977GiB 293GiB /home
4. Partitioning Using LVM
LVM (Logical Volume Management) is an alternative way for partitioning disks in Linux. LVM provides a higher level of abstraction with the ability to pool physical storage. Consequently, enabling flexibility and dynamic resizing when requirements change.
A physical volume (pv) is the lowest level of abstraction in LVM. We can mark a whole physical disk or a partition as a physical volume. And, then, it can be used in pooling.
A volume group (vg) is the next level of abstraction after physical volume. A volume group can pool multiple physical volumes, combining their storage capacity under a single logical unit.
A logical volume (lv) is the highest layer in LVM abstraction. Therefore, users and applications use logical volumes like any standard partition. We can have several logical volumes within a volume group.
4.1. Creating Physical Volumes
We’ll now use some LVM commands to create and monitor volumes. In fact, we’ll use the same partitions from sdb and the whole disk sdc.
Let’s now switch to the terminal and select devices for physical volume preparation:
# lvmdiskscan /dev/sdb1 [ 511,00 MiB] /dev/sdb2 [ 15,50 GiB] /dev/sdb3 [ 374,62 GiB] /dev/sdb4 [ <292,97 GiB] /dev/sdb5 [ <292,97 GiB] /dev/sdc [ 3,81 TiB] 1 disk 5 partitions 0 LVM physical volume whole disks 0 LVM physical volumes
The lvmdiskscan command can scan for devices, partitions, and physical volumes. Although, beware that the output of this command can be exhaustive and may include other device types. We can control this by the file lvm.conf. For instance, in our system, loop devices and the sda drive is filtered out.
Now we’ve one whole disk and five partitions available that we can mark as LVM physical volume.
Let’s see now, how to mark devices as a physical volume:
# pvcreate /dev/sdc Physical volume "/dev/sdc" successfully created. # pvcreate /dev/sdb1 Physical volume "/dev/sdb1" successfully created. # pvcreate /dev/sdb2 Physical volume "/dev/sdb2" successfully created. # pvcreate /dev/sdb3 Physical volume "/dev/sdb3" successfully created.
The pvcreate command can mark partitions or whole disks as a physical volume. We do see some warnings because some partitions have a filesystem on them. Beware that this operation may destroy data on these devices.
Let’s now verify the changes we’ve made:
# lvmdiskscan /dev/sdb1 [ 511,00 MiB] LVM physical volume /dev/sdb2 [ 15,50 GiB] LVM physical volume /dev/sdb3 [ 374,62 GiB] LVM physical volume /dev/sdb4 [ <292,97 GiB] /dev/sdb5 [ <292,97 GiB] /dev/sdc [ 3,81 TiB] LVM physical volume 0 disks 2 partitions 1 LVM physical volume whole disk 3 LVM physical volumes # pvs PV VG Fmt Attr PSize PFree /dev/sdb1 lvm2 --- 511,00m 511,00m /dev/sdb2 lvm2 --- 15,50g 15,50g /dev/sdb3 lvm2 --- 374,62g 374,62g /dev/sdc lvm2 --- 3,81t 3,81t
The lvmdiskscan command now correctly reports the changes we’ve made. Moreover, we can use the pvs command for a summary of all physical volumes including their assignment to volume groups.
4.2. Creating Volume Groups
Let’s now create some volume groups by selecting physical volumes:
# vgcreate VG_Projects /dev/sdb1 /dev/sdb2 Volume group "VG_Projects" successfully created # vgcreate VG_Databases /dev/sdb3 /dev/sdc Volume group "VG_Databases" successfully created
Using the vgcreate command, we’ve created two volume groups. A volume group can include physical volumes from different devices.
Let’s again verify our changes:
# vgs VG #PV #LV #SN Attr VSize VFree VG_Databases 2 0 0 wz--n- 4,18t 4,18t VG_Projects 2 0 0 wz--n- 15,99g 15,99g # pvs PV VG Fmt Attr PSize PFree /dev/sdb1 VG_Projects lvm2 a-- 508,00m 508,00m /dev/sdb2 VG_Projects lvm2 a-- <15,50g <15,50g /dev/sdb3 VG_Databases lvm2 a-- 374,62g 374,62g /dev/sdc VG_Databases lvm2 a-- 3,81t 3,81t
Using the vgs command, we can have a summary of all volume groups. Now we can see that volume groups are reported with respective capacities. Furthermore, we can also see that now the pvs command reports the correct physical volume to volume group mapping.
4.3. Creating Logical Volumes
Finally, we can create some logical volumes within volume groups:
# lvcreate -L 8G -n ProjectA VG_Projects Logical volume "ProjectA" created. # lvcreate -l 100%FREE -n ProjectB VG_Projects Logical volume "ProjectB" created. # lvcreate -l 30%VG -n DatabaseA VG_Databases Logical volume "DatabaseA" created. # lvcreate -l 50%FREE -n DatabaseB VG_Databases Logical volume "DatabaseB" created.
Using the lvcreate command, we’ve created four logical volumes. A fixed-size can be used with -L option. However, with -l option, we can specify the size in percentages.
For instance, 30%VG will use 30 percent of volume group capacity, and 50%FREE will use 50 percent of the remaining space on the volume group.
Let’s get back to the terminal and verify the changes:
# lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert DatabaseA VG_Databases -wi-a----- 1,25t DatabaseB VG_Databases -wi-a----- 1,46t ProjectA VG_Projects -wi-a----- 8,00g ProjectB VG_Projects -wi-a----- 7,99g
With the lvs command, we can see the logical volumes that we’ve created.
4.4. Modifying Logical Volumes and Volume Groups
A logical volume can be accessed either as /dev/VolumeGroup/LogicalVolume or as /dev/mapper/VolumeGroup-LogicalVolume.
Let’s now make some modifications:
# vgreduce VG_Databases /dev/sdb3 Removed "/dev/sdb3" from volume group "VG_Databases" root@LinBox:~# vgs VG #PV #LV #SN Attr VSize VFree VG_Databases 1 2 0 wz--n- 3,81t <1,10t VG_Projects 2 2 0 wz--n- 15,99g 0 root@LinBox:~# vgextend VG_Projects /dev/sdb3 Volume group "VG_Projects" successfully extended root@LinBox:~# vgs VG #PV #LV #SN Attr VSize VFree VG_Databases 1 2 0 wz--n- 3,81t <1,10t VG_Projects 3 2 0 wz--n- 390,61g 374,62g root@LinBox:~# lvextend -L +5G /dev/VG_Projects/ProjectA Size of logical volume VG_Projects/ProjectA changed from 8,00 GiB (2048 extents) to 13,00 GiB (3328 extents). Logical volume VG_Projects/ProjectA successfully resized. root@LinBox:~# lvreduce -L -2G /dev/VG_Projects/ProjectB WARNING: Reducing active and open logical volume to 5,99 GiB. THIS MAY DESTROY YOUR DATA (filesystem etc.) Do you really want to reduce VG_Projects/ProjectB? [y/n]: y Size of logical volume VG_Projects/ProjectB changed from 7,99 GiB (2046 extents) to 5,99 GiB (1534 extents). Logical volume VG_Projects/ProjectB successfully resized. root@LinBox:~# lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert DatabaseA VG_Databases -wi-ao---- 1,25t DatabaseB VG_Databases -wi-ao---- 1,46t ProjectA VG_Projects -wi-ao---- 13,00g ProjectB VG_Projects -wi-ao---- 5,99g
Now we’ve reduced VG_Databases by removing /dev/sdb3 and added this to VG_Projects. Additionally, we extended ProjectA and reduced ProjectB.
We should take special care if reducing logical volumes will result in data loss. However, In this example, all modifications were done while filesystems are live, and no data was lost.
In this article, we discussed some ways of partitioning disks in Linux. Firstly, we discussed some background on MBR/GPT partitioning schemes, BIOS/UEFI boot modes, and their support in new systems. And Later on, we discussed partitioning with the parted tool and the LVM.
The GPT format has more benefits over the older MBR scheme. However, to support legacy systems, we can still see the MBR format being used in production.
Although we can resize standard partitions, this isn’t flexible in case of overlaps. Moreover, after resizing with parted, the filesystem needs to be extended. We need to be cautious when using parted for resizing a partition.
The LVM partitioning does provide a more flexible and robust solution than standard partitioning. That is specifically useful in administrative tasks like resizing or moving volumes without data loss.