How Likely is the Last Block of a Drive to Be a Bad Sector

bad-blocksbad-sectorscygwin;hard drivewindows 7

This is a follow-up question to this one, where zeroing the disk with dd would give me an error towards the very end of the drive.

I then set about trying to determine whether this was a bad sector, as was suggested it might be, as opposed to some sort of issue with the hard drive or with the environment I was running.

Running:

badblocks -o ~/.badblocks_in_X_full -vws /dev/sda 976762584 950000000

…gives the output:

Checking for bad blocks in read-write mode
From block 950000000 to 976762584
Testing with pattern 0xaa: Weird value (4294967295) in do_writerrors)
done
Reading and comparing: done
Testing with pattern 0x55: Weird value (4294967295) in do_writeerrors)
done
Reading and comparing: done
Testing with pattern 0xff: Weird value (4294967295) in do_writeerrors)
done
Reading and comparing: done
Testing with pattern 0x00: Weird value (4294967295) in do_writeerrors)
done
Reading and comparing: done
Pass completed, 1 bad blocks found. (1/0/0 errors)

The resulting output file lists the bad block as block 976762584.

Doing cat /proc/partitions shows that dev/sda has 976762584 blocks.

In other words, badblocks is reporting that the very last block of the drive is bad.

I know it's possible that the very last block/sector of a drive could be the only bad sector on the drive, but it seemed to me such an unlikely occurrence that it would be more likely to be something else.

Is this bad sector reported by badblocks real, or more likely to be just a sign of hardware or environment issues?

Best Answer

Although this is not a direct answer to your question, but it may give you some insight.

First of all for some reason badblocks seem to report a bad block for "last block + 1" anyway (while for "last block + 2" or higher, it correctly return a seek error):

[tom@alarm ~]$ sudo badblocks /dev/mmcblk0 -b 512 -v 31116287 31116287
Checking blocks 31116287 to 31116287
Checking for bad blocks (read-only test): done                                   

Pass completed, 0 bad blocks found. (0/0/0 errors)
[tom@alarm ~]$ sudo badblocks /dev/mmcblk0 -b 512 -v 31116288 31116288
Checking blocks 31116288 to 31116288
Checking for bad blocks (read-only test): 31116288
done
Pass completed, 1 bad blocks found. (1/0/0 errors)
[tom@alarm ~]$ sudo badblocks /dev/mmcblk0 -b 512 -v 31116289 31116289
Checking blocks 31116289 to 31116289
Checking for bad blocks (read-only test): badblocks: Invalid argument during seek
done
Pass completed, 0 bad blocks found. (0/0/0 errors)
[tom@alarm ~]$ sudo badblocks /dev/mmcblk0 -b 512 -v 31116290 31116290
Checking blocks 31116290 to 31116290
Checking for bad blocks (read-only test): badblocks: Invalid argument during seek
done
Pass completed, 0 bad blocks found. (0/0/0 errors)
[tom@alarm ~]$

But dd has no such problem:

[tom@alarm ~]$ sudo dd if=/dev/mmcblk0 of=/dev/null skip=31116287
1+0 records in
1+0 records out                                                                  
512 bytes copied, 0.0254859 s, 20.1 kB/s
[tom@alarm ~]$ sudo dd if=/dev/mmcblk0 of=/dev/null skip=31116288
0+0 records in
0+0 records out
0 bytes copied, 0.000534631 s, 0.0 kB/s
[tom@alarm ~]$ sudo dd if=/dev/mmcblk0 of=/dev/null skip=31116289
dd: /dev/mmcblk0: cannot skip: Invalid argument
0+0 records in
0+0 records out
0 bytes copied, 0.000737962 s, 0.0 kB/s
[tom@alarm ~]$ sudo dd if=/dev/mmcblk0 of=/dev/null skip=31116290
dd: /dev/mmcblk0: cannot skip: Invalid argument
0+0 records in
0+0 records out
0 bytes copied, 0.000694995 s, 0.0 kB/s
[tom@alarm ~]$ sudo dd if=/dev/mmcblk0 of=/dev/null iflag=count_bytes,skip_bytes 
count=1M skip=15192M
2048+0 records in
2048+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.0612828 s, 17.1 MB/s
[tom@alarm ~]$ sudo dd if=/dev/mmcblk0 of=/dev/null iflag=count_bytes,skip_bytes 
count=1M skip=15193M
1024+0 records in
1024+0 records out
524288 bytes (524 kB, 512 KiB) copied, 0.029878 s, 17.5 MB/s
[tom@alarm ~]$ sudo dd if=/dev/mmcblk0 of=/dev/null iflag=count_bytes,skip_bytes 
count=1M skip=15194M
dd: /dev/mmcblk0: cannot skip: Invalid argument
0+0 records in
0+0 records out
0 bytes copied, 0.000814785 s, 0.0 kB/s
[tom@alarm ~]$ sudo dd if=/dev/mmcblk0 of=/dev/null iflag=count_bytes,skip_bytes 
count=1M skip=15195M
dd: /dev/mmcblk0: cannot skip: Invalid argument
0+0 records in
0+0 records out
0 bytes copied, 0.000700151 s, 0.0 kB/s
[tom@alarm ~]$

In any case, if you want to check whether a particular block is bad and/or compare the result of badblocks and dd, it's best that you test with the logical block size (usually 512 bytes) and do not use values that exceeds the actual size of the drive. Both pieces of information can be obtained with fdisk -l:

[tom@alarm ~]$ sudo fdisk -l /dev/mmcblk0
Disk /dev/mmcblk0: 14.86 GiB, 15931539456 bytes, 31116288 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
[tom@alarm ~]$

Also make sure you count from 0 when you are specifying a specific block, and do not count one less when you are specifying numbers of blocks (like for count/skip/seek in dd)

EDIT: It's actually natural that "last block + 1" is a special case as it is valid to seek an entire drive (last block inclusive). It's just that there's no more space to read/write. But for "last block + 2" or higher, even the the seek will go past the end of the drive, hence the seek error. It might also worth noting that current badblocks doesn't exactly check what the write error is (but just return to its caller that the written length is 0): https://github.com/tytso/e2fsprogs/blob/v1.45.4/misc/badblocks.c#L443