It Said "Copied": So Why Won't My USB Drive Let Go?

Lahiru Gunathilake 2026

Theme image

Most of the Ubuntu users eventually meets this moment: Ubuntu's file manager fills its progress bar, the dialog vanishes, and everything looks finished. Then you try to remove the drive and the machine refuses:

$ sudo eject /dev/sdb
eject: cannot open /dev/sdb: Device or resource busy

The next option we try is sync, but it hangs and never returns. udisksctl power-off throws the same brush-off:

$ sudo udisksctl power-off -b /dev/sdb
Error powering off drive: Error opening /dev/sdb for fsync: Device or resource busy (udisks-error-quark, 0)

The copy reported success, but the device is somehow both finished and too busy to touch. That contradiction is not a bug in the file manager. It is the visible edge of a design decision that sits at the heart of the operating system — and, in this particular case, of a drive that quietly stopped answering halfway through the job. This article walks through exactly what happened, using one real crash log as the guide.

Why Ubuntu tells you the files have been transferred

The GUI telling you the copy finished wasn't lying. It was accurately reporting on the wrong layer. The kernel copies your data into a region of RAM called the page cache and reports success as soon as that copy is complete. The physical write to the much slower flash storage is scheduled for later, handled by background kernel worker threads. From the file manager's point of view, its job — getting the bytes into the kernel — really is done; it just isn't telling you that the kernel hasn't finished its part yet.

Think of posting a letter. You drop it into the post box and walk away knowing your part is done. But the letter has not yet reached its destination; it is somewhere in the postal system, waiting for collection and delivery. Your file manager's "100%" is the moment the letter leaves your hand, not the moment it arrives. In the same way, the kernel marks those cached pages as dirty — meaning they have been modified in memory but not yet written to storage — and hands them to background worker threads for eventual write-back. On a fast internal SSD this gap is invisible; on a slow USB stick copying several gigabytes, it can stretch to minutes.

Why the USB cannot be removed

Since the file manager wasn't giving me the result I wanted, I tried the usual escalation:

cp -r /source/path/ /destination/path/

Same result. sync in the terminal froze and never returned. Then the more careful option:

rsync -rt --info=progress2 /source/path/ /destination/path/

Still stuck. The reason all three behave the same way is the same one from the previous section: the kernel will not silently discard data it has promised to write. sync, eject, and udisksctl power-off all have to wait for every dirty page belonging to the drive to actually reach the device before they can return. If the device is still mid-writeback — or, as it turned out here, no longer responding at all — that wait has no end, and the drive reports "busy" because, as far as the kernel is concerned, it genuinely still has outstanding work pending against it.

What is the issue

To find the actual cause rather than guess, the right tool is the kernel's own log, not fuserfuser -m on a device tends to list most of the running system (kernel workers, Xorg, browsers) regardless of whether they touch the drive, so it isn't diagnostic here. dmesg is:

sudo dmesg | grep -iE "usb|uas|sd[a-z]|scsi|xhci|ehci" | tail -n 20

And got the following results.

[ 2063.962039] sdb1: writeback error on inode 609, offset 1232896, sector 19611040
[ 2064.421112] Buffer I/O error on dev sdb1, logical block 786432, lost sync page write
[ 2064.421122] ntfs3(sdb1): ino=3, ntfs_set_state failed, -5.
[ 2064.421129] ntfs3(sdb1): Mark volume as dirty due to NTFS errors
[ 2064.421134] Buffer I/O error on dev sdb1, logical block 786432, lost sync page write
[ 2064.421139] ntfs3(sdb1): ino=3, ntfs_set_state failed, -5.
[ 2064.421173] Buffer I/O error on dev sdb1, logical block 36, lost async page write
[ 2064.421196] Buffer I/O error on dev sdb1, logical block 786301, lost async page write
[ 2064.421213] Buffer I/O error on dev sdb1, logical block 786431, lost async page write
[ 2064.421228] Buffer I/O error on dev sdb1, logical block 786441, lost async page write
[ 2064.421244] Buffer I/O error on dev sdb1, logical block 786443, lost async page write
[ 2064.421248] Buffer I/O error on dev sdb1, logical block 786444, lost async page write
[ 2064.421264] Buffer I/O error on dev sdb1, logical block 786464, lost async page write
[ 2064.421268] Buffer I/O error on dev sdb1, logical block 786465, lost async page write
[ 2064.421669] ntfs3(sdb1): ino=7d, ntfs3_write_inode failed, -5.
[ 2064.421686] ntfs3(sdb1): ino=81, ntfs3_write_inode failed, -5.
[ 2064.421696] ntfs3(sdb1): ino=24, ntfs3_write_inode failed, -5.
[ 2064.421705] ntfs3(sdb1): ino=2b, ntfs3_write_inode failed, -5.
[ 2064.421713] ntfs3(sdb1): ino=7c, ntfs3_write_inode failed, -5.
[ 2064.421722] ntfs3(sdb1): ino=3, ntfs3_write_inode failed, -5.
[ 2194.791201] usb 2-1: new SuperSpeed USB device number 4 using xhci_hcd
[ 2194.804084] usb 2-1: New USB device found, idVendor=0781, idProduct=5581, bcdDevice= 1.00
[ 2194.804094] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 2194.804098] usb 2-1: Product:  SanDisk 3.2Gen1
[ 2194.804101] usb 2-1: Manufacturer:  USB
[ 2194.804104] usb 2-1: SerialNumber: ****
[ 2194.808591] usb-storage 2-1:1.0: USB Mass Storage device detected
[ 2194.808811] scsi host1: usb-storage 2-1:1.0
[ 2195.870006] scsi 1:0:0:0: Direct-Access      USB      SanDisk 3.2Gen1 1.00 PQ: 0 ANSI: 6
[ 2195.870298] sd 1:0:0:0: Attached scsi generic sg1 type 0
[ 2195.873219] sd 1:0:0:0: [sdb] 60088320 512-byte logical blocks: (30.8 GB/28.7 GiB)
[ 2195.873579] sd 1:0:0:0: [sdb] Write Protect is off
[ 2195.873587] sd 1:0:0:0: [sdb] Mode Sense: 43 00 00 00
[ 2195.873905] sd 1:0:0:0: [sdb] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
[ 2195.895803]  sdb: sdb1
[ 2195.895987] sd 1:0:0:0: [sdb] Attached SCSI removable disk
[ 2196.125133] ntfs3(sdb1): It is recommended to use chkdsk.
[ 2196.139273] ntfs3(sdb1): volume is dirty and "force" flag is not set!
[ 2198.493216] ntfs3(sdb1): It is recommended to use chkdsk.
[ 2198.501307] ntfs3(sdb1): volume is dirty and "force" flag is not set!

Lots of errors, but a clear pattern once you read them in order. The comfortable explanation people reach for is that the drive "got hot and choked." For a small USB stick that's almost always fiction, and this log describes something more specific and more useful: the drive stopped answering, was reset by the kernel, and everything still waiting in RAM to be written was lost.

The reason a single slow moment is fatal here comes down to two facts about how USB flash drives are actually driven. A flash drive is a SCSI device wrapped in USB by the usb-storage driver, and for this class of drive that driver only allows one write command in flight at a time — no pipelining, nothing overlapping. Every command also carries a hard 30-second timeout. So if any single write fails to come back inside 30 seconds, the whole transfer doesn't slow down — it hits a wall.

When that happens, the kernel's SCSI error handler steps in and escalates through a fixed recovery ladder: try to abort the stuck command, then reset the device, then the bus, then the whole host. Because there's no real "SCSI bus" behind a USB stick, that escalation ultimately does the only equivalent thing available to it — it resets the physical USB port, the same electrical sequence as unplugging and replugging the drive. That's the origin of this line, appearing long after the writes had already started failing:

usb 2-1: new SuperSpeed USB device number 4 using xhci_hcd
...
usb 2-1: Product:  SanDisk 3.2Gen1

Not the stick cooling down and reviving — the kernel's own recovery machinery reaching the end of its ladder and power-cycling the port.

Why did a single write command stall for over 30 seconds in the first place? That part is inference rather than something the log proves outright. Budget flash drives hide the genuinely slow write speed of their underlying NAND behind a small, fast cache. Sustained writes stay fast until that cache fills, at which point the controller has to fall back to writing the slow memory directly and doing housekeeping to reclaim space — and on a cheap controller, that housekeeping isn't always hidden from the host. A large, uninterrupted multi-gigabyte burst is exactly the kind of load that pushes a budget controller into this state.

The consequence was corruption, because of the very safety property that made the copy look instant. Once the port was reset, the writes still queued in RAM had nowhere to go, and the kernel had to discard them:

sdb1: writeback error on inode 609, offset 1232896, sector 19611040
Buffer I/O error on dev sdb1, logical block 786432, lost sync page write
ntfs3(sdb1): ino=3, ntfs_set_state failed, -5.
ntfs3(sdb1): Mark volume as dirty due to NTFS errors

This is also exactly why sync, eject, and power-off all hung: the kernel doesn't silently throw away undelivered writes, so it waits for an acknowledgement that can never come from a device that, at that USB address, no longer exists. On reconnection, ntfs3 read back its own dirty flag and correctly refused to mount the volume read-write without an explicit override — doing exactly what a careful filesystem should do.

What was the solution

The fix was to stop overwhelming the drive rather than fight the symptoms. Throttling the transfer keeps every individual write comfortably inside the 30-second window, so the drive is never pushed into the stall that triggers a reset in the first place:

rsync -rt --info=progress2 --bwlimit=5M /path/to/source/ /path/to/destination/

This isn't about total data volume — a drive doing a slow, steady 5 MB/s still returns every command well within the timeout. The problem was never sustained slowness; it was one command stalling completely.

To recover the drive itself, clearing NTFS's dirty flag was enough to get it mounting again:

sudo ntfsfix -d /dev/sdb1

This isn't a full chkdsk — it clears the flag and fixes a few common inconsistencies, not a full filesystem check. For anything actually important on the drive, a proper chkdsk /f on Windows, or a backup-and-reformat, is the more thorough option.

Once a copy has genuinely finished cleanly, the correct way to remove a drive is to flush explicitly and then power off the port, rather than yanking it or relying on eject:

sync
sudo udisksctl power-off -b /dev/sdb

And if a drive keeps stalling even with a throttled transfer, that's a sign to stop suspecting the OS and start suspecting the hardware — a different port, a different cable, or a health check with a tool like f3 to rule out a failing or counterfeit stick.