]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/geom/raid3/g_raid3.h
Merge OpenSSL 1.0.2n.
[FreeBSD/FreeBSD.git] / sys / geom / raid3 / g_raid3.h
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30
31 #ifndef _G_RAID3_H_
32 #define _G_RAID3_H_
33
34 #include <sys/endian.h>
35 #include <sys/md5.h>
36
37 #define G_RAID3_CLASS_NAME      "RAID3"
38
39 #define G_RAID3_MAGIC           "GEOM::RAID3"
40 /*
41  * Version history:
42  * 0 - Initial version number.
43  * 1 - Added 'round-robin reading' algorithm.
44  * 2 - Added 'verify reading' algorithm.
45  * 3 - Added md_genid field to metadata.
46  * 4 - Added md_provsize field to metadata.
47  * 5 - Added 'no failure synchronization' flag.
48  */
49 #define G_RAID3_VERSION         5
50
51 #define G_RAID3_DISK_FLAG_DIRTY         0x0000000000000001ULL
52 #define G_RAID3_DISK_FLAG_SYNCHRONIZING 0x0000000000000002ULL
53 #define G_RAID3_DISK_FLAG_FORCE_SYNC    0x0000000000000004ULL
54 #define G_RAID3_DISK_FLAG_HARDCODED     0x0000000000000008ULL
55 #define G_RAID3_DISK_FLAG_BROKEN        0x0000000000000010ULL
56 #define G_RAID3_DISK_FLAG_MASK          (G_RAID3_DISK_FLAG_DIRTY |      \
57                                          G_RAID3_DISK_FLAG_SYNCHRONIZING | \
58                                          G_RAID3_DISK_FLAG_FORCE_SYNC)
59
60 #define G_RAID3_DEVICE_FLAG_NOAUTOSYNC  0x0000000000000001ULL
61 #define G_RAID3_DEVICE_FLAG_ROUND_ROBIN 0x0000000000000002ULL
62 #define G_RAID3_DEVICE_FLAG_VERIFY      0x0000000000000004ULL
63 #define G_RAID3_DEVICE_FLAG_NOFAILSYNC  0x0000000000000008ULL
64 #define G_RAID3_DEVICE_FLAG_MASK        (G_RAID3_DEVICE_FLAG_NOAUTOSYNC | \
65                                          G_RAID3_DEVICE_FLAG_ROUND_ROBIN | \
66                                          G_RAID3_DEVICE_FLAG_VERIFY | \
67                                          G_RAID3_DEVICE_FLAG_NOFAILSYNC)
68
69 #ifdef _KERNEL
70 extern u_int g_raid3_debug;
71
72 #define G_RAID3_DEBUG(lvl, ...) do {                                    \
73         if (g_raid3_debug >= (lvl)) {                                   \
74                 printf("GEOM_RAID3");                                   \
75                 if (g_raid3_debug > 0)                                  \
76                         printf("[%u]", lvl);                            \
77                 printf(": ");                                           \
78                 printf(__VA_ARGS__);                                    \
79                 printf("\n");                                           \
80         }                                                               \
81 } while (0)
82 #define G_RAID3_LOGREQ(lvl, bp, ...)    do {                            \
83         if (g_raid3_debug >= (lvl)) {                                   \
84                 printf("GEOM_RAID3");                                   \
85                 if (g_raid3_debug > 0)                                  \
86                         printf("[%u]", lvl);                            \
87                 printf(": ");                                           \
88                 printf(__VA_ARGS__);                                    \
89                 printf(" ");                                            \
90                 g_print_bio(bp);                                        \
91                 printf("\n");                                           \
92         }                                                               \
93 } while (0)
94
95 #define G_RAID3_BIO_CFLAG_REGULAR       0x01
96 #define G_RAID3_BIO_CFLAG_SYNC          0x02
97 #define G_RAID3_BIO_CFLAG_PARITY        0x04
98 #define G_RAID3_BIO_CFLAG_NODISK        0x08
99 #define G_RAID3_BIO_CFLAG_REGSYNC       0x10
100 #define G_RAID3_BIO_CFLAG_MASK          (G_RAID3_BIO_CFLAG_REGULAR |    \
101                                          G_RAID3_BIO_CFLAG_SYNC |       \
102                                          G_RAID3_BIO_CFLAG_PARITY |     \
103                                          G_RAID3_BIO_CFLAG_NODISK |     \
104                                          G_RAID3_BIO_CFLAG_REGSYNC)
105
106 #define G_RAID3_BIO_PFLAG_DEGRADED      0x01
107 #define G_RAID3_BIO_PFLAG_NOPARITY      0x02
108 #define G_RAID3_BIO_PFLAG_VERIFY        0x04
109 #define G_RAID3_BIO_PFLAG_MASK          (G_RAID3_BIO_PFLAG_DEGRADED |   \
110                                          G_RAID3_BIO_PFLAG_NOPARITY |   \
111                                          G_RAID3_BIO_PFLAG_VERIFY)
112
113 /*
114  * Informations needed for synchronization.
115  */
116 struct g_raid3_disk_sync {
117         struct g_consumer *ds_consumer; /* Consumer connected to our device. */
118         off_t             ds_offset;    /* Offset of next request to send. */
119         off_t             ds_offset_done; /* Offset of already synchronized
120                                            region. */
121         off_t             ds_resync;    /* Resynchronize from this offset. */
122         u_int             ds_syncid;    /* Disk's synchronization ID. */
123         u_int             ds_inflight;  /* Number of in-flight sync requests. */
124         struct bio      **ds_bios;      /* BIOs for synchronization I/O. */
125 };
126
127 /*
128  * Informations needed for synchronization.
129  */
130 struct g_raid3_device_sync {
131         struct g_geom   *ds_geom;       /* Synchronization geom. */
132 };
133
134 #define G_RAID3_DISK_STATE_NODISK               0
135 #define G_RAID3_DISK_STATE_NONE                 1
136 #define G_RAID3_DISK_STATE_NEW                  2
137 #define G_RAID3_DISK_STATE_ACTIVE               3
138 #define G_RAID3_DISK_STATE_STALE                4
139 #define G_RAID3_DISK_STATE_SYNCHRONIZING        5
140 #define G_RAID3_DISK_STATE_DISCONNECTED         6
141 #define G_RAID3_DISK_STATE_DESTROY              7
142 struct g_raid3_disk {
143         u_int            d_no;          /* Disk number. */
144         struct g_consumer *d_consumer;  /* Consumer. */
145         struct g_raid3_softc *d_softc;  /* Back-pointer to softc. */
146         int              d_state;       /* Disk state. */
147         uint64_t         d_flags;       /* Additional flags. */
148         u_int            d_genid;       /* Disk's generation ID. */
149         struct g_raid3_disk_sync d_sync; /* Sync information. */
150         LIST_ENTRY(g_raid3_disk) d_next;
151 };
152 #define d_name  d_consumer->provider->name
153
154 #define G_RAID3_EVENT_DONTWAIT  0x1
155 #define G_RAID3_EVENT_WAIT      0x2
156 #define G_RAID3_EVENT_DEVICE    0x4
157 #define G_RAID3_EVENT_DONE      0x8
158 struct g_raid3_event {
159         struct g_raid3_disk     *e_disk;
160         int                      e_state;
161         int                      e_flags;
162         int                      e_error;
163         TAILQ_ENTRY(g_raid3_event) e_next;
164 };
165
166 #define G_RAID3_DEVICE_FLAG_DESTROY     0x0100000000000000ULL
167 #define G_RAID3_DEVICE_FLAG_WAIT        0x0200000000000000ULL
168 #define G_RAID3_DEVICE_FLAG_DESTROYING  0x0400000000000000ULL
169
170 #define G_RAID3_DEVICE_STATE_STARTING           0
171 #define G_RAID3_DEVICE_STATE_DEGRADED           1
172 #define G_RAID3_DEVICE_STATE_COMPLETE           2
173
174 /* Bump syncid on first write. */
175 #define G_RAID3_BUMP_SYNCID     0x1
176 /* Bump genid immediately. */
177 #define G_RAID3_BUMP_GENID      0x2
178
179 enum g_raid3_zones {
180         G_RAID3_ZONE_64K,
181         G_RAID3_ZONE_16K,
182         G_RAID3_ZONE_4K,
183         G_RAID3_NUM_ZONES
184 };
185
186 static __inline enum g_raid3_zones
187 g_raid3_zone(size_t nbytes) {
188         if (nbytes > 65536)
189                 return (G_RAID3_NUM_ZONES);
190         else if (nbytes > 16384)
191                 return (G_RAID3_ZONE_64K);
192         else if (nbytes > 4096)
193                 return (G_RAID3_ZONE_16K);
194         else
195                 return (G_RAID3_ZONE_4K);
196 };
197
198 struct g_raid3_softc {
199         u_int           sc_state;       /* Device state. */
200         uint64_t        sc_mediasize;   /* Device size. */
201         uint32_t        sc_sectorsize;  /* Sector size. */
202         uint64_t        sc_flags;       /* Additional flags. */
203
204         struct g_geom   *sc_geom;
205         struct g_provider *sc_provider;
206
207         uint32_t        sc_id;          /* Device unique ID. */
208
209         struct sx        sc_lock;
210         struct bio_queue_head sc_queue;
211         struct mtx       sc_queue_mtx;
212         struct proc     *sc_worker;
213         struct bio_queue_head sc_regular_delayed; /* Delayed I/O requests due
214                                                      collision with sync
215                                                      requests. */
216         struct bio_queue_head sc_inflight; /* In-flight regular write
217                                               requests. */
218         struct bio_queue_head sc_sync_delayed; /* Delayed sync requests due
219                                                   collision with regular
220                                                   requests. */
221
222         struct g_raid3_disk *sc_disks;
223         u_int           sc_ndisks;      /* Number of disks. */
224         u_int           sc_round_robin;
225         struct g_raid3_disk *sc_syncdisk;
226
227         struct g_raid3_zone {
228                 uma_zone_t      sz_zone;
229                 size_t          sz_inuse;
230                 size_t          sz_max;
231                 u_int           sz_requested;
232                 u_int           sz_failed;
233         } sc_zones[G_RAID3_NUM_ZONES];
234
235         u_int           sc_genid;       /* Generation ID. */
236         u_int           sc_syncid;      /* Synchronization ID. */
237         int             sc_bump_id;
238         struct g_raid3_device_sync sc_sync;
239         int             sc_idle;        /* DIRTY flags removed. */
240         time_t          sc_last_write;
241         u_int           sc_writes;
242
243         TAILQ_HEAD(, g_raid3_event) sc_events;
244         struct mtx      sc_events_mtx;
245
246         struct callout  sc_callout;
247
248         struct root_hold_token *sc_rootmount;
249 };
250 #define sc_name sc_geom->name
251
252 const char *g_raid3_get_diskname(struct g_raid3_disk *disk);
253 u_int g_raid3_ndisks(struct g_raid3_softc *sc, int state);
254 #define G_RAID3_DESTROY_SOFT    0
255 #define G_RAID3_DESTROY_DELAYED 1
256 #define G_RAID3_DESTROY_HARD    2
257 int g_raid3_destroy(struct g_raid3_softc *sc, int how);
258 int g_raid3_event_send(void *arg, int state, int flags);
259 struct g_raid3_metadata;
260 int g_raid3_add_disk(struct g_raid3_softc *sc, struct g_provider *pp,
261     struct g_raid3_metadata *md);
262 int g_raid3_read_metadata(struct g_consumer *cp, struct g_raid3_metadata *md);
263 void g_raid3_fill_metadata(struct g_raid3_disk *disk,
264     struct g_raid3_metadata *md);
265 int g_raid3_clear_metadata(struct g_raid3_disk *disk);
266 void g_raid3_update_metadata(struct g_raid3_disk *disk);
267
268 g_ctl_req_t g_raid3_config;
269 #endif  /* _KERNEL */
270
271 struct g_raid3_metadata {
272         char            md_magic[16];   /* Magic value. */
273         uint32_t        md_version;     /* Version number. */
274         char            md_name[16];    /* Device name. */
275         uint32_t        md_id;          /* Device unique ID. */
276         uint16_t        md_no;          /* Component number. */
277         uint16_t        md_all;         /* Number of disks in device. */
278         uint32_t        md_genid;       /* Generation ID. */
279         uint32_t        md_syncid;      /* Synchronization ID. */
280         uint64_t        md_mediasize;   /* Size of whole device. */
281         uint32_t        md_sectorsize;  /* Sector size. */
282         uint64_t        md_sync_offset; /* Synchronized offset. */
283         uint64_t        md_mflags;      /* Additional device flags. */
284         uint64_t        md_dflags;      /* Additional disk flags. */
285         char            md_provider[16]; /* Hardcoded provider. */
286         uint64_t        md_provsize;    /* Provider's size. */
287         u_char          md_hash[16];    /* MD5 hash. */
288 };
289 static __inline void
290 raid3_metadata_encode(struct g_raid3_metadata *md, u_char *data)
291 {
292         MD5_CTX ctx;
293
294         bcopy(md->md_magic, data, 16);
295         le32enc(data + 16, md->md_version);
296         bcopy(md->md_name, data + 20, 16);
297         le32enc(data + 36, md->md_id);
298         le16enc(data + 40, md->md_no);
299         le16enc(data + 42, md->md_all);
300         le32enc(data + 44, md->md_genid);
301         le32enc(data + 48, md->md_syncid);
302         le64enc(data + 52, md->md_mediasize);
303         le32enc(data + 60, md->md_sectorsize);
304         le64enc(data + 64, md->md_sync_offset);
305         le64enc(data + 72, md->md_mflags);
306         le64enc(data + 80, md->md_dflags);
307         bcopy(md->md_provider, data + 88, 16);
308         le64enc(data + 104, md->md_provsize);
309         MD5Init(&ctx);
310         MD5Update(&ctx, data, 112);
311         MD5Final(md->md_hash, &ctx);
312         bcopy(md->md_hash, data + 112, 16);
313 }
314 static __inline int
315 raid3_metadata_decode_v0v1v2(const u_char *data, struct g_raid3_metadata *md)
316 {
317         MD5_CTX ctx;
318
319         bcopy(data + 20, md->md_name, 16);
320         md->md_id = le32dec(data + 36);
321         md->md_no = le16dec(data + 40);
322         md->md_all = le16dec(data + 42);
323         md->md_syncid = le32dec(data + 44);
324         md->md_mediasize = le64dec(data + 48);
325         md->md_sectorsize = le32dec(data + 56);
326         md->md_sync_offset = le64dec(data + 60);
327         md->md_mflags = le64dec(data + 68);
328         md->md_dflags = le64dec(data + 76);
329         bcopy(data + 84, md->md_provider, 16);
330         bcopy(data + 100, md->md_hash, 16);
331         MD5Init(&ctx);
332         MD5Update(&ctx, data, 100);
333         MD5Final(md->md_hash, &ctx);
334         if (bcmp(md->md_hash, data + 100, 16) != 0)
335                 return (EINVAL);
336
337         /* New fields. */
338         md->md_genid = 0;
339         md->md_provsize = 0;
340
341         return (0);
342 }
343 static __inline int
344 raid3_metadata_decode_v3(const u_char *data, struct g_raid3_metadata *md)
345 {
346         MD5_CTX ctx;
347
348         bcopy(data + 20, md->md_name, 16);
349         md->md_id = le32dec(data + 36);
350         md->md_no = le16dec(data + 40);
351         md->md_all = le16dec(data + 42);
352         md->md_genid = le32dec(data + 44);
353         md->md_syncid = le32dec(data + 48);
354         md->md_mediasize = le64dec(data + 52);
355         md->md_sectorsize = le32dec(data + 60);
356         md->md_sync_offset = le64dec(data + 64);
357         md->md_mflags = le64dec(data + 72);
358         md->md_dflags = le64dec(data + 80);
359         bcopy(data + 88, md->md_provider, 16);
360         bcopy(data + 104, md->md_hash, 16);
361         MD5Init(&ctx);
362         MD5Update(&ctx, data, 104);
363         MD5Final(md->md_hash, &ctx);
364         if (bcmp(md->md_hash, data + 104, 16) != 0)
365                 return (EINVAL);
366
367         /* New fields. */
368         md->md_provsize = 0;
369
370         return (0);
371 }
372 static __inline int
373 raid3_metadata_decode_v4v5(const u_char *data, struct g_raid3_metadata *md)
374 {
375         MD5_CTX ctx;
376
377         bcopy(data + 20, md->md_name, 16);
378         md->md_id = le32dec(data + 36);
379         md->md_no = le16dec(data + 40);
380         md->md_all = le16dec(data + 42);
381         md->md_genid = le32dec(data + 44);
382         md->md_syncid = le32dec(data + 48);
383         md->md_mediasize = le64dec(data + 52);
384         md->md_sectorsize = le32dec(data + 60);
385         md->md_sync_offset = le64dec(data + 64);
386         md->md_mflags = le64dec(data + 72);
387         md->md_dflags = le64dec(data + 80);
388         bcopy(data + 88, md->md_provider, 16);
389         md->md_provsize = le64dec(data + 104);
390         bcopy(data + 112, md->md_hash, 16);
391         MD5Init(&ctx);
392         MD5Update(&ctx, data, 112);
393         MD5Final(md->md_hash, &ctx);
394         if (bcmp(md->md_hash, data + 112, 16) != 0)
395                 return (EINVAL);
396         return (0);
397 }
398 static __inline int
399 raid3_metadata_decode(const u_char *data, struct g_raid3_metadata *md)
400 {
401         int error;
402
403         bcopy(data, md->md_magic, 16);
404         md->md_version = le32dec(data + 16);
405         switch (md->md_version) {
406         case 0:
407         case 1:
408         case 2:
409                 error = raid3_metadata_decode_v0v1v2(data, md);
410                 break;
411         case 3:
412                 error = raid3_metadata_decode_v3(data, md);
413                 break;
414         case 4:
415         case 5:
416                 error = raid3_metadata_decode_v4v5(data, md);
417                 break;
418         default:
419                 error = EINVAL;
420                 break;
421         }
422         return (error);
423 }
424
425 static __inline void
426 raid3_metadata_dump(const struct g_raid3_metadata *md)
427 {
428         static const char hex[] = "0123456789abcdef";
429         char hash[16 * 2 + 1];
430         u_int i;
431
432         printf("     magic: %s\n", md->md_magic);
433         printf("   version: %u\n", (u_int)md->md_version);
434         printf("      name: %s\n", md->md_name);
435         printf("        id: %u\n", (u_int)md->md_id);
436         printf("        no: %u\n", (u_int)md->md_no);
437         printf("       all: %u\n", (u_int)md->md_all);
438         printf("     genid: %u\n", (u_int)md->md_genid);
439         printf("    syncid: %u\n", (u_int)md->md_syncid);
440         printf(" mediasize: %jd\n", (intmax_t)md->md_mediasize);
441         printf("sectorsize: %u\n", (u_int)md->md_sectorsize);
442         printf("syncoffset: %jd\n", (intmax_t)md->md_sync_offset);
443         printf("    mflags:");
444         if (md->md_mflags == 0)
445                 printf(" NONE");
446         else {
447                 if ((md->md_mflags & G_RAID3_DEVICE_FLAG_NOAUTOSYNC) != 0)
448                         printf(" NOAUTOSYNC");
449                 if ((md->md_mflags & G_RAID3_DEVICE_FLAG_ROUND_ROBIN) != 0)
450                         printf(" ROUND-ROBIN");
451                 if ((md->md_mflags & G_RAID3_DEVICE_FLAG_VERIFY) != 0)
452                         printf(" VERIFY");
453                 if ((md->md_mflags & G_RAID3_DEVICE_FLAG_NOFAILSYNC) != 0)
454                         printf(" NOFAILSYNC");
455         }
456         printf("\n");
457         printf("    dflags:");
458         if (md->md_dflags == 0)
459                 printf(" NONE");
460         else {
461                 if ((md->md_dflags & G_RAID3_DISK_FLAG_DIRTY) != 0)
462                         printf(" DIRTY");
463                 if ((md->md_dflags & G_RAID3_DISK_FLAG_SYNCHRONIZING) != 0)
464                         printf(" SYNCHRONIZING");
465                 if ((md->md_dflags & G_RAID3_DISK_FLAG_FORCE_SYNC) != 0)
466                         printf(" FORCE_SYNC");
467         }
468         printf("\n");
469         printf("hcprovider: %s\n", md->md_provider);
470         printf("  provsize: %ju\n", (uintmax_t)md->md_provsize);
471         bzero(hash, sizeof(hash));
472         for (i = 0; i < 16; i++) {
473                 hash[i * 2] = hex[md->md_hash[i] >> 4];
474                 hash[i * 2 + 1] = hex[md->md_hash[i] & 0x0f];
475         }
476         printf("  MD5 hash: %s\n", hash);
477 }
478 #endif  /* !_G_RAID3_H_ */