Adding storage is routine: a database needs more space, logs need their own volume, or a cloud provider hands you a new unattached disk. The steps are always the same: identify, partition, format, mount, make it permanent. The danger is working on the wrong device, so every step below checks before it changes anything.
Versions in use on this date. Ubuntu 18.04.3 LTS (released 8 August 2019) with util-linux 2.31 and e2fsprogs 1.44. CentOS 7.6 uses XFS by default for new installs; the commands below are for ext4, with the XFS equivalents noted.
From raw disk to mounted storage
flowchart TB
D[New disk /dev/sdb<br/>raw block device] --> I[Identify with lsblk]
I --> PT[Partition table<br/>fdisk or parted]
PT --> PA[Partition /dev/sdb1]
PA --> FS[mkfs.ext4 creates filesystem]
FS --> MT[mount to /data]
MT --> UU[Record UUID with blkid]
UU --> FT[Add line to /etc/fstab]
FT --> TS[Test with mount -a]
TS --> OK[Survives reboot]
1. Identify the right disk
lsblk -f # tree with filesystems, UUIDs, mount points
sudo fdisk -l /dev/sdb # size and any existing partition table
sudo blkid /dev/sdb
The new disk has no partitions and no FSTYPE. If lsblk shows data or a mount point, stop: it is not the empty disk you think it is. In cloud servers, confirm by size, since device names (/dev/sdb, /dev/xvdf, /dev/nvme1n1) can differ between instances.
2. Partition
sudo fdisk /dev/sdb
# n (new) p (primary) 1 Enter Enter w (write)
sudo partprobe /dev/sdb
lsblk /dev/sdb
fdisk changes nothing until you press w; q quits safely. Disks over 2 TB need GPT (sudo parted /dev/sdb mklabel gpt). For a data disk you may also skip partitioning and format the whole device, but a partition table is clearer to the next engineer.
3. Create the filesystem
sudo mkfs.ext4 -L data /dev/sdb1 # ext4 with label "data"
# CentOS default alternative:
# sudo mkfs.xfs -L data /dev/sdb1
sudo tune2fs -m 1 /dev/sdb1 # reduce reserved blocks from 5% to 1% on a data disk
mkfs destroys existing data on that device with no confirmation prompt. Double-check the device name.
4. Mount, then make it permanent
sudo mkdir -p /data
sudo mount /dev/sdb1 /data
df -hT /data
sudo blkid /dev/sdb1 # note the UUID
Edit /etc/fstab using the UUID, not /dev/sdb1, because device names can change between boots:
UUID=3f2c1d0e-xxxx-xxxx-xxxx-xxxxxxxxxxxx /data ext4 defaults,noatime,nofail 0 2
Fields: device, mount point, type, options, dump (0), fsck order (1 for /, 2 for others, 0 for none). nofail lets the system boot even if the disk is missing, which matters for data disks on cloud servers.
Always test before rebooting:
sudo umount /data
sudo mount -a # mounts everything in fstab; errors appear now, not at boot
findmnt /data
A bad fstab line can drop the machine into emergency mode at the next reboot. Keep a copy first: sudo cp /etc/fstab /etc/fstab.bak.
Permissions and ownership
A new ext4 filesystem is owned by root. Give the application what it needs:
sudo chown -R postgres:postgres /data/pgsql
sudo chmod 750 /data/pgsql
Checking health and capacity
df -hT # space; df -i shows inodes
sudo du -xh --max-depth=1 /data | sort -h | tail
sudo fsck -n /dev/sdb1 # read-only check (unmounted only)
sudo smartctl -H /dev/sda # (apt install smartmontools) physical disk health
iostat -x 5 3 # (apt install sysstat) utilisation and latency
Alert before a filesystem reaches 80 to 85% full. Growing a disk without downtime is covered later in this series with LVM.
Pitfalls
- Mount hides existing files: mounting onto a non-empty directory covers its content until you unmount.
- fstab typo causes boot failure: use
mount -afirst andnofailfor non-critical mounts. - Wrong device formatted: always
lsblkimmediately beforemkfs. - Full inodes: millions of tiny files exhaust inodes while space remains;
df -ishows it.