source: mainline/uspace/srv/bd/hr/superblock.c@ 7e8c0e7

Last change on this file since 7e8c0e7 was 7e8c0e7, checked in by Miroslav Cimerman <mc@…>, 4 months ago

hr: superblock.c: remove UUID generation for each extent

  • Property mode set to 100644
File size: 10.0 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 <block.h>
37#include <byteorder.h>
38#include <errno.h>
39#include <io/log.h>
40#include <loc.h>
41#include <mem.h>
42#include <uuid.h>
43#include <stdlib.h>
44#include <stdio.h>
45#include <str.h>
46#include <types/uuid.h>
47
48#include "superblock.h"
49#include "util.h"
50#include "var.h"
51
52static errno_t read_metadata(service_id_t, hr_metadata_t *);
53static errno_t hr_fill_meta_from_vol(hr_volume_t *, hr_metadata_t *);
54
55errno_t hr_write_meta_to_vol(hr_volume_t *vol)
56{
57 HR_DEBUG("%s()", __func__);
58
59 errno_t rc;
60 size_t i;
61 hr_metadata_t *metadata;
62 uuid_t uuid;
63
64 metadata = calloc(1, HR_META_SIZE * vol->bsize);
65 if (metadata == NULL)
66 return ENOMEM;
67
68 rc = hr_fill_meta_from_vol(vol, metadata);
69 if (rc != EOK)
70 goto error;
71
72 /* rndgen */
73 fibril_usleep(1000);
74 rc = uuid_generate(&uuid);
75 if (rc != EOK)
76 goto error;
77
78 /* XXX: for now we just copy byte by byte as "encoding" */
79 memcpy(metadata->uuid, &uuid, HR_UUID_LEN);
80 /* uuid_encode(&uuid, metadata->uuid); */
81
82 for (i = 0; i < vol->extent_no; i++) {
83 metadata->index = host2uint32_t_le(i);
84
85 rc = block_write_direct(vol->extents[i].svc_id, HR_META_OFF,
86 HR_META_SIZE, metadata);
87 if (rc != EOK)
88 goto error;
89
90 }
91
92 memcpy(vol->in_mem_md, metadata, sizeof(hr_metadata_t));
93error:
94 free(metadata);
95 return rc;
96}
97
98errno_t hr_write_meta_to_ext(hr_volume_t *vol, size_t ext)
99{
100 HR_DEBUG("%s()", __func__);
101
102 errno_t rc;
103 hr_metadata_t *metadata;
104
105 /* XXX: use scratchpad */
106 metadata = calloc(1, HR_META_SIZE * vol->bsize);
107 if (metadata == NULL)
108 return ENOMEM;
109
110 rc = hr_fill_meta_from_vol(vol, metadata);
111 if (rc != EOK)
112 goto error;
113
114 metadata->index = host2uint32_t_le(ext);
115
116 rc = block_write_direct(vol->extents[ext].svc_id, HR_META_OFF,
117 HR_META_SIZE, metadata);
118 if (rc != EOK)
119 goto error;
120
121error:
122 free(metadata);
123 return rc;
124}
125
126/*
127 * Fill metadata members from
128 * specified volume.
129 *
130 * Does not fill extent index and UUID.
131 */
132static errno_t hr_fill_meta_from_vol(hr_volume_t *vol, hr_metadata_t *metadata)
133{
134 HR_DEBUG("%s()", __func__);
135
136 size_t meta_blkno = HR_META_OFF + HR_META_SIZE;
137
138 if (vol->level != HR_LVL_1)
139 meta_blkno *= vol->extent_no;
140
141 if (vol->nblocks < meta_blkno) {
142 HR_ERROR("hr_fill_meta_from_vol(): volume \"%s\" does not "
143 " have enough space to store metada, aborting\n",
144 vol->devname);
145 return EINVAL;
146 } else if (vol->nblocks == meta_blkno) {
147 HR_ERROR("hr_fill_meta_from_vol(): volume \"%s\" would have "
148 "zero data blocks after writing metadata, aborting\n",
149 vol->devname);
150 return EINVAL;
151 }
152
153 /* XXX: use scratchpad */
154 str_cpy(metadata->magic, HR_MAGIC_SIZE, HR_MAGIC_STR);
155 metadata->nblocks = host2uint64_t_le(vol->nblocks);
156 metadata->data_blkno = host2uint64_t_le(vol->data_blkno);
157 metadata->truncated_blkno = host2uint64_t_le(vol->truncated_blkno);
158 metadata->data_offset = host2uint64_t_le(vol->data_offset);
159 metadata->counter = host2uint64_t_le(~(0UL)); /* XXX: unused */
160 metadata->version = host2uint32_t_le(~(0U)); /* XXX: unused */
161 metadata->extent_no = host2uint32_t_le(vol->extent_no);
162 /* index filled separately for each extent */
163 metadata->level = host2uint32_t_le(vol->level);
164 metadata->layout = host2uint32_t_le(vol->layout);
165 metadata->strip_size = host2uint32_t_le(vol->strip_size);
166 metadata->bsize = host2uint32_t_le(vol->bsize);
167 str_cpy(metadata->devname, HR_DEVNAME_LEN, vol->devname);
168
169 return EOK;
170}
171
172bool hr_valid_md_magic(hr_metadata_t *md)
173{
174 if (str_lcmp(md->magic, HR_MAGIC_STR, HR_MAGIC_SIZE) != 0)
175 return false;
176
177 return true;
178}
179
180errno_t hr_fill_vol_from_meta(hr_volume_t *vol)
181{
182 HR_DEBUG("%s()", __func__);
183
184 errno_t rc;
185 hr_metadata_t *metadata;
186
187 metadata = calloc(1, HR_META_SIZE * vol->bsize);
188 if (metadata == NULL)
189 return ENOMEM;
190
191 service_id_t assembly_svc_id_order[HR_MAX_EXTENTS] = { 0 };
192 for (size_t i = 0; i < vol->extent_no; i++)
193 assembly_svc_id_order[i] = vol->extents[i].svc_id;
194
195 size_t md_order_indices[HR_MAX_EXTENTS] = { 0 };
196 for (size_t i = 0; i < vol->extent_no; i++) {
197 if (assembly_svc_id_order[i] == 0) {
198 /* set invalid index */
199 md_order_indices[i] = vol->extent_no;
200 continue;
201 }
202 rc = read_metadata(assembly_svc_id_order[i], metadata);
203 if (rc != EOK)
204 goto end;
205 if (!hr_valid_md_magic(metadata))
206 goto end;
207 md_order_indices[i] = uint32_t_le2host(metadata->index);
208 }
209
210 for (size_t i = 0; i < vol->extent_no; i++) {
211 vol->extents[i].svc_id = 0;
212 vol->extents[i].status = HR_EXT_MISSING;
213 }
214
215 /* sort */
216 for (size_t i = 0; i < vol->extent_no; i++) {
217 for (size_t j = 0; j < vol->extent_no; j++) {
218 if (i == md_order_indices[j]) {
219 vol->extents[i].svc_id =
220 assembly_svc_id_order[j];
221 vol->extents[i].status = HR_EXT_ONLINE;
222 }
223 }
224 }
225
226 /*
227 * still assume metadata are in sync across extents
228 */
229
230 if (vol->extent_no != uint32_t_le2host(metadata->extent_no)) {
231 HR_ERROR("number of divices in array differ: specified %zu, "
232 "metadata states %u",
233 vol->extent_no, uint32_t_le2host(metadata->extent_no));
234 rc = EINVAL;
235 goto end;
236 }
237
238 /* TODO: handle version */
239 vol->level = uint32_t_le2host(metadata->level);
240 vol->layout = (uint8_t)uint32_t_le2host(metadata->layout);
241 vol->strip_size = uint32_t_le2host(metadata->strip_size);
242 vol->nblocks = uint64_t_le2host(metadata->nblocks);
243 vol->data_blkno = uint64_t_le2host(metadata->data_blkno);
244 vol->data_offset = uint64_t_le2host(metadata->data_offset);
245 vol->bsize = uint32_t_le2host(metadata->bsize);
246 vol->counter = uint64_t_le2host(0x00); /* unused */
247
248 if (str_cmp(metadata->devname, vol->devname) != 0) {
249 HR_WARN("devname on metadata (%s) and config (%s) differ, "
250 "using config", metadata->devname, vol->devname);
251 }
252end:
253 free(metadata);
254 return rc;
255}
256
257static errno_t read_metadata(service_id_t dev, hr_metadata_t *metadata)
258{
259 errno_t rc;
260 uint64_t nblocks;
261
262 rc = block_get_nblocks(dev, &nblocks);
263 if (rc != EOK)
264 return rc;
265
266 if (nblocks < HR_META_SIZE + HR_META_OFF)
267 return EINVAL;
268
269 rc = block_read_direct(dev, HR_META_OFF, HR_META_SIZE, metadata);
270 if (rc != EOK)
271 return rc;
272
273 return EOK;
274}
275
276errno_t hr_get_metadata_block(service_id_t dev, void **rblock)
277{
278 HR_DEBUG("%s()", __func__);
279 errno_t rc;
280 uint64_t blkno;
281 size_t bsize;
282 void *block;
283
284 rc = block_get_bsize(dev, &bsize);
285 if (rc != EOK)
286 return rc;
287
288 if (bsize < sizeof(hr_metadata_t))
289 return EINVAL;
290
291 rc = block_get_nblocks(dev, &blkno);
292 if (rc != EOK)
293 return rc;
294
295 if (blkno < HR_META_OFF + HR_META_SIZE)
296 return EINVAL;
297
298 block = malloc(bsize);
299 if (block == NULL)
300 return ENOMEM;
301
302 rc = block_read_direct(dev, HR_META_OFF, HR_META_SIZE, block);
303 if (rc != EOK) {
304 free(block);
305 return rc;
306 }
307
308 if (rblock == NULL) {
309 free(block);
310 return EINVAL;
311 }
312
313 *rblock = block;
314 return EOK;
315}
316
317void hr_decode_metadata_from_block(void *block, hr_metadata_t *metadata)
318{
319 /*
320 * Use scratch metadata for easier decoding without the need
321 * for manualy specifying offsets.
322 */
323 hr_metadata_t scratch_md;
324 memcpy(&scratch_md, block, sizeof(hr_metadata_t));
325
326 memcpy(metadata->magic, scratch_md.magic, HR_MAGIC_SIZE);
327 memcpy(metadata->uuid, scratch_md.uuid, HR_UUID_LEN);
328 metadata->nblocks = uint64_t_le2host(scratch_md.nblocks);
329 metadata->data_blkno = uint64_t_le2host(scratch_md.data_blkno);
330 metadata->truncated_blkno = uint64_t_le2host(
331 scratch_md.truncated_blkno);
332 metadata->data_offset = uint64_t_le2host(scratch_md.data_offset);
333 metadata->counter = uint64_t_le2host(scratch_md.counter);
334 metadata->version = uint32_t_le2host(scratch_md.version);
335 metadata->extent_no = uint32_t_le2host(scratch_md.extent_no);
336 metadata->index = uint32_t_le2host(scratch_md.index);
337 metadata->level = uint32_t_le2host(scratch_md.level);
338 metadata->layout = uint32_t_le2host(scratch_md.layout);
339 metadata->strip_size = uint32_t_le2host(scratch_md.strip_size);
340 metadata->bsize = uint64_t_le2host(scratch_md.bsize);
341 memcpy(metadata->devname, scratch_md.devname, HR_DEVNAME_LEN);
342}
343
344void hr_metadata_dump(hr_metadata_t *metadata)
345{
346 printf("\tmagic: %s\n", metadata->magic);
347 printf("\tUUID: ");
348 for (size_t i = 0; i < HR_UUID_LEN; ++i) {
349 printf("%.2X", metadata->uuid[i]);
350 if (i + 1 < HR_UUID_LEN)
351 printf(" ");
352 }
353 printf("\n");
354 printf("\tnblocks: %lu\n", metadata->nblocks);
355 printf("\tdata_blkno: %lu\n", metadata->data_blkno);
356 printf("\ttruncated_blkno: %lu\n", metadata->truncated_blkno);
357 printf("\tdata_offset: %lu\n", metadata->data_offset);
358 printf("\tcounter: %lu\n", metadata->counter);
359 printf("\tversion: %u\n", metadata->version);
360 printf("\textent_no: %u\n", metadata->extent_no);
361 printf("\tindex: %u\n", metadata->index);
362 printf("\tlevel: %u\n", metadata->level);
363 printf("\tlayout: %u\n", metadata->layout);
364 printf("\tstrip_size: %u\n", metadata->strip_size);
365 printf("\tdevname: %s\n", metadata->devname);
366}
367
368/** @}
369 */
Note: See TracBrowser for help on using the repository browser.