Search terms: slow NAS · slow SMB · slow CIFS · 25 MB/s · 40 MB/s · GVFS · gvfsd-fuse ·
smb-share:server= · USB 2.0 · 480 Mbps · ASM225CM · UGREEN · nobarrier · rsync says 100%
but still running
Solved 2026-08-08. Transfers to the UGREEN NAS were running 25-30 MB/s on a gigabit LAN. Two separate causes, neither of them the network. Ended at 74.6 MB/s — a 2.7× improvement.
| Stage | Write speed |
|---|---|
| Starting point (GVFS mount, drive on USB 2.0) | ~25-30 MB/s |
| After switching to a kernel CIFS mount | 40.9 MB/s |
| After moving the NAS’s drive to a USB 3.0 port | 74.6 MB/s |
Both of these produced plausible, completely wrong measurements during this investigation. Neither is obvious.
rsync -ah --progress <3.4GB file> /mnt/nas/test/
3.34G 100% 1.98GB/s 0:00:01
1.98 GB/s on a gigabit link is impossible (~110 MB/s ceiling). rsync measured the speed of
writing into the page cache — RAM — not to the NAS. It printed 100% when it had handed
off every byte, then sat there while the kernel flushed those pages over the network. That gap
between “100%” and the prompt returning is the real transfer.
See what’s actually pending:
watch -n1 'grep -E "^(Dirty|Writeback):" /proc/meminfo'
Dirty = written but not yet sent. Writeback = in flight. The transfer is genuinely done when
both reach zero. During a 3.4 GB copy this box showed 1.4 GB sitting in Writeback long after
rsync claimed completion.
Benchmark writes with conv=fdatasync — it forces everything to the server before dd
stops the clock:
dd if=<big-local-file> of=/mnt/nas/test/benchmark.tmp bs=1M count=1024 conv=fdatasync
Reading the same 1 GB region twice gave 19.3 MB/s, then 72.2 MB/s. The second read was served from the NAS’s memory, not its disks. That nearly produced a claimed “3.7× improvement” that did not exist.
Always benchmark a region you have never read before. Use different offsets for each test:
dd if=/mnt/nas/bigfile.img of=/dev/null bs=1M count=1024 skip=6144 # test A
dd if=/mnt/nas/bigfile.img of=/dev/null bs=1M count=1024 skip=7168 # test B
Paired cold reads gave the honest answer: 21.3 vs 38.3 MB/s.
The accidental cached read turned out to be useful anyway — it measured the NAS’s protocol/CPU path with storage removed, and 72 MB/s later matched the final disk-backed result almost exactly.
Mounting a share by clicking it in the file manager gives you a GVFS/FUSE mount, in
userspace. Every block round-trips through gvfsd-fuse. Check with:
ls /run/user/1000/gvfs/ # gvfs mounts (slow)
mount -t cifs # kernel mounts (fast)
If the first has entries and the second is empty, that’s the problem. Measured cost here: 21.3 vs 38.3 MB/s cold read — roughly half the throughput.
sudo apt install cifs-utils
Credentials in a file, created with restrictive permissions before anything is written to it, and edited in an editor so the password never enters shell history:
install -m 600 /dev/null ~/.smbcredentials && nano ~/.smbcredentials
username=YOUR_USER
password=YOUR_PASSWORD
domain=workgroup
sudo mkdir -p /mnt/nas
sudo mount -t cifs "//10.0.0.15/<share>" /mnt/nas \
-o credentials=/home/aztechguy/.smbcredentials,uid=1000,gid=1000,iocharset=utf8,vers=3.0
uid=1000,gid=1000 makes files yours instead of root’s. Persistent version for /etc/fstab —
nofail and _netdev matter, or an unreachable NAS can hang boot:
//10.0.0.15/<share> /mnt/nas cifs credentials=/home/aztechguy/.smbcredentials,uid=1000,gid=1000,iocharset=utf8,vers=3.0,nofail,_netdev,x-systemd.automount 0 0
rsync note: rsync speaks only user@host:/path (SSH) or rsync://host/module. A bare
10.0.0.15/share/folder is treated as a local relative path. To an SMB-only NAS you must
rsync to the mounted path.
The bigger one, and invisible from the client. Find where the share actually lives:
grep -A4 "<share-name>" /etc/samba/smb.conf
[1.44.1-64570]
path = /mnt/@usb/sda1 <- USB-attached, not an internal array
All prior analysis of the internal disks, RAID layout and free space was aimed at drives that were never in the path. Check the share’s path before profiling storage.
Then check the link speed of that device, on the NAS:
for d in $(readlink -f /sys/block/sda | tr '/' '\n' | grep -E "^[0-9]+-[0-9.]+$"); do
echo "$d: $(cat /sys/bus/usb/devices/$d/speed 2>/dev/null) Mbps"
done
1-1: 480 Mbps <- a USB 2.0 HUB
1-1.1: 480 Mbps <- the drive behind it
480 Mbps = USB 2.0 ≈ 40-45 MB/s real. Measured 38.3 read / 40.9 write — exactly at the ceiling. A 12TB 7200rpm IronWolf capable of 200+ MB/s, throttled to a fifth by its connection.
List every USB controller to see whether a faster one exists:
for d in /sys/bus/usb/devices/usb*; do
echo "$(basename $d): $(cat $d/speed 2>/dev/null) Mbps $(cat $d/product 2>/dev/null)"
done
usb1: 480 Mbps xHCI Host Controller
usb2: 5000 Mbps xHCI Host Controller <- free, unused
Unmount before unplugging — pulling a mounted drive is how filesystems get corrupted.
sudo fuser -vm /mnt/@usb/sda1 # who is holding it?
Read the access column: c = current directory only, f = open file. Only c means
nothing is being read or written and it is safe to clear. Unmount the share on the client
first, then restart Samba to clear leftover children:
sudo systemctl restart smbd.service && sleep 3 && sudo umount /mnt/@usb/sda1 && sync
Then move the cable to a blue/SS port, directly, not through a hub. Verify:
2-1: 5000 Mbps
2-1.3: 5000 Mbps
Result: 40.9 → 74.6 MB/s.
Three ways this move silently fails:
path = /mnt/@usb/sda1). Check the share still resolves afterwards.Four plausible hypotheses died on evidence. Recording them so they aren’t re-chased.
| Hypothesis | Killed by |
|---|---|
| Laptop’s USB-C port was USB 2.0 | Kernel logged new SuperSpeed USB device on both ports — always USB 3.0 |
| Dock contention (DisplayLink video vs NIC) | Moved to the built-in PCIe NIC at gigabit; speed unchanged |
| SMB signing burning NAS CPU | testparm -s → server signing = No, already off |
| NAS CPU too weak | During transfer: 50% idle, smbd at 29% — but 37% iowait |
Moving the dock to a different port cost a monitor (the original port carried DisplayPort Alt Mode, the new one didn’t) and gained nothing. The kernel had already recorded both port speeds in the journal — checking
journalctl -b 0 | grep "new SuperSpeed"would have answered it in ten seconds without touching hardware.
nobarrier on the USB volume/dev/sda1 on /mnt/@usb/sda1 type ext4 (rw,nosuid,nodev,noatime,nodelalloc,nobarrier)
nobarrier disables ext4 write barriers — the mechanism that forces journal writes to commit in
order. Faster, but on power loss or a bus disconnect the journal can end up inconsistent in
exactly the way journaling exists to prevent. It matters more than usual on a USB-attached
drive, which can drop off the bus in ways an internal SATA disk won’t.
Almost certainly a deliberate vendor choice, and it likely resets on reboot or firmware update, so it isn’t really a tunable. Worth knowing before putting anything important on that volume, and an argument for the NAS being on a UPS. Compare with the 509-day-old ext4 orphan-inode error cleared from the local 2TB NVMe on 2026-08-02 — same failure mode, different drive.
74.6 MB/s is about 68% of practical gigabit (~110 MB/s). The next limit looks like the NAS itself: the RAM-served read measured 72.2 MB/s with storage removed from the path, and the final disk-backed write landed at 74.6. Those matching numbers suggest ~72-75 MB/s is what that ARM CPU pushes through SMB regardless of what’s underneath.
The remaining lever is the NAS’s indexing services — index_serv, media_serv, thumb_core,
thumb_serv, with media_worker observed at 83% CPU during a transfer. Exclude the share from
indexing in the NAS web UI (rather than systemctl stop, which won’t survive a reboot) and
re-run the benchmark to see if it’s worth anything.
fdatasync. Both caches will lie to you.journalctl
before the hardware was ever touched.