aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sd_dif.c
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2014-09-26 19:20:08 -0400
committerJens Axboe <axboe@fb.com>2014-09-30 17:17:35 -0400
commitc611529e7cd3465ec0eada0f44200e8420c38908 (patch)
treec1cbfbd9b3229906ec36c897761d06e1521823bd /drivers/scsi/sd_dif.c
parent582940508b5d589229d0232e0eeee8fef0d54809 (diff)
sd: Honor block layer integrity handling flags
A set of flags introduced in the block layer enable better control over how protection information is handled. These flags are useful for both error injection and data recovery purposes. Checking can be enabled and disabled for controller and disk, and the guard tag format is now a per-I/O property. Update sd_protect_op to communicate the relevant information to the low-level device driver via a set of flags in scsi_cmnd. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Reviewed-by: Sagi Grimberg <sagig@mellanox.com> Acked-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/scsi/sd_dif.c')
-rw-r--r--drivers/scsi/sd_dif.c23
1 files changed, 9 insertions, 14 deletions
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
index b7eaeadc18f9..14c7d42a11c2 100644
--- a/drivers/scsi/sd_dif.c
+++ b/drivers/scsi/sd_dif.c
@@ -106,8 +106,7 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
106 * 106 *
107 * Type 3 does not have a reference tag so no remapping is required. 107 * Type 3 does not have a reference tag so no remapping is required.
108 */ 108 */
109void sd_dif_prepare(struct request *rq, sector_t hw_sector, 109void sd_dif_prepare(struct scsi_cmnd *scmd)
110 unsigned int sector_sz)
111{ 110{
112 const int tuple_sz = sizeof(struct t10_pi_tuple); 111 const int tuple_sz = sizeof(struct t10_pi_tuple);
113 struct bio *bio; 112 struct bio *bio;
@@ -115,14 +114,14 @@ void sd_dif_prepare(struct request *rq, sector_t hw_sector,
115 struct t10_pi_tuple *pi; 114 struct t10_pi_tuple *pi;
116 u32 phys, virt; 115 u32 phys, virt;
117 116
118 sdkp = rq->bio->bi_bdev->bd_disk->private_data; 117 sdkp = scsi_disk(scmd->request->rq_disk);
119 118
120 if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION) 119 if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION)
121 return; 120 return;
122 121
123 phys = hw_sector & 0xffffffff; 122 phys = scsi_prot_ref_tag(scmd);
124 123
125 __rq_for_each_bio(bio, rq) { 124 __rq_for_each_bio(bio, scmd->request) {
126 struct bio_integrity_payload *bip = bio_integrity(bio); 125 struct bio_integrity_payload *bip = bio_integrity(bio);
127 struct bio_vec iv; 126 struct bio_vec iv;
128 struct bvec_iter iter; 127 struct bvec_iter iter;
@@ -163,7 +162,7 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
163 struct scsi_disk *sdkp; 162 struct scsi_disk *sdkp;
164 struct bio *bio; 163 struct bio *bio;
165 struct t10_pi_tuple *pi; 164 struct t10_pi_tuple *pi;
166 unsigned int j, sectors, sector_sz; 165 unsigned int j, intervals;
167 u32 phys, virt; 166 u32 phys, virt;
168 167
169 sdkp = scsi_disk(scmd->request->rq_disk); 168 sdkp = scsi_disk(scmd->request->rq_disk);
@@ -171,12 +170,8 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
171 if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION || good_bytes == 0) 170 if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION || good_bytes == 0)
172 return; 171 return;
173 172
174 sector_sz = scmd->device->sector_size; 173 intervals = good_bytes / scsi_prot_interval(scmd);
175 sectors = good_bytes / sector_sz; 174 phys = scsi_prot_ref_tag(scmd);
176
177 phys = blk_rq_pos(scmd->request) & 0xffffffff;
178 if (sector_sz == 4096)
179 phys >>= 3;
180 175
181 __rq_for_each_bio(bio, scmd->request) { 176 __rq_for_each_bio(bio, scmd->request) {
182 struct bio_integrity_payload *bip = bio_integrity(bio); 177 struct bio_integrity_payload *bip = bio_integrity(bio);
@@ -190,7 +185,7 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
190 185
191 for (j = 0; j < iv.bv_len; j += tuple_sz, pi++) { 186 for (j = 0; j < iv.bv_len; j += tuple_sz, pi++) {
192 187
193 if (sectors == 0) { 188 if (intervals == 0) {
194 kunmap_atomic(pi); 189 kunmap_atomic(pi);
195 return; 190 return;
196 } 191 }
@@ -200,7 +195,7 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
200 195
201 virt++; 196 virt++;
202 phys++; 197 phys++;
203 sectors--; 198 intervals--;
204 } 199 }
205 200
206 kunmap_atomic(pi); 201 kunmap_atomic(pi);