Blame view

kernel/linux-imx6_3.14.28/Documentation/block/data-integrity.txt 13.5 KB
6b13f685e   김민수   BSP 최초 추가
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
  ----------------------------------------------------------------------
  1. INTRODUCTION
  
  Modern filesystems feature checksumming of data and metadata to
  protect against data corruption.  However, the detection of the
  corruption is done at read time which could potentially be months
  after the data was written.  At that point the original data that the
  application tried to write is most likely lost.
  
  The solution is to ensure that the disk is actually storing what the
  application meant it to.  Recent additions to both the SCSI family
  protocols (SBC Data Integrity Field, SCC protection proposal) as well
  as SATA/T13 (External Path Protection) try to remedy this by adding
  support for appending integrity metadata to an I/O.  The integrity
  metadata (or protection information in SCSI terminology) includes a
  checksum for each sector as well as an incrementing counter that
  ensures the individual sectors are written in the right order.  And
  for some protection schemes also that the I/O is written to the right
  place on disk.
  
  Current storage controllers and devices implement various protective
  measures, for instance checksumming and scrubbing.  But these
  technologies are working in their own isolated domains or at best
  between adjacent nodes in the I/O path.  The interesting thing about
  DIF and the other integrity extensions is that the protection format
  is well defined and every node in the I/O path can verify the
  integrity of the I/O and reject it if corruption is detected.  This
  allows not only corruption prevention but also isolation of the point
  of failure.
  
  ----------------------------------------------------------------------
  2. THE DATA INTEGRITY EXTENSIONS
  
  As written, the protocol extensions only protect the path between
  controller and storage device.  However, many controllers actually
  allow the operating system to interact with the integrity metadata
  (IMD).  We have been working with several FC/SAS HBA vendors to enable
  the protection information to be transferred to and from their
  controllers.
  
  The SCSI Data Integrity Field works by appending 8 bytes of protection
  information to each sector.  The data + integrity metadata is stored
  in 520 byte sectors on disk.  Data + IMD are interleaved when
  transferred between the controller and target.  The T13 proposal is
  similar.
  
  Because it is highly inconvenient for operating systems to deal with
  520 (and 4104) byte sectors, we approached several HBA vendors and
  encouraged them to allow separation of the data and integrity metadata
  scatter-gather lists.
  
  The controller will interleave the buffers on write and split them on
  read.  This means that Linux can DMA the data buffers to and from
  host memory without changes to the page cache.
  
  Also, the 16-bit CRC checksum mandated by both the SCSI and SATA specs
  is somewhat heavy to compute in software.  Benchmarks found that
  calculating this checksum had a significant impact on system
  performance for a number of workloads.  Some controllers allow a
  lighter-weight checksum to be used when interfacing with the operating
  system.  Emulex, for instance, supports the TCP/IP checksum instead.
  The IP checksum received from the OS is converted to the 16-bit CRC
  when writing and vice versa.  This allows the integrity metadata to be
  generated by Linux or the application at very low cost (comparable to
  software RAID5).
  
  The IP checksum is weaker than the CRC in terms of detecting bit
  errors.  However, the strength is really in the separation of the data
  buffers and the integrity metadata.  These two distinct buffers must
  match up for an I/O to complete.
  
  The separation of the data and integrity metadata buffers as well as
  the choice in checksums is referred to as the Data Integrity
  Extensions.  As these extensions are outside the scope of the protocol
  bodies (T10, T13), Oracle and its partners are trying to standardize
  them within the Storage Networking Industry Association.
  
  ----------------------------------------------------------------------
  3. KERNEL CHANGES
  
  The data integrity framework in Linux enables protection information
  to be pinned to I/Os and sent to/received from controllers that
  support it.
  
  The advantage to the integrity extensions in SCSI and SATA is that
  they enable us to protect the entire path from application to storage
  device.  However, at the same time this is also the biggest
  disadvantage. It means that the protection information must be in a
  format that can be understood by the disk.
  
  Generally Linux/POSIX applications are agnostic to the intricacies of
  the storage devices they are accessing.  The virtual filesystem switch
  and the block layer make things like hardware sector size and
  transport protocols completely transparent to the application.
  
  However, this level of detail is required when preparing the
  protection information to send to a disk.  Consequently, the very
  concept of an end-to-end protection scheme is a layering violation.
  It is completely unreasonable for an application to be aware whether
  it is accessing a SCSI or SATA disk.
  
  The data integrity support implemented in Linux attempts to hide this
  from the application.  As far as the application (and to some extent
  the kernel) is concerned, the integrity metadata is opaque information
  that's attached to the I/O.
  
  The current implementation allows the block layer to automatically
  generate the protection information for any I/O.  Eventually the
  intent is to move the integrity metadata calculation to userspace for
  user data.  Metadata and other I/O that originates within the kernel
  will still use the automatic generation interface.
  
  Some storage devices allow each hardware sector to be tagged with a
  16-bit value.  The owner of this tag space is the owner of the block
  device.  I.e. the filesystem in most cases.  The filesystem can use
  this extra space to tag sectors as they see fit.  Because the tag
  space is limited, the block interface allows tagging bigger chunks by
  way of interleaving.  This way, 8*16 bits of information can be
  attached to a typical 4KB filesystem block.
  
  This also means that applications such as fsck and mkfs will need
  access to manipulate the tags from user space.  A passthrough
  interface for this is being worked on.
  
  
  ----------------------------------------------------------------------
  4. BLOCK LAYER IMPLEMENTATION DETAILS
  
  4.1 BIO
  
  The data integrity patches add a new field to struct bio when
  CONFIG_BLK_DEV_INTEGRITY is enabled.  bio->bi_integrity is a pointer
  to a struct bip which contains the bio integrity payload.  Essentially
  a bip is a trimmed down struct bio which holds a bio_vec containing
  the integrity metadata and the required housekeeping information (bvec
  pool, vector count, etc.)
  
  A kernel subsystem can enable data integrity protection on a bio by
  calling bio_integrity_alloc(bio).  This will allocate and attach the
  bip to the bio.
  
  Individual pages containing integrity metadata can subsequently be
  attached using bio_integrity_add_page().
  
  bio_free() will automatically free the bip.
  
  
  4.2 BLOCK DEVICE
  
  Because the format of the protection data is tied to the physical
  disk, each block device has been extended with a block integrity
  profile (struct blk_integrity).  This optional profile is registered
  with the block layer using blk_integrity_register().
  
  The profile contains callback functions for generating and verifying
  the protection data, as well as getting and setting application tags.
  The profile also contains a few constants to aid in completing,
  merging and splitting the integrity metadata.
  
  Layered block devices will need to pick a profile that's appropriate
  for all subdevices.  blk_integrity_compare() can help with that.  DM
  and MD linear, RAID0 and RAID1 are currently supported.  RAID4/5/6
  will require extra work due to the application tag.
  
  
  ----------------------------------------------------------------------
  5.0 BLOCK LAYER INTEGRITY API
  
  5.1 NORMAL FILESYSTEM
  
      The normal filesystem is unaware that the underlying block device
      is capable of sending/receiving integrity metadata.  The IMD will
      be automatically generated by the block layer at submit_bio() time
      in case of a WRITE.  A READ request will cause the I/O integrity
      to be verified upon completion.
  
      IMD generation and verification can be toggled using the
  
        /sys/block/<bdev>/integrity/write_generate
  
      and
  
        /sys/block/<bdev>/integrity/read_verify
  
      flags.
  
  
  5.2 INTEGRITY-AWARE FILESYSTEM
  
      A filesystem that is integrity-aware can prepare I/Os with IMD
      attached.  It can also use the application tag space if this is
      supported by the block device.
  
  
      int bdev_integrity_enabled(block_device, int rw);
  
        bdev_integrity_enabled() will return 1 if the block device
        supports integrity metadata transfer for the data direction
        specified in 'rw'.
  
        bdev_integrity_enabled() honors the write_generate and
        read_verify flags in sysfs and will respond accordingly.
  
  
      int bio_integrity_prep(bio);
  
        To generate IMD for WRITE and to set up buffers for READ, the
        filesystem must call bio_integrity_prep(bio).
  
        Prior to calling this function, the bio data direction and start
        sector must be set, and the bio should have all data pages
        added.  It is up to the caller to ensure that the bio does not
        change while I/O is in progress.
  
        bio_integrity_prep() should only be called if
        bio_integrity_enabled() returned 1.
  
  
      int bio_integrity_tag_size(bio);
  
        If the filesystem wants to use the application tag space it will
        first have to find out how much storage space is available.
        Because tag space is generally limited (usually 2 bytes per
        sector regardless of sector size), the integrity framework
        supports interleaving the information between the sectors in an
        I/O.
  
        Filesystems can call bio_integrity_tag_size(bio) to find out how
        many bytes of storage are available for that particular bio.
  
        Another option is bdev_get_tag_size(block_device) which will
        return the number of available bytes per hardware sector.
  
  
      int bio_integrity_set_tag(bio, void *tag_buf, len);
  
        After a successful return from bio_integrity_prep(),
        bio_integrity_set_tag() can be used to attach an opaque tag
        buffer to a bio.  Obviously this only makes sense if the I/O is
        a WRITE.
  
  
      int bio_integrity_get_tag(bio, void *tag_buf, len);
  
        Similarly, at READ I/O completion time the filesystem can
        retrieve the tag buffer using bio_integrity_get_tag().
  
  
  5.3 PASSING EXISTING INTEGRITY METADATA
  
      Filesystems that either generate their own integrity metadata or
      are capable of transferring IMD from user space can use the
      following calls:
  
  
      struct bip * bio_integrity_alloc(bio, gfp_mask, nr_pages);
  
        Allocates the bio integrity payload and hangs it off of the bio.
        nr_pages indicate how many pages of protection data need to be
        stored in the integrity bio_vec list (similar to bio_alloc()).
  
        The integrity payload will be freed at bio_free() time.
  
  
      int bio_integrity_add_page(bio, page, len, offset);
  
        Attaches a page containing integrity metadata to an existing
        bio.  The bio must have an existing bip,
        i.e. bio_integrity_alloc() must have been called.  For a WRITE,
        the integrity metadata in the pages must be in a format
        understood by the target device with the notable exception that
        the sector numbers will be remapped as the request traverses the
        I/O stack.  This implies that the pages added using this call
        will be modified during I/O!  The first reference tag in the
        integrity metadata must have a value of bip->bip_sector.
  
        Pages can be added using bio_integrity_add_page() as long as
        there is room in the bip bio_vec array (nr_pages).
  
        Upon completion of a READ operation, the attached pages will
        contain the integrity metadata received from the storage device.
        It is up to the receiver to process them and verify data
        integrity upon completion.
  
  
  5.4 REGISTERING A BLOCK DEVICE AS CAPABLE OF EXCHANGING INTEGRITY
      METADATA
  
      To enable integrity exchange on a block device the gendisk must be
      registered as capable:
  
      int blk_integrity_register(gendisk, blk_integrity);
  
        The blk_integrity struct is a template and should contain the
        following:
  
          static struct blk_integrity my_profile = {
              .name                   = "STANDARDSBODY-TYPE-VARIANT-CSUM",
              .generate_fn            = my_generate_fn,
         	    .verify_fn              = my_verify_fn,
         	    .get_tag_fn             = my_get_tag_fn,
         	    .set_tag_fn             = my_set_tag_fn,
  	    .tuple_size             = sizeof(struct my_tuple_size),
  	    .tag_size               = <tag bytes per hw sector>,
          };
  
        'name' is a text string which will be visible in sysfs.  This is
        part of the userland API so chose it carefully and never change
        it.  The format is standards body-type-variant.
        E.g. T10-DIF-TYPE1-IP or T13-EPP-0-CRC.
  
        'generate_fn' generates appropriate integrity metadata (for WRITE).
  
        'verify_fn' verifies that the data buffer matches the integrity
        metadata.
  
        'tuple_size' must be set to match the size of the integrity
        metadata per sector.  I.e. 8 for DIF and EPP.
  
        'tag_size' must be set to identify how many bytes of tag space
        are available per hardware sector.  For DIF this is either 2 or
        0 depending on the value of the Control Mode Page ATO bit.
  
        See 6.2 for a description of get_tag_fn and set_tag_fn.
  
  ----------------------------------------------------------------------
  2007-12-24 Martin K. Petersen <martin.petersen@oracle.com>