web-dev-qa-db-ja.com

Linuxを使用したSDカードのストレステスト

私は昨日誰かの論理と真実性について少し議論しました 私の答えはここにあります 、対して、適切な(GB +)サイズのSDカードでfsメタデータをログに記録して維持することは決してできなかった妥当な時間(数年後)でカードを使い尽くすのに十分な大きさであること。反論の趣旨は、SDカードを使い古した人の話がオンラインでたくさんあるので、私は間違っているに違いないと思われた。

私は24時間年中無休で残されるrwルートファイルシステムを含むSDカードを搭載したデバイスを持っているので、私は以前に前提をテストしました。私はこのテストを少し調整し、実際には同じカードを使用して繰り返し、ここに提示しています。私が持っている2つの中心的な質問は次のとおりです。

  1. カードを破壊するために使用した方法は、少量の少量のデータを継続的に再書き込みする効果を再現することを意図していることを念頭に置いて、実行可能ですか?
  2. カードを確認するために使用した方法はまだ実行可能ですか?

S.O.ではなく、ここで質問をします。または、SuperUser。最初の部分に対する異論は、おそらく私のテストが実際にカードに書き込む方法ではないことを断言しなければならず、それを断言するにはLinuxの特別な知識が必要になるためです。

[同じ場所への繰り返しの書き込みが摩耗しにくい場所でバッファリング/キャッシュされるように、SDカードが何らかのスマートバッファリングまたはキャッシュを使用している可能性もあります。私はこれの兆候をどこにも見つけていませんが、私は それについて尋ねる をS.U.にしています]

テストの背後にあるアイデアは、カード上の同じ小さなブロックに何百万回も書き込むことです。これは、そのようなデバイスが保持できる書き込みサイクル数の主張をはるかに超えていますが、カードのサイズが適切であれば、 ウェアレベリング の推定は効果的であり、そのような書き込みの数百万はそれほど重要ではありません。 「同じブロック」は文字通り同じ物理ブロックではないからです。これを行うには、すべての書き込みが本当にハードウェアにフラッシュされ、同じapparentの場所にフラッシュされることを確認する必要がありました。

ハードウェアにフラッシュするために、私はPOSIXライブラリコール fdatasync() に依存しました:

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>

// Compile std=gnu99

#define BLOCK 1 << 16

int main (void) {
    int in = open ("/dev/urandom", O_RDONLY);
    if (in < 0) {
        fprintf(stderr,"open in %s", strerror(errno));
        exit(0);
    }

    int out = open("/dev/sdb1", O_WRONLY);
    if (out < 0) {
        fprintf(stderr,"open out %s", strerror(errno));
        exit(0);
    }

    fprintf(stderr,"BEGIN\n");

    char buffer[BLOCK];
    unsigned int count = 0;
    int thousands = 0;
    for (unsigned int i = 1; i !=0; i++) {
        ssize_t r = read(in, buffer, BLOCK);
        ssize_t w = write(out, buffer, BLOCK);
        if (r != w) {
            fprintf(stderr, "r %d w %d\n", r, w);
            if (errno) {
                fprintf(stderr,"%s\n", strerror(errno));
                break;
            }
        }
        if (fdatasync(out) != 0) {
            fprintf(stderr,"Sync failed: %s\n", strerror(errno));
            break;
        }
        count++;
        if (!(count % 1000)) {
            thousands++;
            fprintf(stderr,"%d000...\n", thousands);
        }
        lseek(out, 0, SEEK_SET);
    }
    fprintf(stderr,"TOTAL %lu\n", count);
    close(in);
    close(out);

    return 0;
}                                 

/dev/sdb1パーティションの先頭に200万回以上の書き込みが蓄積されるまで、これを約8時間実行しました。1/dev/sdb(パーティションではなくrawデバイス)を簡単に使用できたかもしれませんが、これがどのような違いをもたらすかはわかりません。

次に、/dev/sdb1にファイルシステムを作成してマウントしようとしてカードをチェックしました。これは機能し、私が一晩中書いていた特定のブロックが実行可能であったことを示しています。ただし、カードの一部の領域が摩耗し、ウェアレベリングによって移動されなかったが、アクセス可能なままになっているという意味ではありません。

これをテストするために、パーティションでbadblocks -v -wを使用しました。これは破壊的読み取り/書き込みテストですが、ウェアレベリングかどうかは異なります。ローリング書き込みごとにスペースを確保する必要があるため、カードの実現可能性を強く示しているはずです。言い換えれば、それはカードを完全に埋め、それがすべて問題がないことを確認することの文字通りの等価物です。何度か、私はいくつかのパターンでbadblockを機能させました。

[下のContra Jason Cのコメント、badblocksをこのように使用することには何の問題もありません。 SDカードの性質上、実際に不良ブロックを特定するのには役立ちませんが、-bおよび-cスイッチを使用して、任意のサイズの破壊的な読み取り/書き込みテストを行うことは問題ありません。改訂されたテストがどこに行ったか(私自身の回答を参照)。マジックやカードのコントローラーによるキャッシングでは、数メガバイトのデータをハードウェアに書き込み、再度正しく読み取ることができるテストをだますことができません。ジェイソンの他のコメントは、誤読-IMOと意図的 1に基づいているようです。そのため、私は議論する気になりませんでした。頭が上がったので、何を意味し、何を意味するかを決めるのは読者に任せますしない。]

1 カードは、私がかろうじて使用した古い4 GB Sandiskカード(「クラス」番号はありません)でした。繰り返しますが、これは文字通り同じ物理的な場所への200万回の書き込みではないことに注意してください。摩耗の平準化により、「最初のブロック」はテスト中にコントローラーによって絶えず移動され、用語のように摩耗が平準化されます。

19
goldilocks

ピーターフの答えは、私にキャッシュの可能性の問題をさらに検討させました。掘り下げた後でも、SDカードの一部、全部、またはすべてがこれを行うかどうかはまだはっきりとは言えませんが、それは可能だと思います。

ただし、キャッシュに消去ブロックよりも大きなデータが含まれるとは思いません。確かに、64 kBではなく16 MBのチャンクを使用してテストを繰り返しました。これは、4 GBカードの総容量の1/250です。これを10,000回行うのに最大8時間かかりました。ウェアレベリングが負荷を分散するために最善を尽くす場合、これは、すべての物理ブロックが40回使用されたことを意味します。

それほど多くはありませんが、テストの元のポイントは、適度な量のデータを繰り返し書き込むことでカードを簡単に損傷できないことを示すことで、ウェアレベリングの効果を示すことでした。同じ(見かけの)場所。 IMO以前の64 kBテストはおそらく本物でした-しかし、16 MBのテストはそうである必要があります。システムはデータをハードウェアにフラッシュし、ハードウェアは書き込みをエラーなしで報告しました。これが詐欺である場合、カードは何の役にも立たず、16 MBをプライマリストレージ以外の場所にキャッシュすることはできません。これは、テストが強調することを目的としています。

うまくいけば、それぞれ16 MBの10,000回の書き込みで、ボトムエンドブランドのカード(値:$ 5 CDN)でも、毎日適度な量のデータを書き込むrwルートファイルシステムを24時間実行することを実証するには十分です摩耗しません)カードは妥当な期間内に発行されます。 10,000日は27年です...そしてカードはまだ問題ありません...

それよりも重いシステムを開発するために給料をもらっていた場合、少なくともいくつかのテストを実行して、カードがどれだけ長く続くかを判断したいと思います。私の直感は、書き込み速度が遅いこのようなものでは、最大速度で数週間、数カ月、または数年の連続書き込みが必要になる可能性があることです(この種の比較テストがオンラインで行われていないという事実は、それは非常に長期にわたる事件であるという事実)。

カードがまだ大丈夫であることを確認することに関して、デフォルトの構成でbadblocksを使用することはもはや適切ではないと思います。代わりに、私はこのようにしました:

badblocks -v -w -b 524288 -c 8

これは、512 kBブロックを8回繰り返してテストすることを意味します(= 4 MB)。これは破壊的なrwテストであるため、連続ループで使用する場合、デバイスにストレスをかけることに関しては、おそらく私が自作したものと同じです。

また、ファイルシステムを作成し、2 GBのファイルにコピーし、元のファイルに対してdiff 'd'を実行しました。次に、ファイルが.isoであるため、イメージとしてマウントして参照しました。その中のファイルシステム。

カードはまだ大丈夫です。おそらくこれはおそらく予想されることです...

;);)

3
goldilocks

SDカードのストレステストは、一般的に次の2つを考えると問題があると思います。

  1. ウェアレベリング次の書き込みが実際にSD上の同じ物理的な場所を実行しているという保証はありません。設置されているSDシステムのほとんどは、私たちが知っているように積極的にブロックを取り、各場所が受けた知覚された「摩耗」に基づいて、それを支える物理的な場所を移動しています。

  2. 異なるテクノロジー(MLCとSLC)これに関して私が目にするもう1つの問題は、テクノロジーの違いです。 SLCタイプのSSDは、MLCの種類よりもはるかに長い寿命を期待しています。また、MLCにはより厳しい許容値があり、SLCで処理する必要はありません。少なくとも、この方法で障害が発生しても許容範囲が広くなります。

    • MLC-マルチレベルセル
    • SLC-シングルレベルセル

MLCの問題は、特定のセルが複数の値を格納できることです。ビットは、たとえば物理的な+ 5Vまたは0Vではなく、基本的に電圧を使用してスタックされるため、SLCよりもはるかに高い故障率が発生する可能性があります。同等。

平均寿命

このリンクは、ハードウェアの持続時間について少し説明しています。タイトルは Snow Your SSDs-SLC vs. MLC です。

SLC

SLC ssdsは、ほとんどの場合、平均して49年から149年の間のどこにでも住むように計算できます。 Memorightテストでは、1日あたり平均100Gbの書き込みで200年を超える書き込み耐久性を持つ128Gb SSDを検証できます。

MLC

ここで、mlcの設計が不十分です。まだリリースされたものはありません。 mlcでどのような平均寿命が保証されているかを実際に調べた人は誰もいませんが、それ以外はかなり低くなります。 slcの設計により、平均して10対1の寿命になるいくつかの異なる信念を受け取りました。保守的な推測では、各メーカーのコントローラー内の「ウェアレベリングアルゴリズム」の進歩に応じて、ほとんどの寿命の見積もりは7〜10年で行われます。

比較

書き込みサイクルによる比較を行うために、slcは、10,000書き込みサイクルの寿命を持つmlcと比較して、100,000完全な書き込みサイクルの寿命を持ちます。これは、使用する「ウェアレベリング」の設計によっては大幅に増加する可能性があります。

12
slm

テストにはいくつかの問題があります。あいまいな場合もあれば、そうでない場合もあります。それはあなたの目標にも依存します。次の2つの微妙なファジー問題があります。

  • あなたが書いているのと同じ領域から読んでいないので、あなたの読み取りテストは効果的に何もしません(コントローラが読み取り妨害訂正を行わない限り、その場合、読み取られているページを別の場所に移動することがありますが、これはまだしますテストには影響しません)。
  • 不良ブロックへの読み取り/書き込みがコントローラーによって検出および報告されると想定します(保証はありません)-データを書き込み、それを再度読み取り、保証されたチェックと比較する必要があります。

しかし、それらは間違いなく教訓的です。より深刻なのは:

  • badblocksを使用して、フラッシュメモリ上の失敗したページを表示することはできません。すべての障害検出と後続のページマッピングはコントローラーによって行われ、OSに対して透過的です。 SMARTドライブからサポートされている場合は、情報が得られます(サポートしているSDカードがないことは知っています。サポートしているハイエンドサムドライブがある可能性があります)。
  • ウェアレベリングは、以前のTRIMコマンド、テスト中のドライブの未使用/使用状態、および予約済みスペースを考慮していないため、テストによって複雑になります。

ウェアレベリング:主な問題は、ウェアレベリングがテストの主要な変数であることです。これは(通常)コントローラーで発生し、いずれの場合でも、デバイスシーク+読み取り/書き込みを直接実行する場合でも透過的です。あなたの例では、ウェアレベリング状態が実際にはわかりません(特に、最近ブロックを解放するためにTRIMコマンドが発行されましたか?)...

デバイスの動的ウェアレベリング(実質的にすべてのコンシューマーグレードのストレージデバイスに存在)の場合は、どの状態でもかまいません。極端な場合、どのページも空きとしてマークされていないため、コントローラーが機能する必要があるのは唯一のページです。 withは予約されたスペースにあるものです(存在する場合)。 isデバイスに予約済みの領域がある場合、それはwillページ書き込みでの保証された失敗を開始する前に完全に失敗する必要があることに注意してください(他のページに空きとしてマークが付けられていないと仮定します)残り)。反対に、すべてのページが空きとしてマークされます。この場合、理論的には、書き込みエラーが発生し始める前に、デバイス上のeveryページが失敗する必要があります。

スタティックウェアレベリングの場合(SSDにはありがち、SDカードにはない傾向があり、サムドライブはさまざまです):デバイス上のすべてのページに繰り返し書き込むことを除いて、それを回避する方法はありません。

...言い換えると、知る方法がなく、制御する方法もないウェアレベリングの詳細があります。特に、動的ウェアレベリングが使用されているかどうか、静的ウェアレベリングが使用されているかどうか、およびウェアレベリングのためにデバイス上に予約されているスペースの量(これは、コントローラー(またはM-Systems古いDiskOnChipのようないくつかのケースではドライバー)からは見えません)。

SLC/MLC:SLCとMLCの場合、これは予想される制限に非常に直接的な影響を及ぼしますが、一般的なウェアレベリング手順テスト手順はどちらも同じです。多くのベンダーは、デバイスがより安価な消費者向け製品のSLCまたはMLCであるかどうかを公開していませんが、ページあたり100k +サイクルの制限を主張するフラッシュドライブはSLCである可能性が高いです(簡略化されたトレードオフはSLC =耐久性、MLC =密度です)。

Caching:キャッシュに関しては、少し不明瞭です。もちろん、OSレベルでは、一般的なケースで、fsync/fdatasyncはデータが実際に書き込まれることを保証しません。ただし、リムーバブルドライブは一般的に次の一般的な使用パターンのために設計されているため、この場合はそうである(または少なくともコントローラーがそうするようにコミットしている、つまり書き込みがキャッシュに飲み込まれない)と推定しても安全だと思います。 「イジェクト」(アンマウント>同期)してから削除(電源切断)します。確かなことはわかりませんが、特に書き込み->同期->リードバックの場合、同期によって書き込みが完全に行われることが同期によって保証されると想定しても安全だと推測されています(そうでない場合、ドライブは信頼できません)イジェクト後)。取り出し時に発行できる「同期」以外のコマンドはありません。

コントローラーでは何でも可能ですが、上記の仮定には、少なくともコントローラーが同期後のデータ損失のリスクを伴うほど「複雑」なことは何もしていないという仮定も含まれます。同じデータが(限られた範囲で)書き換えられている場合、コントローラは、たとえば、バッファおよびグループ書き込みを行うか、データを書き込まない可能性があります。以下のプログラムでは、2つの異なるデータブロックを交互に切り替え、特にリードバックの前に同期を実行して、適切なコントローラーキャッシュメカニズムを無効にします。それでも、もちろん、保証はなく、知る方法もありませんが、これらのデバイスの正常な使用法と正気/共通のキャッシュメカニズムに基づいて合理的な仮定を行うことができます。

テスト:

残念ながら、真実は、あなたがknowデバイスに予約スペースがなく、静的レベリングを実行していない限り、特定のページのサイクル制限を明確にテストする方法はありません。ただし、取得できる最も近いのは次のとおりです(静的なウェアレベリングがないと想定)。

first必要なことは、カード全体にデータを入力することです。 これは重要であり、元のテストで残された主要な変数です。これは、予約済みのスペース(アクセスする方法がありません)。単一のパーティションでの作業はデバイス上の特定の1つの領域のみに影響するため、デバイス全体で作業していることに注意してください(これによりすべてのデータが破壊されます)。

_dd if=/dev/urandom bs=512k of=/dev/sdb conv=fsync oflag=sync
_

あなたがプログレスバータイプなら:

_pv -pterb -s <device_size> /dev/urandom | dd bs=512k of=/dev/sdb conv=fsync oflag=sync
_

編集:4MBの消去ブロックを持つカードの場合、これを試して書き込みを高速化します。

_dd if=/dev/urandom bs=4M of=/dev/sdb conv=fsync oflag=direct,sync iflag=fullblock
_

次に、次のようにサイクルテストプログラムを記述し、_O_DIRECT_と_O_SYNC_(および偏執狂的、fsync()の冗長な使用)を利用して、OSバッファリングを削減します。可能な限り画像からキャッシュし、理論的にはコントローラーに直接書き込み、操作が終了したことを報告するまで待機します。

_#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>

using namespace std;

static const int BLOCK_SIZE = 512;
static const int ALIGNMENT = 512;
static const int OFFSET = 1024 * ALIGNMENT; // 1024 is arbitrary


int main (int argc, char **argv) {

    if (argc != 2) {
        fprintf(stderr, "usage: %s device\n", argv[0]);
        return 1;
    }

    int d = open(argv[1], O_RDWR | O_DIRECT | O_SYNC);
    if (d == -1) {
        perror(argv[1]);
        return 1;
    }

    char *block[2], *buffer;
    int index = 0, count = -1;

    // buffers must be aligned for O_DIRECT.
    posix_memalign((void **)&(block[0]), ALIGNMENT, BLOCK_SIZE);
    posix_memalign((void **)&(block[1]), ALIGNMENT, BLOCK_SIZE);
    posix_memalign((void **)&buffer, ALIGNMENT, BLOCK_SIZE);

    // different contents in each buffer
    memset(block[0], 0x55, BLOCK_SIZE);
    memset(block[1], 0xAA, BLOCK_SIZE);

    while (true) {

        // alternate buffers
        index = 1 - index;

        if (!((++ count) % 100)) {
            printf("%i\n", count);
            fflush(stdout);
        }

        // write -> sync -> read back -> compare
        if (lseek(d, OFFSET, SEEK_SET) == (off_t)-1)
            perror("lseek(w)");
        else if (write(d, block[index], BLOCK_SIZE) != BLOCK_SIZE)
            perror("write");
        else if (fsync(d))
            perror("fsync");
        else if (lseek(d, OFFSET, SEEK_SET) == (off_t)-1)
            perror("lseek(r)");
        else if (read(d, buffer, BLOCK_SIZE) != BLOCK_SIZE)
            perror("read");
        else if (memcmp(block[index], buffer, BLOCK_SIZE))
            fprintf(stderr, "memcmp: test failed\n");
        else
            continue;

        printf("failed after %i successful cycles.\n", count);
        break;

    }

}
_

_O_DIRECT_の場合、バッファーは適切に位置合わせする必要があることに注意してください。通常、512バイトの境界で十分です。次のようにコンパイルできます:

_g++ -O0 test.cpp -o test
_

必要に応じて_-D_POSIX_C_SOURCE=200112L_を追加します。

次に、上記のようにデバイスを完全に満たした後、一晩実行しておきます。

_./test /dev/sdb
_

512バイトの整列書き込みは問題なく、1ページ全体が消去および再書き込みされます。より大きなブロックサイズを使用すると、テストを大幅にスピードアップできますが、具体的な結果に到達するのが複雑になります。

私は現在、昨日歩道で見つけたかなり風変わりな4GB PNYサムドライブでテストしています( http://www3.pny.com/4GB-Micro-Sleekの残されたもののようです) -Attach --- Purple-P2990C418.aspx )。

上記のプログラムは基本的にbadblocksの限定バージョンであり、すべての予約済みスペースが使い果たされるまでエラーは発生しません。したがって、期待されること(反復ごとに1ページが書き込まれる)は、上記の手順が平均して失敗することです。 reserved_pa​​ge_count * write_cycle_limit 繰り返し(繰り返しになりますが、ウェアレベリングは主要な変数です)。サムドライブは不良であり、SDカードは通常、予約されたスペースサイズを報告する機能を備えたSMARTをサポートしていません。

ちなみに、このテストでは、fsyncfdatasyncを比較しても、ブロックデバイスの書き込みに違いはありません。 open()モードは重要です。

技術的な詳細に興味がある場合は、 SDカードの内部動作について知りたい(さらに詳しく)のすべてを次に示します。 https://www.sdcard.org/downloads/pls/simplified_specs/part1_410.pdf

編集:バイトvsページ:これらのタイプのテストのコンテキストでは、バイトではなくページの観点から物事を考えることが重要です。反対のことをするのは非常に誤解を招く可能性があります。たとえば、SanDisk 8GB SDでは、コントローラーに応じたページサイズ(_/sys/classes/mmc_Host/mmc?/mmc?:????/preferred_erase_size_を介してアクセス可能)はフル4MBです。 16MBを書き込んで(4MB境界に揃えて)、4ページを消去/書き込みします。ただし、互いに4MBのオフセットでそれぞれ4つのシングルバイトを書き込むと、4ページも消去/書き込みされます。

「16MBの書き込みでテストした」と言うのは不正確です。これは、「4バイトの書き込みでテストした」のと同じ量の摩耗であるためです。より正確には、「4ページの書き込みでテストしました」。

6
Jason C

Slmの答えにいくつかのポイントを追加するだけです-SSDはデータを再生するので、「ダム」SDカードよりもSSDの方がより適切であることに注意してくださいmuchデータの汚れたトリック(重複排除など):

  • デバイスの先頭に64KBを書き込んでいます-これ自体に2つの問題があります。

    1. フラッシュセルには、通常、16KB以上のサイズの消去ブロックがあります(ただし、128-512KBの範囲がより一般的です)。つまり、少なくともこのサイズのキャッシュが必要です。したがって、64KBを書くだけでは十分ではないようです。

    2. ローエンド(「非エンタープライズ」を読む)ソリューションの場合(そして、SD/CFカードの場合、SSDよりもこれをさらに期待します)、製造元はデバイスの最初の部分を他の部分よりも回復力があるようにすることを選択できます。重要な構造-デバイスの単一パーティションのパーティションテーブルとFAT(ほとんどのメモリカードはこの設定を使用しています)-はそこにあります。したがって、カードの最初のテストは偏っている可能性があります。

  • fdatasync()は、データが物理メディアに書き込まれることを実際に保証するものではありません(ただし、OSの制御下にあるものはおそらく最善の結果を出します)-manページを参照してください:

    呼び出しはデバイスが報告するまで転送が完了したことをブロックします

    外部電源が失われた場合に、キャッシュされたデータをフラッシュメモリに書き込むためのエネルギーを提供できる小さなコンデンサがあることが判明しても、私は過度に驚かないでしょう。

    いずれにせよ、カードにキャッシュが存在するという前提( SUに関する質問への私の回答 を参照)では、64KBの書き込みと(fdatasync()を使用した)同期は、この目的のために十分説得力があります。 「電源バックアップ」がなくても、ファームウェアはそれを安全に再生できず、予想よりも少し長い間データを未書き込みのままにしておく可能性があります(通常の使用例では問題が発生しないため)。

  • 新しいブロックを書き込んで比較する前にデータを読み取って、それが実際に機能することを確認することもできます(十分に偏執狂の場合は、読み取り用にクリアされたバッファーを使用します)。

5
peterph