Last updated: 2026-08-20

Linux filesystem quotas

Category: Storage AllocationTechnologies: ext4 quotas, XFS xfs_quota, Btrfs qgroups, ZFS quotas, project quotas

Filesystem quotas limit disk space and inode usage per user, group, or directory tree. They prevent any single user or application from consuming all available storage. Quotas are essential for multi-user systems, shared hosting, and capacity planning across Linux filesystems. Container runtimes also need per-container limits; the OverlayFS and container storage guide covers quota options for Docker and Podman.

Quota types

TypeScopeUse case
User quotasAll files owned by a specific user (UID)Multi-user systems, per-user limits
Group quotasAll files owned by members of a group (GID)Project teams, departmental limits
Project quotasAll files within a directory tree, regardless of ownerPer-tenant limits in shared hosting, application directories

Soft vs hard limits

LimitBehavior
Soft limitCan be exceeded for a grace period. When grace expires, enforced as hard limit.
Hard limitAbsolute limit; cannot be exceeded (except with CAP_SYS_RESOURCE).
Grace periodTime allowed to exceed soft limit before enforcement. Default: 7 days. Per-filesystem and per-resource (blocks vs inodes).

ext2/3/4 quotas

Mount options

# Enable quotas at mount
mount -o usrquota,grpquota,prjquota /dev/sda1 /mnt

# /etc/fstab
/dev/sda1  /mnt  ext4  defaults,usrquota,grpquota  0 0

Modern ext4 quota feature (kernel 4.x+)

# Create ext4 with quota feature
mkfs.ext4 -O quota -E quotatype=usrquota:grpquota:prjquota /dev/sda1

# Enable on existing filesystem
tune2fs -Q usrquota,grpquota,prjquota /dev/sda1

Quota files

ext4 stores quota information in files at the filesystem root: aquota.user, aquota.group, aquota.project (v2 format, current). The older v1 format used quota.user, quota.group.

Workflow

# 1. Mount with quota options
mount -o usrquota,grpquota /dev/sda1 /mnt

# 2. Create/check quota files
quotacheck -cug /mnt

# 3. Enable quotas
quotaon -vug /mnt

# 4. Set quotas
setquota username 500000 550000 0 0 /mnt
# (block-soft block-hard inode-soft inode-hard, blocks in 1KB units)

# 5. Report
repquota -u /mnt

# 6. Disable
quotaoff -vug /mnt

XFS quotas

XFS stores quota information in filesystem metadata (no separate quota files), providing better performance. Quotas have two components: accounting (enabled at mount) and enforcement (can be toggled with xfs_quota).

Mount options

# User quota with enforcement
mount -o uquota /dev/sda1 /mnt
# or: mount -o usrquota /dev/sda1 /mnt

# Group quota
mount -o gquota /dev/sda1 /mnt

# Project quota
mount -o pquota /dev/sda1 /mnt

# Accounting only (no enforcement)
mount -o uqnoenforce /dev/sda1 /mnt

xfs_quota commands

# Report quotas (human-readable)
xfs_quota -c 'report -h' /mnt

# Report user/group/project quotas
xfs_quota -c 'report -u' /mnt
xfs_quota -c 'report -g' /mnt
xfs_quota -c 'report -p' /mnt

# Show quota state
xfs_quota -c 'state' /mnt

# Enable enforcement (expert mode required)
xfs_quota -x -c 'enable -u' /mnt
xfs_quota -x -c 'enable -g' /mnt
xfs_quota -x -c 'enable -p' /mnt

# Disable enforcement (accounting remains active)
xfs_quota -x -c 'disable' /mnt

# Set limits (expert mode)
xfs_quota -x -c 'limit bsoft=500m bhard=550m username' /mnt
xfs_quota -x -c 'limit isoft=10000 ihard=12000 username' /mnt
xfs_quota -x -c 'limit -g bsoft=10g bhard=12g groupname' /mnt
xfs_quota -x -c 'limit -p bsoft=20g bhard=25g projectname' /mnt

# Set default limits for new users
xfs_quota -x -c 'limit -d bsoft=500m bhard=550m' /mnt

Btrfs qgroups

Btrfs uses qgroups (quota groups) for subvolume-level quotas. Each subvolume automatically gets a qgroup with ID 0/<subvolumeID>. Higher-level qgroups (1/ID, 2/ID, etc.) can group subvolumes together.

Btrfs qgroup performance

Qgroups add significant overhead to all extent processing. Only enable if needed. Consider simple quotas (-s) for reduced overhead.

Enable and manage

# Enable quotas
btrfs quota enable /mnt

# Enable with simple quotas (less overhead, accounts to first owner)
btrfs quota enable -s /mnt

# Disable
btrfs quota disable /mnt

# Rescan quota metadata
btrfs quota rescan /mnt
btrfs quota rescan -w /mnt   # wait for completion
btrfs quota status /mnt

Qgroup management

# Show qgroups
btrfs qgroup show /mnt
btrfs qgroup show -r /mnt   # show referenced
btrfs qgroup show -e /mnt   # show exclusive

# Create qgroup
btrfs qgroup create 1/100 /mnt

# Assign subvolume to qgroup
btrfs qgroup assign 0/261 1/100 /mnt

# Set limits
btrfs qgroup limit 10G 1/100 /mnt
btrfs qgroup limit -e 5G 1/100 /mnt   # exclusive limit
btrfs qgroup limit -r 15G 1/100 /mnt  # referenced limit
btrfs qgroup limit none 1/100 /mnt    # remove limit

# Remove qgroup
btrfs qgroup remove 0/261 1/100 /mnt
btrfs qgroup destroy 1/100 /mnt

Referenced vs exclusive limits

TypeMeaning
Referenced (rfer)Total space reachable from any subvolume in the qgroup (includes shared data from snapshots/reflinks/dedup)
Exclusive (excl)Space unique to this qgroup (would be freed if all subvolumes in qgroup were deleted)

ZFS quotas

ZFS provides dataset-level, user/group/project-level, and reference quotas. All are set via ZFS properties, no separate quota files or mount options.

Dataset quotas

# Set quota (includes descendants and snapshots)
zfs set quota=100G pool/home/alice

# Set refquota (dataset's own referenced space only)
zfs set refquota=80G pool/home/alice

# View
zfs get quota,refquota,used,referenced pool/home/alice

# Remove
zfs set quota=none pool/home/alice

quota vs refquota

PropertyCountsUse case
quotaDataset + all descendants (including snapshots)Bound total space including snapshots
refquotaDataset's own referenced space onlyUser-visible limit (snapshots don't count against user)

User/group/project quotas

# User quota within a dataset
zfs set userquota@alice=10G pool/home
zfs set userquota@bob=15G pool/home

# Group quota
zfs set groupquota@staff=200G pool/home

# Project quota
zfs set projectquota@42=50G pool/data

# Default quotas (fallback for users without specific quota)
zfs set defaultuserquota=5G pool/home
zfs set defaultgroupquota=100G pool/home

# Object quotas (limit number of objects instead of bytes)
zfs set userobjquota@alice=100000 pool/home

# View user space usage
zfs userspace pool/home
zfs groupspace pool/home

Project quotas (directory quotas)

Project quotas provide directory-based quota limits independent of file ownership. They allow administrators to limit disk usage for specific directory trees regardless of which users own the files within them.

XFS project quotas

# 1. Add project to /etc/projects (ID:directory)
echo "100:/project/data" >> /etc/projects

# 2. Add project name to /etc/projid (name:ID)
echo "myproject:100" >> /etc/projid

# 3. Initialize the project directory
xfs_quota -x -c 'project -s myproject' /project/data

# 4. Set quota limits
xfs_quota -x -c 'limit -p bhard=10g myproject' /project/data

# Set project ID directly
xfs_io -c 'chproj 100' /project/data
xfs_io -c 'chproj -R 100' /project/data  # recursive

# Set project inheritance (new files inherit project ID)
chattr +P /project/data
chattr +P -R /project/data  # recursive

ext4 project quotas

# Set project ID
chattr -p 100 /project/data
chattr -p -R 100 /project/data  # recursive

# View project ID
lsattr -p /project/data

# Set project inheritance
chattr +P /project/data

Command reference

edquota (interactive)

# Edit user quota (opens $EDITOR)
edquota username

# Edit group quota
edquota -g groupname

# Edit project quota
edquota -P projectname

# Edit grace periods globally
edquota -t

# Edit grace period for specific user
edquota -T username

# Copy quota from prototype user
edquota -p prototype_user new_user

setquota (scriptable)

# Set user quota (blocks in 1KB units)
setquota username 500000 550000 50000 60000 /mnt

# Set group quota
setquota -g groupname 1000000 1100000 0 0 /mnt

# Set project quota
setquota -P projectname 2000000 2200000 0 0 /mnt

# Set grace period (seconds)
setquota -t 604800 604800 /mnt

# Copy from prototype
setquota -p prototype_user new_user /mnt

# Batch mode (read from stdin)
setquota -b /mnt < quotafile.txt

repquota (reporting)

# Report user quotas
repquota -u /mnt

# Report group quotas
repquota -g /mnt

# Report project quotas
repquota -P /mnt

# All filesystems, human-readable
repquota -a -s

# Don't resolve names (faster)
repquota -n /mnt

quota (user's own usage)

# Show user's own quotas
quota

# Group quotas
quota -g

# Project quotas
quota -P

# Verbose (show filesystems with no storage)
quota -v

# Human-readable
quota -s

warnquota (email alerts)

# Send email to users over quota
warnquota

# Check specific filesystems
warnquota /home /var

# Group quotas
warnquota -g

NFS quotas

NFS quota reporting uses rpc.rquotad on the server. The client quota command automatically queries the server via RPC.

# Start rpc.rquotad on server
systemctl enable --now rpc-rquotad

# /etc/hosts.allow (restrict access)
rquotad: 192.168.1.0/24

# /etc/hosts.deny
rquotad: ALL
NFS quota limitations

The rquota protocol only supports user quotas over NFS in most implementations. Group quotas may not be reported. Quota enforcement happens on the server, not the client.

Performance implications

FilesystemImplementationPerformance impact
ext4Separate quota files, journaledSome overhead on high-throughput workloads due to journal writes; benchmark before enabling
XFSMetadata-based (no separate files)Lower overhead than ext4; accounting always on, enforcement can be toggled
BtrfsExtent reference countingSignificant overhead; only enable if needed. Simple quotas (-s) reduce impact.
ZFSProperty-basedAsynchronous enforcement (small overage possible). Low overhead.

Best practices

  1. Use XFS for high-performance quota requirements. Metadata-based quotas have lower overhead than ext4's separate quota files.
  2. Set soft limit at 80-90% of hard limit to provide a warning buffer.
  3. Use grace periods: 7 days is standard; shorter for strict limits, longer for development environments.
  4. Use project quotas for shared hosting: directory-based limits independent of ownership.
  5. Use refquota on ZFS for user-visible limits, so snapshots don't count against the user.
  6. Only enable Btrfs qgroups if needed. They carry significant performance overhead.
  7. Monitor with repquota and schedule regular reports with trend analysis.
  8. Use warnquota to alert users before they hit hard limits.
  9. Test before production: validate quota configuration in a test environment first.
  10. Document quota policies and communicate limits clearly to users.

Sources & references

  1. Quota subsystem — Linux Kernel documentation — official kernel quota documentation validating soft/hard limits, grace periods, and quota architecture
  2. setquota(8) — Linux manual page — official setquota documentation validating quota setting syntax and grace period configuration
  3. repquota(8) — Linux manual page — official repquota documentation confirming quota reporting capabilities and options
  4. xfs_quota(8) — Linux manual page — official XFS quota documentation confirming XFS-specific quota commands and metadata-based implementation
  5. Btrfs Qgroups Documentation — official Btrfs qgroups documentation validating subvolume quotas, referenced/exclusive limits, and performance warnings

Frequently asked questions

What is the difference between soft and hard quota limits?

A soft limit can be exceeded for a grace period (default 7 days); once the grace period expires it is enforced as a hard limit. A hard limit is an absolute ceiling that cannot be exceeded except with `CAP_SYS_RESOURCE`. Grace periods are per-filesystem and per-resource (blocks vs inodes).

How do I enable quotas on ext4?

Mount with `usrquota,grpquota,prjquota` options, run `quotacheck -cug /mnt` to create quota files, then `quotaon -vug /mnt` to enable. On kernel 4.x+, you can use the ext4 quota feature with `mkfs.ext4 -O quota` or enable it on an existing filesystem with `tune2fs -Q`.

Does XFS need separate quota files?

No. XFS stores quota information in filesystem metadata, not separate quota files. Quotas have two components: accounting (enabled at mount with options like `uquota`) and enforcement (can be toggled with `xfs_quota -x -c 'enable -u'`). This gives lower overhead than ext4.

What are Btrfs qgroups?

Btrfs qgroups (quota groups) provide subvolume-level quotas. Each subvolume gets a qgroup with ID `0/`, and higher-level qgroups (`1/ID`, `2/ID`) can group subvolumes together. Qgroups add significant overhead to extent processing, so only enable them if needed. Simple quotas (`-s`) reduce the impact.

What is the difference between ZFS quota and refquota?

`quota` counts the dataset plus all descendants including snapshots, so it bounds total space. `refquota` counts only the dataset's own referenced space, so snapshots do not count against the user. Use `refquota` for user-visible limits where snapshots should not reduce a user's available space.

What are project quotas?

Project quotas provide directory-based quota limits independent of file ownership. They limit disk usage for a specific directory tree regardless of which users own the files within it. They are useful for per-tenant limits in shared hosting and application directories. XFS and ext4 both support project quotas.

How do I report quota usage?

Use `repquota -u /mnt` for user quotas, `repquota -g /mnt` for group quotas, and `repquota -P /mnt` for project quotas. Run `repquota -a -s` for all filesystems in human-readable format. On XFS, use `xfs_quota -c 'report -h' /mnt`. Individual users can check their own usage with the `quota` command.