]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/geom/raid3/g_raid3.h
THIS BRANCH IS OBSOLETE, PLEASE READ:
[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, ...) \
73     _GEOM_DEBUG("GEOM_RAID3", g_raid3_debug, (lvl), NULL, __VA_ARGS__)
74 #define G_RAID3_LOGREQ(lvl, bp, ...) \
75     _GEOM_DEBUG("GEOM_RAID3", g_raid3_debug, (lvl), (bp), __VA_ARGS__)
76
77 #define G_RAID3_BIO_CFLAG_REGULAR       0x01
78 #define G_RAID3_BIO_CFLAG_SYNC          0x02
79 #define G_RAID3_BIO_CFLAG_PARITY        0x04
80 #define G_RAID3_BIO_CFLAG_NODISK        0x08
81 #define G_RAID3_BIO_CFLAG_REGSYNC       0x10
82 #define G_RAID3_BIO_CFLAG_MASK          (G_RAID3_BIO_CFLAG_REGULAR |    \
83                                          G_RAID3_BIO_CFLAG_SYNC |       \
84                                          G_RAID3_BIO_CFLAG_PARITY |     \
85                                          G_RAID3_BIO_CFLAG_NODISK |     \
86                                          G_RAID3_BIO_CFLAG_REGSYNC)
87
88 #define G_RAID3_BIO_PFLAG_DEGRADED      0x01
89 #define G_RAID3_BIO_PFLAG_NOPARITY      0x02
90 #define G_RAID3_BIO_PFLAG_VERIFY        0x04
91 #define G_RAID3_BIO_PFLAG_MASK          (G_RAID3_BIO_PFLAG_DEGRADED |   \
92                                          G_RAID3_BIO_PFLAG_NOPARITY |   \
93                                          G_RAID3_BIO_PFLAG_VERIFY)
94
95 /*
96  * Informations needed for synchronization.
97  */
98 struct g_raid3_disk_sync {
99         struct g_consumer *ds_consumer; /* Consumer connected to our device. */
100         off_t             ds_offset;    /* Offset of next request to send. */
101         off_t             ds_offset_done; /* Offset of already synchronized
102                                            region. */
103         off_t             ds_resync;    /* Resynchronize from this offset. */
104         u_int             ds_syncid;    /* Disk's synchronization ID. */
105         u_int             ds_inflight;  /* Number of in-flight sync requests. */
106         struct bio      **ds_bios;      /* BIOs for synchronization I/O. */
107 };
108
109 /*
110  * Informations needed for synchronization.
111  */
112 struct g_raid3_device_sync {
113         struct g_geom   *ds_geom;       /* Synchronization geom. */
114 };
115
116 #define G_RAID3_DISK_STATE_NODISK               0
117 #define G_RAID3_DISK_STATE_NONE                 1
118 #define G_RAID3_DISK_STATE_NEW                  2
119 #define G_RAID3_DISK_STATE_ACTIVE               3
120 #define G_RAID3_DISK_STATE_STALE                4
121 #define G_RAID3_DISK_STATE_SYNCHRONIZING        5
122 #define G_RAID3_DISK_STATE_DISCONNECTED         6
123 #define G_RAID3_DISK_STATE_DESTROY              7
124 struct g_raid3_disk {
125         u_int            d_no;          /* Disk number. */
126         struct g_consumer *d_consumer;  /* Consumer. */
127         struct g_raid3_softc *d_softc;  /* Back-pointer to softc. */
128         int              d_state;       /* Disk state. */
129         uint64_t         d_flags;       /* Additional flags. */
130         u_int            d_genid;       /* Disk's generation ID. */
131         struct g_raid3_disk_sync d_sync; /* Sync information. */
132         LIST_ENTRY(g_raid3_disk) d_next;
133 };
134 #define d_name  d_consumer->provider->name
135
136 #define G_RAID3_EVENT_DONTWAIT  0x1
137 #define G_RAID3_EVENT_WAIT      0x2
138 #define G_RAID3_EVENT_DEVICE    0x4
139 #define G_RAID3_EVENT_DONE      0x8
140 struct g_raid3_event {
141         struct g_raid3_disk     *e_disk;
142         int                      e_state;
143         int                      e_flags;
144         int                      e_error;
145         TAILQ_ENTRY(g_raid3_event) e_next;
146 };
147
148 #define G_RAID3_DEVICE_FLAG_DESTROY     0x0100000000000000ULL
149 #define G_RAID3_DEVICE_FLAG_WAIT        0x0200000000000000ULL
150 #define G_RAID3_DEVICE_FLAG_DESTROYING  0x0400000000000000ULL
151
152 #define G_RAID3_DEVICE_STATE_STARTING           0
153 #define G_RAID3_DEVICE_STATE_DEGRADED           1
154 #define G_RAID3_DEVICE_STATE_COMPLETE           2
155
156 /* Bump syncid on first write. */
157 #define G_RAID3_BUMP_SYNCID     0x1
158 /* Bump genid immediately. */
159 #define G_RAID3_BUMP_GENID      0x2
160
161 enum g_raid3_zones {
162         G_RAID3_ZONE_64K,
163         G_RAID3_ZONE_16K,
164         G_RAID3_ZONE_4K,
165         G_RAID3_NUM_ZONES
166 };
167
168 static __inline enum g_raid3_zones
169 g_raid3_zone(size_t nbytes) {
170         if (nbytes > 65536)
171                 return (G_RAID3_NUM_ZONES);
172         else if (nbytes > 16384)
173                 return (G_RAID3_ZONE_64K);
174         else if (nbytes > 4096)
175                 return (G_RAID3_ZONE_16K);
176         else
177                 return (G_RAID3_ZONE_4K);
178 };
179
180 struct g_raid3_softc {
181         u_int           sc_state;       /* Device state. */
182         uint64_t        sc_mediasize;   /* Device size. */
183         uint32_t        sc_sectorsize;  /* Sector size. */
184         uint64_t        sc_flags;       /* Additional flags. */
185
186         struct g_geom   *sc_geom;
187         struct g_provider *sc_provider;
188
189         uint32_t        sc_id;          /* Device unique ID. */
190
191         struct sx        sc_lock;
192         struct bio_queue_head sc_queue;
193         struct mtx       sc_queue_mtx;
194         struct proc     *sc_worker;
195         struct bio_queue_head sc_regular_delayed; /* Delayed I/O requests due
196                                                      collision with sync
197                                                      requests. */
198         struct bio_queue_head sc_inflight; /* In-flight regular write
199                                               requests. */
200         struct bio_queue_head sc_sync_delayed; /* Delayed sync requests due
201                                                   collision with regular
202                                                   requests. */
203
204         struct g_raid3_disk *sc_disks;
205         u_int           sc_ndisks;      /* Number of disks. */
206         u_int           sc_round_robin;
207         struct g_raid3_disk *sc_syncdisk;
208
209         struct g_raid3_zone {
210                 uma_zone_t      sz_zone;
211                 size_t          sz_inuse;
212                 size_t          sz_max;
213                 u_int           sz_requested;
214                 u_int           sz_failed;
215         } sc_zones[G_RAID3_NUM_ZONES];
216
217         u_int           sc_genid;       /* Generation ID. */
218         u_int           sc_syncid;      /* Synchronization ID. */
219         int             sc_bump_id;
220         struct g_raid3_device_sync sc_sync;
221         int             sc_idle;        /* DIRTY flags removed. */
222         time_t          sc_last_write;
223         u_int           sc_writes;
224
225         TAILQ_HEAD(, g_raid3_event) sc_events;
226         struct mtx      sc_events_mtx;
227
228         struct callout  sc_callout;
229
230         struct root_hold_token *sc_rootmount;
231 };
232 #define sc_name sc_geom->name
233
234 const char *g_raid3_get_diskname(struct g_raid3_disk *disk);
235 u_int g_raid3_ndisks(struct g_raid3_softc *sc, int state);
236 #define G_RAID3_DESTROY_SOFT    0
237 #define G_RAID3_DESTROY_DELAYED 1
238 #define G_RAID3_DESTROY_HARD    2
239 int g_raid3_destroy(struct g_raid3_softc *sc, int how);
240 int g_raid3_event_send(void *arg, int state, int flags);
241 struct g_raid3_metadata;
242 int g_raid3_add_disk(struct g_raid3_softc *sc, struct g_provider *pp,
243     struct g_raid3_metadata *md);
244 int g_raid3_read_metadata(struct g_consumer *cp, struct g_raid3_metadata *md);
245 void g_raid3_fill_metadata(struct g_raid3_disk *disk,
246     struct g_raid3_metadata *md);
247 int g_raid3_clear_metadata(struct g_raid3_disk *disk);
248 void g_raid3_update_metadata(struct g_raid3_disk *disk);
249
250 g_ctl_req_t g_raid3_config;
251 #endif  /* _KERNEL */
252
253 struct g_raid3_metadata {
254         char            md_magic[16];   /* Magic value. */
255         uint32_t        md_version;     /* Version number. */
256         char            md_name[16];    /* Device name. */
257         uint32_t        md_id;          /* Device unique ID. */
258         uint16_t        md_no;          /* Component number. */
259         uint16_t        md_all;         /* Number of disks in device. */
260         uint32_t        md_genid;       /* Generation ID. */
261         uint32_t        md_syncid;      /* Synchronization ID. */
262         uint64_t        md_mediasize;   /* Size of whole device. */
263         uint32_t        md_sectorsize;  /* Sector size. */
264         uint64_t        md_sync_offset; /* Synchronized offset. */
265         uint64_t        md_mflags;      /* Additional device flags. */
266         uint64_t        md_dflags;      /* Additional disk flags. */
267         char            md_provider[16]; /* Hardcoded provider. */
268         uint64_t        md_provsize;    /* Provider's size. */
269         u_char          md_hash[16];    /* MD5 hash. */
270 };
271 static __inline void
272 raid3_metadata_encode(struct g_raid3_metadata *md, u_char *data)
273 {
274         MD5_CTX ctx;
275
276         bcopy(md->md_magic, data, 16);
277         le32enc(data + 16, md->md_version);
278         bcopy(md->md_name, data + 20, 16);
279         le32enc(data + 36, md->md_id);
280         le16enc(data + 40, md->md_no);
281         le16enc(data + 42, md->md_all);
282         le32enc(data + 44, md->md_genid);
283         le32enc(data + 48, md->md_syncid);
284         le64enc(data + 52, md->md_mediasize);
285         le32enc(data + 60, md->md_sectorsize);
286         le64enc(data + 64, md->md_sync_offset);
287         le64enc(data + 72, md->md_mflags);
288         le64enc(data + 80, md->md_dflags);
289         bcopy(md->md_provider, data + 88, 16);
290         le64enc(data + 104, md->md_provsize);
291         MD5Init(&ctx);
292         MD5Update(&ctx, data, 112);
293         MD5Final(md->md_hash, &ctx);
294         bcopy(md->md_hash, data + 112, 16);
295 }
296 static __inline int
297 raid3_metadata_decode_v0v1v2(const u_char *data, struct g_raid3_metadata *md)
298 {
299         MD5_CTX ctx;
300
301         bcopy(data + 20, md->md_name, 16);
302         md->md_id = le32dec(data + 36);
303         md->md_no = le16dec(data + 40);
304         md->md_all = le16dec(data + 42);
305         md->md_syncid = le32dec(data + 44);
306         md->md_mediasize = le64dec(data + 48);
307         md->md_sectorsize = le32dec(data + 56);
308         md->md_sync_offset = le64dec(data + 60);
309         md->md_mflags = le64dec(data + 68);
310         md->md_dflags = le64dec(data + 76);
311         bcopy(data + 84, md->md_provider, 16);
312         bcopy(data + 100, md->md_hash, 16);
313         MD5Init(&ctx);
314         MD5Update(&ctx, data, 100);
315         MD5Final(md->md_hash, &ctx);
316         if (bcmp(md->md_hash, data + 100, 16) != 0)
317                 return (EINVAL);
318
319         /* New fields. */
320         md->md_genid = 0;
321         md->md_provsize = 0;
322
323         return (0);
324 }
325 static __inline int
326 raid3_metadata_decode_v3(const u_char *data, struct g_raid3_metadata *md)
327 {
328         MD5_CTX ctx;
329
330         bcopy(data + 20, md->md_name, 16);
331         md->md_id = le32dec(data + 36);
332         md->md_no = le16dec(data + 40);
333         md->md_all = le16dec(data + 42);
334         md->md_genid = le32dec(data + 44);
335         md->md_syncid = le32dec(data + 48);
336         md->md_mediasize = le64dec(data + 52);
337         md->md_sectorsize = le32dec(data + 60);
338         md->md_sync_offset = le64dec(data + 64);
339         md->md_mflags = le64dec(data + 72);
340         md->md_dflags = le64dec(data + 80);
341         bcopy(data + 88, md->md_provider, 16);
342         bcopy(data + 104, md->md_hash, 16);
343         MD5Init(&ctx);
344         MD5Update(&ctx, data, 104);
345         MD5Final(md->md_hash, &ctx);
346         if (bcmp(md->md_hash, data + 104, 16) != 0)
347                 return (EINVAL);
348
349         /* New fields. */
350         md->md_provsize = 0;
351
352         return (0);
353 }
354 static __inline int
355 raid3_metadata_decode_v4v5(const u_char *data, struct g_raid3_metadata *md)
356 {
357         MD5_CTX ctx;
358
359         bcopy(data + 20, md->md_name, 16);
360         md->md_id = le32dec(data + 36);
361         md->md_no = le16dec(data + 40);
362         md->md_all = le16dec(data + 42);
363         md->md_genid = le32dec(data + 44);
364         md->md_syncid = le32dec(data + 48);
365         md->md_mediasize = le64dec(data + 52);
366         md->md_sectorsize = le32dec(data + 60);
367         md->md_sync_offset = le64dec(data + 64);
368         md->md_mflags = le64dec(data + 72);
369         md->md_dflags = le64dec(data + 80);
370         bcopy(data + 88, md->md_provider, 16);
371         md->md_provsize = le64dec(data + 104);
372         bcopy(data + 112, md->md_hash, 16);
373         MD5Init(&ctx);
374         MD5Update(&ctx, data, 112);
375         MD5Final(md->md_hash, &ctx);
376         if (bcmp(md->md_hash, data + 112, 16) != 0)
377                 return (EINVAL);
378         return (0);
379 }
380 static __inline int
381 raid3_metadata_decode(const u_char *data, struct g_raid3_metadata *md)
382 {
383         int error;
384
385         bcopy(data, md->md_magic, 16);
386         md->md_version = le32dec(data + 16);
387         switch (md->md_version) {
388         case 0:
389         case 1:
390         case 2:
391                 error = raid3_metadata_decode_v0v1v2(data, md);
392                 break;
393         case 3:
394                 error = raid3_metadata_decode_v3(data, md);
395                 break;
396         case 4:
397         case 5:
398                 error = raid3_metadata_decode_v4v5(data, md);
399                 break;
400         default:
401                 error = EINVAL;
402                 break;
403         }
404         return (error);
405 }
406
407 static __inline void
408 raid3_metadata_dump(const struct g_raid3_metadata *md)
409 {
410         static const char hex[] = "0123456789abcdef";
411         char hash[16 * 2 + 1];
412         u_int i;
413
414         printf("     magic: %s\n", md->md_magic);
415         printf("   version: %u\n", (u_int)md->md_version);
416         printf("      name: %s\n", md->md_name);
417         printf("        id: %u\n", (u_int)md->md_id);
418         printf("        no: %u\n", (u_int)md->md_no);
419         printf("       all: %u\n", (u_int)md->md_all);
420         printf("     genid: %u\n", (u_int)md->md_genid);
421         printf("    syncid: %u\n", (u_int)md->md_syncid);
422         printf(" mediasize: %jd\n", (intmax_t)md->md_mediasize);
423         printf("sectorsize: %u\n", (u_int)md->md_sectorsize);
424         printf("syncoffset: %jd\n", (intmax_t)md->md_sync_offset);
425         printf("    mflags:");
426         if (md->md_mflags == 0)
427                 printf(" NONE");
428         else {
429                 if ((md->md_mflags & G_RAID3_DEVICE_FLAG_NOAUTOSYNC) != 0)
430                         printf(" NOAUTOSYNC");
431                 if ((md->md_mflags & G_RAID3_DEVICE_FLAG_ROUND_ROBIN) != 0)
432                         printf(" ROUND-ROBIN");
433                 if ((md->md_mflags & G_RAID3_DEVICE_FLAG_VERIFY) != 0)
434                         printf(" VERIFY");
435                 if ((md->md_mflags & G_RAID3_DEVICE_FLAG_NOFAILSYNC) != 0)
436                         printf(" NOFAILSYNC");
437         }
438         printf("\n");
439         printf("    dflags:");
440         if (md->md_dflags == 0)
441                 printf(" NONE");
442         else {
443                 if ((md->md_dflags & G_RAID3_DISK_FLAG_DIRTY) != 0)
444                         printf(" DIRTY");
445                 if ((md->md_dflags & G_RAID3_DISK_FLAG_SYNCHRONIZING) != 0)
446                         printf(" SYNCHRONIZING");
447                 if ((md->md_dflags & G_RAID3_DISK_FLAG_FORCE_SYNC) != 0)
448                         printf(" FORCE_SYNC");
449         }
450         printf("\n");
451         printf("hcprovider: %s\n", md->md_provider);
452         printf("  provsize: %ju\n", (uintmax_t)md->md_provsize);
453         bzero(hash, sizeof(hash));
454         for (i = 0; i < 16; i++) {
455                 hash[i * 2] = hex[md->md_hash[i] >> 4];
456                 hash[i * 2 + 1] = hex[md->md_hash[i] & 0x0f];
457         }
458         printf("  MD5 hash: %s\n", hash);
459 }
460 #endif  /* !_G_RAID3_H_ */