source: mainline/uspace/srv/bd/hr/metadata/foreign/softraid/hr_softraid.c

Last change on this file was b127da2f, checked in by Miroslav Cimerman <mc@…>, 3 months ago

hr: careful assembly

  • Property mode set to 100644
File size: 19.1 KB
Line 
1/*
2 * Copyright (c) 2025 Miroslav Cimerman
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup hr
30 * @{
31 */
32/**
33 * @file
34 */
35
36#include <adt/list.h>
37#include <block.h>
38#include <byteorder.h>
39#include <errno.h>
40#include <inttypes.h>
41#include <io/log.h>
42#include <loc.h>
43#include <mem.h>
44#include <uuid.h>
45#include <stdlib.h>
46#include <stdio.h>
47#include <str.h>
48#include <types/uuid.h>
49
50#include "../../../io.h"
51#include "../../../util.h"
52#include "../../../var.h"
53
54#include "softraidvar.h"
55
56/* not exposed */
57static void *meta_softraid_alloc_struct(void);
58static void meta_softraid_encode(void *, void *);
59static errno_t meta_softraid_decode(const void *, void *);
60static errno_t meta_softraid_get_block(service_id_t, void **);
61static errno_t meta_softraid_write_block(service_id_t, const void *);
62
63static errno_t meta_softraid_probe(service_id_t, void **);
64static errno_t meta_softraid_init_vol2meta(hr_volume_t *);
65static errno_t meta_softraid_init_meta2vol(const list_t *, hr_volume_t *);
66static errno_t meta_softraid_erase_block(service_id_t);
67static bool meta_softraid_compare_uuids(const void *, const void *);
68static void meta_softraid_inc_counter(hr_volume_t *);
69static errno_t meta_softraid_save(hr_volume_t *, bool);
70static errno_t meta_softraid_save_ext(hr_volume_t *, size_t, bool);
71static const char *meta_softraid_get_devname(const void *);
72static hr_level_t meta_softraid_get_level(const void *);
73static uint64_t meta_softraid_get_data_offset(void);
74static size_t meta_softraid_get_size(void);
75static uint8_t meta_softraid_get_flags(void);
76static hr_metadata_type_t meta_softraid_get_type(void);
77static void meta_softraid_dump(const void *);
78
79hr_superblock_ops_t metadata_softraid_ops = {
80 .probe = meta_softraid_probe,
81 .init_vol2meta = meta_softraid_init_vol2meta,
82 .init_meta2vol = meta_softraid_init_meta2vol,
83 .erase_block = meta_softraid_erase_block,
84 .compare_uuids = meta_softraid_compare_uuids,
85 .inc_counter = meta_softraid_inc_counter,
86 .save = meta_softraid_save,
87 .save_ext = meta_softraid_save_ext,
88 .get_devname = meta_softraid_get_devname,
89 .get_level = meta_softraid_get_level,
90 .get_data_offset = meta_softraid_get_data_offset,
91 .get_size = meta_softraid_get_size,
92 .get_flags = meta_softraid_get_flags,
93 .get_type = meta_softraid_get_type,
94 .dump = meta_softraid_dump
95};
96
97static errno_t meta_softraid_probe(service_id_t svc_id, void **rmd)
98{
99 errno_t rc;
100 void *meta_block;
101
102 void *metadata_struct = meta_softraid_alloc_struct();
103 if (metadata_struct == NULL)
104 return ENOMEM;
105
106 rc = meta_softraid_get_block(svc_id, &meta_block);
107 if (rc != EOK)
108 goto error;
109
110 rc = meta_softraid_decode(meta_block, metadata_struct);
111
112 free(meta_block);
113
114 if (rc != EOK)
115 goto error;
116
117 *rmd = metadata_struct;
118 return EOK;
119
120error:
121 free(metadata_struct);
122 return rc;
123}
124
125static errno_t meta_softraid_init_vol2meta(hr_volume_t *vol)
126{
127 (void)vol;
128
129 return ENOTSUP;
130}
131
132static errno_t meta_softraid_init_meta2vol(const list_t *list, hr_volume_t *vol)
133{
134 HR_DEBUG("%s()", __func__);
135
136 errno_t rc = EOK;
137
138 struct sr_metadata *main_meta = NULL;
139 uint64_t max_counter_val = 0;
140
141 list_foreach(*list, link, struct dev_list_member, iter) {
142 struct sr_metadata *iter_meta = iter->md;
143
144 if (iter_meta->ssd_ondisk >= max_counter_val) {
145 max_counter_val = iter_meta->ssd_ondisk;
146 main_meta = iter_meta;
147 }
148 }
149
150 assert(main_meta != NULL);
151
152 vol->bsize = main_meta->ssdi.ssd_secsize;
153
154 vol->data_blkno = main_meta->ssdi.ssd_size;
155
156 /* get coerced size from some (first) chunk metadata */
157 struct sr_meta_chunk *mc = (struct sr_meta_chunk *)(main_meta + 1);
158 vol->truncated_blkno = mc->scmi.scm_coerced_size;
159
160 vol->data_offset = main_meta->ssd_data_blkno;
161
162 if (main_meta->ssdi.ssd_chunk_no > HR_MAX_EXTENTS) {
163 HR_DEBUG("Assembled volume has %u extents (max = %u)",
164 (unsigned)main_meta->ssdi.ssd_chunk_no,
165 HR_MAX_EXTENTS);
166 rc = EINVAL;
167 goto error;
168 }
169
170 vol->extent_no = main_meta->ssdi.ssd_chunk_no;
171
172 if (main_meta->ssdi.ssd_level == 5)
173 vol->layout = HR_LAYOUT_RAID5_NR;
174 else
175 vol->layout = HR_LAYOUT_NONE;
176
177 vol->strip_size = main_meta->ssdi.ssd_strip_size;
178
179 vol->in_mem_md = calloc(1, SR_META_SIZE * DEV_BSIZE);
180 if (vol->in_mem_md == NULL)
181 return ENOMEM;
182 memcpy(vol->in_mem_md, main_meta, SR_META_SIZE * DEV_BSIZE);
183
184 bool rebuild_set = false;
185 list_foreach(*list, link, struct dev_list_member, iter) {
186 struct sr_metadata *iter_meta = iter->md;
187
188 uint8_t index = iter_meta->ssdi.ssd_chunk_id;
189
190 vol->extents[index].svc_id = iter->svc_id;
191
192 struct sr_meta_chunk *mc =
193 ((struct sr_meta_chunk *)(main_meta + 1)) + index;
194
195 bool invalidate = false;
196 bool rebuild_this_ext = false;
197
198 if (iter_meta->ssd_meta_flags & SR_META_DIRTY)
199 invalidate = true;
200 if (iter_meta->ssd_ondisk != max_counter_val)
201 invalidate = true;
202
203 if (mc->scm_status == BIOC_SDREBUILD && !invalidate) {
204 if (rebuild_set) {
205 HR_DEBUG("only 1 rebuilt extent allowed");
206 rc = EINVAL;
207 goto error;
208 }
209 rebuild_set = true;
210 rebuild_this_ext = true;
211 vol->rebuild_blk = iter_meta->ssd_rebuild;
212 }
213
214 if (!rebuild_this_ext && !invalidate)
215 vol->extents[index].state = HR_EXT_ONLINE;
216 else if (rebuild_this_ext && !invalidate)
217 vol->extents[index].state = HR_EXT_REBUILD;
218 else
219 vol->extents[index].state = HR_EXT_INVALID;
220 }
221
222 for (size_t i = 0; i < vol->extent_no; i++) {
223 if (vol->extents[i].state == HR_EXT_NONE)
224 vol->extents[i].state = HR_EXT_MISSING;
225 }
226
227error:
228 return rc;
229}
230
231static errno_t meta_softraid_erase_block(service_id_t dev)
232{
233 HR_DEBUG("%s()", __func__);
234
235 (void)dev;
236
237 return ENOTSUP;
238}
239
240static bool meta_softraid_compare_uuids(const void *m1_v, const void *m2_v)
241{
242 const struct sr_metadata *m1 = m1_v;
243 const struct sr_metadata *m2 = m2_v;
244 if (memcmp(&m1->ssdi.ssd_uuid, &m2->ssdi.ssd_uuid, SR_UUID_MAX) == 0)
245 return true;
246
247 return false;
248}
249
250static void meta_softraid_inc_counter(hr_volume_t *vol)
251{
252 fibril_mutex_lock(&vol->md_lock);
253
254 struct sr_metadata *md = vol->in_mem_md;
255
256 md->ssd_ondisk++;
257
258 fibril_mutex_unlock(&vol->md_lock);
259}
260
261static errno_t meta_softraid_save(hr_volume_t *vol, bool with_state_callback)
262{
263 HR_DEBUG("%s()", __func__);
264
265 fibril_rwlock_read_lock(&vol->extents_lock);
266
267 for (size_t i = 0; i < vol->extent_no; i++)
268 meta_softraid_save_ext(vol, i, with_state_callback);
269
270 fibril_rwlock_read_unlock(&vol->extents_lock);
271
272 return EOK;
273}
274
275static errno_t meta_softraid_save_ext(hr_volume_t *vol, size_t ext_idx,
276 bool with_state_callback)
277{
278 HR_DEBUG("%s()", __func__);
279
280 assert(fibril_rwlock_is_locked(&vol->extents_lock));
281
282 void *md_block = hr_calloc_waitok(1, vol->bsize * SR_META_SIZE);
283
284 struct sr_metadata *md = vol->in_mem_md;
285 struct sr_meta_chunk *mc =
286 ((struct sr_meta_chunk *)(md + 1)) + ext_idx;
287
288 hr_extent_t *ext = &vol->extents[ext_idx];
289
290 fibril_rwlock_read_lock(&vol->states_lock);
291 hr_ext_state_t s = ext->state;
292 fibril_rwlock_read_unlock(&vol->states_lock);
293
294 if (s != HR_EXT_ONLINE && s != HR_EXT_REBUILD) {
295 return EINVAL;
296 }
297
298 fibril_mutex_lock(&vol->md_lock);
299
300 md->ssd_rebuild = vol->rebuild_blk;
301 md->ssdi.ssd_chunk_id = ext_idx;
302
303 if (s == HR_EXT_REBUILD)
304 mc->scm_status = BIOC_SDREBUILD;
305 else
306 mc->scm_status = BIOC_SDONLINE;
307
308 meta_softraid_encode(md, md_block);
309 errno_t rc = meta_softraid_write_block(ext->svc_id, md_block);
310 if (rc != EOK && with_state_callback)
311 vol->hr_ops.ext_state_cb(vol, ext_idx, rc);
312
313 fibril_mutex_unlock(&vol->md_lock);
314
315 if (with_state_callback)
316 vol->hr_ops.vol_state_eval(vol);
317
318 free(md_block);
319 return EOK;
320}
321
322static const char *meta_softraid_get_devname(const void *md_v)
323{
324 const struct sr_metadata *md = md_v;
325
326 return md->ssd_devname;
327}
328
329static hr_level_t meta_softraid_get_level(const void *md_v)
330{
331 const struct sr_metadata *md = md_v;
332
333 switch (md->ssdi.ssd_level) {
334 case 0:
335 return HR_LVL_0;
336 case 1:
337 return HR_LVL_1;
338 case 5:
339 return HR_LVL_5;
340 default:
341 return HR_LVL_UNKNOWN;
342 }
343}
344
345static uint64_t meta_softraid_get_data_offset(void)
346{
347 return SR_DATA_OFFSET;
348}
349
350static size_t meta_softraid_get_size(void)
351{
352 return SR_META_SIZE;
353}
354
355static uint8_t meta_softraid_get_flags(void)
356{
357 uint8_t flags = 0;
358
359 flags |= HR_METADATA_ALLOW_REBUILD;
360
361 return flags;
362}
363
364static hr_metadata_type_t meta_softraid_get_type(void)
365{
366 return HR_METADATA_SOFTRAID;
367}
368
369static void meta_softraid_dump(const void *md_v)
370{
371 HR_DEBUG("%s()", __func__);
372
373 const struct sr_metadata *md = md_v;
374
375 sr_meta_print(md);
376}
377
378static void *meta_softraid_alloc_struct(void)
379{
380 return calloc(1, SR_META_SIZE * DEV_BSIZE);
381}
382
383static void meta_softraid_encode(void *md_v, void *block)
384{
385 HR_DEBUG("%s()", __func__);
386
387 errno_t rc = EOK;
388 struct sr_metadata *md = md_v;
389 uint8_t md5_hash[16];
390
391 struct sr_metadata *scratch_md =
392 hr_calloc_waitok(1, SR_META_SIZE * DEV_BSIZE);
393
394 scratch_md->ssdi.ssd_magic = host2uint64_t_le(md->ssdi.ssd_magic);
395 scratch_md->ssdi.ssd_version = host2uint32_t_le(md->ssdi.ssd_version);
396 scratch_md->ssdi.ssd_vol_flags =
397 host2uint32_t_le(md->ssdi.ssd_vol_flags);
398 memcpy(&scratch_md->ssdi.ssd_uuid, &md->ssdi.ssd_uuid, SR_UUID_MAX);
399 scratch_md->ssdi.ssd_chunk_no =
400 host2uint32_t_le(md->ssdi.ssd_chunk_no);
401 scratch_md->ssdi.ssd_chunk_id =
402 host2uint32_t_le(md->ssdi.ssd_chunk_id);
403 scratch_md->ssdi.ssd_opt_no = host2uint32_t_le(md->ssdi.ssd_opt_no);
404 scratch_md->ssdi.ssd_secsize = host2uint32_t_le(md->ssdi.ssd_secsize);
405 scratch_md->ssdi.ssd_volid = host2uint32_t_le(md->ssdi.ssd_volid);
406 scratch_md->ssdi.ssd_level = host2uint32_t_le(md->ssdi.ssd_level);
407 scratch_md->ssdi.ssd_size = host2int64_t_le(md->ssdi.ssd_size);
408 memcpy(scratch_md->ssdi.ssd_vendor, md->ssdi.ssd_vendor, 8);
409 memcpy(scratch_md->ssdi.ssd_product, md->ssdi.ssd_product, 16);
410 memcpy(scratch_md->ssdi.ssd_revision, md->ssdi.ssd_revision, 4);
411 scratch_md->ssdi.ssd_strip_size =
412 host2uint32_t_le(md->ssdi.ssd_strip_size);
413 rc = create_hash((const uint8_t *)&scratch_md->ssdi,
414 sizeof(struct sr_meta_invariant), md5_hash, HASH_MD5);
415 assert(rc == EOK);
416 memcpy(scratch_md->ssd_checksum, md5_hash, MD5_DIGEST_LENGTH);
417
418 memcpy(scratch_md->ssd_devname, md->ssd_devname, 32);
419
420 scratch_md->ssd_meta_flags = host2uint32_t_le(md->ssd_meta_flags);
421 scratch_md->ssd_data_blkno = host2uint32_t_le(md->ssd_data_blkno);
422 scratch_md->ssd_ondisk = host2uint64_t_le(md->ssd_ondisk);
423 scratch_md->ssd_rebuild = host2int64_t_le(md->ssd_rebuild);
424
425 struct sr_meta_chunk *scratch_mc =
426 (struct sr_meta_chunk *)(scratch_md + 1);
427 struct sr_meta_chunk *mc = (struct sr_meta_chunk *)(md + 1);
428 for (size_t i = 0; i < md->ssdi.ssd_chunk_no; i++, mc++, scratch_mc++) {
429 scratch_mc->scmi.scm_volid =
430 host2uint32_t_le(mc->scmi.scm_volid);
431 scratch_mc->scmi.scm_chunk_id =
432 host2uint32_t_le(mc->scmi.scm_chunk_id);
433 memcpy(scratch_mc->scmi.scm_devname, mc->scmi.scm_devname, 32);
434 scratch_mc->scmi.scm_size = host2int64_t_le(mc->scmi.scm_size);
435 scratch_mc->scmi.scm_coerced_size =
436 host2int64_t_le(mc->scmi.scm_coerced_size);
437 memcpy(&scratch_mc->scmi.scm_uuid, &mc->scmi.scm_uuid,
438 SR_UUID_MAX);
439
440 rc = create_hash((const uint8_t *)&scratch_mc->scmi,
441 sizeof(struct sr_meta_chunk_invariant), md5_hash, HASH_MD5);
442 assert(rc == EOK);
443
444 memcpy(scratch_mc->scm_checksum, md5_hash,
445 MD5_DIGEST_LENGTH);
446 scratch_mc->scm_status = host2uint32_t_le(mc->scm_status);
447 }
448
449 struct sr_meta_opt_hdr *scratch_om =
450 (struct sr_meta_opt_hdr *)((u_int8_t *)(scratch_md + 1) +
451 sizeof(struct sr_meta_chunk) * md->ssdi.ssd_chunk_no);
452 struct sr_meta_opt_hdr *om =
453 (struct sr_meta_opt_hdr *)((u_int8_t *)(md + 1) +
454 sizeof(struct sr_meta_chunk) * md->ssdi.ssd_chunk_no);
455 for (size_t i = 0; i < md->ssdi.ssd_opt_no; i++) {
456 scratch_om->som_type = host2uint32_t_le(om->som_type);
457 scratch_om->som_length = host2uint32_t_le(om->som_length);
458 memcpy(scratch_om->som_checksum, om->som_checksum,
459 MD5_DIGEST_LENGTH);
460
461 /*
462 * No need to do checksum, we don't support optional headers.
463 * Despite this, still load it the headers.
464 */
465
466 om = (struct sr_meta_opt_hdr *)((void *)om +
467 om->som_length);
468 scratch_om = (struct sr_meta_opt_hdr *)((void *)scratch_om +
469 om->som_length);
470 }
471
472 memcpy(block, scratch_md, meta_softraid_get_size() * 512);
473
474 free(scratch_md);
475}
476
477static errno_t meta_softraid_decode(const void *block, void *md_v)
478{
479 HR_DEBUG("%s()", __func__);
480
481 errno_t rc = EOK;
482 struct sr_metadata *md = md_v;
483 uint8_t md5_hash[16];
484
485 struct sr_metadata *scratch_md = meta_softraid_alloc_struct();
486 if (scratch_md == NULL)
487 return ENOMEM;
488
489 memcpy(scratch_md, block, meta_softraid_get_size() * 512);
490
491 md->ssdi.ssd_magic =
492 uint64_t_le2host(scratch_md->ssdi.ssd_magic);
493 if (md->ssdi.ssd_magic != SR_MAGIC) {
494 rc = EINVAL;
495 goto error;
496 }
497 md->ssdi.ssd_version = uint32_t_le2host(scratch_md->ssdi.ssd_version);
498 if (md->ssdi.ssd_version != SR_META_VERSION) {
499 HR_DEBUG("unsupported metadata version\n");
500 rc = EINVAL;
501 goto error;
502 }
503 md->ssdi.ssd_vol_flags =
504 uint32_t_le2host(scratch_md->ssdi.ssd_vol_flags);
505 memcpy(&md->ssdi.ssd_uuid, &scratch_md->ssdi.ssd_uuid, SR_UUID_MAX);
506
507 md->ssdi.ssd_chunk_no =
508 uint32_t_le2host(scratch_md->ssdi.ssd_chunk_no);
509 md->ssdi.ssd_chunk_id =
510 uint32_t_le2host(scratch_md->ssdi.ssd_chunk_id);
511
512 md->ssdi.ssd_opt_no = uint32_t_le2host(scratch_md->ssdi.ssd_opt_no);
513 if (md->ssdi.ssd_opt_no > 0) {
514 HR_DEBUG("unsupported optional metadata\n");
515 rc = EINVAL;
516 goto error;
517 }
518 md->ssdi.ssd_secsize = uint32_t_le2host(scratch_md->ssdi.ssd_secsize);
519 if (md->ssdi.ssd_secsize != DEV_BSIZE) {
520 HR_DEBUG("unsupported sector size\n");
521 rc = EINVAL;
522 goto error;
523 }
524
525 md->ssdi.ssd_volid = uint32_t_le2host(scratch_md->ssdi.ssd_volid);
526 md->ssdi.ssd_level = uint32_t_le2host(scratch_md->ssdi.ssd_level);
527 md->ssdi.ssd_size = int64_t_le2host(scratch_md->ssdi.ssd_size);
528 memcpy(md->ssdi.ssd_vendor, scratch_md->ssdi.ssd_vendor, 8);
529 memcpy(md->ssdi.ssd_product, scratch_md->ssdi.ssd_product, 16);
530 memcpy(md->ssdi.ssd_revision, scratch_md->ssdi.ssd_revision, 4);
531 md->ssdi.ssd_strip_size =
532 uint32_t_le2host(scratch_md->ssdi.ssd_strip_size);
533
534 rc = create_hash((const uint8_t *)&scratch_md->ssdi,
535 sizeof(struct sr_meta_invariant), md5_hash, HASH_MD5);
536 assert(rc == EOK);
537 if (memcmp(md5_hash, scratch_md->ssd_checksum, 16) != 0) {
538 HR_DEBUG("ssd_checksum invalid\n");
539 rc = EINVAL;
540 goto error;
541 }
542
543 memcpy(md->ssd_checksum, scratch_md->ssd_checksum, MD5_DIGEST_LENGTH);
544
545 memcpy(md->ssd_devname, scratch_md->ssd_devname, 32);
546 md->ssd_meta_flags = uint32_t_le2host(scratch_md->ssd_meta_flags);
547 md->ssd_data_blkno = uint32_t_le2host(scratch_md->ssd_data_blkno);
548 md->ssd_ondisk = uint64_t_le2host(scratch_md->ssd_ondisk);
549 md->ssd_rebuild = int64_t_le2host(scratch_md->ssd_rebuild);
550
551 struct sr_meta_chunk *scratch_mc =
552 (struct sr_meta_chunk *)(scratch_md + 1);
553 struct sr_meta_chunk *mc = (struct sr_meta_chunk *)(md + 1);
554 for (size_t i = 0; i < md->ssdi.ssd_chunk_no; i++, mc++, scratch_mc++) {
555 mc->scmi.scm_volid =
556 uint32_t_le2host(scratch_mc->scmi.scm_volid);
557 mc->scmi.scm_chunk_id =
558 uint32_t_le2host(scratch_mc->scmi.scm_chunk_id);
559 memcpy(mc->scmi.scm_devname, scratch_mc->scmi.scm_devname, 32);
560 mc->scmi.scm_size = int64_t_le2host(scratch_mc->scmi.scm_size);
561 mc->scmi.scm_coerced_size =
562 int64_t_le2host(scratch_mc->scmi.scm_coerced_size);
563 memcpy(&mc->scmi.scm_uuid, &scratch_mc->scmi.scm_uuid,
564 SR_UUID_MAX);
565
566 memcpy(mc->scm_checksum, scratch_mc->scm_checksum,
567 MD5_DIGEST_LENGTH);
568 mc->scm_status = uint32_t_le2host(scratch_mc->scm_status);
569
570 /*
571 * This commented piece of code found a bug in
572 * OpenBSD softraid chunk metadata initialization,
573 * fix has been proposed [1], if it is fixed, feel free
574 * to uncomment, although it will work only on new
575 * volumes.
576 *
577 * [1]: https://marc.info/?l=openbsd-tech&m=174535579711235&w=2
578 */
579 /*
580 * rc = create_hash((const uint8_t *)&scratch_mc->scmi,
581 * sizeof(struct sr_meta_chunk_invariant), md5_hash, HASH_MD5);
582 * assert(rc == EOK);
583 * if (memcmp(md5_hash, mc->scm_checksum, 16) != 0) {
584 * HR_DEBUG("chunk %zu, scm_checksum invalid\n", i);
585 * rc = EINVAL;
586 * goto error;
587 * }
588 */
589 }
590
591 struct sr_meta_opt_hdr *scratch_om =
592 (struct sr_meta_opt_hdr *)((u_int8_t *)(scratch_md + 1) +
593 sizeof(struct sr_meta_chunk) * md->ssdi.ssd_chunk_no);
594 struct sr_meta_opt_hdr *om =
595 (struct sr_meta_opt_hdr *)((u_int8_t *)(md + 1) +
596 sizeof(struct sr_meta_chunk) * md->ssdi.ssd_chunk_no);
597 for (size_t i = 0; i < md->ssdi.ssd_opt_no; i++) {
598 om->som_type = uint32_t_le2host(scratch_om->som_type);
599 om->som_length = uint32_t_le2host(scratch_om->som_length);
600 memcpy(om->som_checksum, scratch_om->som_checksum,
601 MD5_DIGEST_LENGTH);
602
603 /*
604 * No need to do checksum, we don't support optional headers.
605 * Despite this, still load it the headers.
606 */
607
608 om = (struct sr_meta_opt_hdr *)((void *)om +
609 om->som_length);
610 scratch_om = (struct sr_meta_opt_hdr *)((void *)scratch_om +
611 om->som_length);
612 }
613
614error:
615 free(scratch_md);
616
617 return rc;
618}
619
620static errno_t meta_softraid_get_block(service_id_t dev, void **rblock)
621{
622 HR_DEBUG("%s()", __func__);
623
624 errno_t rc;
625 uint64_t blkno;
626 size_t bsize;
627 void *block;
628
629 if (rblock == NULL)
630 return EINVAL;
631
632 rc = block_get_bsize(dev, &bsize);
633 if (rc != EOK)
634 return rc;
635
636 if (bsize != DEV_BSIZE)
637 return EINVAL;
638
639 rc = block_get_nblocks(dev, &blkno);
640 if (rc != EOK)
641 return rc;
642
643 if (blkno < SR_META_OFFSET + SR_META_SIZE)
644 return EINVAL;
645
646 block = malloc(bsize * SR_META_SIZE);
647 if (block == NULL)
648 return ENOMEM;
649
650 rc = hr_read_direct(dev, SR_META_OFFSET, SR_META_SIZE, block);
651 if (rc != EOK) {
652 free(block);
653 return rc;
654 }
655
656 *rblock = block;
657 return EOK;
658}
659
660static errno_t meta_softraid_write_block(service_id_t dev, const void *block)
661{
662 HR_DEBUG("%s()", __func__);
663
664 errno_t rc;
665 uint64_t blkno;
666 size_t bsize;
667
668 rc = block_get_bsize(dev, &bsize);
669 if (rc != EOK)
670 return rc;
671
672 if (bsize != 512)
673 return EINVAL;
674
675 rc = block_get_nblocks(dev, &blkno);
676 if (rc != EOK)
677 return rc;
678
679 if (blkno < SR_META_OFFSET + SR_META_SIZE)
680 return EINVAL;
681
682 rc = hr_write_direct(dev, SR_META_OFFSET, SR_META_SIZE, block);
683
684 return rc;
685}
686
687/** @}
688 */
Note: See TracBrowser for help on using the repository browser.