Fix for deb9 SCSI drives
The last fix to `__DATTOBD_PASSTHROUGH` worked fine for all major distro
kernels except Debian 9, on kernel 4.9. This time in kernel history
(after 4.7 and before 4.10), there was a transition in `struct bio` with
how it was processing opcodes and flags; it moved from `bi_rw` to `bi_opf`.
`bi_rw` was a bitfield of a bunch of flags, and many of the higher bits went
unused. We decided to take advantage of this and plop our flag in these
bits. This worked fine until the transition to `bi_opf` happened. `enum req_op`
defined opcodes for struct bio and the value of that enum saturated the
top 3 bits in `bi_opf`. This change is the root cause of our problem, but
more on that later. In 4.10, the space allocated to `enum req_op` in `bi_opf`
was too small, so the allocation expanded to a full byte and `enum req_opf`
was created to list the new opcodes. Luckily, all 8 bits have not been
saturated yet, so bit 30 is still unused.
Bit 30 in the `enum req_op` era would place the bit smack dab in the
middle of the opcode portion of `bi_opf`. So what does this have to do
with SCSI drives? `REQ_OP_SECURE_ERASE` is an ATA command for "securely"
erasing disk blocks. ATA is a newer standard than SCSI, and SCSI doesn't
support the command. `REQ_OP_SECURE_ERASE` has an enum value of 3.
`REQ_OP_WRITE` has an enum value of 1. Since `enum req_op` holds the top
3 bits in `bi_opf`, a write looks like this: `0 0 1 (bit 28 ... bit 0)`.
Flipping bit 30 would change this write to look like: `0 1 1 (bit 28 ...
bit 0)`, which is the opcode to REQ_OP_SECURE_ERASE. Every time we'd
apply the passthrough bit on writes, it would turn it into a secure
erase, and then sd_mod would throw a tantrum because it wouldn't know
what to do about the opcode. More frighteningly, this would still happen
on non-SCSI drives silently because it *would* know what to do with
the opcode, potentially causing data loss during a snapshot.