Learn how to effectively manage and monitor XFS filesystem inodes to prevent exhaustion and maintain optimal system performance.

Understanding XFS Inodes

What are Inodes?

Inodes are fundamental filesystem structures that:

  • Store metadata about files
  • Track file permissions
  • Maintain file locations
  • Handle file attributes
  • Manage file links

XFS Inode Management

1. Checking Inode Usage

# View filesystem information
df -i

# Detailed XFS information
xfs_info /mount/point

# Find directories with most inodes
find / -xdev -printf '%h\n' | sort | uniq -c | sort -k 1 -n

2. Monitoring Tools

#!/bin/bash
# monitor-inodes.sh

check_inodes() {
    local mount_point=$1
    local threshold=90
    
    # Get inode usage percentage
    usage=$(df -i $mount_point | tail -1 | awk '{print $5}' | sed 's/%//')
    
    if [ $usage -gt $threshold ]; then
        echo "Warning: Inode usage on $mount_point is at ${usage}%"
        
        # Find top inode-using directories
        echo "Top inode-consuming directories:"
        find $mount_point -xdev -printf '%h\n' | sort | uniq -c | sort -k 1 -n | tail -5
    fi
}

# Check all XFS filesystems
for fs in $(df -t xfs | tail -n+2 | awk '{print $6}'); do
    check_inodes $fs
done

Preventing Inode Exhaustion

1. Filesystem Creation

# Create XFS with custom inode size
mkfs.xfs -i size=512 /dev/sda1

# Specify inode ratio
mkfs.xfs -i maxpct=25 /dev/sda1

2. Runtime Management

# Monitor file creation patterns
#!/bin/bash
# track-file-creation.sh

log_file_creation() {
    local dir=$1
    
    inotifywait -m -r $dir -e create |
    while read path action file; do
        echo "$(date): New file created - $path$file"
        current_inodes=$(df -i $dir | tail -1 | awk '{print $3}')
        echo "Current inode usage: $current_inodes"
    done
}

# Start monitoring
log_file_creation /path/to/monitor

Performance Optimization

1. Inode Allocation

# Optimize inode allocation
xfs_io -c "extsize=64k" /mount/point

# Set project quota for inode limits
xfs_quota -x -c 'project -s myproject' /mount/point

2. Directory Indexing

# Enable directory indexing
xfs_io -c "chattr +i" /path/to/directory

# Check directory attributes
xfs_io -c "lsattr" /path/to/directory

Maintenance and Recovery

1. Filesystem Check

# Check XFS filesystem
xfs_repair -n /dev/sda1

# Force check and repair
xfs_repair /dev/sda1

2. Backup and Restore

# Backup XFS metadata
xfs_metadump /dev/sda1 metadata.img

# Restore from backup
xfs_mdrestore metadata.img /dev/sda1

Monitoring Scripts

1. Automated Inode Monitoring

#!/usr/bin/env python3
# inode_monitor.py

import os
import subprocess
import time

def get_inode_usage(mount_point):
    df = subprocess.check_output(['df', '-i', mount_point]).decode()
    usage = df.split('\n')[1].split()[4].rstrip('%')
    return int(usage)

def alert_high_usage(mount_point, threshold=90):
    usage = get_inode_usage(mount_point)
    if usage > threshold:
        print(f"Alert: High inode usage ({usage}%) on {mount_point}")
        return True
    return False

def find_large_directories(mount_point):
    cmd = f"find {mount_point} -xdev -type d -exec sh -c 'echo $(find \"$1\" -maxdepth 1 | wc -l) $1' _ {{}} \\;"
    output = subprocess.check_output(cmd, shell=True).decode()
    return sorted(output.split('\n'), key=lambda x: int(x.split()[0]) if len(x.split()) > 1 else 0)

def main():
    mount_points = [line.split()[1] for line in open('/proc/mounts') 
                   if line.split()[2] == 'xfs']
    
    for mount in mount_points:
        if alert_high_usage(mount):
            print("\nLargest directories by file count:")
            large_dirs = find_large_directories(mount)[-5:]
            for dir_info in large_dirs:
                if dir_info:
                    count, path = dir_info.split(' ', 1)
                    print(f"{path}: {count} files")

if __name__ == "__main__":
    main()

2. Trend Analysis

#!/usr/bin/env python3
# inode_trends.py

import sqlite3
import time
from datetime import datetime

def init_db():
    conn = sqlite3.connect('inode_history.db')
    c = conn.cursor()
    c.execute('''CREATE TABLE IF NOT EXISTS inode_usage
                 (timestamp TEXT, mount_point TEXT, 
                  total_inodes INTEGER, used_inodes INTEGER)''')
    return conn

def record_usage(conn, mount_point):
    c = conn.cursor()
    df = subprocess.check_output(['df', '-i', mount_point]).decode()
    _, total, used, _, _, _ = df.split('\n')[1].split()
    
    c.execute('''INSERT INTO inode_usage VALUES
                 (?, ?, ?, ?)''',
              (datetime.now().isoformat(), mount_point, 
               int(total), int(used)))
    conn.commit()

def analyze_trends(conn, mount_point, days=30):
    c = conn.cursor()
    c.execute('''SELECT date(timestamp), avg(used_inodes * 100.0 / total_inodes)
                 FROM inode_usage
                 WHERE mount_point = ?
                 GROUP BY date(timestamp)
                 ORDER BY timestamp DESC
                 LIMIT ?''', (mount_point, days))
    return c.fetchall()

Best Practices

  1. Planning

    • Size inodes appropriately
    • Monitor usage patterns
    • Plan for growth
  2. Maintenance

    • Regular monitoring
    • Proactive cleanup
    • Trend analysis
  3. Documentation

    • Track configuration changes
    • Document cleanup procedures
    • Maintain usage history

Remember that proper inode management is crucial for maintaining healthy XFS filesystems. Regular monitoring and proactive management can prevent inode-related issues before they impact system performance.