source: mainline/uspace/srv/bd/hr/superblock.c@ 800d188

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

hr: metadata saving on stop

New bool argument for hr_metadata_save() to indicate if
we want callback too (on array stop we don't, so we won't
init a rebuild).

  • Property mode set to 100644
File size: 8.5 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 <inttypes.h>
40#include <io/log.h>
41#include <loc.h>
42#include <mem.h>
43#include <uuid.h>
44#include <stdlib.h>
45#include <stdio.h>
46#include <str.h>
47#include <types/uuid.h>
48
49#include "superblock.h"
50#include "util.h"
51#include "var.h"
52
53errno_t hr_metadata_init(hr_volume_t *vol, hr_metadata_t *md)
54{
55 HR_DEBUG("%s()", __func__);
56
57 str_cpy(md->magic, HR_MAGIC_SIZE, HR_MAGIC_STR);
58
59 md->version = HR_METADATA_VERSION;
60 vol->metadata_version = md->version;
61
62 md->counter = 0;
63
64 uuid_t uuid;
65 /* rndgen */
66 fibril_usleep(1000);
67 errno_t rc = uuid_generate(&uuid);
68 if (rc != EOK)
69 return rc;
70
71 /* XXX: for now we just copy byte by byte as "encoding" */
72 memcpy(md->uuid, &uuid, HR_UUID_LEN);
73 /* uuid_encode(&uuid, metadata->uuid); */
74
75 md->nblocks = vol->nblocks;
76 md->data_blkno = vol->data_blkno;
77 md->truncated_blkno = vol->truncated_blkno;
78 md->data_offset = vol->data_offset;
79 md->extent_no = vol->extent_no;
80 md->level = vol->level;
81 md->layout = vol->layout;
82 md->strip_size = vol->strip_size;
83 md->bsize = vol->bsize;
84 memcpy(md->devname, vol->devname, HR_DEVNAME_LEN);
85
86 return EOK;
87}
88
89/*
90 * XXX: finish this fcn documentation
91 *
92 * Returns ENOMEM else EOK
93 */
94errno_t hr_metadata_save(hr_volume_t *vol, bool with_state_callback)
95{
96 HR_DEBUG("%s()", __func__);
97
98 errno_t rc = EOK;
99
100 void *md_block = calloc(1, vol->bsize);
101 if (md_block == NULL)
102 return ENOMEM;
103
104 fibril_rwlock_read_lock(&vol->extents_lock);
105
106 fibril_mutex_lock(&vol->md_lock);
107
108 for (size_t i = 0; i < vol->extent_no; i++) {
109 hr_extent_t *ext = &vol->extents[i];
110
111 fibril_rwlock_read_lock(&vol->states_lock);
112
113 /* TODO: special case for REBUILD */
114 if (ext->status != HR_EXT_ONLINE)
115 continue;
116
117 fibril_rwlock_read_unlock(&vol->states_lock);
118
119 vol->in_mem_md->index = i;
120 hr_encode_metadata_to_block(vol->in_mem_md, md_block);
121 rc = hr_write_metadata_block(ext->svc_id, md_block);
122 if (with_state_callback && rc != EOK)
123 vol->state_callback(vol, i, rc);
124 }
125
126 fibril_mutex_unlock(&vol->md_lock);
127
128 fibril_rwlock_read_unlock(&vol->extents_lock);
129
130 if (with_state_callback)
131 vol->hr_ops.status_event(vol);
132
133 free(md_block);
134 return EOK;
135}
136
137bool hr_valid_md_magic(hr_metadata_t *md)
138{
139 HR_DEBUG("%s()", __func__);
140
141 if (str_lcmp(md->magic, HR_MAGIC_STR, HR_MAGIC_SIZE) != 0)
142 return false;
143
144 return true;
145}
146
147errno_t hr_write_metadata_block(service_id_t dev, const void *block)
148{
149 HR_DEBUG("%s()", __func__);
150
151 errno_t rc;
152 uint64_t blkno;
153 size_t bsize;
154
155 rc = block_get_bsize(dev, &bsize);
156 if (rc != EOK)
157 return rc;
158
159 if (bsize < sizeof(hr_metadata_t))
160 return EINVAL;
161
162 rc = block_get_nblocks(dev, &blkno);
163 if (rc != EOK)
164 return rc;
165
166 if (blkno < HR_META_SIZE)
167 return EINVAL;
168
169 rc = block_write_direct(dev, blkno - 1, HR_META_SIZE, block);
170
171 return rc;
172}
173
174errno_t hr_get_metadata_block(service_id_t dev, void **rblock)
175{
176 HR_DEBUG("%s()", __func__);
177
178 errno_t rc;
179 uint64_t blkno;
180 size_t bsize;
181 void *block;
182
183 rc = block_get_bsize(dev, &bsize);
184 if (rc != EOK)
185 return rc;
186
187 if (bsize < sizeof(hr_metadata_t))
188 return EINVAL;
189
190 rc = block_get_nblocks(dev, &blkno);
191 if (rc != EOK)
192 return rc;
193
194 if (blkno < HR_META_SIZE)
195 return EINVAL;
196
197 block = malloc(bsize);
198 if (block == NULL)
199 return ENOMEM;
200
201 rc = block_read_direct(dev, blkno - 1, HR_META_SIZE, block);
202 /*
203 * XXX: here maybe call vol status event or the state callback...
204 *
205 * but need to pass vol pointer
206 */
207 if (rc != EOK) {
208 free(block);
209 return rc;
210 }
211
212 if (rblock == NULL) {
213 free(block);
214 return EINVAL;
215 }
216
217 *rblock = block;
218 return EOK;
219}
220
221void hr_encode_metadata_to_block(hr_metadata_t *metadata, void *block)
222{
223 HR_DEBUG("%s()", __func__);
224
225 /*
226 * Use scratch metadata for easier encoding without the need
227 * for manualy specifying offsets.
228 */
229 hr_metadata_t scratch_md;
230
231 memcpy(scratch_md.magic, metadata->magic, HR_MAGIC_SIZE);
232 memcpy(scratch_md.uuid, metadata->uuid, HR_UUID_LEN);
233 /* uuid_decode((uint8_t *)scratch_md.uuid, (uuid_t *)metadata->uuid); */
234
235 scratch_md.nblocks = host2uint64_t_le(metadata->nblocks);
236 scratch_md.data_blkno = host2uint64_t_le(metadata->data_blkno);
237 scratch_md.truncated_blkno = host2uint64_t_le(
238 metadata->truncated_blkno);
239 scratch_md.data_offset = host2uint64_t_le(metadata->data_offset);
240 scratch_md.counter = host2uint64_t_le(metadata->counter);
241 scratch_md.version = host2uint32_t_le(metadata->version);
242 scratch_md.extent_no = host2uint32_t_le(metadata->extent_no);
243 scratch_md.index = host2uint32_t_le(metadata->index);
244 scratch_md.level = host2uint32_t_le(metadata->level);
245 scratch_md.layout = host2uint32_t_le(metadata->layout);
246 scratch_md.strip_size = host2uint32_t_le(metadata->strip_size);
247 scratch_md.bsize = host2uint32_t_le(metadata->bsize);
248 memcpy(scratch_md.devname, metadata->devname, HR_DEVNAME_LEN);
249
250 memcpy(block, &scratch_md, sizeof(hr_metadata_t));
251}
252
253void hr_decode_metadata_from_block(const void *block, hr_metadata_t *metadata)
254{
255 HR_DEBUG("%s()", __func__);
256
257 /*
258 * Use scratch metadata for easier decoding without the need
259 * for manualy specifying offsets.
260 */
261 hr_metadata_t scratch_md;
262 memcpy(&scratch_md, block, sizeof(hr_metadata_t));
263
264 memcpy(metadata->magic, scratch_md.magic, HR_MAGIC_SIZE);
265 memcpy(metadata->uuid, scratch_md.uuid, HR_UUID_LEN);
266 /* uuid_decode((uint8_t *)scratch_md.uuid, (uuid_t *)metadata->uuid); */
267
268 metadata->nblocks = uint64_t_le2host(scratch_md.nblocks);
269 metadata->data_blkno = uint64_t_le2host(scratch_md.data_blkno);
270 metadata->truncated_blkno = uint64_t_le2host(
271 scratch_md.truncated_blkno);
272 metadata->data_offset = uint64_t_le2host(scratch_md.data_offset);
273 metadata->counter = uint64_t_le2host(scratch_md.counter);
274 metadata->version = uint32_t_le2host(scratch_md.version);
275 metadata->extent_no = uint32_t_le2host(scratch_md.extent_no);
276 metadata->index = uint32_t_le2host(scratch_md.index);
277 metadata->level = uint32_t_le2host(scratch_md.level);
278 metadata->layout = uint32_t_le2host(scratch_md.layout);
279 metadata->strip_size = uint32_t_le2host(scratch_md.strip_size);
280 metadata->bsize = uint32_t_le2host(scratch_md.bsize);
281 memcpy(metadata->devname, scratch_md.devname, HR_DEVNAME_LEN);
282}
283
284void hr_metadata_dump(hr_metadata_t *metadata)
285{
286 HR_DEBUG("%s()", __func__);
287
288 printf("\tmagic: %s\n", metadata->magic);
289 printf("\tUUID: ");
290 for (size_t i = 0; i < HR_UUID_LEN; ++i) {
291 printf("%.2X", metadata->uuid[i]);
292 if (i + 1 < HR_UUID_LEN)
293 printf(" ");
294 }
295 printf("\n");
296 printf("\tnblocks: %" PRIu64 "\n", metadata->nblocks);
297 printf("\tdata_blkno: %" PRIu64 "\n", metadata->data_blkno);
298 printf("\ttruncated_blkno: %" PRIu64 "\n", metadata->truncated_blkno);
299 printf("\tdata_offset: %" PRIu64 "\n", metadata->data_offset);
300 printf("\tcounter: %" PRIu64 "\n", metadata->counter);
301 printf("\tversion: %" PRIu32 "\n", metadata->version);
302 printf("\textent_no: %" PRIu32 "\n", metadata->extent_no);
303 printf("\tindex: %" PRIu32 "\n", metadata->index);
304 printf("\tlevel: %" PRIu32 "\n", metadata->level);
305 printf("\tlayout: %" PRIu32 "\n", metadata->layout);
306 printf("\tstrip_size: %" PRIu32 "\n", metadata->strip_size);
307 printf("\tbsize: %" PRIu32 "\n", metadata->bsize);
308 printf("\tdevname: %s\n", metadata->devname);
309}
310
311/** @}
312 */
Note: See TracBrowser for help on using the repository browser.