On Wed, Oct 31 2007 at 10:49 +0200, Jeff Garzik <jeff@xxxxxxxxxx> wrote:I looked into killing sg_last(), but really, this is the best its gonnaOK Now I'm confused. I thought that ULD's can give you SG's that are actually longer than bufflen and that, at the end, the bufflen should govern the transfer length.
get (moving sg_last to libata-core.c).
You could maybe kill one use with caching, but in the other sg_last()
callsites there isn't another s/g loop we can stick a "last_sg = sg;"
into.
libata is stuck because we undertake the highly unusual operation of
fiddling with the final S/G element, to enforce 32-bit alignment.
Of course we could eliminate all that nasty fiddling/padding
completely, including sg_last(), if other areas of the kernel would
guarantee ahead of time that buffer lengths are always a multiple
of 4........
Jeff
Now FS_PC commands are sector aligned so you do not have
problems with that.
The BLOCK_PC commands have 2 main sources that I know of
one is sg && bsg from user mode that can easily enforce
4 bytes alignment. The second is kernel services which 80%
of these are done by scsi_execute(). All These can be found
and fixed. Starting with scsi_execute(). Another place can be
blk_rq_map_sg(), since all IO's are bio based. It can enforce alignment too.
I would start by sticking a WARN_ON(qc->pad_len) and
see if it triggers, what are the sources of that.