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

Last change on this file since 1cfa162 was e47a032, checked in by Miroslav Cimerman <mc@…>, 12 months ago

hr: base for status handling

  • Property mode set to 100644
File size: 5.8 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 *);
53
54errno_t hr_write_meta_to_vol(hr_volume_t *vol)
55{
56 log_msg(LOG_DEFAULT, LVL_NOTE, "hr_write_meta_to_vol()");
57
58 errno_t rc;
59 size_t i;
60 size_t meta_blkno; /* blocks needed to write metadata */
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 meta_blkno = (HR_META_OFF + HR_META_SIZE);
69 if (vol->level != HR_LVL_1)
70 meta_blkno *= vol->dev_no;
71
72 if (vol->nblocks < meta_blkno) {
73 log_msg(LOG_DEFAULT, LVL_ERROR,
74 "not enough blocks to write metadata");
75 rc = EINVAL;
76 goto error;
77 } else if (vol->nblocks == meta_blkno) {
78 log_msg(LOG_DEFAULT, LVL_ERROR,
79 "there would be zero data blocks after writing metadata, aborting");
80 rc = EINVAL;
81 goto error;
82 }
83
84 metadata->magic = host2uint64_t_le(HR_MAGIC);
85 metadata->extent_no = host2uint32_t_le(vol->dev_no);
86 metadata->level = host2uint32_t_le(vol->level);
87 metadata->nblocks = host2uint64_t_le(vol->nblocks);
88 metadata->data_blkno = host2uint64_t_le(vol->data_blkno);
89 metadata->data_offset = host2uint32_t_le(vol->data_offset);
90 metadata->strip_size = host2uint32_t_le(vol->strip_size);
91 for (i = 0; i < vol->dev_no; i++) {
92 metadata->index = host2uint32_t_le(i);
93
94 rc = uuid_generate(&uuid);
95 if (rc != EOK)
96 goto error;
97 uuid_encode(&uuid, metadata->uuid);
98
99 str_cpy(metadata->devname, HR_DEVNAME_LEN, vol->devname);
100
101 rc = block_write_direct(vol->extents[i].svc_id, HR_META_OFF,
102 HR_META_SIZE, metadata);
103 if (rc != EOK)
104 goto error;
105
106 /* rndgen */
107 fibril_usleep(1000);
108 }
109error:
110 free(metadata);
111 return rc;
112}
113
114static errno_t validate_meta(hr_metadata_t *md)
115{
116 if (uint64_t_le2host(md->magic) != HR_MAGIC) {
117 printf("invalid magic\n");
118 return EINVAL;
119 }
120 return EOK;
121}
122
123errno_t hr_fill_vol_from_meta(hr_volume_t *vol)
124{
125 log_msg(LOG_DEFAULT, LVL_NOTE, "hr_get_vol_from_meta()");
126
127 errno_t rc;
128 hr_metadata_t *metadata;
129
130 metadata = calloc(1, HR_META_SIZE * vol->bsize);
131 if (metadata == NULL)
132 return ENOMEM;
133
134 service_id_t cfg_svc_id_order[HR_MAXDEVS] = { 0 };
135 for (size_t i = 0; i < vol->dev_no; i++) {
136 cfg_svc_id_order[i] = vol->extents[i].svc_id;
137 vol->extents[i].svc_id = 0;
138 vol->extents[i].status = HR_EXT_MISSING;
139 }
140
141 int32_t md_order[HR_MAXDEVS] = { 0 };
142 for (size_t i = 0; i < vol->dev_no; i++) {
143 if (cfg_svc_id_order[i] == 0) {
144 md_order[i] = -1;
145 continue;
146 }
147 rc = read_metadata(cfg_svc_id_order[i], metadata);
148 if (rc != EOK)
149 goto end;
150 rc = validate_meta(metadata);
151 if (rc != EOK)
152 goto end;
153 md_order[i] = uint32_t_le2host(metadata->index);
154 }
155
156 for (size_t i = 0; i < vol->dev_no; i++) {
157 for (size_t j = 0; j < vol->dev_no; j++) {
158 if (i == (uint32_t) md_order[j]) {
159 vol->extents[i].svc_id = cfg_svc_id_order[j];
160 vol->extents[i].status = HR_EXT_ONLINE;
161 }
162 }
163 }
164
165 /*
166 * still assume metadata are in sync across extents
167 */
168
169 if (vol->dev_no != uint32_t_le2host(metadata->extent_no)) {
170 log_msg(LOG_DEFAULT, LVL_ERROR,
171 "number of divices in array differ: specified %zu, metadata states %u",
172 vol->dev_no, uint32_t_le2host(metadata->extent_no));
173 rc = EINVAL;
174 goto end;
175 }
176
177 vol->level = uint32_t_le2host(metadata->level);
178 vol->nblocks = uint64_t_le2host(metadata->nblocks);
179 vol->data_blkno = uint64_t_le2host(metadata->data_blkno);
180 vol->data_offset = uint32_t_le2host(metadata->data_offset);
181 vol->strip_size = uint32_t_le2host(metadata->strip_size);
182
183 if (str_cmp(metadata->devname, vol->devname) != 0) {
184 log_msg(LOG_DEFAULT, LVL_NOTE,
185 "devname on metadata (%s) and config (%s) differ, using config",
186 metadata->devname, vol->devname);
187 }
188end:
189 free(metadata);
190 return rc;
191}
192
193static errno_t read_metadata(service_id_t dev, hr_metadata_t *metadata)
194{
195 errno_t rc;
196 size_t bsize;
197 uint64_t nblocks;
198
199 rc = block_get_bsize(dev, &bsize);
200 if (rc != EOK)
201 return rc;
202
203 rc = block_get_nblocks(dev, &nblocks);
204 if (rc != EOK)
205 return rc;
206
207 if (nblocks < (HR_META_SIZE + HR_META_OFF) * bsize)
208 return EINVAL;
209
210 rc = block_read_direct(dev, HR_META_OFF, HR_META_SIZE, metadata);
211 if (rc != EOK)
212 return rc;
213
214 return EOK;
215}
216
217/** @}
218 */
Note: See TracBrowser for help on using the repository browser.