source: mainline/uspace/srv/bd/hr/metadata/native.c@ 372a9fc

Last change on this file since 372a9fc was 6a854c5, checked in by Miroslav Cimerman <mc@…>, 7 months ago

srv/hr/metadata/native.c: no explicit arg casting

  • Property mode set to 100644
File size: 13.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 "../util.h"
51#include "../var.h"
52
53#include "native.h"
54
55static void *meta_native_alloc_struct(void);
56static errno_t meta_native_init_vol2meta(const hr_volume_t *, void *);
57static errno_t meta_native_init_meta2vol(const list_t *,
58 hr_volume_t *);
59static void meta_native_encode(const void *, void *);
60static void meta_native_decode(const void *, void *);
61static errno_t meta_native_get_block(service_id_t, void **);
62static errno_t meta_native_write_block(service_id_t, const void *);
63static bool meta_native_has_valid_magic(const void *);
64static bool meta_native_compare_uuids(const void *, const void *);
65static void meta_native_inc_counter(void *);
66static errno_t meta_native_save(hr_volume_t *, bool);
67static const char *meta_native_get_devname(const void *);
68static hr_level_t meta_native_get_level(const void *);
69static uint64_t meta_native_get_data_offset(void);
70static size_t meta_native_get_size(void);
71static uint8_t meta_native_get_flags(void);
72static metadata_type_t meta_native_get_type(void);
73static void meta_native_dump(const void *);
74
75hr_superblock_ops_t metadata_native_ops = {
76 .alloc_struct = meta_native_alloc_struct,
77 .init_vol2meta = meta_native_init_vol2meta,
78 .init_meta2vol = meta_native_init_meta2vol,
79 .encode = meta_native_encode,
80 .decode = meta_native_decode,
81 .get_block = meta_native_get_block,
82 .write_block = meta_native_write_block,
83 .has_valid_magic = meta_native_has_valid_magic,
84 .compare_uuids = meta_native_compare_uuids,
85 .inc_counter = meta_native_inc_counter,
86 .save = meta_native_save,
87 .get_devname = meta_native_get_devname,
88 .get_level = meta_native_get_level,
89 .get_data_offset = meta_native_get_data_offset,
90 .get_size = meta_native_get_size,
91 .get_flags = meta_native_get_flags,
92 .get_type = meta_native_get_type,
93 .dump = meta_native_dump
94};
95
96static void *meta_native_alloc_struct(void)
97{
98 return calloc(1, sizeof(hr_metadata_t));
99}
100
101static errno_t meta_native_init_vol2meta(const hr_volume_t *vol, void *md_v)
102{
103 HR_DEBUG("%s()", __func__);
104
105 hr_metadata_t *md = md_v;
106
107 str_cpy(md->magic, HR_NATIVE_MAGIC_SIZE, HR_NATIVE_MAGIC_STR);
108
109 md->version = HR_NATIVE_METADATA_VERSION;
110
111 md->counter = 0;
112
113 uuid_t uuid;
114 /* rndgen */
115 fibril_usleep(1000);
116 errno_t rc = uuid_generate(&uuid);
117 if (rc != EOK)
118 return rc;
119
120 /* XXX: for now we just copy byte by byte as "encoding" */
121 memcpy(md->uuid, &uuid, HR_NATIVE_UUID_LEN);
122 /* uuid_encode(&uuid, metadata->uuid); */
123
124 md->nblocks = vol->nblocks;
125 md->data_blkno = vol->data_blkno;
126 md->truncated_blkno = vol->truncated_blkno;
127 md->data_offset = vol->data_offset;
128 md->extent_no = vol->extent_no;
129 md->level = vol->level;
130 md->layout = vol->layout;
131 md->strip_size = vol->strip_size;
132 md->bsize = vol->bsize;
133 memcpy(md->devname, vol->devname, HR_DEVNAME_LEN);
134
135 return EOK;
136}
137
138static errno_t meta_native_init_meta2vol(const list_t *list, hr_volume_t *vol)
139{
140 HR_DEBUG("%s()", __func__);
141
142 errno_t rc = EOK;
143
144 hr_metadata_t *main_meta = NULL;
145 size_t max_counter_val = 0;
146
147 list_foreach(*list, link, struct dev_list_member, iter) {
148 hr_metadata_t *iter_meta = (hr_metadata_t *)iter->md;
149 if (iter_meta->counter >= max_counter_val) {
150 max_counter_val = iter_meta->counter;
151 main_meta = iter_meta;
152 }
153 }
154
155 assert(main_meta != NULL);
156
157 vol->nblocks = main_meta->nblocks;
158 vol->data_blkno = main_meta->data_blkno;
159 vol->truncated_blkno = main_meta->truncated_blkno;
160 vol->data_offset = main_meta->data_offset;
161 vol->extent_no = main_meta->extent_no;
162 /* vol->level = main_meta->level; */
163 vol->layout = main_meta->layout;
164 vol->strip_size = main_meta->strip_size;
165 vol->bsize = main_meta->bsize;
166 /* memcpy(vol->devname, main_meta->devname, HR_DEVNAME_LEN); */
167 memcpy(vol->in_mem_md, main_meta, sizeof(hr_metadata_t));
168
169 list_foreach(*list, link, struct dev_list_member, iter) {
170 hr_metadata_t *iter_meta = (hr_metadata_t *)iter->md;
171
172 vol->extents[iter_meta->index].svc_id = iter->svc_id;
173
174 uint64_t blkno;
175 rc = block_get_nblocks(iter->svc_id, &blkno);
176 if (rc != EOK)
177 goto error;
178
179 vol->extents[iter_meta->index].blkno = blkno;
180
181 if (iter_meta->counter == max_counter_val)
182 vol->extents[iter_meta->index].status = HR_EXT_ONLINE;
183 else
184 vol->extents[iter_meta->index].status = HR_EXT_INVALID;
185 }
186
187 for (size_t i = 0; i < vol->extent_no; i++) {
188 if (vol->extents[i].status == HR_EXT_NONE)
189 vol->extents[i].status = HR_EXT_MISSING;
190 }
191
192error:
193 return rc;
194}
195
196static void meta_native_encode(const void *md_v, void *block)
197{
198 HR_DEBUG("%s()", __func__);
199
200 const hr_metadata_t *metadata = md_v;
201
202 /*
203 * Use scratch metadata for easier encoding without the need
204 * for manualy specifying offsets.
205 */
206 hr_metadata_t scratch_md;
207
208 memcpy(scratch_md.magic, metadata->magic, HR_NATIVE_MAGIC_SIZE);
209 memcpy(scratch_md.uuid, metadata->uuid, HR_NATIVE_UUID_LEN);
210 /* uuid_decode((uint8_t *)scratch_md.uuid, (uuid_t *)metadata->uuid); */
211
212 scratch_md.nblocks = host2uint64_t_le(metadata->nblocks);
213 scratch_md.data_blkno = host2uint64_t_le(metadata->data_blkno);
214 scratch_md.truncated_blkno = host2uint64_t_le(
215 metadata->truncated_blkno);
216 scratch_md.data_offset = host2uint64_t_le(metadata->data_offset);
217 scratch_md.counter = host2uint64_t_le(metadata->counter);
218 scratch_md.version = host2uint32_t_le(metadata->version);
219 scratch_md.extent_no = host2uint32_t_le(metadata->extent_no);
220 scratch_md.index = host2uint32_t_le(metadata->index);
221 scratch_md.level = host2uint32_t_le(metadata->level);
222 scratch_md.layout = host2uint32_t_le(metadata->layout);
223 scratch_md.strip_size = host2uint32_t_le(metadata->strip_size);
224 scratch_md.bsize = host2uint32_t_le(metadata->bsize);
225 memcpy(scratch_md.devname, metadata->devname, HR_DEVNAME_LEN);
226
227 memcpy(block, &scratch_md, sizeof(hr_metadata_t));
228}
229
230static void meta_native_decode(const void *block, void *md_v)
231{
232 HR_DEBUG("%s()", __func__);
233
234 hr_metadata_t *metadata = md_v;
235
236 /*
237 * Use scratch metadata for easier decoding without the need
238 * for manualy specifying offsets.
239 */
240 hr_metadata_t scratch_md;
241 memcpy(&scratch_md, block, sizeof(hr_metadata_t));
242
243 memcpy(metadata->magic, scratch_md.magic, HR_NATIVE_MAGIC_SIZE);
244 memcpy(metadata->uuid, scratch_md.uuid, HR_NATIVE_UUID_LEN);
245 /* uuid_decode((uint8_t *)scratch_md.uuid, (uuid_t *)metadata->uuid); */
246
247 metadata->nblocks = uint64_t_le2host(scratch_md.nblocks);
248 metadata->data_blkno = uint64_t_le2host(scratch_md.data_blkno);
249 metadata->truncated_blkno = uint64_t_le2host(
250 scratch_md.truncated_blkno);
251 metadata->data_offset = uint64_t_le2host(scratch_md.data_offset);
252 metadata->counter = uint64_t_le2host(scratch_md.counter);
253 metadata->version = uint32_t_le2host(scratch_md.version);
254 metadata->extent_no = uint32_t_le2host(scratch_md.extent_no);
255 metadata->index = uint32_t_le2host(scratch_md.index);
256 metadata->level = uint32_t_le2host(scratch_md.level);
257 metadata->layout = uint32_t_le2host(scratch_md.layout);
258 metadata->strip_size = uint32_t_le2host(scratch_md.strip_size);
259 metadata->bsize = uint32_t_le2host(scratch_md.bsize);
260 memcpy(metadata->devname, scratch_md.devname, HR_DEVNAME_LEN);
261}
262
263static errno_t meta_native_get_block(service_id_t dev, void **rblock)
264{
265 HR_DEBUG("%s()", __func__);
266
267 errno_t rc;
268 uint64_t blkno;
269 size_t bsize;
270 void *block;
271
272 if (rblock == NULL)
273 return EINVAL;
274
275 rc = block_get_bsize(dev, &bsize);
276 if (rc != EOK)
277 return rc;
278
279 if (bsize < sizeof(hr_metadata_t))
280 return EINVAL;
281
282 rc = block_get_nblocks(dev, &blkno);
283 if (rc != EOK)
284 return rc;
285
286 if (blkno < HR_NATIVE_META_SIZE)
287 return EINVAL;
288
289 block = malloc(bsize);
290 if (block == NULL)
291 return ENOMEM;
292
293 rc = block_read_direct(dev, blkno - 1, HR_NATIVE_META_SIZE, block);
294 /*
295 * XXX: here maybe call vol status event or the state callback...
296 *
297 * but need to pass vol pointer
298 */
299 if (rc != EOK) {
300 free(block);
301 return rc;
302 }
303
304 *rblock = block;
305 return EOK;
306}
307
308static errno_t meta_native_write_block(service_id_t dev, const void *block)
309{
310 HR_DEBUG("%s()", __func__);
311
312 errno_t rc;
313 uint64_t blkno;
314 size_t bsize;
315
316 rc = block_get_bsize(dev, &bsize);
317 if (rc != EOK)
318 return rc;
319
320 if (bsize < sizeof(hr_metadata_t))
321 return EINVAL;
322
323 rc = block_get_nblocks(dev, &blkno);
324 if (rc != EOK)
325 return rc;
326
327 if (blkno < HR_NATIVE_META_SIZE)
328 return EINVAL;
329
330 rc = block_write_direct(dev, blkno - 1, HR_NATIVE_META_SIZE, block);
331
332 return rc;
333}
334
335static bool meta_native_has_valid_magic(const void *md_v)
336{
337 HR_DEBUG("%s()", __func__);
338
339 const hr_metadata_t *md = md_v;
340
341 if (str_lcmp(md->magic, HR_NATIVE_MAGIC_STR, HR_NATIVE_MAGIC_SIZE) != 0)
342 return false;
343
344 return true;
345}
346
347static bool meta_native_compare_uuids(const void *m1p, const void *m2p)
348{
349 const hr_metadata_t *m1 = m1p;
350 const hr_metadata_t *m2 = m2p;
351 if (memcmp(m1->uuid, m2->uuid, HR_NATIVE_UUID_LEN) == 0)
352 return true;
353
354 return false;
355}
356
357static void meta_native_inc_counter(void *md_v)
358{
359 hr_metadata_t *md = md_v;
360
361 md->counter++;
362}
363
364/*
365 * XXX: finish this fcn documentation
366 *
367 * Returns ENOMEM else EOK
368 */
369static errno_t meta_native_save(hr_volume_t *vol, bool with_state_callback)
370{
371 HR_DEBUG("%s()", __func__);
372
373 errno_t rc = EOK;
374
375 void *md_block = calloc(1, vol->bsize);
376 if (md_block == NULL)
377 return ENOMEM;
378
379 hr_metadata_t *md = (hr_metadata_t *)vol->in_mem_md;
380
381 fibril_rwlock_read_lock(&vol->extents_lock);
382
383 fibril_mutex_lock(&vol->md_lock);
384
385 for (size_t i = 0; i < vol->extent_no; i++) {
386 hr_extent_t *ext = &vol->extents[i];
387
388 fibril_rwlock_read_lock(&vol->states_lock);
389
390 /* TODO: special case for REBUILD */
391 if (ext->status != HR_EXT_ONLINE)
392 continue;
393
394 fibril_rwlock_read_unlock(&vol->states_lock);
395
396 md->index = i;
397 meta_native_encode(md, md_block);
398 rc = meta_native_write_block(ext->svc_id, md_block);
399 if (with_state_callback && rc != EOK)
400 vol->state_callback(vol, i, rc);
401 }
402
403 fibril_mutex_unlock(&vol->md_lock);
404
405 fibril_rwlock_read_unlock(&vol->extents_lock);
406
407 if (with_state_callback)
408 vol->hr_ops.status_event(vol);
409
410 free(md_block);
411 return EOK;
412}
413
414static const char *meta_native_get_devname(const void *md_v)
415{
416 const hr_metadata_t *md = md_v;
417
418 return md->devname;
419}
420
421static hr_level_t meta_native_get_level(const void *md_v)
422{
423 const hr_metadata_t *md = md_v;
424
425 return md->level;
426}
427
428static uint64_t meta_native_get_data_offset(void)
429{
430 return HR_NATIVE_DATA_OFF;
431}
432
433static size_t meta_native_get_size(void)
434{
435 return HR_NATIVE_META_SIZE;
436}
437
438static uint8_t meta_native_get_flags(void)
439{
440 uint8_t flags = 0;
441
442 flags |= HR_METADATA_HOTSPARE_SUPPORT;
443
444 return flags;
445}
446
447static metadata_type_t meta_native_get_type(void)
448{
449 return HR_METADATA_NATIVE;
450}
451
452static void meta_native_dump(const void *md_v)
453{
454 HR_DEBUG("%s()", __func__);
455
456 const hr_metadata_t *metadata = md_v;
457
458 printf("\tmagic: %s\n", metadata->magic);
459 printf("\tUUID: ");
460 for (size_t i = 0; i < HR_NATIVE_UUID_LEN; ++i) {
461 printf("%.2X", metadata->uuid[i]);
462 if (i + 1 < HR_NATIVE_UUID_LEN)
463 printf(" ");
464 }
465 printf("\n");
466 printf("\tnblocks: %" PRIu64 "\n", metadata->nblocks);
467 printf("\tdata_blkno: %" PRIu64 "\n", metadata->data_blkno);
468 printf("\ttruncated_blkno: %" PRIu64 "\n", metadata->truncated_blkno);
469 printf("\tdata_offset: %" PRIu64 "\n", metadata->data_offset);
470 printf("\tcounter: %" PRIu64 "\n", metadata->counter);
471 printf("\tversion: %" PRIu32 "\n", metadata->version);
472 printf("\textent_no: %" PRIu32 "\n", metadata->extent_no);
473 printf("\tindex: %" PRIu32 "\n", metadata->index);
474 printf("\tlevel: %" PRIu32 "\n", metadata->level);
475 printf("\tlayout: %" PRIu32 "\n", metadata->layout);
476 printf("\tstrip_size: %" PRIu32 "\n", metadata->strip_size);
477 printf("\tbsize: %" PRIu32 "\n", metadata->bsize);
478 printf("\tdevname: %s\n", metadata->devname);
479}
480
481/** @}
482 */
Note: See TracBrowser for help on using the repository browser.