<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>README</title>
<style>
html {
color: #1a1a1a;
background-color: #fdfdfd;
}
body {
margin: 0 auto;
max-width: 36em;
padding-left: 50px;
padding-right: 50px;
padding-top: 50px;
padding-bottom: 50px;
hyphens: auto;
overflow-wrap: break-word;
text-rendering: optimizeLegibility;
font-kerning: normal;
}
@media (max-width: 600px) {
body {
font-size: 0.9em;
padding: 12px;
}
h1 {
font-size: 1.8em;
}
}
@media print {
html {
background-color: white;
}
body {
background-color: transparent;
color: black;
font-size: 12pt;
}
p, h2, h3 {
orphans: 3;
widows: 3;
}
h2, h3, h4 {
page-break-after: avoid;
}
}
p {
margin: 1em 0;
}
a {
color: #1a1a1a;
}
a:visited {
color: #1a1a1a;
}
img {
max-width: 100%;
}
svg {
height: auto;
max-width: 100%;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 1.4em;
}
h5, h6 {
font-size: 1em;
font-style: italic;
}
h6 {
font-weight: normal;
}
ol, ul {
padding-left: 1.7em;
margin-top: 1em;
}
li > ol, li > ul {
margin-top: 0;
}
blockquote {
margin: 1em 0 1em 1.7em;
padding-left: 1em;
border-left: 2px solid #e6e6e6;
color: #606060;
}
code {
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
font-size: 85%;
margin: 0;
hyphens: manual;
}
pre {
margin: 1em 0;
overflow: auto;
}
pre code {
padding: 0;
overflow: visible;
overflow-wrap: normal;
}
.sourceCode {
background-color: transparent;
overflow: visible;
}
hr {
background-color: #1a1a1a;
border: none;
height: 1px;
margin: 1em 0;
}
table {
margin: 1em 0;
border-collapse: collapse;
width: 100%;
overflow-x: auto;
display: block;
font-variant-numeric: lining-nums tabular-nums;
}
table caption {
margin-bottom: 0.75em;
}
tbody {
margin-top: 0.5em;
border-top: 1px solid #1a1a1a;
border-bottom: 1px solid #1a1a1a;
}
th {
border-top: 1px solid #1a1a1a;
padding: 0.25em 0.5em 0.25em 0.5em;
}
td {
padding: 0.125em 0.5em 0.25em 0.5em;
}
header {
margin-bottom: 4em;
text-align: center;
}
#TOC li {
list-style: none;
}
#TOC ul {
padding-left: 1.3em;
}
#TOC > ul {
padding-left: 0;
}
#TOC a:not(:hover) {
text-decoration: none;
}
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list[class]{list-style: none;}
ul.task-list li input[type="checkbox"] {
font-size: inherit;
width: 0.8em;
margin: 0 0.8em 0.2em -1.6em;
vertical-align: middle;
}
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { display: inline-block; text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; }
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; }
code span.at { color: #7d9029; }
code span.bn { color: #40a070; }
code span.bu { color: #008000; }
code span.cf { color: #007020; font-weight: bold; }
code span.ch { color: #4070a0; }
code span.cn { color: #880000; }
code span.co { color: #60a0b0; font-style: italic; }
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; }
code span.do { color: #ba2121; font-style: italic; }
code span.dt { color: #902000; }
code span.dv { color: #40a070; }
code span.er { color: #ff0000; font-weight: bold; }
code span.ex { }
code span.fl { color: #40a070; }
code span.fu { color: #06287e; }
code span.im { color: #008000; font-weight: bold; }
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; }
code span.kw { color: #007020; font-weight: bold; }
code span.op { color: #666666; }
code span.ot { color: #007020; }
code span.pp { color: #bc7a00; }
code span.sc { color: #4070a0; }
code span.ss { color: #bb6688; }
code span.st { color: #4070a0; }
code span.va { color: #19177c; }
code span.vs { color: #4070a0; }
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; }
</style>
</head>
<body>
<header id="title-block-header">
<h1 class="title">README</h1>
</header>
<h1
id="disktest---tester-for-solid-state-disks-ssds-non-volatile-memory-storage-nvme-hard-disks-hdds-usb-sticks-sd-cards-etc.">disktest
- Tester for Solid State Disks (SSDs), Non-Volatile Memory Storage
(NVMe), Hard Disks (HDDs), USB Sticks, SD-Cards, etc.</h1>
<p><a href="https://bues.ch/h/disktest">Homepage</a></p>
<p><a href="https://bues.ch/cgit/disktest.git">Git repository</a></p>
<p><a href="https://github.com/mbuesch/disktest">Github
repository</a></p>
<p><a href="https://crates.io/crates/disktest">crates.io site</a></p>
<p>Disktest is a tool to check Solid State Disks, Non-Volatile Memory
Storage, Hard Disks, USB sticks, SD cards or other storage media for
errors.</p>
<p>It does so by writing a pseudo-random sequence to the device and then
reading it back and verifying it against the same pseudo-random
sequence.</p>
<p>This tool can be used to:</p>
<ul>
<li>Check disks for hardware errors (e.g. platter errors, flash errors,
etc.).</li>
<li>Overwrite storage media with a cryptographically-strong
pseudo-random stream. This can either be used to delete existing data on
the disk, or to prepare the disk for encryption.</li>
<li>Test for tampered media that pretend to have more storage area than
they physically have. Sometimes such media are sold by fraudulent
sellers at cheap prices.</li>
<li>Measure read and write speed.</li>
<li>… probably lots of other tasks.</li>
</ul>
<p>The pseudo-random number stream is generated by the following
algorithm:</p>
<pre><code>OUTPUT_DATA := CHACHA20(PBKDF2(SEED | THREAD_ID | ROUND_ID))</code></pre>
<p>If more than one thread is used, then each thread generates such a
stream, and the streams are interleaved in an alternating pattern.</p>
<h1 id="security">Security</h1>
<p>The default algorithm <a
href="https://en.wikipedia.org/wiki/Salsa20">ChaCha20</a> is a
cryptographically strong random number generator. That means if the seed
is kept secret, the pseudo-random sequence cannot be predicted or
reconstructed by anybody else.</p>
<p>See option <code>--seed</code> under <code>--help</code> for more
details.</p>
<h1 id="linux-example">Linux example</h1>
<p>The following disktest invocation will write a secure sequence to the
disk device <code>/dev/sdc</code> and subsequently read back and verify
the sequence.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ex">disktest</span> <span class="at">--write</span> <span class="at">--verify</span> <span class="at">-j0</span> /dev/sdc</span></code></pre></div>
<p>For NVMe:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">disktest</span> <span class="at">--write</span> <span class="at">--verify</span> <span class="at">-j0</span> /dev/nvme0n1</span></code></pre></div>
<p>For SD / MMC:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">disktest</span> <span class="at">--write</span> <span class="at">--verify</span> <span class="at">-j0</span> /dev/mmcblk0</span></code></pre></div>
<p><em>WARNING</em>: This will irrevocably overwrite all data on the
storage device! Be absolutely certain that the device path is correct
before starting the command. Your data will not be recoverable.</p>
<p>You probably need <code>root</code> permissions to write to raw disk
devices (<code>/dev/sdX</code>, <code>/dev/nvmeXn1</code> or
<code>/dev/mmcblkX</code>).</p>
<p>The target <code>device</code> does not have to be an actual hardware
device node. It can be any file path on any file system. For example you
can mount an USB stick file system and write to a file on that file
system. However, please note that this leaves a couple of minor untested
spots in the USB stick’s memory, which are reserved for the file system.
Also see the <code>Windows</code> section below.</p>
<h1 id="windows-example">Windows example</h1>
<p>On Windows disktest can write to any file on any mounted storage
media or raw disks.</p>
<p>If your storage media under test is drive E, then the following
command would write a test file on drive E and verify it:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ex">disktest</span> <span class="at">--write</span> <span class="at">--verify</span> <span class="at">-j0</span> E:<span class="dt">\t</span>estfile.img</span></code></pre></div>
<p>But note that testing on the filesystem level, as shown above, does
not test the full device. It will omit the disk areas that the
filesystem uses internally. Therefore, you may want to write to the raw
disk E using the Windows raw drive notation, as follows:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ex">disktest</span> <span class="at">--write</span> <span class="at">--verify</span> <span class="at">-j0</span> <span class="dt">\\</span>.<span class="dt">\E</span>:</span></code></pre></div>
<p>or</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ex">disktest</span> <span class="at">--write</span> <span class="at">--verify</span> <span class="at">-j0</span> <span class="dt">\\</span>.<span class="dt">\P</span>hysicalDrive2</span></code></pre></div>
<p>Doing so will completely wipe all data (including the filesystem) on
this disk.</p>
<p>Always make sure that you selected the correct drive. Especially in
the <code>\\\\.\PhysicalDriveX</code> notation, it is extremely easy to
overwrite the wrong drive by accident. Therefore, the
<code>\\\\.\X:</code> (where X is the drive letter) notation is
preferred.</p>
<h1 id="dependencies">Dependencies</h1>
<ul>
<li><a href="https://www.rust-lang.org/">Rust 1.75.0</a> or later.</li>
<li>Crate dependencies are automatically downloaded by Cargo.</li>
</ul>
<h1 id="installing-from-crates.io">Installing from crates.io</h1>
<p>Download the latest version of disktest from <a
href="https://crates.io/">crates.io</a> and install it to
<code>$HOME/.cargo/bin</code>:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ex">cargo</span> install disktest</span></code></pre></div>
<h1 id="installing-from-source-package">Installing from source
package</h1>
<p>Build disktest and install it to <code>$HOME/.cargo/bin</code>:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> path/to/source/package</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="ex">cargo</span> install <span class="at">--path</span> .</span></code></pre></div>
<h1 id="running-from-source-package-without-installing">Running from
source package without installing</h1>
<p>Build and run disktest in place without installing it:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> path/to/source/package</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="ex">cargo</span> run <span class="at">--release</span> <span class="at">--</span> DISKTEST_OPTIONS_HERE</span></code></pre></div>
<p>See below for a description of the available <code>disktest</code>
options.</p>
<h1 id="disktest-command-line-options">Disktest command line
options</h1>
<p>Please run either of the following commands to show more information
about the available command-line options.</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ex">cargo</span> run <span class="at">--release</span> <span class="at">--</span> <span class="at">--help</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="ex">disktest</span> <span class="at">--help</span></span></code></pre></div>
<h1 id="speed">Speed</h1>
<p>The following table shows some example speed measurements of disktest
in various operation modes on different hardware.</p>
<p>These speed tests don’t write to an actual disk, but only to the
<code>/dev/null</code> device, which is a device that does nothing. So
these speed test results do not include the speed limits of any physical
disk hardware.</p>
<table>
<colgroup>
<col style="width: 39%" />
<col style="width: 9%" />
<col style="width: 32%" />
<col style="width: 18%" />
</colgroup>
<thead>
<tr class="header">
<th>Command</th>
<th>Algorithm</th>
<th>Hardware</th>
<th>Data rate written</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>disktest -j12 -ACHACHA20 -w /dev/null</td>
<td>ChaCha20</td>
<td>AMD Ryzen 5 5500U; 6x2 cores</td>
<td>8.4 GiB/s</td>
</tr>
<tr class="even">
<td>disktest -j12 -ACHACHA12 -w /dev/null</td>
<td>ChaCha12</td>
<td>AMD Ryzen 5 5500U; 6x2 cores</td>
<td>8.7 GiB/s</td>
</tr>
<tr class="odd">
<td>disktest -j12 -ACHACHA8 -w /dev/null</td>
<td>ChaCha8</td>
<td>AMD Ryzen 5 5500U; 6x2 cores</td>
<td>8.7 GiB/s</td>
</tr>
<tr class="even">
<td>disktest -j12 -ACRC -w /dev/null</td>
<td>CRC</td>
<td>AMD Ryzen 5 5500U; 6x2 cores</td>
<td>8.8 GiB/s</td>
</tr>
<tr class="odd">
<td>disktest -j4 -ACHACHA20 -w /dev/null</td>
<td>ChaCha20</td>
<td>Intel i5-3320M; 2x2 cores</td>
<td>2.1 GiB/s</td>
</tr>
<tr class="even">
<td>disktest -j4 -ACHACHA12 -w /dev/null</td>
<td>ChaCha12</td>
<td>Intel i5-3320M; 2x2 cores</td>
<td>3.3 GiB/s</td>
</tr>
<tr class="odd">
<td>disktest -j4 -ACHACHA8 -w /dev/null</td>
<td>ChaCha8</td>
<td>Intel i5-3320M; 2x2 cores</td>
<td>4.5 GiB/s</td>
</tr>
<tr class="even">
<td>disktest -j4 -ACRC -w /dev/null</td>
<td>CRC</td>
<td>Intel i5-3320M; 2x2 cores</td>
<td>8.2 GiB/s</td>
</tr>
<tr class="odd">
<td>disktest -j4 -ACHACHA20 -w /dev/null</td>
<td>ChaCha20</td>
<td>Raspberry Pi 4; 4 cores 1.5 GHz</td>
<td>455 MiB/s</td>
</tr>
<tr class="even">
<td>disktest -j4 -ACHACHA12 -w /dev/null</td>
<td>ChaCha12</td>
<td>Raspberry Pi 4; 4 cores 1.5 GHz</td>
<td>720 MiB/s</td>
</tr>
<tr class="odd">
<td>disktest -j4 -ACHACHA8 -w /dev/null</td>
<td>ChaCha8</td>
<td>Raspberry Pi 4; 4 cores 1.5 GHz</td>
<td>990 MiB/s</td>
</tr>
<tr class="even">
<td>disktest -j4 -ACRC -w /dev/null</td>
<td>CRC</td>
<td>Raspberry Pi 4; 4 cores 1.5 GHz</td>
<td>3.1 GiB/s</td>
</tr>
</tbody>
</table>
<p>The read data rates are similar because the algorithm used is exactly
the same.</p>
<h1 id="cpu-native-optimization">CPU native optimization</h1>
<p>Note that the default <a href=".cargo/config.toml">cargo
configuration</a> supplied with this package sets the Rust compiler
option <code>-Ctarget-cpu=native</code> to optimize for the best
performance on your CPU.</p>
<p>But this means that binaries compiled with this optimizations are
non-portable to older CPUs. If you want portable binaries, then you
probably want to remove this optimization option.</p>
<h1 id="license">License</h1>
<p>Copyright (c) 2020-2025 Michael Büsch <a href="mailto:m@bues.ch"
class="email">m@bues.ch</a> and contributors</p>
<p>Licensed under the Apache License version 2.0 or the MIT license, at
your option.</p>
</body>
</html>