Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Quota

Overview

Disk quota is a mechanism for limiting the amount of disk space and number of inodes a user or group can consume on a filesystem. The Linux kernel provides a VFS quota subsystem that individual filesystems implement through well-defined operations.

Quotas are essential for multi-user systems, shared hosting environments, and any scenario where fair resource allocation is required.

See also: ext4 Filesystem, XFS Filesystem, VFS Layer


VFS Quota Architecture

Core Subsystem

The VFS quota layer lives in fs/quota/ and provides:

  • Generic quota operationsdquot_operations interface
  • Quota on/off controlquotactl() syscall
  • Quota format plugins — VFS v0, v1, v2 formats
  • Accounting — Block and inode usage tracking per ID
┌─────────────────────────────────────────┐
│             Userspace                    │
│   quotaon/quotaoff/repquota/quota tools  │
└──────────────────┬──────────────────────┘
                   │ quotactl() syscall
┌──────────────────▼──────────────────────┐
│            VFS Quota Layer               │
│  fs/quota/dquot.c — generic operations  │
│  fs/quota/quota.c — quotactl handler    │
└──────────────────┬──────────────────────┘
                   │ dquot_operations
         ┌─────────┴─────────┐
         │                   │
    ┌────▼────┐         ┌────▼────┐
    │  ext4   │         │  XFS    │
    │ quota   │         │  quota  │
    └─────────┘         └─────────┘

struct dquot

Each quota entry is represented by a struct dquot:

struct dquot {
    struct hlist_node dq_hash;     /* Hash table linkage */
    struct list_head dq_inuse;     /* In-use list */
    struct list_head dq_free;      /* Free list */
    struct super_block *dq_sb;     /* Owning superblock */
    struct kqid dq_id;             /* User or group ID */
    qsize_t dq_dqb[MAXQUOTAS];    /* Block and inode usage */
    /* ... */
};

Quota Types

TypeConstantTracks
User quotaUSRQUOTAPer-user block/inode usage
Group quotaGRPQUOTAPer-group block/inode usage
Project quotaPRJQUOTAPer-project usage (XFS, ext4)

The quotactl() System Call

All quota management from userspace goes through quotactl():

#include <sys/quota.h>

int quotactl(int cmd, const char *special, int id, caddr_t addr);

Command Codes

CommandDescription
Q_QUOTAONEnable quotas on a filesystem
Q_QUOTAOFFDisable quotas
Q_GETQUOTAGet quota limits for a specific ID
Q_SETQUOTASet quota limits for a specific ID
Q_SETUSESet current usage (admin only)
Q_GETFMTGet quota format version
Q_SYNCFlush quota info to disk
Q_GETSTATSGet filesystem-wide quota statistics
Q_GETINFOGet quota info (grace times, etc.)
Q_SETINFOSet grace times

Example: Query User Quota

#include <stdio.h>
#include <sys/quota.h>

int main(void)
{
    struct dqblk dq;

    if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), "/dev/sda1",
                 1000, (caddr_t)&dq) < 0) {
        perror("quotactl");
        return 1;
    }

    printf("Blocks: used=%llu soft=%llu hard=%llu\n",
           (unsigned long long)dq.dqb_curspace,
           (unsigned long long)dq.dqb_bsoftlimit,
           (unsigned long long)dq.dqb_bhardlimit);
    return 0;
}

ext4 Quota

Features

  • Supports user, group, and project quotas (since kernel 4.13)
  • Quota files stored as hidden files in the filesystem root
  • Integrates with journaled quota for consistency

Enabling Quotas

# Create quota files (traditional method)
quotacheck -cugm /home

# Enable quotas
quotaon -ug /home

# Or mount with quota options
mount -o usrquota,grpquota /dev/sda1 /home

Persistent Configuration (/etc/fstab)

/dev/sda1  /home  ext4  defaults,usrquota,grpquota  0 2

Project Quotas on ext4

Project quotas allow grouping directories/files under a single quota regardless of user/group ownership:

# Enable project quota support
tune2fs -O project /dev/sda1

# Define a project
echo "100:/data/projects/webapp" >> /etc/projects
echo "webapp:100" >> /etc/projid

# Set limits
edquota -p webapp -f /home

Journaled Quota

ext4 can store quota information in the journal for crash consistency:

tune2fs -O quota /dev/sda1
# Quota info is automatically journaled

XFS Quota

XFS has its own quota implementation, historically more mature than ext4’s:

XFS Quota Types

TypeMount OptionDescription
UseruquotaPer-user limits
GroupgquotaPer-group limits
ProjectpquotaPer-project limits
AccountaccountAccounting only (no limits)

Enabling XFS Quotas

# Mount with all quota types
mount -o uquota,gquota,pquota /dev/sdb1 /data

# Or remount an existing filesystem
mount -o remount,uquota /data

XFS Quota Commands

# Set user quota (blocks in 1K units)
xfs_quota -x -c 'limit bsoft=500m bhard=600m user1' /data

# Set inode limits
xfs_quota -x -c 'limit isoft=5000 ihard=6000 user1' /data

# Report usage
xfs_quota -x -c 'report -h' /data

# Project quota setup
xfs_quota -x -c 'project -s webapp' /data
xfs_quota -x -c 'limit bsoft=1g bhard=2g webapp' /data

XFS vs ext4 Quota Differences

FeatureXFSext4
ImplementationNative XFS quota subsystemVFS quota generic layer
Project quota supportLong-standing (since XFS inception)Since kernel 4.13
Realtime subvolumeSeparate quota accountingN/A
Grace periodsPer-ID per-typePer-type only
EnforcementReal-time, at allocationDelayed (allocation-time)

Project Quota

Concept

Project quotas provide a way to enforce disk limits on a directory tree independent of who owns the files. This is valuable for:

  • Multi-tenant environments (limiting per-customer storage)
  • Container rootfs size control
  • Application-specific storage limits

Setup (ext4)

# 1. Enable project quota feature
tune2fs -O project /dev/sda1

# 2. Assign project IDs via /etc/projid
echo "webapp:100" >> /etc/projid
echo "database:101" >> /etc/projid

# 3. Map directories to projects via /etc/projects
echo "100:/var/www/webapp" >> /etc/projects
echo "101:/var/lib/mysql" >> /etc/projects

# 4. Enable project quota
mount -o prjquota /dev/sda1 /mnt

# 5. Set limits
edquota -p webapp -f /mnt

Setup (XFS)

# XFS uses xfs_quota directly
xfs_quota -x -c 'project -s webapp /var/www/webapp' /data
xfs_quota -x -c 'limit bhard=10g webapp' /data

Quota Files and Metadata

Traditional Quota Files

File (ext2/3/4)Purpose
aquota.userUser quota database
aquota.groupGroup quota database

Modern Quota (Hidden Inodes)

In ext4 with QUOTA feature, quota data is stored in hidden inodes:

# View hidden quota inodes
debugfs -R 'stat <8>' /dev/sda1   # User quota inode
debugfs -R 'stat <9>' /dev/sda1   # Group quota inode

Quota Format Versions

FormatDescription
v0Original quota format (legacy)
v132-bit UID/GID support
v264-bit space accounting, grace time tracking

Grace Times

When a user exceeds a soft limit, a grace period begins. If usage remains above the soft limit beyond the grace period, the soft limit is enforced as a hard limit.

# Set grace times
setquota -u user1 --block-grace 86400 --inode-grace 604800 /home

# View current grace times
repquota -s /home

# Or via quotactl()
struct dqinfo info;
quotactl(QCMD(Q_GETINFO, USRQUOTA), "/dev/sda1", 0, (caddr_t)&info);
printf("Block grace: %u seconds\n", info.dqi_bgrace);

Default Grace Periods

  • Blocks: 7 days (604800 seconds)
  • Inodes: 7 days

Quota Tools

Essential Commands

CommandDescription
quotacheckScan filesystem and build quota database
quotaonEnable quota enforcement
quotaoffDisable quota enforcement
repquotaReport quota usage for a filesystem
edquotaEdit quotas for a user/group
setquotaSet quotas from command line
warnquotaSend email warnings to users over quota
quotaDisplay current user’s quota

Common Usage

# Check and repair quota databases
quotacheck -ugm /home

# View your own quota
quota -v

# Report all quotas on /home
repquota /home

# Edit quota for user 'alice'
edquota alice

# Copy quota from user 'alice' to 'bob'
edquota -p alice bob

Monitoring

Kernel Counters

# View quota statistics
cat /proc/fs/ext4/sda1/quotas

# XFS-specific
xfs_quota -x -c 'report -h' /mount

Per-Filesystem Quota Status

# Check if quotas are active
mount | grep quota
# or
findmnt -o TARGET,OPTIONS | grep quota

Programmatic Monitoring

#include <sys/quota.h>
#include <stdio.h>

void check_quota(const char *dev, int uid)
{
    struct dqblk dq;
    if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), dev, uid,
                 (caddr_t)&dq) == 0) {
        double usage_pct = 100.0 * dq.dqb_curspace /
                           dq.dqb_bhardlimit;
        printf("User %d: %.1f%% of quota used\n", uid, usage_pct);
    }
}

Containers and Quotas

Docker and Quota

Docker uses project quotas (XFS) or overlay2 size limits to enforce container storage limits:

# Docker daemon must be started with XFS + pquota
mount -o pquota /dev/sdb1 /var/lib/docker

# Set container storage limit
docker run --storage-opt size=10G ubuntu

Kubernetes Ephemeral Storage

Kubernetes can use XFS project quotas to enforce ephemeral storage limits:

resources:
  limits:
    ephemeral-storage: "10Gi"

Troubleshooting

Common Issues

ProblemCauseSolution
Quota not enforcingNot mounted with quota optionAdd usrquota to mount options
Wrong usage numbersDirty quota databaseRun quotacheck -ugm
Project quota not workingFeature not enabledtune2fs -O project
Grace time not expiringClock skew or wrong timezoneVerify system time

Checking Quota Consistency

# Force quota database rebuild (unmount or read-only first)
quotacheck -ugm /home

# For XFS, quota is always consistent (no separate database)

Quota Internals

dquot Lifecycle

stateDiagram-v2
    [*] --> Allocated: User first writes
    Allocated --> Active: Quota loaded from disk
    Active --> Dirty: Usage changes
    Dirty --> Writeback: Periodic flush
    Writeback --> Active: Written to disk
    Active --> Freed: Quota disabled or inode freed
    Freed --> [*]

Quota Accounting

The kernel tracks quota usage at multiple levels:

/* Simplified quota accounting */
struct dquot {
    struct hlist_node dq_hash;     /* Hash table linkage */
    struct list_head dq_inuse;     /* In-use list */
    struct list_head dq_free;      /* Free list */
    struct super_block *dq_sb;     /* Owning superblock */
    struct kqid dq_id;             /* User or group ID */
    qsize_t dq_dqb[MAXQUOTAS];    /* Block and inode usage */
    /* ... */
};

/* Quota data structure */
struct dquot {
    qsize_t dqb_curspace;     /* Current space used */
    qsize_t dqb_curinodes;    /* Current inodes used */
    qsize_t dqb_bsoftlimit;   /* Block soft limit */
    qsize_t dqb_bhardlimit;   /* Block hard limit */
    qsize_t dqb_isoftlimit;   /* Inode soft limit */
    qsize_t dqb_ihardlimit;   /* Inode hard limit */
    time_t dqb_btime;         /* Block grace time */
    time_t dqb_itime;         /* Inode grace time */
};

Quota Hash Table

Dquots are stored in a hash table for fast lookup:

/* Hash function for dquot lookup */
static inline struct hlist_bl_head *
dqhash(struct super_block *sb, struct kqid qid)\{
    unsigned int n = hash_32(qid.val + sb->s_dev,
                             dq_hash_bits);
    return &dq_hashtable[n];
}

Quota Performance Impact

Overhead Analysis

OperationOverheadNotes
File create~1-2%Inode quota check
File write~1-3%Block quota check + update
File delete~1-2%Quota release
mkdir~1-2%Inode quota check
Quota report~5-10%Scans quota database

Tuning Quota Performance

# Reduce quota sync frequency (trade consistency for performance)
# /etc/fstab mount options
/dev/sda1  /home  ext4  defaults,usrquota,grpquota,jqfmt=vfsv1  0 2

# For XFS, quota is always on (no performance tuning needed)
# But you can disable enforcement while keeping accounting:
mount -o remount,account /data

Quota in Production

Multi-User Server Example

#!/bin/bash
# Setup quotas for a shared hosting server

# Enable quota on /home
mount -o remount,usrquota,grpquota /home

# Create quota files
quotacheck -cugm /home

# Set default quotas for new users
setquota -u default 5G 6G 5000 6000 /home

# Set quotas for specific users
setquota -u alice 10G 12G 10000 12000 /home
setquota -u bob 2G 3G 2000 3000 /home

# Set group quotas
setquota -g developers 50G 60G 50000 60000 /home

# Enable quotas
quotaon -ug /home

# Verify
repquota -s /home

Quota Monitoring Script

#!/bin/bash
# Monitor quota usage and alert on threshold

THRESHOLD=90

for user in $(awk -F: '$3 >= 1000 {print $1}' /etc/passwd); do
    usage=$(quota -u $user | tail -1 | awk '{print $2}' | sed 's/%//')
    if [ "$usage" -ge "$THRESHOLD" ]; then
        echo "WARNING: User $user is at $usage% quota"
        # Send alert email
        echo "User $user quota usage: $usage%" | mail -s "Quota Alert" admin@example.com
    fi
done

Quota and Containers

Docker Storage Limits

# Docker uses project quotas for storage limits
# Requires XFS with pquota mount option

# Mount with project quota support
mount -o pquota /dev/sdb1 /var/lib/docker

# Set container storage limit
docker run --storage-opt size=10G ubuntu

# Verify quota
xfs_quota -x -c 'report -h' /var/lib/docker

Kubernetes Ephemeral Storage

# Kubernetes ephemeral storage limits
apiVersion: v1
kind: Pod
metadata:
  name: myapp
spec:
  containers:
  - name: app
    image: myapp:latest
    resources:
      limits:
        ephemeral-storage: "10Gi"
      requests:
        ephemeral-storage: "5Gi"

Quota Troubleshooting

Common Issues

ProblemCauseSolution
Quota not enforcingNot mounted with quota optionAdd usrquota to mount options
Wrong usage numbersDirty quota databaseRun quotacheck -ugm
Project quota not workingFeature not enabledtune2fs -O project
Grace time not expiringClock skew or wrong timezoneVerify system time
“Quota exceeded” errorHard limit reachedIncrease limit or free space
Quota database corruptionUnclean shutdownRun quotacheck -ugm

Debugging Quota Issues

# Check quota status
quota -v

# View quota for specific user
repquota -u alice /home

# Check quota database integrity
quotacheck -ugm /home

# Force quota database rebuild
quotacheck -fugm /home

# View kernel quota messages
dmesg | grep -i quota

# Check quota format
dumpe2fs /dev/sda1 | grep -i quota

Quota Format Versions

FormatDescriptionFeatures
v0Original quota format32-bit UIDs, basic limits
v1Improved format32-bit UIDs, grace times
v2Modern format64-bit space accounting, project quotas
# Check current quota format
quotactl -f /home

# Convert quota format
quotacheck -cugm -F vfsv1 /home

References

Further Reading

Related topics: ext4 Filesystem, XFS Filesystem, VFS Layer, Disk Management