Linux filesystem 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 and are essential for multi-user systems, shared hosting, and capacity planning.
Quota types
| Type | Scope | Use case |
|---|---|---|
| User quotas | All files owned by a specific user (UID) | Multi-user systems, per-user limits |
| Group quotas | All files owned by members of a group (GID) | Project teams, departmental limits |
| Project quotas | All files within a directory tree, regardless of owner | Per-tenant limits in shared hosting, application directories |
Soft vs hard limits
| Limit | Behavior |
|---|---|
| Soft limit | Can be exceeded for a grace period. When grace expires, enforced as hard limit. |
| Hard limit | Absolute limit; cannot be exceeded (except with CAP_SYS_RESOURCE). |
| Grace period | Time 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 0Modern 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/sda1Quota 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 /mntXFS 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 /mntxfs_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' /mntBtrfs 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.
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 /mntQgroup 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 /mntReferenced vs exclusive limits
| Type | Meaning |
|---|---|
| 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/alicequota vs refquota
| Property | Counts | Use case |
|---|---|---|
quota | Dataset + all descendants (including snapshots) | Bound total space including snapshots |
refquota | Dataset's own referenced space only | User-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/homeProject 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 # recursiveext4 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/dataCommand 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_usersetquota (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.txtrepquota (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 /mntquota (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 -swarnquota (email alerts)
# Send email to users over quota
warnquota
# Check specific filesystems
warnquota /home /var
# Group quotas
warnquota -gNFS 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: ALLThe 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
| Filesystem | Implementation | Performance impact |
|---|---|---|
| ext4 | Separate quota files, journaled | Some overhead on high-throughput workloads due to journal writes; benchmark before enabling |
| XFS | Metadata-based (no separate files) | Lower overhead than ext4; accounting always on, enforcement can be toggled |
| Btrfs | Extent reference counting | Significant overhead; only enable if needed. Simple quotas (-s) reduce impact. |
| ZFS | Property-based | Asynchronous enforcement (small overage possible). Low overhead. |
Best practices
- Use XFS for high-performance quota requirements. Metadata-based quotas have lower overhead than ext4's separate quota files.
- Set soft limit at 80-90% of hard limit to provide a warning buffer.
- Use grace periods: 7 days is standard; shorter for strict limits, longer for development environments.
- Use project quotas for shared hosting: directory-based limits independent of ownership.
- Use
refquotaon ZFS for user-visible limits, so snapshots don't count against the user. - Only enable Btrfs qgroups if needed. They carry significant performance overhead.
- Monitor with
repquotaand schedule regular reports with trend analysis. - Use
warnquotato alert users before they hit hard limits. - Test before production: validate quota configuration in a test environment first.
- Document quota policies and communicate limits clearly to users.