source: mainline/uspace/srv/bd/hr/metadata/native.c@ 40f56a4

Last change on this file since 40f56a4 was dd76b46, checked in by Miroslav Cimerman <mc@…>, 6 months ago

hr: metadata/native.c: use uint64_t for counter

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