aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAkinobu Mita <akinobu.mita@gmail.com>2013-09-18 08:27:26 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-10-25 04:58:12 -0400
commit65f72f2a2fe89f072d6a88e5cd69a64270b9c436 (patch)
tree05da71cdc92fcb9ea0888fdd2316c340ac89baf9
parentbb8c063c6afcd930b8da944927144f2982609638 (diff)
[SCSI] scsi_debug: avoid partial copying PI from prot_sglist to dif_storep
If data integrity support is enabled, prot_verify_write() is called in response to WRITE commands and it verifies protection info from prot_sglist by comparing against data sglist, and copies protection info to dif_storep. When multiple blocks are transfered by a WRITE command, it verifies and copies these blocks one by one. So if it fails to verify protection info in the middle of blocks, the actual data transfer to fake_storep isn't proceeded at all although protection info for some blocks are already copied to dif_storep. Therefore, it breaks the data integrity between fake_storep and dif_storep. This fixes it by ensuring that copying protection info to dif_storep is done after all blocks are successfully verified. Reusing dif_copy_prot() with supporting the opposite direction simplifies this fix. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Acked-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/scsi_debug.c40
1 files changed, 17 insertions, 23 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 99e74d75cf08..43369e9071f7 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -1790,7 +1790,7 @@ static int dif_verify(struct sd_dif_tuple *sdt, const void *data,
1790} 1790}
1791 1791
1792static void dif_copy_prot(struct scsi_cmnd *SCpnt, sector_t sector, 1792static void dif_copy_prot(struct scsi_cmnd *SCpnt, sector_t sector,
1793 unsigned int sectors) 1793 unsigned int sectors, bool read)
1794{ 1794{
1795 unsigned int i, resid; 1795 unsigned int i, resid;
1796 struct scatterlist *psgl; 1796 struct scatterlist *psgl;
@@ -1809,10 +1809,18 @@ static void dif_copy_prot(struct scsi_cmnd *SCpnt, sector_t sector,
1809 rest = start + len - dif_store_end; 1809 rest = start + len - dif_store_end;
1810 1810
1811 paddr = kmap_atomic(sg_page(psgl)) + psgl->offset; 1811 paddr = kmap_atomic(sg_page(psgl)) + psgl->offset;
1812 memcpy(paddr, start, len - rest);
1813 1812
1814 if (rest) 1813 if (read)
1815 memcpy(paddr + len - rest, dif_storep, rest); 1814 memcpy(paddr, start, len - rest);
1815 else
1816 memcpy(start, paddr, len - rest);
1817
1818 if (rest) {
1819 if (read)
1820 memcpy(paddr + len - rest, dif_storep, rest);
1821 else
1822 memcpy(dif_storep, paddr + len - rest, rest);
1823 }
1816 1824
1817 sector += len / sizeof(*dif_storep); 1825 sector += len / sizeof(*dif_storep);
1818 resid -= len; 1826 resid -= len;
@@ -1845,7 +1853,7 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
1845 ei_lba++; 1853 ei_lba++;
1846 } 1854 }
1847 1855
1848 dif_copy_prot(SCpnt, start_sec, sectors); 1856 dif_copy_prot(SCpnt, start_sec, sectors, true);
1849 dix_reads++; 1857 dix_reads++;
1850 1858
1851 return 0; 1859 return 0;
@@ -1928,15 +1936,12 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
1928{ 1936{
1929 int i, j, ret; 1937 int i, j, ret;
1930 struct sd_dif_tuple *sdt; 1938 struct sd_dif_tuple *sdt;
1931 struct scatterlist *dsgl = scsi_sglist(SCpnt); 1939 struct scatterlist *dsgl;
1932 struct scatterlist *psgl = scsi_prot_sglist(SCpnt); 1940 struct scatterlist *psgl = scsi_prot_sglist(SCpnt);
1933 void *daddr, *paddr; 1941 void *daddr, *paddr;
1934 sector_t tmp_sec = start_sec; 1942 sector_t sector = start_sec;
1935 sector_t sector;
1936 int ppage_offset; 1943 int ppage_offset;
1937 1944
1938 sector = do_div(tmp_sec, sdebug_store_sectors);
1939
1940 BUG_ON(scsi_sg_count(SCpnt) == 0); 1945 BUG_ON(scsi_sg_count(SCpnt) == 0);
1941 BUG_ON(scsi_prot_sg_count(SCpnt) == 0); 1946 BUG_ON(scsi_prot_sg_count(SCpnt) == 0);
1942 1947
@@ -1964,25 +1969,13 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
1964 1969
1965 sdt = paddr + ppage_offset; 1970 sdt = paddr + ppage_offset;
1966 1971
1967 ret = dif_verify(sdt, daddr + j, start_sec, ei_lba); 1972 ret = dif_verify(sdt, daddr + j, sector, ei_lba);
1968 if (ret) { 1973 if (ret) {
1969 dump_sector(daddr + j, scsi_debug_sector_size); 1974 dump_sector(daddr + j, scsi_debug_sector_size);
1970 goto out; 1975 goto out;
1971 } 1976 }
1972 1977
1973 /* Would be great to copy this in bigger
1974 * chunks. However, for the sake of
1975 * correctness we need to verify each sector
1976 * before writing it to "stable" storage
1977 */
1978 memcpy(dif_storep + sector, sdt, sizeof(*sdt));
1979
1980 sector++; 1978 sector++;
1981
1982 if (sector == sdebug_store_sectors)
1983 sector = 0; /* Force wrap */
1984
1985 start_sec++;
1986 ei_lba++; 1979 ei_lba++;
1987 ppage_offset += sizeof(struct sd_dif_tuple); 1980 ppage_offset += sizeof(struct sd_dif_tuple);
1988 } 1981 }
@@ -1991,6 +1984,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
1991 kunmap_atomic(daddr); 1984 kunmap_atomic(daddr);
1992 } 1985 }
1993 1986
1987 dif_copy_prot(SCpnt, start_sec, sectors, false);
1994 dix_writes++; 1988 dix_writes++;
1995 1989
1996 return 0; 1990 return 0;