The drive may become slow because of unstable sectors (that's sectors that the drive cannot currently read, but may become readable after being overwritten or reallocated). I observed this in an external drive myself. In my case, the unstable sectors caused I/O errors in a frequently used part of the filesystem. While no file appeared to fail, the transfer rate spuriously dropped down to about 100 kB/s.
A rough but easy attempt to repair this would be to erase the disk with Disk Utility
using the secure erase option Zero Out Data
. This may either fix the unstable sectors or reallocate them to a small spare section of the drive.
I'll instruct you here how to find and possibly correct read errors from the command line (Terminal
application). You must have administrator rights and give your account password to do this. Before you start, you should backup your data. And in either case, you should inspect the drive's health with a S.M.A.R.T. tool after you are finished.
First identify the device corresponding to your drive with diskutil
:
$ diskutil list
/dev/disk0
#: TYPE NAME SIZE IDENTIFIER
0: GUID_partition_scheme *256.1 GB disk0
1: EFI 209.7 MB disk0s1
2: Apple_HFS Internal HD 255.7 GB disk0s2
/dev/disk1
#: TYPE NAME SIZE IDENTIFIER
0: FDisk_partition_scheme *3.0 TB disk1
1: Apple_HFS External HD 3.0 TB disk1s1
$
In this case, the external drive is /dev/disk1
. Now do a raw copy of this drive to 'nowhere', using the dd
command.
$ sudo dd if=/dev/rdisk1 of=/dev/null bs=65536
Password:
(notice the use of rdisk1
instead of disk1
here, this turns off buffering and speeds up dd
).
Even for a healthy disk connected via USB2, this command takes roughly 9 h/TB. To check its progress, hit ctrl-t
while it is executing.
In case of a read error, dd
will exit with a notification like this:
dd: reading '/dev/rdisk1': Input/output error
11233976+0 records in
11233976+0 records out
736229851136 bytes transferred in 23179.173766 seconds (3176255 bytes/sec)
The records in/out
numbers indicate where on disk the error occured. Multiply by 128 to obtain the offending LBA address (this is because I chose bs=65536
for dd
, blocksize 65536 bytes, which is 128 sectors).
You should backup your data now if you haven't already done so.
Try to overwrite the offending segment with zeroes (use the records in/out
number as the skip
argument). Note that this step may destroy data that is yet intact.
$ sudo dd if=/dev/zero of=/dev/rdisk1 bs=65536 skip=11233976 count=1
Password:
1+0 records in
1+0 records out
65536 bytes transferred in 0.001996 secs (32833004 bytes/sec)
Then continue reading, starting with the freshly written segment (again, use the records in/out
number as the skip
argument).
$ sudo dd if=/dev/rdisk1 of=/dev/null bs=65536 skip=11233976
Once you don't run into any further read errors, the drive is ready for erasing. Since you overwrote the erroneous segments by hand, you need not choose Zero Out Data
now.
Remember to inspect the drive's health with a S.M.A.R.T. toll after you finished.
dd
,iozone
,bonnie++
, etc.) If the results are worse than expected I'd replace the drive.