Converting ext4 to xfs on Linux: Filesystem Migration Guide
How to convert a Linux filesystem from ext4 to xfs, including data migration, performance comparison, and when to choose each filesystem.
Introduction
ext4 and xfs are the two most common Linux filesystems, each with different strengths. ext4 is the default on many distributions and excels at general-purpose use. xfs is preferred for large files and parallel I/O workloads. Converting between them requires a data migration strategy since there is no in-place conversion tool. This post covers the migration process and when to choose each filesystem.
Environment
The examples convert a 500 GB ext4 partition to xfs on Ubuntu 22.04 LTS. The partition contains a mix of small files and large media files.
df -T /data
# Filesystem Type 1K-blocks Used Available Use% Mounted on
# /dev/sdb1 ext4 524288000 123456789 376831211 25% /data
blkid /dev/sdb1
# /dev/sdb1: UUID="12345678-1234-1234-1234-123456789abc" TYPE="ext4"Problem
You want to migrate from ext4 to xfs for better performance with large files, or because your distribution defaults to xfs. The challenge is that there is no direct conversion tool. The migration requires:
- Backing up data
- Recreating the partition as xfs
- Restoring data
- Updating system configuration
Analysis
ext4 vs xfs comparison:
| Feature | ext4 | xfs |
|---|---|---|
| Max file size | 16 TB | 8 EB |
| Max volume size | 1 EB | 8 EB |
| Default on | Debian, Ubuntu | RHEL, CentOS |
| Journal | Metadata only | Data + metadata |
| Online defrag | Yes | Yes (xfs_fsr) |
| Quota | Yes | Yes (better) |
| Snapshots | No | No |
| Allocation | Block-based | Extent-based |
When to choose xfs:
- Large files (media, databases)
- High parallel I/O
- Large volumes (> 16 TB)
- Server workloads
When to choose ext4:
- General-purpose use
- Many small files
- USB drives, SD cards
- Recovery tools are more mature
Solution
1. Back up the data
# Create a full backup
sudo rsync -av /data/ /backup/data/
# Or use tar
sudo tar -czf /backup/data-backup.tar.gz -C / data
# Verify backup
ls -lh /backup/data-backup.tar.gz2. Unmount the partition
# Stop any services using the partition
sudo systemctl stop nginx # If serving web content
# Unmount
sudo umount /data
# If the partition is busy, find what is using it
sudo lsof +D /data
sudo fuser -m /data3. Recreate the partition as xfs
# Check partition table
sudo fdisk -l /dev/sdb
# Device Boot Start End Sectors Size Id Type
# /dev/sdb1 2048 1048575999 1048573952 500G 83 Linux
# Create new xfs filesystem
sudo mkfs.xfs -f /dev/sdb1
# meta-data=/dev/sdb1 isize=512 agcount=4, agsize=32768000 blks
# = sectsz=512 attr=2, projid32bit=1
# data = bsize=4096 blocks=131072000, imaxpct=25
# = sunit=0 swidth=0 blks
# naming =version 2 bsize=4096 ascii-ci=0 ftype=1
# log =internal log bsize=4096 blocks=64000, version=2
# = sectsz=512 sunit=0 blks, lazy-count=1
# realtime =none extsz=4096 blocks=0, rtextents=04. Mount the new filesystem
# Create mount point (if not exists)
sudo mkdir -p /data
# Mount
sudo mount /dev/sdb1 /data
# Update /etc/fstab
# Find the old entry
grep /data /etc/fstab
# UUID=12345678-1234-1234-1234-123456789abc /data ext4 defaults 0 2
# Update to xfs with new UUID
sudo blkid /dev/sdb1
# /dev/sdb1: UUID="abcdef01-2345-6789-abcd-ef0123456789" TYPE="xfs"
# Edit /etc/fstab
sudo nano /etc/fstab
# UUID=abcdef01-2345-6789-abcd-ef0123456789 /data xfs defaults 0 25. Restore data
# Restore from rsync
sudo rsync -av /backup/data/ /data/
# Or restore from tar
sudo tar -xzf /backup/data-backup.tar.gz -C /
# Verify data
du -sh /data
ls -la /data6. Set permissions
# Set ownership
sudo chown -R root:root /data
# Set permissions
sudo chmod -R 755 /data
# For specific directories
sudo chown -R www-data:www-data /data/web
sudo chmod -R 750 /data/web7. Enable xfs-specific features
# Enable discard for SSDs
sudo mount -o remount,discard /data
# Or update /etc/fstab
# UUID=abcdef01-... /data xfs defaults,discard 0 2
# Enable user quotas
sudo mount -o remount,usrquota /data
# Initialize quota
sudo quotacheck -cmu /data
sudo quotaon /data8. Verify the migration
# Check filesystem type
df -T /data
# Filesystem Type 1K-blocks Used Available Use% Mounted on
# /dev/sdb1 xfs 524288000 123456789 376831211 25% /data
# Check mount options
mount | grep /data
# /dev/sdb1 on /data type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=256k,noquota)
# Run a performance test
dd if=/dev/zero of=/data/test bs=1M count=1024 oflag=direct9. Performance comparison
# Test read performance
dd if=/data/test of=/dev/null bs=1M
# Test write performance
dd if=/dev/zero of=/data/test bs=1M count=1024 oflag=direct
# Test random I/O with fio
fio --name=test --rw=randwrite --bs=4k --size=1G --numjobs=4 --runtime=6010. Cleanup
# Remove backup (after verifying)
# sudo rm -rf /backup/data
# Remove old backup archive
# sudo rm /backup/data-backup.tar.gzLessons Learned
Filesystem migration from ext4 to xfs requires a backup-and-restore approach since there is no in-place conversion tool. Always verify backups before proceeding. xfs excels for large files and server workloads, while ext4 remains excellent for general-purpose use. The migration is straightforward but requires planning and downtime. Test the migration procedure in a staging environment before applying to production.
This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.