F3 - an alternative to h2testw

I've bought a 32GB microSDHC card for my Android that always fails when one fills it up. Googling about this issue, I arrived at the blogs Fight Flash Fraud and SOSFakeFlash, which recomend the software H2testw (see here or here) to test flash memories. I downloaded H2testw and found two issues with it: (1) it is for Windows only, and (2) it is not open source. However, its author was kind enough to include a text file that explains what it does; this page is about my GPLv3 implementation of that algorithm.

My implementation is simple and reliable, and I don't know exactly how F3 compares to H2testw since I've never run H2testw. I call my implementation F3, what is short for Fight Flash Fraud, or Fight Fake Flash.

Download and Compile

The files of the stable version of F3 are here. The command below uncompresses the files. Follow instructions in file README to compile it on a Linux machine, or a Mac:

$ unzip f3v2.zip
  

Versions older than 2.0 do not compile on Macs!

How to use F3

F3 is composed of two binaries: f3write, and f3read. f3write fills a file system up with 1GB files named NNNN.fff, where N is a number (i.e. /[0-9]/). Whereas, f3read validates those files. If the content of all NNNN.fff files is valid, the memory is fine. The last file may be less than 1GB since f3write takes all available space for data. Below the result on my fake card:

$ ./f3write /media/5EBD-5C80/
Free space: 28.83 GB
Creating file 0001.fff ... OK!
Creating file 0002.fff ... OK!
Creating file 0003.fff ... OK!
Creating file 0004.fff ... OK!
Creating file 0005.fff ... OK!
Creating file 0006.fff ... OK!
Creating file 0007.fff ... OK!
Creating file 0008.fff ... OK!
Creating file 0009.fff ... OK!
Creating file 0010.fff ... OK!
Creating file 0011.fff ... OK!
Creating file 0012.fff ... OK!
Creating file 0013.fff ... OK!
Creating file 0014.fff ... OK!
Creating file 0015.fff ... OK!
Creating file 0016.fff ... OK!
Creating file 0017.fff ... OK!
Creating file 0018.fff ... OK!
Creating file 0019.fff ... OK!
Creating file 0020.fff ... OK!
Creating file 0021.fff ... OK!
Creating file 0022.fff ... OK!
Creating file 0023.fff ... OK!
Creating file 0024.fff ... OK!
Creating file 0025.fff ... OK!
Creating file 0026.fff ... OK!
Creating file 0027.fff ... OK!
Creating file 0028.fff ... OK!
Creating file 0029.fff ... OK!
Free space: 0.00 Byte
Average Writing speed: 2.60 MB/s

$ ./f3read /media/5EBD-5C80/
                     SECTORS      ok/corrupted/changed/overwritten
Validating file 0001.fff ...       0/  2097152/      0/      0
Validating file 0002.fff ...       0/  2097152/      0/      0
Validating file 0003.fff ...       0/  2097152/      0/      0
Validating file 0004.fff ...       0/  2097152/      0/      0
Validating file 0005.fff ...       0/  2097152/      0/      0
Validating file 0006.fff ...       0/  2097152/      0/      0
Validating file 0007.fff ...       0/  2097152/      0/      0
Validating file 0008.fff ...       0/  2097152/      0/      0
Validating file 0009.fff ...       0/  2097152/      0/      0
Validating file 0010.fff ...       0/  2097152/      0/      0
Validating file 0011.fff ...       0/  2097152/      0/      0
Validating file 0012.fff ...       0/  2097152/      0/      0
Validating file 0013.fff ...       0/  2097152/      0/      0
Validating file 0014.fff ...       0/  2097152/      0/      0
Validating file 0015.fff ...       0/  2097152/      0/      0
Validating file 0016.fff ...       0/  2097152/      0/      0
Validating file 0017.fff ...       0/  2097152/      0/      0
Validating file 0018.fff ...       0/  2097152/      0/      0
Validating file 0019.fff ...       0/  2097152/      0/      0
Validating file 0020.fff ...       0/  2097152/      0/      0
Validating file 0021.fff ...       0/  2097152/      0/      0
Validating file 0022.fff ...       0/  2097152/      0/      0
Validating file 0023.fff ...       0/  2097152/      0/      0
Validating file 0024.fff ... 1916384/   180768/      0/      0
Validating file 0025.fff ...  186816/  1910336/      0/      0
Validating file 0026.fff ...       0/  2097152/      0/      0
Validating file 0027.fff ...       0/  2097152/      0/      0
Validating file 0028.fff ...       0/  2097152/      0/      0
Validating file 0029.fff ...   28224/  1705280/      0/      0

  Data OK: 1.02 GB (2131424 sectors)
Data LOST: 27.81 GB (58322336 sectors)
	       Corrupted: 27.81 GB (58322336 sectors)
	Slightly changed: 0.00 Byte (0 sectors)
	     Overwritten: 0.00 Byte (0 sectors)
Average Reading speed: 9.54 MB/s
  

This report shows that my flash card is pretty much garbage since it can only hold 1.02GB. f3write only writes to free space, and will not overwrite existing files as long as they aren't named NNNN.fff. However, as the previous report also shows files from 0001.fff to 0023.fff were written before 0024.fff and yet had all their content destroyed. Therefore, it is not wise to test nonempty cards because if the card has a problem, it may erase the old files.

When f3read reads a sector (i.e. 512 bytes, the unit of communication with the card), f3read can check if the sector was correctly written by f3write, and figure out in which file the sector should be and in which position in that file the sector should be. Thus, if a sector is well formed, or with a few bits flipped, but read in an unexpected position, f3read counts it as overwritten. Slightly changed sectors, are sectors at right position with a fews bits flipped.

Notice that f3write doesn't overwrite sectors by itself, it's done by the memory card's controller as a way to difficult a user to uncover its fault. So, the way sectors are overwritten is totally dependent on the controller; from the point of view of a file system, what f3read sees, the way the controller wraps around seems often contrived, but I think that from the memory chip's view, what the controller sees, it is just a truncation of addresses.

The last lines of the output of f3write and f3read provide good estimates of the writing and reading speeds of the tested card. This information can be used to check if the claimed class of the card is correct. Check this link out for more information about classes. Note that the speeds provided by F3 are estimates, don't take them as perfect since they suffer influence even from other processes in your machine!

Later I bought a second card that works just fine; I got the following output running F3 on it:

$ ./f3write /media/6135-3363/
Free space: 29.71 GB
Creating file 0001.fff ... OK!
Creating file 0002.fff ... OK!
Creating file 0003.fff ... OK!
Creating file 0004.fff ... OK!
Creating file 0005.fff ... OK!
Creating file 0006.fff ... OK!
Creating file 0007.fff ... OK!
Creating file 0008.fff ... OK!
Creating file 0009.fff ... OK!
Creating file 0010.fff ... OK!
Creating file 0011.fff ... OK!
Creating file 0012.fff ... OK!
Creating file 0013.fff ... OK!
Creating file 0014.fff ... OK!
Creating file 0015.fff ... OK!
Creating file 0016.fff ... OK!
Creating file 0017.fff ... OK!
Creating file 0018.fff ... OK!
Creating file 0019.fff ... OK!
Creating file 0020.fff ... OK!
Creating file 0021.fff ... OK!
Creating file 0022.fff ... OK!
Creating file 0023.fff ... OK!
Creating file 0024.fff ... OK!
Creating file 0025.fff ... OK!
Creating file 0026.fff ... OK!
Creating file 0027.fff ... OK!
Creating file 0028.fff ... OK!
Creating file 0029.fff ... OK!
Creating file 0030.fff ... OK!
Free space: 0.00 Byte
Average Writing speed: 4.90 MB/s

$ ./f3read /media/6135-3363/
                     SECTORS      ok/corrupted/changed/overwritten
Validating file 0001.fff ... 2097152/        0/      0/      0
Validating file 0002.fff ... 2097152/        0/      0/      0
Validating file 0003.fff ... 2097152/        0/      0/      0
Validating file 0004.fff ... 2097152/        0/      0/      0
Validating file 0005.fff ... 2097152/        0/      0/      0
Validating file 0006.fff ... 2097152/        0/      0/      0
Validating file 0007.fff ... 2097152/        0/      0/      0
Validating file 0008.fff ... 2097152/        0/      0/      0
Validating file 0009.fff ... 2097152/        0/      0/      0
Validating file 0010.fff ... 2097152/        0/      0/      0
Validating file 0011.fff ... 2097152/        0/      0/      0
Validating file 0012.fff ... 2097152/        0/      0/      0
Validating file 0013.fff ... 2097152/        0/      0/      0
Validating file 0014.fff ... 2097152/        0/      0/      0
Validating file 0015.fff ... 2097152/        0/      0/      0
Validating file 0016.fff ... 2097152/        0/      0/      0
Validating file 0017.fff ... 2097152/        0/      0/      0
Validating file 0018.fff ... 2097152/        0/      0/      0
Validating file 0019.fff ... 2097152/        0/      0/      0
Validating file 0020.fff ... 2097152/        0/      0/      0
Validating file 0021.fff ... 2097152/        0/      0/      0
Validating file 0022.fff ... 2097152/        0/      0/      0
Validating file 0023.fff ... 2097152/        0/      0/      0
Validating file 0024.fff ... 2097152/        0/      0/      0
Validating file 0025.fff ... 2097152/        0/      0/      0
Validating file 0026.fff ... 2097152/        0/      0/      0
Validating file 0027.fff ... 2097152/        0/      0/      0
Validating file 0028.fff ... 2097152/        0/      0/      0
Validating file 0029.fff ... 2097152/        0/      0/      0
Validating file 0030.fff ... 1491904/        0/      0/      0

  Data OK: 29.71 GB (62309312 sectors)
Data LOST: 0.00 Byte (0 sectors)
	       Corrupted: 0.00 Byte (0 sectors)
	Slightly changed: 0.00 Byte (0 sectors)
	     Overwritten: 0.00 Byte (0 sectors)
Average Reading speed: 9.42 MB/s
  

As a final remark, since f3write and f3read are independent, f3read can be used as many times as one wants, although f3write is needed only once. This allows one to easily repeat a test of a card as long as the NNNN.fff files are still available.

Users' notes

Randy Champoux has brought to my attention that, on small fake flash cards, there could be an issue with f3read reading some data from the system cache instead of from the flash card. Since version 2.0, F3 eliminates this possibility as long as the kernel honors the system call posix_fadvise(2) with advice POSIX_FADV_DONTNEED. Linux has and honor posix_fadvise(2)/POSIX_FADV_DONTNEED, whereas Mac does not. Although it's still a real possibility for older vesions of F3, or on kernels that don't follow advices, it should be very rare because the cache works on the announced size of the flash card not on its real size, and f3read starts from the beginning of the data written, that is, there is a rotation of what's on the buffers. In my experience, with exception of servers, which easily have buffers larger than 1GB, the issue shouldn't come out on desktops for any flash card that announces a size of 4GB or more. Finally, unmounting and mounting the device again before calling f3read should eliminate this issue.

When Art Gibbens tested a flash card hosted in a camera connected to his Linux box, at some point F3 didn't show progress, and could not be killed. After a reboot, the card was read only. Using an adapter to connect his card directly to his machine, he recreated the partition of the card adapting the steps described in section "How to 'fix" a fake card', and successfully run F3 with the card in the adpater. Thus, Art's experience is a good warning if you're testing your card in a device other than an adapter. Please, don't take it as a bug of F3. I'm aware of only two things that can make a process "survive" a kill signal: hardware failure, and/or bug in the kernel. F3 doesn't run in kernel mode, so Art's camera is likely the root of the problem.

Darrell Johnson has reported that a flash card he got stopped working after he filled it up. This could be that the only memory chip the card had died, but it is just speculation since Darrell was not able to obtain more information. The important message here is that if you test your card with F3, or just copy files into it, and it stops working, it's not your fault because writing files to a card shouldn't damage it if it is a legitimate card!

How to "fix" a fake card

IMPORTANT: this section is only intended for advanced users, if you don't understand it, don't follow the instructions described here! If you make a mistake with fdisk, you may erase all your data.

If you are reading this section, you already realized that you own a fake card, and would like to be able to use it without losing data. I haven't extensively tested the process listed below, but it worked for me, and MAY work for you as well.

As shown in the previous section, my fake card can only hold 1GB. So, using fdisk I have removed the old partition and created a new one with only 1GB. My card was recognized at /dev/sdh, change this parameter according to your case. My fdisk session was as follows:

# fdisk -l /dev/sdh

Disk /dev/sdh: 32.5 GB, 32505331712 bytes
1 heads, 32 sectors/track, 1983968 cylinders
Units = cylinders of 32 * 512 = 16384 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sdh1   *           5     1983968    31743423+   c  W95 FAT32 (LBA)
Partition 1 does not end on cylinder boundary.

# fdisk /dev/sdh

WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help): d
Selected partition 1

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (2-1983968, default 2): 
Using default value 2
Last cylinder, +cylinders or +size{K,M,G} (2-1983968, default 1983968): +1G

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): c
Changed system type of partition 1 to c (W95 FAT32 (LBA))

Command (m for help): a
Partition number (1-4): 1

Command (m for help): p

Disk /dev/sdh: 32.5 GB, 32505331712 bytes
1 heads, 32 sectors/track, 1983968 cylinders
Units = cylinders of 32 * 512 = 16384 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sdh1   *           2       65538     1048592    c  W95 FAT32 (LBA)

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: If you have created or modified any DOS 6.x
partitions, please see the fdisk manual page for additional
information.
Syncing disks.
  

Once the new partition is created, just format it:

# mkfs.vfat /dev/sdh1
mkfs.vfat 3.0.7 (24 Dec 2009)
  

At this point your card should be working just fine, but before using it, test it again with F3! The test of my card went as follows:

$ ./f3write /media/45B9-B05C/
Free space: 1022.00 MB
Creating file 0001.fff ... OK!
Free space: 0.00 Byte
Average Writing speed: 1.88 MB/s

$ ./f3read /media/45B9-B05C/
                     SECTORS      ok/corrupted/changed/overwritten
Validating file 0001.fff ... 2093048/        0/      0/      0

  Data OK: 1022.00 MB (2093048 sectors)
Data LOST: 0.00 Byte (0 sectors)
	       Corrupted: 0.00 Byte (0 sectors)
	Slightly changed: 0.00 Byte (0 sectors)
	     Overwritten: 0.00 Byte (0 sectors)
Average Reading speed: 8.45 MB/s
  

Repository

The Git repository is kept here. The old page with the history is here; it is no longer maintained.

Author

Michel Machado. E-mail me at michel at digirati dot com dot br.

Copyright and License

F3 is licensed under the GNU General Public License (GPL) version 3.

Copyright (c) 2010 Digirati.