Mike
Mike

Reputation: 49473

How can I check for bad sectors of a flash device with C?

I need to create a utility to check for bad sectors in flash memory.

I started out with an old flash drive that I have, I stuck it in my Ubuntu laptop and checked the dmesg to see it was mounted as /dev/sdb, I then ran fdisk to see the number/size of the sectors:

mike@mike-Qosmio-X770:~$ sudo fdisk -l [sudo] password for mike:

Disk /dev/sdb: 127 MB, 127926272 bytes 16 heads, 32 sectors/track, 488 cylinders, total 249856 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x6b3ee723

Device Boot      Start         End      Blocks   Id  System 
/dev/sdb1   *     32         249854     124911+   b  W95 FAT32

So great, I know a sector is 512 bytes and there should be a total of 249,856 of them. Based on that I wrote this small test program to double check:

#include <stdio.h>
#include <strings.h>
#include <stdlib.h>

int main (int argc, char *argv[]) {
    FILE * fp = NULL;
    char buffer[512] = {0};  // size of a sector, 512 bytes
    long sector_count = 0;

     fp = fopen("/dev/sdb", "rb");  // open the flash device as binary

    if(fp == NULL) {
        printf("Can't open the flash drive!\n");
        return -1;
    }
    while(!feof(fp) && (fread(buffer, sizeof(buffer), 1, fp) > 0)){
         sector_count++;
    }

    fclose(fp);
    printf("Sectors: %ld\n", sector_count);
    return 0;
}

Worked wonderfully, reported 249856. Now I'm stuck thinking how to proceed. Would it work to write a series of 0xFF's to the drive (512x249856 1 bit's), then read it back to make sure it got set to 1? Then write the same number of 0s to make sure it can be cleared?

Would that verify that everything's working? Is there any chance I could overwrite the FTL (Flash translation layer) code or is that protected even from me messing around with the drive like this?

<background for interested parties>
This is for a project where we have a uCLinux 2.4 kernel with strange behavior.. we suspect bad hardware (specificly the flash) but I can't find good tools that work on 2.4 to test the flash fs so I thought I'd try to write my own.
</background>

Upvotes: 3

Views: 3508

Answers (2)

MvG
MvG

Reputation: 61027

Modern hardware can usually recognize data corruption, i.e. you are more likely to encounter an I/O error than actually reading bad data from a device. Furthermore, the devices usually contain some amount of redundancy, so bad blocks will be detected and replaced with good ones. For modern hard discs, S.M.A.R.T. will give information on the bad block count. Not sure whether this works for common flash devices as well, but I'd guess so.

Upvotes: 0

marko
marko

Reputation: 9169

I'm guessing that since your device is mounted on /dev/sdb1 we're dealing with some kind of removable flash media device such as a USB-stick or media-card. If you are dealing with an SATA attached SSD, similar considerations apply.

In these devices, the block-interface is an abstraction for a complex device controller that sits on top of the flash.

Flash devices typically have very large blocks (called erase units, 128kB is not uncommon as a size) which can be written once before a much slower erase takes place. The device's controller implements a logical<->physical mapping between the block interface - as seen by the host - and erase-units on the physical device. As part of the management process, the controller will implemented error detection and correction and manage defective erase units. This entire process is invisible at the block interface.

Consequently, as logical blocks never have a permanent mapping to physical erase units, it is impossible to perform a meaningful bad-block scan from the block-interface.

If you happen to have a directly attached flash array managed by the mtd layer, mtd-tools is what you want, along with the corresponding kernel-modules. Documentation can be found here

Upvotes: 2

Related Questions