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

Last change on this file since eb31781 was 37a9c1e, checked in by Miroslav Cimerman <mc@…>, 10 months ago

hr: hr_volume_t: rename RLQ → layout

  • Property mode set to 100644
File size: 7.3 KB
Line 
1/*
2 * Copyright (c) 2024 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("hr_write_meta_to_vol()\n");
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 for (i = 0; i < vol->extent_no; i++) {
73 metadata->index = host2uint32_t_le(i);
74
75 rc = uuid_generate(&uuid);
76 if (rc != EOK)
77 goto error;
78 uuid_encode(&uuid, metadata->uuid);
79
80 rc = block_write_direct(vol->extents[i].svc_id, HR_META_OFF,
81 HR_META_SIZE, metadata);
82 if (rc != EOK)
83 goto error;
84
85 /* rndgen */
86 fibril_usleep(1000);
87 }
88error:
89 free(metadata);
90 return rc;
91}
92
93errno_t hr_write_meta_to_ext(hr_volume_t *vol, size_t ext)
94{
95 HR_DEBUG("hr_write_meta_to_vol()\n");
96
97 errno_t rc;
98 hr_metadata_t *metadata;
99 uuid_t uuid;
100
101 metadata = calloc(1, HR_META_SIZE * vol->bsize);
102 if (metadata == NULL)
103 return ENOMEM;
104
105 rc = hr_fill_meta_from_vol(vol, metadata);
106 if (rc != EOK)
107 goto error;
108
109 metadata->index = host2uint32_t_le(ext);
110
111 rc = uuid_generate(&uuid);
112 if (rc != EOK)
113 goto error;
114 uuid_encode(&uuid, metadata->uuid);
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("hr_fill_meta_from_vol()\n");
135
136 size_t meta_blkno; /* blocks needed to write metadata */
137
138 meta_blkno = (HR_META_OFF + HR_META_SIZE);
139 if (vol->level != HR_LVL_1)
140 meta_blkno *= vol->extent_no;
141
142 if (vol->nblocks < meta_blkno) {
143 HR_ERROR("hr_fill_meta_from_vol(): volume \"%s\" does not "
144 " have enough space to store metada, aborting\n",
145 vol->devname);
146 return EINVAL;
147 } else if (vol->nblocks == meta_blkno) {
148 HR_ERROR("hr_fill_meta_from_vol(): volume \"%s\" would have "
149 "zero data blocks after writing metadata, aborting\n",
150 vol->devname);
151 return EINVAL;
152 }
153
154 metadata->magic = host2uint64_t_le(HR_MAGIC);
155 metadata->version = host2uint32_t_le(~(0U)); /* unused */
156 metadata->extent_no = host2uint32_t_le(vol->extent_no);
157 /* index filled separately for each extent */
158 metadata->level = host2uint32_t_le(vol->level);
159 metadata->layout = host2uint32_t_le(vol->layout);
160 metadata->strip_size = host2uint32_t_le(vol->strip_size);
161 metadata->nblocks = host2uint64_t_le(vol->nblocks);
162 metadata->data_blkno = host2uint64_t_le(vol->data_blkno);
163 metadata->data_offset = host2uint64_t_le(vol->data_offset);
164 metadata->counter = host2uint64_t_le(~(0UL)); /* unused */
165 /* UUID generated separately for each extent */
166 str_cpy(metadata->devname, HR_DEVNAME_LEN, vol->devname);
167
168 return EOK;
169}
170
171static errno_t validate_meta(hr_metadata_t *md)
172{
173 if (uint64_t_le2host(md->magic) != HR_MAGIC) {
174 HR_ERROR("invalid magic\n");
175 return EINVAL;
176 }
177 return EOK;
178}
179
180errno_t hr_fill_vol_from_meta(hr_volume_t *vol)
181{
182 HR_DEBUG("hr_get_vol_from_meta()\n");
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 cfg_svc_id_order[HR_MAX_EXTENTS] = { 0 };
192 for (size_t i = 0; i < vol->extent_no; i++)
193 cfg_svc_id_order[i] = vol->extents[i].svc_id;
194
195 int32_t md_order[HR_MAX_EXTENTS] = { 0 };
196 for (size_t i = 0; i < vol->extent_no; i++) {
197 if (cfg_svc_id_order[i] == 0) {
198 md_order[i] = -1;
199 continue;
200 }
201 rc = read_metadata(cfg_svc_id_order[i], metadata);
202 if (rc != EOK)
203 goto end;
204 rc = validate_meta(metadata);
205 if (rc != EOK)
206 goto end;
207 md_order[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 == (uint32_t)md_order[j]) {
219 vol->extents[i].svc_id = cfg_svc_id_order[j];
220 vol->extents[i].status = HR_EXT_ONLINE;
221 }
222 }
223 }
224
225 /*
226 * still assume metadata are in sync across extents
227 */
228
229 if (vol->extent_no != uint32_t_le2host(metadata->extent_no)) {
230 HR_ERROR("number of divices in array differ: specified %zu, "
231 "metadata states %u",
232 vol->extent_no, uint32_t_le2host(metadata->extent_no));
233 rc = EINVAL;
234 goto end;
235 }
236
237 /* TODO: handle version */
238 vol->level = uint32_t_le2host(metadata->level);
239 vol->layout = (uint8_t)uint32_t_le2host(metadata->layout);
240 vol->strip_size = uint32_t_le2host(metadata->strip_size);
241 vol->nblocks = uint64_t_le2host(metadata->nblocks);
242 vol->data_blkno = uint64_t_le2host(metadata->data_blkno);
243 vol->data_offset = uint64_t_le2host(metadata->data_offset);
244 vol->counter = uint64_t_le2host(0x00); /* unused */
245
246 if (str_cmp(metadata->devname, vol->devname) != 0) {
247 HR_WARN("devname on metadata (%s) and config (%s) differ, "
248 "using config", metadata->devname, vol->devname);
249 }
250end:
251 free(metadata);
252 return rc;
253}
254
255static errno_t read_metadata(service_id_t dev, hr_metadata_t *metadata)
256{
257 errno_t rc;
258 size_t bsize;
259 uint64_t nblocks;
260
261 rc = block_get_bsize(dev, &bsize);
262 if (rc != EOK)
263 return rc;
264
265 rc = block_get_nblocks(dev, &nblocks);
266 if (rc != EOK)
267 return rc;
268
269 if (nblocks < (HR_META_SIZE + HR_META_OFF) * bsize)
270 return EINVAL;
271
272 rc = block_read_direct(dev, HR_META_OFF, HR_META_SIZE, metadata);
273 if (rc != EOK)
274 return rc;
275
276 return EOK;
277}
278
279/** @}
280 */
Note: See TracBrowser for help on using the repository browser.