]> git.hungrycats.org Git - linux/commitdiff
storvsc: do not assume SG list is continuous when doing bounce buffers
authorLong Li <longli@microsoft.com>
Wed, 10 Jan 2018 20:21:29 +0000 (13:21 -0700)
committerSasha Levin <alexander.levin@microsoft.com>
Sun, 21 Jan 2018 14:59:00 +0000 (09:59 -0500)
The original patch was made for stable 4.1 and was Acked on 08/22/2017, but for
some reason it never made it to the stable tree.

Change from v1:
Changed comment that this patch is for linux-stable 4.1 and all prior stable
kernels.

storvsc checks the SG list for gaps before passing them to Hyper-v device.
If there are gaps, data is copied to a bounce buffer and a continuous data
buffer is passed to Hyper-V.

The check on gaps assumes SG list is continuous, and not chained. This is
 not always true. Failing the check may result in incorrect I/O data
passed to the Hyper-v device.

This code path is not used post Linux 4.1.

[LL: Backport for 4.1]
Signed-off-by: Long Li <longli@microsoft.com>
Acked-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
drivers/scsi/storvsc_drv.c

index e4b103d5d2896f8008b7c4b61e3a55b5eab616b0..98b56a7069d3d1aaad38feebc570290357b1367e 100644 (file)
@@ -582,17 +582,18 @@ static int do_bounce_buffer(struct scatterlist *sgl, unsigned int sg_count)
        for (i = 0; i < sg_count; i++) {
                if (i == 0) {
                        /* make sure 1st one does not have hole */
-                       if (sgl[i].offset + sgl[i].length != PAGE_SIZE)
+                       if (sgl->offset + sgl->length != PAGE_SIZE)
                                return i;
                } else if (i == sg_count - 1) {
                        /* make sure last one does not have hole */
-                       if (sgl[i].offset != 0)
+                       if (sgl->offset != 0)
                                return i;
                } else {
                        /* make sure no hole in the middle */
-                       if (sgl[i].length != PAGE_SIZE || sgl[i].offset != 0)
+                       if (sgl->length != PAGE_SIZE || sgl->offset != 0)
                                return i;
                }
+               sgl = sg_next(sgl);
        }
        return -1;
 }