If for whatever reason you prefer to try to clear those bad sectors, and you do not care about the existing contents of a drive, the below shell snippet may help. I tested this on an older Seagate Barracuda drive that is well past its warranty anyway. It might not work right with other drive models or manufacturers, but it should put you on the right path if you must script something. It will destroy any content you have on the drive.
You may prefer just running badblocks, an hdparm Secure Erase (SE) (https://wiki.archlinux.org/index.php/Securely_wipe_disk), or some other tool that is actually designed for this. Or even the manufacturer provided tools like SeaTools (there is a 32bit linux 'enterprise' version, google it).
Make sure the drive in question is completely unused/unmounted before doing this. Also, I know, while loop, no excuses. It is a hack, you can make it better...
baddrive=/dev/sdb
badsect=1
while true; do
echo Testing from LBA $badsect
smartctl -t select,${badsect}-max ${baddrive} 2>&1 >> /dev/null
echo "Waiting for test to stop (each dot is 5 sec)"
while [ "$(smartctl -l selective ${baddrive} | awk '/^ *1/{print substr($4,1,9)}')" != "Completed" ]; do
echo -n .
sleep 5
done
echo
badsect=$(smartctl -l selective ${baddrive} | awk '/# 1 Selective offline Completed: read failure/ {print $10}')
[ $badsect = "-" ] && exit 0
echo Attempting to fix sector $badsect on $baddrive
hdparm --repair-sector ${badsect} --yes-i-know-what-i-am-doing $baddrive
echo Continuning test
done
One advantage of using the 'selftest' method is the load is handled by the drive firmware, so the PC it is connected to is not loaded down like it would be with dd or badblocks.
NOTE : I'm sorry, I made a mistake, the correct while condition is like this :
while [ "$(smartctl -l selective ${baddrive} | awk '/^ *1/{print $4}')" = "Self_test_in_progess" ]; do
And the exit condition of the script becomes :
[ $badsect = "-" ] || [ "$badsect" = "" ] && exit 0
I think you are in the same case than I in Generating a lot of dirty pages is blocking synchronous writes
kjournald among top processes.
you are using a journaling file system like ext3 which apparently is causing synchronous writes to block.
You can try
Reducing the amount of dirty memory a process is able to create:
echo 100000000 > /proc/sys/vm/dirty_background_bytes
echo 200000000 > /proc/sys/vm/dirty_bytes
The process doing the copy will not be able to write too much at once. It will write a piece of data and then ensure this data is flushed to disk before writing the next piece. It will ensure the journaling thread does not have too much to work with, and will still be able to work on requests from other processes while the copy is occurring.
Another thing you can try is doing the copy with dd and ensure you are writing synchronously:
dd if=foo of=bar bs=4096 oflag=sync
This will ensure also that blocks are written little by little.
And also if it matches your use case, you can remove journaling on your destination folder, if you understand the risk. You can remount your (I suppose ext3?) file system with the option
data=writeback
These are the stuff I tried with my system. This question has been opened 2 years ago, have you found a solution in the meantime?
Best Answer
This command performs an "identify device", which is a specific ATA protocol that requests the identifying information from the device's firmware. In the case of a physical drive, you could, for instance, connect a bus analyzer between the host bus adapter of your computer and the drive itself and see the identify request traverse the SATA interface and the responding data from the drive.
In the case of a virtual machine, libata is talking to hard drive firmware (through a virtual HBA) that is being emulated as a virtual device. The identify device information that is returned from hdparm depends on how the virtual device has implemented the response to that ATA command. The hdparm command doesn't know that it's talking to a virtual device. It only knows how to execute the command through libata and how to parse the data structure that is returned.
In this context, perhaps it makes more sense to see if there is a way to set the "garbage" fields of your virtual device to whatever values you choose.
If you are using VirtualBox, see this: https://www.virtualbox.org/manual/ch09.html#changevpd
Alternatively, if you just want to remove binary characters from the output, you can pipe it through tr: