Blame view

block/t10-pi.c 4.89 KB
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  /*
   * t10_pi.c - Functions for generating and verifying T10 Protection
   *	      Information.
   *
   * Copyright (C) 2007, 2008, 2014 Oracle Corporation
   * Written by: Martin K. Petersen <martin.petersen@oracle.com>
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License version
   * 2 as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; see the file COPYING.  If not, write to
   * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
   * USA.
   *
   */
  
  #include <linux/t10-pi.h>
  #include <linux/blkdev.h>
  #include <linux/crc-t10dif.h>
  #include <net/checksum.h>
  
  typedef __be16 (csum_fn) (void *, unsigned int);
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  static __be16 t10_pi_crc_fn(void *data, unsigned int len)
  {
  	return cpu_to_be16(crc_t10dif(data, len));
  }
  
  static __be16 t10_pi_ip_fn(void *data, unsigned int len)
  {
  	return (__force __be16)ip_compute_csum(data, len);
  }
  
  /*
   * Type 1 and Type 2 protection use the same format: 16 bit guard tag,
   * 16 bit app tag, 32 bit reference tag. Type 3 does not define the ref
   * tag.
   */
4e4cbee93   Christoph Hellwig   block: switch bio...
45
46
  static blk_status_t t10_pi_generate(struct blk_integrity_iter *iter,
  		csum_fn *fn, unsigned int type)
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  {
  	unsigned int i;
  
  	for (i = 0 ; i < iter->data_size ; i += iter->interval) {
  		struct t10_pi_tuple *pi = iter->prot_buf;
  
  		pi->guard_tag = fn(iter->data_buf, iter->interval);
  		pi->app_tag = 0;
  
  		if (type == 1)
  			pi->ref_tag = cpu_to_be32(lower_32_bits(iter->seed));
  		else
  			pi->ref_tag = 0;
  
  		iter->data_buf += iter->interval;
  		iter->prot_buf += sizeof(struct t10_pi_tuple);
  		iter->seed++;
  	}
4e4cbee93   Christoph Hellwig   block: switch bio...
65
  	return BLK_STS_OK;
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
66
  }
4e4cbee93   Christoph Hellwig   block: switch bio...
67
68
  static blk_status_t t10_pi_verify(struct blk_integrity_iter *iter,
  		csum_fn *fn, unsigned int type)
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
69
70
71
72
73
74
75
76
77
78
  {
  	unsigned int i;
  
  	for (i = 0 ; i < iter->data_size ; i += iter->interval) {
  		struct t10_pi_tuple *pi = iter->prot_buf;
  		__be16 csum;
  
  		switch (type) {
  		case 1:
  		case 2:
128b6f9fd   Dmitry Monakhov   t10-pi: Move open...
79
  			if (pi->app_tag == T10_PI_APP_ESCAPE)
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
80
81
82
83
84
85
86
87
88
  				goto next;
  
  			if (be32_to_cpu(pi->ref_tag) !=
  			    lower_32_bits(iter->seed)) {
  				pr_err("%s: ref tag error at location %llu " \
  				       "(rcvd %u)
  ", iter->disk_name,
  				       (unsigned long long)
  				       iter->seed, be32_to_cpu(pi->ref_tag));
a462b9508   Bart Van Assche   block: Dedicated ...
89
  				return BLK_STS_PROTECTION;
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
90
91
92
  			}
  			break;
  		case 3:
128b6f9fd   Dmitry Monakhov   t10-pi: Move open...
93
94
  			if (pi->app_tag == T10_PI_APP_ESCAPE &&
  			    pi->ref_tag == T10_PI_REF_ESCAPE)
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
95
96
97
98
99
100
101
102
103
104
105
106
  				goto next;
  			break;
  		}
  
  		csum = fn(iter->data_buf, iter->interval);
  
  		if (pi->guard_tag != csum) {
  			pr_err("%s: guard tag error at sector %llu " \
  			       "(rcvd %04x, want %04x)
  ", iter->disk_name,
  			       (unsigned long long)iter->seed,
  			       be16_to_cpu(pi->guard_tag), be16_to_cpu(csum));
4e4cbee93   Christoph Hellwig   block: switch bio...
107
  			return BLK_STS_PROTECTION;
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
108
109
110
111
112
113
114
  		}
  
  next:
  		iter->data_buf += iter->interval;
  		iter->prot_buf += sizeof(struct t10_pi_tuple);
  		iter->seed++;
  	}
4e4cbee93   Christoph Hellwig   block: switch bio...
115
  	return BLK_STS_OK;
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
116
  }
4e4cbee93   Christoph Hellwig   block: switch bio...
117
  static blk_status_t t10_pi_type1_generate_crc(struct blk_integrity_iter *iter)
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
118
119
120
  {
  	return t10_pi_generate(iter, t10_pi_crc_fn, 1);
  }
4e4cbee93   Christoph Hellwig   block: switch bio...
121
  static blk_status_t t10_pi_type1_generate_ip(struct blk_integrity_iter *iter)
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
122
123
124
  {
  	return t10_pi_generate(iter, t10_pi_ip_fn, 1);
  }
4e4cbee93   Christoph Hellwig   block: switch bio...
125
  static blk_status_t t10_pi_type1_verify_crc(struct blk_integrity_iter *iter)
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
126
127
128
  {
  	return t10_pi_verify(iter, t10_pi_crc_fn, 1);
  }
4e4cbee93   Christoph Hellwig   block: switch bio...
129
  static blk_status_t t10_pi_type1_verify_ip(struct blk_integrity_iter *iter)
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
130
131
132
  {
  	return t10_pi_verify(iter, t10_pi_ip_fn, 1);
  }
4e4cbee93   Christoph Hellwig   block: switch bio...
133
  static blk_status_t t10_pi_type3_generate_crc(struct blk_integrity_iter *iter)
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
134
135
136
  {
  	return t10_pi_generate(iter, t10_pi_crc_fn, 3);
  }
4e4cbee93   Christoph Hellwig   block: switch bio...
137
  static blk_status_t t10_pi_type3_generate_ip(struct blk_integrity_iter *iter)
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
138
139
140
  {
  	return t10_pi_generate(iter, t10_pi_ip_fn, 3);
  }
4e4cbee93   Christoph Hellwig   block: switch bio...
141
  static blk_status_t t10_pi_type3_verify_crc(struct blk_integrity_iter *iter)
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
142
143
144
  {
  	return t10_pi_verify(iter, t10_pi_crc_fn, 3);
  }
4e4cbee93   Christoph Hellwig   block: switch bio...
145
  static blk_status_t t10_pi_type3_verify_ip(struct blk_integrity_iter *iter)
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
146
147
148
  {
  	return t10_pi_verify(iter, t10_pi_ip_fn, 3);
  }
869ab90f0   Eric Biggers   block: constify s...
149
  const struct blk_integrity_profile t10_pi_type1_crc = {
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
150
151
152
  	.name			= "T10-DIF-TYPE1-CRC",
  	.generate_fn		= t10_pi_type1_generate_crc,
  	.verify_fn		= t10_pi_type1_verify_crc,
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
153
154
  };
  EXPORT_SYMBOL(t10_pi_type1_crc);
869ab90f0   Eric Biggers   block: constify s...
155
  const struct blk_integrity_profile t10_pi_type1_ip = {
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
156
157
158
  	.name			= "T10-DIF-TYPE1-IP",
  	.generate_fn		= t10_pi_type1_generate_ip,
  	.verify_fn		= t10_pi_type1_verify_ip,
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
159
160
  };
  EXPORT_SYMBOL(t10_pi_type1_ip);
869ab90f0   Eric Biggers   block: constify s...
161
  const struct blk_integrity_profile t10_pi_type3_crc = {
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
162
163
164
  	.name			= "T10-DIF-TYPE3-CRC",
  	.generate_fn		= t10_pi_type3_generate_crc,
  	.verify_fn		= t10_pi_type3_verify_crc,
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
165
166
  };
  EXPORT_SYMBOL(t10_pi_type3_crc);
869ab90f0   Eric Biggers   block: constify s...
167
  const struct blk_integrity_profile t10_pi_type3_ip = {
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
168
169
170
  	.name			= "T10-DIF-TYPE3-IP",
  	.generate_fn		= t10_pi_type3_generate_ip,
  	.verify_fn		= t10_pi_type3_verify_ip,
2341c2f8c   Martin K. Petersen   block: Add T10 Pr...
171
172
  };
  EXPORT_SYMBOL(t10_pi_type3_ip);