Optimizing rsync Performance with NAS: Solving Full Recopy Issues on SMB/CIFS Shares


2 views

When I first set up my daily backup routine from Ubuntu to a D-Link DNS-321 NAS using rsync, I encountered a frustrating behavior:

rsync -r /home/user/source /media/nas/destination

Despite expecting rsync's delta-transfer algorithm to only copy changed files, the operation consistently took 2.5 hours to complete for my 76GB dataset over a 1Gbps LAN. The system was essentially performing a full copy every time.

I tested multiple rsync flags to troubleshoot:

# Attempt 1: Using checksum comparison
rsync -rc /home/user/source /media/nas/destination

# Attempt 2: Explicitly preserving timestamps
rsync -r --times /home/user/source /media/nas/destination

Neither approach solved the issue. Running stat on source and destination files revealed the core problem - file timestamps weren't being preserved during transfer:

# Source file
stat /home/user/source/document.pdf
Access: 2023-10-15 14:30:00
Modify: 2023-10-14 09:15:00
Change: 2023-10-14 09:15:00

# Destination file
stat /media/nas/destination/document.pdf
Access: 2023-10-16 08:00:00  # Current transfer time
Modify: 2023-10-16 08:00:00
Change: 2023-10-16 08:00:00

The issue stemmed from incorrect SMB/CIFS mount options in /etc/fstab. My original configuration:

//192.168.10.199/Volume_1 /media/Volume_1 cifs guest,rw,iocharset=utf8,file_mode=0777,dir_mode=0777 0 0

This configuration had several problems:
- Anonymous guest access
- Overly permissive 0777 permissions
- No user/group mapping
- Missing critical options for timestamp preservation

The corrected mount configuration that resolved all issues:

//192.168.10.199/Volume_2 /media/Volume_2 cifs 
username=sam,password=some_password,uid=developer,gid=developer,_netdev 0 0

Key improvements:
- Proper authentication instead of guest access
- UID/GID mapping to maintain ownership
- _netdev for network dependency handling
- Default permissions allowing proper metadata handling

With the corrected mount, this rsync command now works efficiently:

rsync -avh --progress --delete /home/user/source/ /media/nas/destination/

Flags explanation:
- -a: Archive mode (preserves everything)
- -v: Verbose output
- -h: Human-readable units
- --progress: Transfer progress
- --delete: Remove extraneous files
- Trailing slashes: Important for correct path interpretation

After fixing the mount configuration:
- Initial sync: ~2.5 hours (expected for full transfer)
- Subsequent syncs: 3-5 minutes (only changed files)
- CPU usage dropped from 80% to under 10%
- Network utilization became intermittent instead of sustained

For environments where SMB mounting isn't optimal:

# Using rsync directly with SMB credentials
rsync -avz --progress --rsync-path="sudo rsync" \
-e "ssh -i /path/to/key" \
/home/user/source/ user@nas:/path/to/destination/

# Using rclone for cloud-like interfaces
rclone sync /home/user/source nas:destination \
--progress --checksum --transfers=8

When running daily backups using rsync to a NAS device, many administrators encounter a frustrating scenario where rsync appears to recopy all files despite using proper sync parameters. The typical command:

rsync -r /home/user/source /media/nas/destination

Or even with checksum verification:

rsync -rc /home/user/source /media/nas/destination

Still results in the entire dataset being transferred each time, despite only needing incremental updates.

The core issue stems from improper Samba share mounting configurations that prevent rsync from:

  • Preserving file timestamps (mtime/ctime)
  • Maintaining proper file ownership metadata
  • Utilizing efficient delta-transfer algorithms

When examining file metadata:

stat /home/user/source/example.txt
stat /media/nas/destination/example.txt

The output reveals timestamp discrepancies, confirming the sync mechanism can't properly identify unchanged files.

The breakthrough comes from proper CIFS mount configuration in /etc/fstab. Instead of:

//192.168.10.199/Volume_1 /media/Volume_1 cifs guest,rw,iocharset=utf8,file_mode=0777,dir_mode=0777 0 0

Use this authenticated, permission-aware alternative:

//192.168.10.199/Volume_2 /media/Volume_2 cifs username=sam,password=some_password,uid=developer,gid=developer,_netdev 0 0

Combine the correct mount with these rsync flags:

rsync -avh --progress --stats --delete \
--partial --partial-dir=.rsync-partial \
/home/user/source/ /media/nas/destination/

Key parameters explained:

  • -a: Archive mode (preserves everything)
  • -v: Verbose output
  • -h: Human-readable numbers
  • --delete: Remove extraneous destination files
  • --partial: Keep partially transferred files

To confirm the solution works:

  1. Run initial full backup (will take time)
  2. Modify a few test files
  3. Run rsync again - should only transfer changes
  4. Check transfer times and network utilization

For automated daily backups, consider this wrapper script:

#!/bin/bash
LOG="/var/log/rsync_nas.log"
echo "Starting backup $(date)" >> $LOG
rsync -avh --progress --stats --delete \
--partial --partial-dir=.rsync-partial \
/home/user/source/ /media/nas/destination/ >> $LOG 2>&1
echo "Backup completed $(date)" >> $LOG