diff options
author | Max Gurtovoy <maxg@mellanox.com> | 2018-07-29 17:15:32 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2018-07-30 10:27:02 -0400 |
commit | 10c41ddd61323b27b447bc8e18296ac6c06107ad (patch) | |
tree | 116e298295cfafda21080e0c83b501862753fcf1 /drivers/scsi/sd_dif.c | |
parent | ddd0bc756983dc4d19000a4fe021b4c7f9d59aab (diff) |
block: move dif_prepare/dif_complete functions to block layer
Currently these functions are implemented in the scsi layer, but their
actual place should be the block layer since T10-PI is a general data
integrity feature that is used in the nvme protocol as well. Also, use
the tuple size from the integrity profile since it may vary between
integrity types.
Suggested-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Max Gurtovoy <maxg@mellanox.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/scsi/sd_dif.c')
-rw-r--r-- | drivers/scsi/sd_dif.c | 113 |
1 files changed, 0 insertions, 113 deletions
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c index d8de43d359ac..db72c82486e3 100644 --- a/drivers/scsi/sd_dif.c +++ b/drivers/scsi/sd_dif.c | |||
@@ -95,116 +95,3 @@ out: | |||
95 | blk_integrity_register(disk, &bi); | 95 | blk_integrity_register(disk, &bi); |
96 | } | 96 | } |
97 | 97 | ||
98 | /* | ||
99 | * The virtual start sector is the one that was originally submitted | ||
100 | * by the block layer. Due to partitioning, MD/DM cloning, etc. the | ||
101 | * actual physical start sector is likely to be different. Remap | ||
102 | * protection information to match the physical LBA. | ||
103 | * | ||
104 | * From a protocol perspective there's a slight difference between | ||
105 | * Type 1 and 2. The latter uses 32-byte CDBs exclusively, and the | ||
106 | * reference tag is seeded in the CDB. This gives us the potential to | ||
107 | * avoid virt->phys remapping during write. However, at read time we | ||
108 | * don't know whether the virt sector is the same as when we wrote it | ||
109 | * (we could be reading from real disk as opposed to MD/DM device. So | ||
110 | * we always remap Type 2 making it identical to Type 1. | ||
111 | * | ||
112 | * Type 3 does not have a reference tag so no remapping is required. | ||
113 | */ | ||
114 | void sd_dif_prepare(struct scsi_cmnd *scmd) | ||
115 | { | ||
116 | const int tuple_sz = sizeof(struct t10_pi_tuple); | ||
117 | struct bio *bio; | ||
118 | struct scsi_disk *sdkp; | ||
119 | struct t10_pi_tuple *pi; | ||
120 | u32 phys, virt; | ||
121 | |||
122 | sdkp = scsi_disk(scmd->request->rq_disk); | ||
123 | |||
124 | if (sdkp->protection_type == T10_PI_TYPE3_PROTECTION) | ||
125 | return; | ||
126 | |||
127 | phys = t10_pi_ref_tag(scmd->request); | ||
128 | |||
129 | __rq_for_each_bio(bio, scmd->request) { | ||
130 | struct bio_integrity_payload *bip = bio_integrity(bio); | ||
131 | struct bio_vec iv; | ||
132 | struct bvec_iter iter; | ||
133 | unsigned int j; | ||
134 | |||
135 | /* Already remapped? */ | ||
136 | if (bip->bip_flags & BIP_MAPPED_INTEGRITY) | ||
137 | break; | ||
138 | |||
139 | virt = bip_get_seed(bip) & 0xffffffff; | ||
140 | |||
141 | bip_for_each_vec(iv, bip, iter) { | ||
142 | pi = kmap_atomic(iv.bv_page) + iv.bv_offset; | ||
143 | |||
144 | for (j = 0; j < iv.bv_len; j += tuple_sz, pi++) { | ||
145 | |||
146 | if (be32_to_cpu(pi->ref_tag) == virt) | ||
147 | pi->ref_tag = cpu_to_be32(phys); | ||
148 | |||
149 | virt++; | ||
150 | phys++; | ||
151 | } | ||
152 | |||
153 | kunmap_atomic(pi); | ||
154 | } | ||
155 | |||
156 | bip->bip_flags |= BIP_MAPPED_INTEGRITY; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | /* | ||
161 | * Remap physical sector values in the reference tag to the virtual | ||
162 | * values expected by the block layer. | ||
163 | */ | ||
164 | void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes) | ||
165 | { | ||
166 | const int tuple_sz = sizeof(struct t10_pi_tuple); | ||
167 | struct scsi_disk *sdkp; | ||
168 | struct bio *bio; | ||
169 | struct t10_pi_tuple *pi; | ||
170 | unsigned int j, intervals; | ||
171 | u32 phys, virt; | ||
172 | |||
173 | sdkp = scsi_disk(scmd->request->rq_disk); | ||
174 | |||
175 | if (sdkp->protection_type == T10_PI_TYPE3_PROTECTION || good_bytes == 0) | ||
176 | return; | ||
177 | |||
178 | intervals = good_bytes / scsi_prot_interval(scmd); | ||
179 | phys = t10_pi_ref_tag(scmd->request); | ||
180 | |||
181 | __rq_for_each_bio(bio, scmd->request) { | ||
182 | struct bio_integrity_payload *bip = bio_integrity(bio); | ||
183 | struct bio_vec iv; | ||
184 | struct bvec_iter iter; | ||
185 | |||
186 | virt = bip_get_seed(bip) & 0xffffffff; | ||
187 | |||
188 | bip_for_each_vec(iv, bip, iter) { | ||
189 | pi = kmap_atomic(iv.bv_page) + iv.bv_offset; | ||
190 | |||
191 | for (j = 0; j < iv.bv_len; j += tuple_sz, pi++) { | ||
192 | |||
193 | if (intervals == 0) { | ||
194 | kunmap_atomic(pi); | ||
195 | return; | ||
196 | } | ||
197 | |||
198 | if (be32_to_cpu(pi->ref_tag) == phys) | ||
199 | pi->ref_tag = cpu_to_be32(virt); | ||
200 | |||
201 | virt++; | ||
202 | phys++; | ||
203 | intervals--; | ||
204 | } | ||
205 | |||
206 | kunmap_atomic(pi); | ||
207 | } | ||
208 | } | ||
209 | } | ||
210 | |||