bio_integrity_verify() bug causing READ verify to be silentlyskipped

From: Nicholas A. Bellinger
Date: Mon Dec 23 2013 - 23:19:51 EST


Hi Martin & Co,

So after playing with the mainline DIF client against an initial WIP
target DIF support patch, I've started hitting a bug in
bio_integrity_verify() that causes READ verify logic to be silently
skipped for both WIP target and existing scsi_debug DIF code.

The issue is with the scsi_end_request() -> blk_end_request() completion
path, where eventually blk_update_request() -> req_bio_endio() ->
bio_advance() is called to increment bio->bi_idx to a non-zero value.

Given that bio_integrity_verify() is using bio_for_each_segment(), the
loop starts from the updated bio->bi_idx, and not a zero value, which
ends up skipping individual bio segment calls to bi->verify_fn().

The following patch changes bio_integrity_verify() to use
bio_for_each_segment_all() instead of bio_for_each_segment() to ensure
that the segment walk always starts from zero, regardless of the current
bio->bi_idx value after bio_advance().

Note this bug has been observed with v3.13-rc3 code, and I haven't yet
looked back to figure out when this bug was first introduced.. Any
ideas..?

Interestingly enough, the scsi-mq alpha code does not suffer from this
bug, as blk_end_request() is never called from scsi_mq_end_request() ->
blk_mq_end_io() completion path code.

Thank you,

--nab