4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.gnu.org/licenses/gpl-2.0.html
23 * Copyright (c) 2018, DataDirect Networks Storage.
26 * Data integrity functions for OSD
27 * Codes copied from kernel 3.10.0-862.el7
28 * drivers/scsi/sd_dif.c and block/t10-pi.c
30 #include <linux/blkdev.h>
31 #include <linux/blk_types.h>
33 #include <obd_cksum.h>
34 #include <lustre_compat.h>
36 #include "osd_internal.h"
39 * Data Integrity Field tuple.
42 __be16 guard_tag; /* Checksum */
43 __be16 app_tag; /* Opaque storage */
44 __be32 ref_tag; /* Target LBA or indirect LBA */
48 * Type 1 and Type 2 protection use the same format: 16 bit guard tag,
49 * 16 bit app tag, 32 bit reference tag.
51 static void osd_dif_type1_generate(struct blk_integrity_exchg *bix,
54 void *buf = bix->data_buf;
55 struct sd_dif_tuple *sdt = bix->prot_buf;
56 struct bio *bio = bix->bio;
57 struct osd_bio_private *bio_private = bio->bi_private;
58 struct osd_iobuf *iobuf = bio_private->obp_iobuf;
59 int index = bio_private->obp_start_page_idx + bix->bi_idx;
60 struct niobuf_local *lnb = iobuf->dr_lnbs[index];
61 __u16 *guard_buf = lnb->lnb_guards;
62 sector_t sector = bix->sector;
65 for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
66 if (lnb->lnb_guard_rpc) {
67 sdt->guard_tag = *guard_buf;
70 sdt->guard_tag = fn(buf, bix->sector_size);
71 sdt->ref_tag = cpu_to_be32(sector & 0xffffffff);
74 buf += bix->sector_size;
79 static void osd_dif_type1_generate_crc(struct blk_integrity_exchg *bix)
81 osd_dif_type1_generate(bix, obd_dif_crc_fn);
84 static void osd_dif_type1_generate_ip(struct blk_integrity_exchg *bix)
86 osd_dif_type1_generate(bix, obd_dif_ip_fn);
89 static int osd_dif_type1_verify(struct blk_integrity_exchg *bix,
92 void *buf = bix->data_buf;
93 struct sd_dif_tuple *sdt = bix->prot_buf;
94 struct bio *bio = bix->bio;
95 struct osd_bio_private *bio_private = bio->bi_private;
96 struct osd_iobuf *iobuf = bio_private->obp_iobuf;
97 int index = bio_private->obp_start_page_idx + bix->bi_idx;
98 struct niobuf_local *lnb = iobuf->dr_lnbs[index];
99 __u16 *guard_buf = lnb->lnb_guards;
100 sector_t sector = bix->sector;
104 for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
105 /* Unwritten sectors */
106 if (sdt->app_tag == 0xffff)
109 if (be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
110 CERROR("%s: ref tag error on sector %lu (rcvd %u)\n",
111 bix->disk_name, (unsigned long)sector,
112 be32_to_cpu(sdt->ref_tag));
116 csum = fn(buf, bix->sector_size);
118 if (sdt->guard_tag != csum) {
119 CERROR("%s: guard tag error on sector %lu " \
120 "(rcvd %04x, data %04x)\n", bix->disk_name,
121 (unsigned long)sector,
122 be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum));
129 buf += bix->sector_size;
133 lnb->lnb_guard_disk = 1;
137 static int osd_dif_type1_verify_crc(struct blk_integrity_exchg *bix)
139 return osd_dif_type1_verify(bix, obd_dif_crc_fn);
142 static int osd_dif_type1_verify_ip(struct blk_integrity_exchg *bix)
144 return osd_dif_type1_verify(bix, obd_dif_ip_fn);
148 * Type 3 protection has a 16-bit guard tag and 16 + 32 bits of opaque
151 static void osd_dif_type3_generate(struct blk_integrity_exchg *bix,
154 void *buf = bix->data_buf;
155 struct sd_dif_tuple *sdt = bix->prot_buf;
156 struct bio *bio = bix->bio;
157 struct osd_bio_private *bio_private = bio->bi_private;
158 struct osd_iobuf *iobuf = bio_private->obp_iobuf;
159 int index = bio_private->obp_start_page_idx + bix->bi_idx;
160 struct niobuf_local *lnb = iobuf->dr_lnbs[index];
161 __u16 *guard_buf = lnb->lnb_guards;
164 for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
165 if (lnb->lnb_guard_rpc) {
166 sdt->guard_tag = *guard_buf;
169 sdt->guard_tag = fn(buf, bix->sector_size);
173 buf += bix->sector_size;
177 static void osd_dif_type3_generate_crc(struct blk_integrity_exchg *bix)
179 osd_dif_type3_generate(bix, obd_dif_crc_fn);
182 static void osd_dif_type3_generate_ip(struct blk_integrity_exchg *bix)
184 osd_dif_type3_generate(bix, obd_dif_ip_fn);
187 static int osd_dif_type3_verify(struct blk_integrity_exchg *bix,
190 void *buf = bix->data_buf;
191 struct sd_dif_tuple *sdt = bix->prot_buf;
192 struct bio *bio = bix->bio;
193 struct osd_bio_private *bio_private = bio->bi_private;
194 struct osd_iobuf *iobuf = bio_private->obp_iobuf;
195 int index = bio_private->obp_start_page_idx + bix->bi_idx;
196 struct niobuf_local *lnb = iobuf->dr_lnbs[index];
197 __u16 *guard_buf = lnb->lnb_guards;
198 sector_t sector = bix->sector;
202 for (i = 0 ; i < bix->data_size ; i += bix->sector_size, sdt++) {
203 /* Unwritten sectors */
204 if (sdt->app_tag == 0xffff && sdt->ref_tag == 0xffffffff)
207 csum = fn(buf, bix->sector_size);
209 if (sdt->guard_tag != csum) {
210 CERROR("%s: guard tag error on sector %lu " \
211 "(rcvd %04x, data %04x)\n", bix->disk_name,
212 (unsigned long)sector,
213 be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum));
220 buf += bix->sector_size;
224 lnb->lnb_guard_disk = 1;
228 static int osd_dif_type3_verify_crc(struct blk_integrity_exchg *bix)
230 return osd_dif_type3_verify(bix, obd_dif_crc_fn);
233 static int osd_dif_type3_verify_ip(struct blk_integrity_exchg *bix)
235 return osd_dif_type3_verify(bix, obd_dif_ip_fn);
238 int osd_get_integrity_profile(struct osd_device *osd,
239 integrity_gen_fn **generate_fn,
240 integrity_vrfy_fn **verify_fn)
242 switch (osd->od_t10_type) {
243 case OSD_T10_TYPE1_CRC:
244 *verify_fn = osd_dif_type1_verify_crc;
245 *generate_fn = osd_dif_type1_generate_crc;
247 case OSD_T10_TYPE3_CRC:
248 *verify_fn = osd_dif_type3_verify_crc;
249 *generate_fn = osd_dif_type3_generate_crc;
251 case OSD_T10_TYPE1_IP:
252 *verify_fn = osd_dif_type1_verify_ip;
253 *generate_fn = osd_dif_type1_generate_ip;
255 case OSD_T10_TYPE3_IP:
256 *verify_fn = osd_dif_type3_verify_ip;
257 *generate_fn = osd_dif_type3_generate_ip;