t10-pi.c (594ce0b8a998aa4d05827cd7c0d0dcec9a1e3ae2) | t10-pi.c (e9f5f44ad3725335d9c559c3c22cd3726152a7b1) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * t10_pi.c - Functions for generating and verifying T10 Protection 4 * Information. 5 */ 6 7#include <linux/t10-pi.h> 8#include <linux/blk-integrity.h> 9#include <linux/crc-t10dif.h> 10#include <linux/crc64.h> 11#include <linux/module.h> 12#include <net/checksum.h> 13#include <asm/unaligned.h> | 1// SPDX-License-Identifier: GPL-2.0 2/* 3 * t10_pi.c - Functions for generating and verifying T10 Protection 4 * Information. 5 */ 6 7#include <linux/t10-pi.h> 8#include <linux/blk-integrity.h> 9#include <linux/crc-t10dif.h> 10#include <linux/crc64.h> 11#include <linux/module.h> 12#include <net/checksum.h> 13#include <asm/unaligned.h> |
14#include "blk.h" |
|
14 | 15 |
15typedef __be16 (csum_fn) (__be16, void *, unsigned int); 16 17static __be16 t10_pi_crc_fn(__be16 crc, void *data, unsigned int len) | 16static __be16 t10_pi_csum(__be16 csum, void *data, unsigned int len, 17 unsigned char csum_type) |
18{ | 18{ |
19 return cpu_to_be16(crc_t10dif_update(be16_to_cpu(crc), data, len)); | 19 if (csum_type == BLK_INTEGRITY_CSUM_IP) 20 return (__force __be16)ip_compute_csum(data, len); 21 return cpu_to_be16(crc_t10dif_update(be16_to_cpu(csum), data, len)); |
20} 21 | 22} 23 |
22static __be16 t10_pi_ip_fn(__be16 csum, void *data, unsigned int len) 23{ 24 return (__force __be16)ip_compute_csum(data, len); 25} 26 | |
27/* 28 * Type 1 and Type 2 protection use the same format: 16 bit guard tag, 29 * 16 bit app tag, 32 bit reference tag. Type 3 does not define the ref 30 * tag. 31 */ | 24/* 25 * Type 1 and Type 2 protection use the same format: 16 bit guard tag, 26 * 16 bit app tag, 32 bit reference tag. Type 3 does not define the ref 27 * tag. 28 */ |
32static blk_status_t t10_pi_generate(struct blk_integrity_iter *iter, 33 csum_fn *fn, enum t10_dif_type type) | 29static void t10_pi_generate(struct blk_integrity_iter *iter, 30 struct blk_integrity *bi) |
34{ | 31{ |
35 u8 offset = iter->pi_offset; | 32 u8 offset = bi->pi_offset; |
36 unsigned int i; 37 38 for (i = 0 ; i < iter->data_size ; i += iter->interval) { 39 struct t10_pi_tuple *pi = iter->prot_buf + offset; 40 | 33 unsigned int i; 34 35 for (i = 0 ; i < iter->data_size ; i += iter->interval) { 36 struct t10_pi_tuple *pi = iter->prot_buf + offset; 37 |
41 pi->guard_tag = fn(0, iter->data_buf, iter->interval); | 38 pi->guard_tag = t10_pi_csum(0, iter->data_buf, iter->interval, 39 bi->csum_type); |
42 if (offset) | 40 if (offset) |
43 pi->guard_tag = fn(pi->guard_tag, iter->prot_buf, 44 offset); | 41 pi->guard_tag = t10_pi_csum(pi->guard_tag, 42 iter->prot_buf, offset, bi->csum_type); |
45 pi->app_tag = 0; 46 | 43 pi->app_tag = 0; 44 |
47 if (type == T10_PI_TYPE1_PROTECTION) | 45 if (bi->flags & BLK_INTEGRITY_REF_TAG) |
48 pi->ref_tag = cpu_to_be32(lower_32_bits(iter->seed)); 49 else 50 pi->ref_tag = 0; 51 52 iter->data_buf += iter->interval; | 46 pi->ref_tag = cpu_to_be32(lower_32_bits(iter->seed)); 47 else 48 pi->ref_tag = 0; 49 50 iter->data_buf += iter->interval; |
53 iter->prot_buf += iter->tuple_size; | 51 iter->prot_buf += bi->tuple_size; |
54 iter->seed++; 55 } | 52 iter->seed++; 53 } |
56 57 return BLK_STS_OK; | |
58} 59 60static blk_status_t t10_pi_verify(struct blk_integrity_iter *iter, | 54} 55 56static blk_status_t t10_pi_verify(struct blk_integrity_iter *iter, |
61 csum_fn *fn, enum t10_dif_type type) | 57 struct blk_integrity *bi) |
62{ | 58{ |
63 u8 offset = iter->pi_offset; | 59 u8 offset = bi->pi_offset; |
64 unsigned int i; 65 | 60 unsigned int i; 61 |
66 BUG_ON(type == T10_PI_TYPE0_PROTECTION); 67 | |
68 for (i = 0 ; i < iter->data_size ; i += iter->interval) { 69 struct t10_pi_tuple *pi = iter->prot_buf + offset; 70 __be16 csum; 71 | 62 for (i = 0 ; i < iter->data_size ; i += iter->interval) { 63 struct t10_pi_tuple *pi = iter->prot_buf + offset; 64 __be16 csum; 65 |
72 if (type == T10_PI_TYPE1_PROTECTION || 73 type == T10_PI_TYPE2_PROTECTION) { | 66 if (bi->flags & BLK_INTEGRITY_REF_TAG) { |
74 if (pi->app_tag == T10_PI_APP_ESCAPE) 75 goto next; 76 77 if (be32_to_cpu(pi->ref_tag) != 78 lower_32_bits(iter->seed)) { 79 pr_err("%s: ref tag error at location %llu " \ 80 "(rcvd %u)\n", iter->disk_name, 81 (unsigned long long) 82 iter->seed, be32_to_cpu(pi->ref_tag)); 83 return BLK_STS_PROTECTION; 84 } | 67 if (pi->app_tag == T10_PI_APP_ESCAPE) 68 goto next; 69 70 if (be32_to_cpu(pi->ref_tag) != 71 lower_32_bits(iter->seed)) { 72 pr_err("%s: ref tag error at location %llu " \ 73 "(rcvd %u)\n", iter->disk_name, 74 (unsigned long long) 75 iter->seed, be32_to_cpu(pi->ref_tag)); 76 return BLK_STS_PROTECTION; 77 } |
85 } else if (type == T10_PI_TYPE3_PROTECTION) { | 78 } else { |
86 if (pi->app_tag == T10_PI_APP_ESCAPE && 87 pi->ref_tag == T10_PI_REF_ESCAPE) 88 goto next; 89 } 90 | 79 if (pi->app_tag == T10_PI_APP_ESCAPE && 80 pi->ref_tag == T10_PI_REF_ESCAPE) 81 goto next; 82 } 83 |
91 csum = fn(0, iter->data_buf, iter->interval); | 84 csum = t10_pi_csum(0, iter->data_buf, iter->interval, 85 bi->csum_type); |
92 if (offset) | 86 if (offset) |
93 csum = fn(csum, iter->prot_buf, offset); | 87 csum = t10_pi_csum(csum, iter->prot_buf, offset, 88 bi->csum_type); |
94 95 if (pi->guard_tag != csum) { 96 pr_err("%s: guard tag error at sector %llu " \ 97 "(rcvd %04x, want %04x)\n", iter->disk_name, 98 (unsigned long long)iter->seed, 99 be16_to_cpu(pi->guard_tag), be16_to_cpu(csum)); 100 return BLK_STS_PROTECTION; 101 } 102 103next: 104 iter->data_buf += iter->interval; | 89 90 if (pi->guard_tag != csum) { 91 pr_err("%s: guard tag error at sector %llu " \ 92 "(rcvd %04x, want %04x)\n", iter->disk_name, 93 (unsigned long long)iter->seed, 94 be16_to_cpu(pi->guard_tag), be16_to_cpu(csum)); 95 return BLK_STS_PROTECTION; 96 } 97 98next: 99 iter->data_buf += iter->interval; |
105 iter->prot_buf += iter->tuple_size; | 100 iter->prot_buf += bi->tuple_size; |
106 iter->seed++; 107 } 108 109 return BLK_STS_OK; 110} 111 | 101 iter->seed++; 102 } 103 104 return BLK_STS_OK; 105} 106 |
112static blk_status_t t10_pi_type1_generate_crc(struct blk_integrity_iter *iter) 113{ 114 return t10_pi_generate(iter, t10_pi_crc_fn, T10_PI_TYPE1_PROTECTION); 115} 116 117static blk_status_t t10_pi_type1_generate_ip(struct blk_integrity_iter *iter) 118{ 119 return t10_pi_generate(iter, t10_pi_ip_fn, T10_PI_TYPE1_PROTECTION); 120} 121 122static blk_status_t t10_pi_type1_verify_crc(struct blk_integrity_iter *iter) 123{ 124 return t10_pi_verify(iter, t10_pi_crc_fn, T10_PI_TYPE1_PROTECTION); 125} 126 127static blk_status_t t10_pi_type1_verify_ip(struct blk_integrity_iter *iter) 128{ 129 return t10_pi_verify(iter, t10_pi_ip_fn, T10_PI_TYPE1_PROTECTION); 130} 131 | |
132/** 133 * t10_pi_type1_prepare - prepare PI prior submitting request to device 134 * @rq: request with PI that should be prepared 135 * 136 * For Type 1/Type 2, the virtual start sector is the one that was 137 * originally submitted by the block layer for the ref_tag usage. Due to 138 * partitioning, MD/DM cloning, etc. the actual physical start sector is 139 * likely to be different. Remap protection information to match the --- 80 unchanged lines hidden (view full) --- 220 intervals--; 221 p += tuple_sz; 222 } 223 kunmap_local(p); 224 } 225 } 226} 227 | 107/** 108 * t10_pi_type1_prepare - prepare PI prior submitting request to device 109 * @rq: request with PI that should be prepared 110 * 111 * For Type 1/Type 2, the virtual start sector is the one that was 112 * originally submitted by the block layer for the ref_tag usage. Due to 113 * partitioning, MD/DM cloning, etc. the actual physical start sector is 114 * likely to be different. Remap protection information to match the --- 80 unchanged lines hidden (view full) --- 195 intervals--; 196 p += tuple_sz; 197 } 198 kunmap_local(p); 199 } 200 } 201} 202 |
228static blk_status_t t10_pi_type3_generate_crc(struct blk_integrity_iter *iter) 229{ 230 return t10_pi_generate(iter, t10_pi_crc_fn, T10_PI_TYPE3_PROTECTION); 231} 232 233static blk_status_t t10_pi_type3_generate_ip(struct blk_integrity_iter *iter) 234{ 235 return t10_pi_generate(iter, t10_pi_ip_fn, T10_PI_TYPE3_PROTECTION); 236} 237 238static blk_status_t t10_pi_type3_verify_crc(struct blk_integrity_iter *iter) 239{ 240 return t10_pi_verify(iter, t10_pi_crc_fn, T10_PI_TYPE3_PROTECTION); 241} 242 243static blk_status_t t10_pi_type3_verify_ip(struct blk_integrity_iter *iter) 244{ 245 return t10_pi_verify(iter, t10_pi_ip_fn, T10_PI_TYPE3_PROTECTION); 246} 247 248/* Type 3 does not have a reference tag so no remapping is required. */ 249static void t10_pi_type3_prepare(struct request *rq) 250{ 251} 252 253/* Type 3 does not have a reference tag so no remapping is required. */ 254static void t10_pi_type3_complete(struct request *rq, unsigned int nr_bytes) 255{ 256} 257 258const struct blk_integrity_profile t10_pi_type1_crc = { 259 .name = "T10-DIF-TYPE1-CRC", 260 .generate_fn = t10_pi_type1_generate_crc, 261 .verify_fn = t10_pi_type1_verify_crc, 262 .prepare_fn = t10_pi_type1_prepare, 263 .complete_fn = t10_pi_type1_complete, 264}; 265EXPORT_SYMBOL(t10_pi_type1_crc); 266 267const struct blk_integrity_profile t10_pi_type1_ip = { 268 .name = "T10-DIF-TYPE1-IP", 269 .generate_fn = t10_pi_type1_generate_ip, 270 .verify_fn = t10_pi_type1_verify_ip, 271 .prepare_fn = t10_pi_type1_prepare, 272 .complete_fn = t10_pi_type1_complete, 273}; 274EXPORT_SYMBOL(t10_pi_type1_ip); 275 276const struct blk_integrity_profile t10_pi_type3_crc = { 277 .name = "T10-DIF-TYPE3-CRC", 278 .generate_fn = t10_pi_type3_generate_crc, 279 .verify_fn = t10_pi_type3_verify_crc, 280 .prepare_fn = t10_pi_type3_prepare, 281 .complete_fn = t10_pi_type3_complete, 282}; 283EXPORT_SYMBOL(t10_pi_type3_crc); 284 285const struct blk_integrity_profile t10_pi_type3_ip = { 286 .name = "T10-DIF-TYPE3-IP", 287 .generate_fn = t10_pi_type3_generate_ip, 288 .verify_fn = t10_pi_type3_verify_ip, 289 .prepare_fn = t10_pi_type3_prepare, 290 .complete_fn = t10_pi_type3_complete, 291}; 292EXPORT_SYMBOL(t10_pi_type3_ip); 293 | |
294static __be64 ext_pi_crc64(u64 crc, void *data, unsigned int len) 295{ 296 return cpu_to_be64(crc64_rocksoft_update(crc, data, len)); 297} 298 | 203static __be64 ext_pi_crc64(u64 crc, void *data, unsigned int len) 204{ 205 return cpu_to_be64(crc64_rocksoft_update(crc, data, len)); 206} 207 |
299static blk_status_t ext_pi_crc64_generate(struct blk_integrity_iter *iter, 300 enum t10_dif_type type) | 208static void ext_pi_crc64_generate(struct blk_integrity_iter *iter, 209 struct blk_integrity *bi) |
301{ | 210{ |
302 u8 offset = iter->pi_offset; | 211 u8 offset = bi->pi_offset; |
303 unsigned int i; 304 305 for (i = 0 ; i < iter->data_size ; i += iter->interval) { 306 struct crc64_pi_tuple *pi = iter->prot_buf + offset; 307 308 pi->guard_tag = ext_pi_crc64(0, iter->data_buf, iter->interval); 309 if (offset) 310 pi->guard_tag = ext_pi_crc64(be64_to_cpu(pi->guard_tag), 311 iter->prot_buf, offset); 312 pi->app_tag = 0; 313 | 212 unsigned int i; 213 214 for (i = 0 ; i < iter->data_size ; i += iter->interval) { 215 struct crc64_pi_tuple *pi = iter->prot_buf + offset; 216 217 pi->guard_tag = ext_pi_crc64(0, iter->data_buf, iter->interval); 218 if (offset) 219 pi->guard_tag = ext_pi_crc64(be64_to_cpu(pi->guard_tag), 220 iter->prot_buf, offset); 221 pi->app_tag = 0; 222 |
314 if (type == T10_PI_TYPE1_PROTECTION) | 223 if (bi->flags & BLK_INTEGRITY_REF_TAG) |
315 put_unaligned_be48(iter->seed, pi->ref_tag); 316 else 317 put_unaligned_be48(0ULL, pi->ref_tag); 318 319 iter->data_buf += iter->interval; | 224 put_unaligned_be48(iter->seed, pi->ref_tag); 225 else 226 put_unaligned_be48(0ULL, pi->ref_tag); 227 228 iter->data_buf += iter->interval; |
320 iter->prot_buf += iter->tuple_size; | 229 iter->prot_buf += bi->tuple_size; |
321 iter->seed++; 322 } | 230 iter->seed++; 231 } |
323 324 return BLK_STS_OK; | |
325} 326 327static bool ext_pi_ref_escape(u8 *ref_tag) 328{ 329 static u8 ref_escape[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 330 331 return memcmp(ref_tag, ref_escape, sizeof(ref_escape)) == 0; 332} 333 334static blk_status_t ext_pi_crc64_verify(struct blk_integrity_iter *iter, | 232} 233 234static bool ext_pi_ref_escape(u8 *ref_tag) 235{ 236 static u8 ref_escape[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 237 238 return memcmp(ref_tag, ref_escape, sizeof(ref_escape)) == 0; 239} 240 241static blk_status_t ext_pi_crc64_verify(struct blk_integrity_iter *iter, |
335 enum t10_dif_type type) | 242 struct blk_integrity *bi) |
336{ | 243{ |
337 u8 offset = iter->pi_offset; | 244 u8 offset = bi->pi_offset; |
338 unsigned int i; 339 340 for (i = 0; i < iter->data_size; i += iter->interval) { 341 struct crc64_pi_tuple *pi = iter->prot_buf + offset; 342 u64 ref, seed; 343 __be64 csum; 344 | 245 unsigned int i; 246 247 for (i = 0; i < iter->data_size; i += iter->interval) { 248 struct crc64_pi_tuple *pi = iter->prot_buf + offset; 249 u64 ref, seed; 250 __be64 csum; 251 |
345 if (type == T10_PI_TYPE1_PROTECTION) { | 252 if (bi->flags & BLK_INTEGRITY_REF_TAG) { |
346 if (pi->app_tag == T10_PI_APP_ESCAPE) 347 goto next; 348 349 ref = get_unaligned_be48(pi->ref_tag); 350 seed = lower_48_bits(iter->seed); 351 if (ref != seed) { 352 pr_err("%s: ref tag error at location %llu (rcvd %llu)\n", 353 iter->disk_name, seed, ref); 354 return BLK_STS_PROTECTION; 355 } | 253 if (pi->app_tag == T10_PI_APP_ESCAPE) 254 goto next; 255 256 ref = get_unaligned_be48(pi->ref_tag); 257 seed = lower_48_bits(iter->seed); 258 if (ref != seed) { 259 pr_err("%s: ref tag error at location %llu (rcvd %llu)\n", 260 iter->disk_name, seed, ref); 261 return BLK_STS_PROTECTION; 262 } |
356 } else if (type == T10_PI_TYPE3_PROTECTION) { | 263 } else { |
357 if (pi->app_tag == T10_PI_APP_ESCAPE && 358 ext_pi_ref_escape(pi->ref_tag)) 359 goto next; 360 } 361 362 csum = ext_pi_crc64(0, iter->data_buf, iter->interval); 363 if (offset) 364 csum = ext_pi_crc64(be64_to_cpu(csum), iter->prot_buf, --- 4 unchanged lines hidden (view full) --- 369 "(rcvd %016llx, want %016llx)\n", 370 iter->disk_name, (unsigned long long)iter->seed, 371 be64_to_cpu(pi->guard_tag), be64_to_cpu(csum)); 372 return BLK_STS_PROTECTION; 373 } 374 375next: 376 iter->data_buf += iter->interval; | 264 if (pi->app_tag == T10_PI_APP_ESCAPE && 265 ext_pi_ref_escape(pi->ref_tag)) 266 goto next; 267 } 268 269 csum = ext_pi_crc64(0, iter->data_buf, iter->interval); 270 if (offset) 271 csum = ext_pi_crc64(be64_to_cpu(csum), iter->prot_buf, --- 4 unchanged lines hidden (view full) --- 276 "(rcvd %016llx, want %016llx)\n", 277 iter->disk_name, (unsigned long long)iter->seed, 278 be64_to_cpu(pi->guard_tag), be64_to_cpu(csum)); 279 return BLK_STS_PROTECTION; 280 } 281 282next: 283 iter->data_buf += iter->interval; |
377 iter->prot_buf += iter->tuple_size; | 284 iter->prot_buf += bi->tuple_size; |
378 iter->seed++; 379 } 380 381 return BLK_STS_OK; 382} 383 | 285 iter->seed++; 286 } 287 288 return BLK_STS_OK; 289} 290 |
384static blk_status_t ext_pi_type1_verify_crc64(struct blk_integrity_iter *iter) 385{ 386 return ext_pi_crc64_verify(iter, T10_PI_TYPE1_PROTECTION); 387} 388 389static blk_status_t ext_pi_type1_generate_crc64(struct blk_integrity_iter *iter) 390{ 391 return ext_pi_crc64_generate(iter, T10_PI_TYPE1_PROTECTION); 392} 393 | |
394static void ext_pi_type1_prepare(struct request *rq) 395{ 396 struct blk_integrity *bi = &rq->q->integrity; 397 const int tuple_sz = bi->tuple_size; 398 u64 ref_tag = ext_pi_ref_tag(rq); 399 u8 offset = bi->pi_offset; 400 struct bio *bio; 401 --- 60 unchanged lines hidden (view full) --- 462 intervals--; 463 p += tuple_sz; 464 } 465 kunmap_local(p); 466 } 467 } 468} 469 | 291static void ext_pi_type1_prepare(struct request *rq) 292{ 293 struct blk_integrity *bi = &rq->q->integrity; 294 const int tuple_sz = bi->tuple_size; 295 u64 ref_tag = ext_pi_ref_tag(rq); 296 u8 offset = bi->pi_offset; 297 struct bio *bio; 298 --- 60 unchanged lines hidden (view full) --- 359 intervals--; 360 p += tuple_sz; 361 } 362 kunmap_local(p); 363 } 364 } 365} 366 |
470static blk_status_t ext_pi_type3_verify_crc64(struct blk_integrity_iter *iter) | 367void blk_integrity_generate(struct blk_integrity_iter *iter, 368 struct blk_integrity *bi) |
471{ | 369{ |
472 return ext_pi_crc64_verify(iter, T10_PI_TYPE3_PROTECTION); | 370 switch (bi->csum_type) { 371 case BLK_INTEGRITY_CSUM_CRC64: 372 ext_pi_crc64_generate(iter, bi); 373 break; 374 case BLK_INTEGRITY_CSUM_CRC: 375 case BLK_INTEGRITY_CSUM_IP: 376 t10_pi_generate(iter, bi); 377 break; 378 default: 379 break; 380 } |
473} 474 | 381} 382 |
475static blk_status_t ext_pi_type3_generate_crc64(struct blk_integrity_iter *iter) | 383blk_status_t blk_integrity_verify(struct blk_integrity_iter *iter, 384 struct blk_integrity *bi) |
476{ | 385{ |
477 return ext_pi_crc64_generate(iter, T10_PI_TYPE3_PROTECTION); | 386 switch (bi->csum_type) { 387 case BLK_INTEGRITY_CSUM_CRC64: 388 return ext_pi_crc64_verify(iter, bi); 389 case BLK_INTEGRITY_CSUM_CRC: 390 case BLK_INTEGRITY_CSUM_IP: 391 return t10_pi_verify(iter, bi); 392 default: 393 return BLK_STS_OK; 394 } |
478} 479 | 395} 396 |
480const struct blk_integrity_profile ext_pi_type1_crc64 = { 481 .name = "EXT-DIF-TYPE1-CRC64", 482 .generate_fn = ext_pi_type1_generate_crc64, 483 .verify_fn = ext_pi_type1_verify_crc64, 484 .prepare_fn = ext_pi_type1_prepare, 485 .complete_fn = ext_pi_type1_complete, 486}; 487EXPORT_SYMBOL_GPL(ext_pi_type1_crc64); | 397void blk_integrity_prepare(struct request *rq) 398{ 399 struct blk_integrity *bi = &rq->q->integrity; |
488 | 400 |
489const struct blk_integrity_profile ext_pi_type3_crc64 = { 490 .name = "EXT-DIF-TYPE3-CRC64", 491 .generate_fn = ext_pi_type3_generate_crc64, 492 .verify_fn = ext_pi_type3_verify_crc64, 493 .prepare_fn = t10_pi_type3_prepare, 494 .complete_fn = t10_pi_type3_complete, 495}; 496EXPORT_SYMBOL_GPL(ext_pi_type3_crc64); | 401 if (!(bi->flags & BLK_INTEGRITY_REF_TAG)) 402 return; |
497 | 403 |
404 if (bi->csum_type == BLK_INTEGRITY_CSUM_CRC64) 405 ext_pi_type1_prepare(rq); 406 else 407 t10_pi_type1_prepare(rq); 408} 409 410void blk_integrity_complete(struct request *rq, unsigned int nr_bytes) 411{ 412 struct blk_integrity *bi = &rq->q->integrity; 413 414 if (!(bi->flags & BLK_INTEGRITY_REF_TAG)) 415 return; 416 417 if (bi->csum_type == BLK_INTEGRITY_CSUM_CRC64) 418 ext_pi_type1_complete(rq, nr_bytes); 419 else 420 t10_pi_type1_complete(rq, nr_bytes); 421} 422 |
|
498MODULE_DESCRIPTION("T10 Protection Information module"); 499MODULE_LICENSE("GPL"); | 423MODULE_DESCRIPTION("T10 Protection Information module"); 424MODULE_LICENSE("GPL"); |