Filesystem Quotas Explained

Filesystem Quotas Explained

Quotas limit how much disk space and how many files a user or group may consume on a filesystem. On a shared machine they are what stops one account filling the disk for everyone.

Two limits, and the second one surprises people

Quotas control blocks (disk space) and inodes (number of files) separately.

Block quotas are obvious. Inode quotas exist because every file consumes one inode regardless of size, so a user can exhaust a filesystem’s inode table with a million empty files while using almost no space.

df -h /home     # space
df -i /home     # inodes

When someone reports being out of quota with gigabytes free, it is nearly always inodes.

Each limit has a soft and a hard form

Hard limit: cannot be exceeded. The write fails with EDQUOT.

Soft limit: can be exceeded for a grace period, default seven days. During the grace period the user is over quota and still working. After it expires, the soft limit behaves as a hard limit.

The soft limit exists because an abrupt write failure loses work. A warning with a week to clean up is a far better experience, and it is what you should set for interactive users.

ext4

Quotas must be enabled at mount time.

# /etc/fstab
UUID=abc123  /home  ext4  defaults,usrquota,grpquota  0  2
sudo mount -o remount /home

For the root filesystem this means a reboot. Our fstab guide and the fstab builder cover the syntax.

Then initialise:

sudo apt install quota           # Debian and Ubuntu
sudo dnf install quota           # Fedora and RHEL

sudo quotacheck -cugm /home      # build the quota database
sudo quotaon -v /home

quotacheck scans the filesystem and builds aquota.user and aquota.group. It needs the filesystem quiet, ideally unmounted or read-only, because scanning a filesystem being written to produces inaccurate counts.

Modern ext4 supports journalled quotas, which avoid the need for quotacheck after an unclean shutdown:

UUID=abc123 /home ext4 defaults,usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv1 0 2

Worth using. Without it, a crash means a long quotacheck on the next boot.

XFS

Different mechanism, similar concepts. Quotas are part of the filesystem and are enabled only at mount time.

UUID=def456  /data  xfs  defaults,uquota,gquota  0  0

XFS cannot enable quotas on a remount, so the root filesystem requires a reboot with no way around it.

There is no quotacheck; XFS maintains the accounting internally.

sudo xfs_quota -x -c 'report -h' /data
sudo xfs_quota -x -c 'limit bsoft=8g bhard=10g colton' /data
sudo xfs_quota -x -c 'limit isoft=50000 ihard=60000 colton' /data

XFS also supports project quotas, which limit a directory tree rather than a user. That is frequently what you actually want:

UUID=def456  /data  xfs  defaults,pquota  0  0
echo "42:/data/projects/alpha" | sudo tee -a /etc/projects
echo "alpha:42" | sudo tee -a /etc/projid

sudo xfs_quota -x -c 'project -s alpha' /data
sudo xfs_quota -x -c 'limit -p bhard=100g alpha' /data

Now /data/projects/alpha is capped at 100GB regardless of who writes into it.

Setting limits on ext4

sudo edquota -u colton

Opens an editor:

Filesystem  blocks  soft    hard  inodes  soft   hard
/dev/sda2    52400  8000000 10000000  1823  50000 60000

Blocks are in kilobytes. 8000000 is roughly 8GB, not 8MB. Getting this wrong by three orders of magnitude is a common first mistake.

Non-interactively:

sudo setquota -u colton 8000000 10000000 50000 60000 /home
#              user     bsoft   bhard    isoft ihard  fs

Copy to other users:

sudo edquota -p colton -u alice bob carol

That is the efficient way to apply a standard allocation across an account set.

Grace periods:

sudo edquota -t
Filesystem   Block grace period   Inode grace period
/dev/sda2    7days                7days

Checking usage

sudo repquota -a           # all filesystems
sudo repquota -s /home     # human-readable
quota -s                   # your own
sudo quota -s -u colton    # one user
                        Block limits              File limits
User      used    soft    hard  grace    used  soft  hard  grace
colton   7891M   8000M  10000M           1823 50000 60000
alice   10240M*  8000M  10000M  6days   48211 50000 60000

The asterisk marks over-quota. alice has six days before her soft limit becomes hard.

A monitoring check worth having:

sudo repquota -a | awk '$3 ~ /\*/ {print $1 " is over quota"}'

Btrfs and ZFS

The traditional quota tools do not apply.

Btrfs uses qgroups on subvolumes:

sudo btrfs quota enable /mnt/data
sudo btrfs qgroup limit 100G /mnt/data/subvol1
sudo btrfs qgroup show -reF /mnt/data

Be aware that Btrfs qgroups have historically carried a performance cost on write-heavy workloads, which has improved and is worth testing before enabling on something busy.

ZFS uses dataset properties:

sudo zfs set quota=100G tank/home/colton
sudo zfs set refquota=80G tank/home/colton
sudo zfs userspace tank/home

quota includes snapshots and descendant datasets; refquota counts only the dataset’s own referenced data. The distinction matters: with quota alone, snapshots accumulating can push a user over their limit without them writing anything new.

Our ZFS and Btrfs guides cover the wider picture.

What a user actually experiences

Hitting a hard limit produces EDQUOT, which surfaces as “Disk quota exceeded”.

Well-written software reports this clearly. A great deal of software does not, and produces truncated files, a failed save with a vague error, or silent data loss. Desktop sessions can fail to start if the user cannot write to their own home directory, which looks like a broken login rather than a quota problem.

This is the practical argument for soft limits with a real grace period: the user gets a warning while everything still works.

Where possible, warn before the limit rather than at it. A nightly repquota check that mails anyone above 80 percent prevents most of the pain, and a systemd timer is the obvious way to run it.

Frequently Asked Questions

What is the difference between a soft and a hard quota limit?

A hard limit cannot be exceeded and writes fail immediately once reached. A soft limit can be exceeded temporarily for a grace period, typically seven days, after which it behaves as a hard limit. The soft limit exists so a user gets a warning and time to clean up rather than an abrupt failure.

Why does a user hit a quota with plenty of space left?

Almost certainly the inode quota rather than the block quota. Every file consumes one inode regardless of size, so thousands of tiny files exhaust the inode limit while using very little disk. Run repquota and look at the files column rather than the blocks column.

Do quotas work on Btrfs and ZFS?

Not through the traditional quota tools. Btrfs uses qgroups tied to subvolumes, and ZFS sets quota and refquota properties per dataset. Both are managed with their own commands and are arguably more flexible, since the limit applies to a dataset rather than to a user identity.

Do I need to reboot to enable quotas?

On ext4 you need to remount the filesystem with the quota options, which for the root filesystem usually means a reboot. XFS requires the quota mount options to be present at mount time and cannot enable them on a remount, so the root filesystem definitely needs a reboot there.

How do I apply the same quota to many users?

Set it once on a prototype user, then use edquota with the -p flag to copy that configuration to others. This is considerably faster than editing each one and avoids the transcription errors that come from setting dozens by hand.

What happens to a running process when it hits a hard quota?

Writes fail with EDQUOT, which the application sees as a disk quota exceeded error. Well-written software reports it clearly, and a great deal of software handles it badly, producing truncated files or confusing errors. This is why soft limits with grace periods are worth using.