Being a complete fanny, I managed to drop my phone and break the display assembly again.
I was in the pub the next day with a friend recounting my tale of woe, and as he was showing off his shiny new phone to me, it suddenly occurred to me that we used to have the same phone. I ended up buying his old phone off him for parts, and repaired my phone there and then.
I bought a new 64GB SD card on ebay and when it arrived I decided to do a check of its integrity:
$ dd if=/dev/urandom bs=1M count=64000|pv|sudo tee /dev/mmcblk0|sha1sum -
Already things were seeming suspicious: It claimed to be a class 10 card (10MB/s) but it initially wrote (at least for the first few GB when I was paying attention) at about 2-2.5MB/s.
When I came back later, it was ~45GB in and had sped up to about 15MB/s.
I had planned to read it back and check that the data were the same:
$ sudo pv /dev/mmcblk0 | sha1sum -
But it read at about 10MB/s (rather than the advertised 50MB/s) so I lost interest and tried a different approach, writing to random locations and reading back. 54MiB in was fine, but 54722MiB in returned garbage.
I threw together a quick script to check random 1MiB blocks throughout the disk:
#!/bin/bash dd if=/dev/urandom bs=1M count=1 of=somerandom for i in $(seq 1 1000) do thisblock=$(shuf -i 0-63999 -n 1) sudo dd if=somerandom of=/dev/mmcblk0 bs=1M seek=$thisblock sudo sync sudo dd if=/dev/mmcblk0 skip=$thisblock bs=1M count=1 | diff - somerandom if [ $? == 1 ] then echo "bad" echo $thisblock >> badblocks else echo "good" echo $thisblock >> goodblocks fi done
(I don’t know if the sync is necessary – I wasn’t sure if maybe there’d be some transparent caching in play whereby the OS would assume what it’s just written is still there.)
This gave me two lists, one of the known good blocks and one of the known bad blocks. About 3/4 of the blocks were bad, so it was looking like this 64GB was a 16GB in disguise:
$ wc -l goodblocks badblocks 240 goodblocks 760 badblocks 1000 total
I threw together a piece of octave too, to make a visualisation:
goodblocks=dlmread("goodblocks"); badblocks=dlmread("badblocks"); image=zeros(320,200); for i=goodblocks' x=floor(i/200)+1; y=(mod(i,200))+1; image(x,y)=1; end for i=badblocks' x=floor(i/200)+1; y=(mod(i,200))+1; image(x,y)=2; end colourmap=[0 0 0; 0 1 0; 1 0 0]; imshow(image+1,colourmap); imwrite(image+1,colourmap,"image.png")
Each pixel represents a 1MiB block of the SD card, top left being the start, working right then down, with the bottom right being 64GB (more accurately 64kMiB, or 64000MiB). Black pixels are unknown (the script took a random sample of 1000 blocks out of 64k), green are good (read back the same) and red are bad. This looks pretty conclusively like it’s a 16GB card in disguise.
The bad section seems to be the same 512 byte pattern repeated over and over for a bit, then the repeated pattern changes sometimes for no discernible reason. I haven’t invested much energy into figuring out why yet.