]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/scsi/sd.c
Merge branches 'pm-core', 'pm-qos', 'pm-domains' and 'pm-opp'
[linux.git] / drivers / scsi / sd.c
index 0b09638fa39be80768701f991cceccc1bee9988f..1f5d92a25a49dd0f928c194c5d64372fb2b071f6 100644 (file)
@@ -836,6 +836,7 @@ static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
        struct bio *bio = rq->bio;
        sector_t sector = blk_rq_pos(rq);
        unsigned int nr_sectors = blk_rq_sectors(rq);
+       unsigned int nr_bytes = blk_rq_bytes(rq);
        int ret;
 
        if (sdkp->device->no_write_same)
@@ -868,7 +869,21 @@ static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
 
        cmd->transfersize = sdp->sector_size;
        cmd->allowed = SD_MAX_RETRIES;
-       return scsi_init_io(cmd);
+
+       /*
+        * For WRITE SAME the data transferred via the DATA OUT buffer is
+        * different from the amount of data actually written to the target.
+        *
+        * We set up __data_len to the amount of data transferred via the
+        * DATA OUT buffer so that blk_rq_map_sg sets up the proper S/G list
+        * to transfer a single sector of data first, but then reset it to
+        * the amount of data to be written right after so that the I/O path
+        * knows how much to actually write.
+        */
+       rq->__data_len = sdp->sector_size;
+       ret = scsi_init_io(cmd);
+       rq->__data_len = nr_bytes;
+       return ret;
 }
 
 static int sd_setup_flush_cmnd(struct scsi_cmnd *cmd)