source: mainline/uspace/srv/bd/hr/metadata/native.c@ 5cb1631

Last change on this file since 5cb1631 was b883aa8, checked in by Miroslav Cimerman <mc@…>, 6 months ago

hr: move metadata_type_t to lib/hr for type printing

Also renames metadata_type_t → hr_metadata_type_t.

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