4

Recently my SD card died, becoming permanently locked in a read-only state. I realized it a few weeks after the fact, when I saw that files I would create disappeared after a reboot. Of course, all changes I've done in these couple of weeks are also gone.

I wonder if there's a way I could get an early warning on the issue: a test which I could run in a cron job or similar, which ideally wouldn't require a reboot and wouldn't trash the SD card too much.

Any ideas?

4
  • If you create a new file and try to save it on a read only file system you immediately get an error message. You don't see that? Do you had a look into the journal?
    – Ingo
    Commented Aug 20, 2018 at 8:12
  • @Ingo The filesystem is not read-only, the meduim is. SD cards don't seem to report their end-of-life state to the OS (or the OS ignores those errors). Try running sudo sdtool /dev/mmcblk0 lock and see how long it takes for Raspbian to report IO errors. Unless you run a torrent client, it will take days. Commented Aug 20, 2018 at 8:32
  • what is sdtool @DmitryGrigoryev Commented Aug 21, 2018 at 5:12
  • @JaromandaX click on the link. Commented Aug 21, 2018 at 7:16

1 Answer 1

5

You could do a simple write/read test with a test pattern. A good test pattern is a byte with binary '01010101' = 0x55 hex and a byte '10101010' = 0xaa. Writing both will toggle every bit.

As I had realized by the comments the real problem is that the hardware of the storage does not report any error if it does not accept data. So even sync does not help. The operating system writes the buffered data (synchronize) to the storage and assumes buffer and storage content are identical when no error occurs. It continues reading data from the buffer it just has written and the error is not checked.

So we have to use unbuffered IO to check this. Python can do this with Raw I/O:

Raw I/O (also called unbuffered I/O) is generally used as a low-level building-block for binary and text streams; it is rarely useful to directly manipulate a raw stream from user code. Nevertheless, you can create a raw stream by opening a file in binary mode with buffering disabled.

Here is my example code. I write 64 bit (8 byte) test pattern and compare it. I open the test file only once and seek to the beginning for new comparison. Because we read and write direct to the storage there is no need to close and open always I think.

#!/usr/bin/python3

testpattern_55 = bytes( [0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55] )
f = open("/tmp/rwtst.raw", "w+b", buffering=0)
f.write(testpattern_55)
f.seek(0)
testpattern_read = f.read(8)
if testpattern_read != testpattern_55:
    print("ERROR writing test pattern!")
    f.close()
    exit(1)

testpattern_aa = bytes( [0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa] )
f.seek(0)
f.write(testpattern_aa)
f.seek(0)
testpattern_read = f.read(8)
if testpattern_read != testpattern_aa:
    print("ERROR writing test pattern!")
    f.close()
    exit(1)

f.close()

You can call it in a cron job to check automatically from time to time.

9
  • 1
    I'm pretty certain cat /tmp/rwtst.bin will read from cache instead of SD card. Commented Aug 20, 2018 at 11:42
  • Hmm... haven't thought of this. Just looking for a flush or sync possibility. Or reading after a delay longer than the sync period?
    – Ingo
    Commented Aug 20, 2018 at 11:56
  • @DmitryGrigoryev Seems to be simple. Just added sync to the script.
    – Ingo
    Commented Aug 20, 2018 at 12:01
  • 1
    sync does not clear caches, it just writes cached content to the disk. I'm looking at /proc/sys/vm/drop_caches. Commented Aug 20, 2018 at 12:10
  • @DmitryGrigoryev OK have realized the real problem now and have changed my answer.
    – Ingo
    Commented Aug 20, 2018 at 15:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.