Disks and Block Devices
Managing any server starts with disks: how many are attached, what they're named, which name maps to which physical device, and how large each one is. This storage module begins with exactly that question — how Linux sees disks and how it names them. Later articles build on this foundation to partition a disk, make it more flexible with RAID and LVM, create a filesystem on it, and mount it — but all of that rests on what's covered here.
What You Will Learn
By the end of this article you will be able to:
- explain what a block device is and how it differs from a character device;
- distinguish the
/dev/sd*,/dev/nvme*, and/dev/vd*naming conventions; - inspect the disks attached to a system with
lsblk,blkid,fdisk -l, andlsscsi; - explain why major/minor numbers exist;
- find kernel-level information about a disk through
/sys/block; - explain the difference between logical and physical sector size.
What a Block Device Is
Linux exposes every device as a file under /dev. These files fall into two categories:
- Character device — data is transferred as a byte stream, one byte at a time. Examples:
/dev/tty,/dev/random. - Block device — data is transferred in fixed-size blocks (typically 512 or 4096 bytes) and supports random access to any position. Hard disks, SSDs, and USB flash drives are all block devices.
The b at the start of the line marks this as a block device (it would be c for a character device). 8, 0 is the major and minor number pair.
Major and Minor Numbers
The kernel identifies every device file with two numbers:
- Major number — identifies the driver that manages the device (for example,
8is the SCSI/SATA disk driver). - Minor number — identifies the specific device or partition within that driver (
0is the whole disk,1is the first partition, and so on).
brw-rw---- 1 root disk 8, 0 Jul 25 10:00 /dev/sda
brw-rw---- 1 root disk 8, 1 Jul 25 10:00 /dev/sda1
brw-rw---- 1 root disk 8, 2 Jul 25 10:00 /dev/sda2
brw-rw---- 1 root disk 8, 16 Jul 25 10:00 /dev/sdb
/dev/sda and /dev/sda1 share the same major number (8), since the same driver handles both; the minor number identifies exactly which partition it is.
Disk Naming Conventions
The device name depends on which driver or interface is in use:
| Name pattern | Device type | Partition naming |
|---|---|---|
/dev/sda, /dev/sdb, ... |
SATA/SAS/USB disk (SCSI subsystem) | /dev/sda1, /dev/sda2 |
/dev/nvme0n1, /dev/nvme1n1, ... |
NVMe SSD (attached via PCIe) | /dev/nvme0n1p1, /dev/nvme0n1p2 |
/dev/vda, /dev/vdb, ... |
Virtio virtual disk (KVM/QEMU virtual machines) | /dev/vda1, /dev/vda2 |
/dev/xvda, /dev/xvdb, ... |
Xen virtual disk (some cloud providers) | /dev/xvda1 |
sd* naming follows alphabetical order: a, b, c, ... z, then aa, ab, and so on. This order isn't guaranteed to stay the same across reboots — disk detection order can change, which is why production systems should rely on a UUID rather than a name like /dev/sda (covered in depth in fstab).
The NVMe naming format is different: nvme0n1 — controller number 0, n1 — namespace 1 under that controller, p1 — partition 1 within that namespace. The p is needed as a separator because nvme0n1 already ends in a digit.
Info
NVMe disks connect directly over PCIe rather than through the SCSI subsystem, and are handled by the nvme driver — which is why they use a different naming convention.
Commands for Inspecting Disks
lsblk — the Block Device Tree
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 40G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 39G 0 part /
sdb 8:16 0 100G 0 disk
nvme0n1 259:0 0 500G 0 disk
└─nvme0n1p1 259:1 0 500G 0 part /data
Useful flags:
lsblk -f # filesystem type, UUID, and label
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT
lsblk -d # disks only, no partitions
blkid — UUID and Filesystem Type
/dev/sda1: UUID="1a2b3c4d-5e6f-7890-abcd-ef1234567890" TYPE="ext4" PARTUUID="..."
/dev/sda2: UUID="9f8e7d6c-5b4a-3210-fedc-ba0987654321" TYPE="ext4" PARTUUID="..."
blkid reports each partition's UUID, label, and filesystem type — the primary source of information when writing /etc/fstab.
fdisk -l — Partition Table and Disk Size
Disk /dev/sda: 40 GiB, 42949672960 bytes, 83886080 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
Disklabel type: gpt
Device Start End Sectors Size Type
/dev/sda1 2048 2099199 2097152 1G EFI System
/dev/sda2 2099200 83884031 81784832 39G Linux filesystem
fdisk -l without an argument lists every detected disk; with an argument (fdisk -l /dev/sda) it shows only that disk. This command is read-only — it changes nothing, which makes it safe for inspecting a system.
lsscsi — Listing SCSI Devices
lsscsi shows the disk at the physical/virtual controller level — model, manufacturer, and SCSI address (host:channel:target:lun) together. It's especially useful for telling apart multiple disks of identical size.
/sys/block — Kernel-Level Information
The kernel exposes information about every block device as virtual files under /sys/block/:
size— the disk's size in sectors (multiply by 512 to get the size in bytes);queue/rotational—1for a spinning disk (HDD),0for an SSD/NVMe;removable— whether the device is removable (e.g. a USB flash drive).
This script shows whether every sd* disk is an HDD or an SSD — information lsblk doesn't provide directly, which is why /sys/block is handy for low-level checks.
Logical vs. Physical Sector Size
Modern disks often report two distinct sector sizes:
- Logical sector size — the minimal addressing unit the operating system sees (usually 512 bytes, for compatibility).
- Physical sector size — the disk's actual physical write unit (often 4096 bytes on modern disks, referred to as "4Kn" or "512e").
If a partition's boundaries don't align with physical sector boundaries, disk performance can drop noticeably — modern partitioning tools (fdisk, parted) account for this automatically, but knowing about it is useful when troubleshooting disk performance.
Practical Scenario: Identifying a New Disk
Problem. A new virtual disk was just added to a server, but its /dev/sd* name is unknown — picking the wrong disk on a production server risks losing data on it.
1. Record the state before adding the disk:
2. Check again after adding the disk:
3. Confirm the new disk by size and model:
4. Confirm the disk has no existing partition or filesystem:
If the command returns nothing (empty output), the disk is still unpartitioned and filesystem-free — safe to partition.
Conclusion. Comparing before/after with diff is the most reliable identification method when several disks share the same size. "Guessing" based on size and model number is risky in a production environment.
Warning
Never pick a disk based only on "the largest unused number" (e.g. /dev/sdd) — disk numbering can change after a reboot or when another disk is removed. Always positively confirm the disk with blkid, lsscsi, or its size, especially before a step that destroys data on it (fdisk, mkfs, dd).
Detecting a Hot-Added Disk Without a Reboot
The scenario above assumes the new disk already shows up in lsblk. On a running physical or virtual server, a freshly attached disk sometimes doesn't appear until the kernel is told to rescan the bus — and rebooting a production box just to see a new disk is rarely acceptable.
For a SATA/SAS/SCSI disk, trigger a rescan of every SCSI host:
The - - - is channel target lun, and three dashes mean "any" — i.e. scan everything on that host.
If an existing disk was resized on the hypervisor/SAN side (a common cloud operation) but still shows the old size, rescan that specific device instead:
For an NVMe namespace:
Info
After the disk itself shows the new size, its partition and filesystem still won't have grown — those are separate layers resized with growpart + resize2fs/xfs_growfs, covered in Partitions and LVM: Resizing and Snapshots.
Persistent Device Names: /dev/disk/by-*
Before a filesystem (and therefore a UUID) exists, a disk still needs a stable name for scripts and automation — and /dev/sdb is exactly the name that can change on the next boot. The kernel maintains stable symlinks under /dev/disk/:
by-id— based on the hardware serial/WWN (e.g.wwn-0x5000c500...,nvme-Samsung_SSD_...); tied to the physical disk, so it survives reboots and cabling changes. This is the right identifier to pin a whole disk inmdadm/LVM automation.by-path— based on the physical connection (PCI/SCSI path); stable as long as the disk stays in the same slot, but changes if moved.by-uuid/by-label— appear only after a filesystem is created, and are what fstab uses.
Common Mistakes
Assuming /dev/sda Is a Permanent Name
Disk names can change across reboots or when a device is added or removed. Scripts and fstab should use a UUID rather than a hardcoded name (/dev/sdb1).
Not Knowing the Difference Between lsblk and fdisk -l
lsblk shows the current state as seen by the kernel, in a hierarchical view (with mount points). fdisk -l shows the partition table in more detail (sector boundaries, type codes), but requires sudo and doesn't show mount state.
Confusing a Partition with a Disk
/dev/sda is the whole disk; /dev/sda1 is the first partition on it. mkfs or mount should target the intended partition (or, in special cases like LVM, a logical volume) — never the whole disk.
Exercises
- Compare the output of
lsblk,blkid, andfdisk -l— note which columns/fields each one provides. - Check the
rotationalvalue for every disk under/sys/block/on your system and determine which are HDDs and which are SSDs. - Add a new virtual disk to a disposable test VM and identify it using the "before/after
diff" method from this article, then confirm its size withfdisk -l.
Verification criterion: you should be able to identify a newly added disk with confidence, using at least two independent pieces of evidence (size, model, or a before/after comparison) rather than a guess.
Summary
Linux represents every disk as a block device under /dev, identified by major/minor numbers; naming differs by interface (sd*, nvme*, vd*). lsblk, blkid, fdisk -l, lsscsi, and /sys/block are the core, read-only tools for inspecting the disks on a system. Once a disk is correctly identified, the next step is partitioning it, using fdisk, gdisk, or parted.