Gerd Hoffmann wrote:
> On 11/26/09 11:57, Hannes Reinecke wrote:
>> Then the guest would see a partial request and retry the
>> remainder of the request, which (possibly after some iterations)
>> would result in all data transferred, albeit at a lower speed.
> 
> Except they don't.
> 
> /me looks at drivers/scsi/sd.c:sd_done()
> 
> I can't see any sane way to tell linux that the request was too big.
> 
residuals is the key:

drivers/scsi/scsi.c:scsi_finish_command()


        good_bytes = scsi_bufflen(cmd);
        if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
                int old_good_bytes = good_bytes;
                drv = scsi_cmd_to_driver(cmd);
                if (drv->done)
                        good_bytes = drv->done(cmd);
                /*
                 * USB may not give sense identifying bad sector and
                 * simply return a residue instead, so subtract off the
                 * residue if drv->done() error processing indicates no
                 * change to the completion length.
                 */
                if (good_bytes == old_good_bytes)
                        good_bytes -= scsi_get_resid(cmd);
        }
        scsi_io_completion(cmd, good_bytes);

and in

drivers/scsi/scsi_lib.c:scsi_io_completion()

        /*
         * A number of bytes were successfully read.  If there
         * are leftovers and there is some kind of error
         * (result != 0), retry the rest.
         */
        if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL)
                return;


No-one forces us to complete the _entire_ request; just completing
the request partially is perfectly okay as long as we mark it properly.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                   zSeries & Storage
h...@suse.de                          +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Markus Rex, HRB 16746 (AG Nürnberg)


Reply via email to