Я тестирую СОЛНЕЧНОЕ СОСТОЯНИЕ времени записи (код c), и устройство не выходит из строя - PullRequest
0 голосов
/ 14 января 2019

Оказывается, я неверно истолковал выравнивание износа. Сначала я подумал, что при обращении к диску как к RAW, я потеряю эту функцию, но, как функция на контроллере, это объясняет, почему я выполняю миллионы записей в «логическом секторе». Я тестирую

Я пишу приложение, в котором я буду использовать раздел диска RAW, например, кольцевой буфер, т.е. без файловой системы.

Мне нужно где-то отслеживать мои буферы чтения / записи, которые сохраняются при загрузке, я думал, что смогу создать еще один раздел для хранения этих 2 указателей.

Но меня беспокоит, сколько раз я могу записать в сектор устройства SOLID State Drive до того, как сектор умирает, поэтому я написал приведенный ниже код, чтобы забить один сектор и посмотреть, как быстро он выходит из строя.

  1. создать случайный блок (512 байт)
  2. запись в сектор 0 с использованием pwrite
  3. чтение блока из сектора 0 с использованием преада
  4. сравнить каждый байт
  5. выход при обнаружении разницы.

но он работал уже миллионы секторных записей !!

Я бы ожидал, что он выйдет из строя где-то стандартным, например, между 10 000-100 000 раз?

Я использую pread / pwrite, как показано ниже, со случайным буфером в каждом цикле и последующим сравнением обоих буферов.

void WriteBlock(const char* device, unsigned char* dataBlock, size_t sector, int size)
{
    int fd = open(device, O_WRONLY);
    if(fd <= 0)
    {
        std::cout << "error opening " << device << " '" << strerror(errno) << "'\r\n";
        exit(EXIT_FAILURE);
    }

    ssize_t r = pwrite(fd, dataBlock, size, sector*SECTOR_SIZE);
    if (r<=0 || r<size)
    {
        std::cout << "failure writing '" << strerror(errno) << "'\r\n";
        exit(EXIT_FAILURE);
    }
    close(fd);
}

void ReadBlock(const char* device, unsigned char* dataBlock, size_t sector, int size)
{
    int fd = open(device, O_RDONLY);
    if(fd <= 0)
    {
        std::cout << "error opening " << device << "\r\n";
        exit(EXIT_FAILURE);
    }

    ssize_t r = pread(fd, dataBlock, size, sector*SECTOR_SIZE);
    if (r<=0 || r<size)
    {
        std::cout << "failure writing '" << strerror(errno) << "'\r\n";
        exit(EXIT_FAILURE);
    }

    close(fd);
}

код просто продолжает работать с буфером записи, равным буферу чтения каждый раз.

К вашему сведению, я не сравниваю буфер записи с самим собой! если я жестко запишу значение в буфер чтения, он поймает это и интерпретирует как сбой.

1 Ответ

0 голосов
/ 14 января 2019

Я бы ожидал, что он выйдет из строя где-то стандартно, например, между 10000 и 100000 раз?

Большинство твердотельных накопителей имеют выравнивание износа. Это означает, что когда вы записываете в логический блок 0, устройство говорит: «Эй, старые данные в логическом блоке 0 перезаписываются, поэтому я могу просто притвориться, что совершенно другой физический блок теперь является логическим блоком 0». Постоянно записывая в один и тот же логический блок, вы можете записывать во множество совершенно разных физических блоков.

Чтобы победить выравнивание износа (и фактически записать в тот же физический блок), вы должны убедить устройство, что все остальные блоки используются. Это невозможно, потому что есть запасная емкость. Например, для устройства на 1 ТБ вы можете заполнить все 1 ТБ логических блоков данными (без каких-либо «усечений» и т. Д.), Но может быть дополнительно 512 ГБ свободного места, и ваши записи в один и тот же логический блок будут распределиться по этим 512 ГиБ свободного места; и к тому времени, когда вы действительно увидите ошибку, это может означать, что каждый блок в этих 512 ГБ свободного места вышел из строя (а не только один блок).

Если вы знаете, сколько на самом деле есть свободного места, то вы можете сделать расчеты на основе этого - например, если есть 1 тысяча резервных блоков и вы делаете 1 миллиард записей перед тем, как увидеть ошибку, то вы можете сказать: «1 миллиард записей / 1 тысяча блоков = 1 миллион записей в каждый физический блок».

Теперь представьте, что вы производитель, и у вас есть накопитель 1000 ГиБ. Вы решаете продавать его как потребительский диск (при условии, что диск будет в основном пустым и выравнивание износа будет работать нормально), и что вы можете сказать, что это диск на 900 ГБ (с 100 ГБ запасных блоков), который будет сбой после 10000 пишет. Затем вы решаете также продать тот же самый диск, что и корпоративный диск (при условии, что диск, вероятно, будет заполнен и выравнивание износа не будет таким эффективным), и вы можете сказать, что это диск на 900 ГБ (с 100 ГБ на запасные блоки), которые потерпят неудачу после 2000 пишет. Затем вы решаете, что можете увеличить объем свободного места, а также продать «в основном тот же» диск, что и корпоративный диск 500 ГБ (с 500 ГБ резервных блоков), который выйдет из строя после записи 20000.

Далее; представьте, что вы тестируете 1000 идентичных дисков (с программным обеспечением, которое вы пишете) и измеряете «20000 операций записи в среднем до сбоя в определенных условиях, используемых для тестирования (например, с остальными логическими блоками, свободными / пустыми)». Эта информация в основном бесполезна - если кто-то использует один и тот же диск в разных условиях (например, с меньшим количеством свободных / пустых логических блоков), то он выйдет из строя раньше (или позже), чем вы сказали.

Для (потенциально лучшей) альтернативы; Вы можете использовать информацию, полученную от "S.M.A.R.T." (см. https://en.wikipedia.org/wiki/S.M.A.R.T.). К сожалению, некоторые из наиболее полезных элементов информации, которые вы можете получить, зависят от производителя (например, общее количество зарезервированных блоков, общее количество не зарезервированных блоков), а некоторые устройства (флэш-память USB) вообще его не поддерживают.

...