source: mainline/uspace/srv/bd/hr/metadata/foreign/geom/stripe.c@ 5cb1631

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

hr: FreeBSD GEOM::STRIPE metadata support

  • 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 <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 "g_stripe.h"
54
55static void *meta_stripe_alloc_struct(void);
56static errno_t meta_stripe_init_vol2meta(const hr_volume_t *, void *);
57static errno_t meta_stripe_init_meta2vol(const list_t *,
58 hr_volume_t *);
59static void meta_stripe_encode(void *, void *);
60static errno_t meta_stripe_decode(const void *, void *);
61static errno_t meta_stripe_get_block(service_id_t, void **);
62static errno_t meta_stripe_write_block(service_id_t, const void *);
63static bool meta_stripe_has_valid_magic(const void *);
64static bool meta_stripe_compare_uuids(const void *, const void *);
65static void meta_stripe_inc_counter(void *);
66static errno_t meta_stripe_save(hr_volume_t *, bool);
67static const char *meta_stripe_get_devname(const void *);
68static hr_level_t meta_stripe_get_level(const void *);
69static uint64_t meta_stripe_get_data_offset(void);
70static size_t meta_stripe_get_size(void);
71static uint8_t meta_stripe_get_flags(void);
72static hr_metadata_type_t meta_stripe_get_type(void);
73static void meta_stripe_dump(const void *);
74
75hr_superblock_ops_t metadata_stripe_ops = {
76 .alloc_struct = meta_stripe_alloc_struct,
77 .init_vol2meta = meta_stripe_init_vol2meta,
78 .init_meta2vol = meta_stripe_init_meta2vol,
79 .encode = meta_stripe_encode,
80 .decode = meta_stripe_decode,
81 .get_block = meta_stripe_get_block,
82 .write_block = meta_stripe_write_block,
83 .has_valid_magic = meta_stripe_has_valid_magic,
84 .compare_uuids = meta_stripe_compare_uuids,
85 .inc_counter = meta_stripe_inc_counter,
86 .save = meta_stripe_save,
87 .get_devname = meta_stripe_get_devname,
88 .get_level = meta_stripe_get_level,
89 .get_data_offset = meta_stripe_get_data_offset,
90 .get_size = meta_stripe_get_size,
91 .get_flags = meta_stripe_get_flags,
92 .get_type = meta_stripe_get_type,
93 .dump = meta_stripe_dump
94};
95
96static void *meta_stripe_alloc_struct(void)
97{
98 return calloc(1, sizeof(struct g_stripe_metadata));
99}
100
101static errno_t meta_stripe_init_vol2meta(const hr_volume_t *vol, void *md_v)
102{
103 (void)vol;
104 (void)md_v;
105 return ENOTSUP;
106}
107
108static errno_t meta_stripe_init_meta2vol(const list_t *list, hr_volume_t *vol)
109{
110 HR_DEBUG("%s()", __func__);
111
112 errno_t rc = EOK;
113
114 /* get bsize */
115 size_t bsize;
116 struct dev_list_member *memb = list_get_instance(list_first(list),
117 struct dev_list_member, link);
118 rc = block_get_bsize(memb->svc_id, &bsize);
119 if (rc != EOK)
120 goto error;
121
122 vol->bsize = bsize;
123
124 uint64_t smallest_provider_size = ~0ULL;
125 struct g_stripe_metadata *main_meta = NULL;
126
127 list_foreach(*list, link, struct dev_list_member, iter) {
128 struct g_stripe_metadata *iter_meta = iter->md;
129
130 meta_stripe_dump(iter_meta);
131
132 if (iter_meta->md_provsize < smallest_provider_size) {
133 smallest_provider_size = iter_meta->md_provsize;
134 main_meta = iter_meta;
135 }
136 }
137
138 assert(main_meta != NULL);
139
140 vol->truncated_blkno =
141 main_meta->md_provsize / bsize;
142
143 vol->extent_no = main_meta->md_all;
144
145 vol->data_blkno = (vol->truncated_blkno - 1) * vol->extent_no;
146
147 vol->data_offset = 0;
148
149 if (main_meta->md_all > HR_MAX_EXTENTS) {
150 HR_DEBUG("Assembled volume has %u extents (max = %u)",
151 (unsigned)main_meta->md_all, HR_MAX_EXTENTS);
152 rc = EINVAL;
153 goto error;
154 }
155
156 vol->strip_size = main_meta->md_stripesize;
157
158 memcpy(vol->in_mem_md, main_meta, sizeof(struct g_stripe_metadata));
159
160 list_foreach(*list, link, struct dev_list_member, iter) {
161 struct g_stripe_metadata *iter_meta = iter->md;
162 uint16_t index = iter_meta->md_no;
163
164 vol->extents[index].svc_id = iter->svc_id;
165 iter->fini = false;
166
167 vol->extents[index].status = HR_EXT_ONLINE;
168 }
169
170 for (size_t i = 0; i < vol->extent_no; i++) {
171 if (vol->extents[i].status == HR_EXT_NONE)
172 vol->extents[i].status = HR_EXT_MISSING;
173 }
174
175error:
176 return rc;
177}
178
179static void meta_stripe_encode(void *md_v, void *block)
180{
181 HR_DEBUG("%s()", __func__);
182
183 stripe_metadata_encode(md_v, block);
184}
185
186static errno_t meta_stripe_decode(const void *block, void *md_v)
187{
188 HR_DEBUG("%s()", __func__);
189
190 stripe_metadata_decode(block, md_v);
191
192 return EOK;
193}
194
195static errno_t meta_stripe_get_block(service_id_t dev, void **rblock)
196{
197 HR_DEBUG("%s()", __func__);
198
199 errno_t rc;
200 uint64_t blkno;
201 size_t bsize;
202 void *block;
203
204 if (rblock == NULL)
205 return EINVAL;
206
207 rc = block_get_bsize(dev, &bsize);
208 if (rc != EOK)
209 return rc;
210
211 if (bsize < sizeof(struct g_stripe_metadata))
212 return EINVAL;
213
214 rc = block_get_nblocks(dev, &blkno);
215 if (rc != EOK)
216 return rc;
217
218 if (blkno < 1)
219 return EINVAL;
220
221 block = malloc(bsize);
222 if (block == NULL)
223 return ENOMEM;
224
225 rc = block_read_direct(dev, blkno - 1, 1, block);
226 /*
227 * XXX: here maybe call vol status event or the state callback...
228 *
229 * but need to pass vol pointer
230 */
231 if (rc != EOK) {
232 free(block);
233 return rc;
234 }
235
236 *rblock = block;
237 return EOK;
238}
239
240static errno_t meta_stripe_write_block(service_id_t dev, const void *block)
241{
242 HR_DEBUG("%s()", __func__);
243
244 errno_t rc;
245 uint64_t blkno;
246 size_t bsize;
247
248 rc = block_get_bsize(dev, &bsize);
249 if (rc != EOK)
250 return rc;
251
252 if (bsize < sizeof(struct g_stripe_metadata))
253 return EINVAL;
254
255 rc = block_get_nblocks(dev, &blkno);
256 if (rc != EOK)
257 return rc;
258
259 if (blkno < 1)
260 return EINVAL;
261
262 rc = block_write_direct(dev, blkno - 1, 1, block);
263
264 return rc;
265}
266
267static bool meta_stripe_has_valid_magic(const void *md_v)
268{
269 HR_DEBUG("%s()", __func__);
270
271 const struct g_stripe_metadata *md = md_v;
272
273 if (str_lcmp(md->md_magic, G_STRIPE_MAGIC, 16) != 0)
274 return false;
275
276 return true;
277}
278
279static bool meta_stripe_compare_uuids(const void *md1_v, const void *md2_v)
280{
281 const struct g_stripe_metadata *md1 = md1_v;
282 const struct g_stripe_metadata *md2 = md2_v;
283 if (md1->md_id == md2->md_id)
284 return true;
285
286 return false;
287}
288
289static void meta_stripe_inc_counter(void *md_v)
290{
291 (void)md_v;
292}
293
294static errno_t meta_stripe_save(hr_volume_t *vol, bool with_state_callback)
295{
296 HR_DEBUG("%s()", __func__);
297
298 return EOK;
299}
300
301static const char *meta_stripe_get_devname(const void *md_v)
302{
303 const struct g_stripe_metadata *md = md_v;
304
305 return md->md_name;
306}
307
308static hr_level_t meta_stripe_get_level(const void *md_v)
309{
310 (void)md_v;
311
312 return HR_LVL_0;
313}
314
315static uint64_t meta_stripe_get_data_offset(void)
316{
317 return 0;
318}
319
320static size_t meta_stripe_get_size(void)
321{
322 return 1;
323}
324
325static uint8_t meta_stripe_get_flags(void)
326{
327 uint8_t flags = 0;
328
329 return flags;
330}
331
332static hr_metadata_type_t meta_stripe_get_type(void)
333{
334 return HR_METADATA_GEOM_STRIPE;
335}
336
337static void meta_stripe_dump(const void *md_v)
338{
339 HR_DEBUG("%s()", __func__);
340
341 const struct g_stripe_metadata *md = md_v;
342
343 printf(" magic: %s\n", md->md_magic);
344 printf(" version: %u\n", (u_int)md->md_version);
345 printf(" name: %s\n", md->md_name);
346 printf(" id: %u\n", (u_int)md->md_id);
347 printf(" no: %u\n", (u_int)md->md_no);
348 printf(" all: %u\n", (u_int)md->md_all);
349 printf("stripesize: %u\n", (u_int)md->md_stripesize);
350 printf(" mediasize: %jd\n", (intmax_t)md->md_provsize);
351}
352
353/** @}
354 */
Note: See TracBrowser for help on using the repository browser.