source: mainline/uspace/lib/device/src/hr.c@ 3a68baa

Last change on this file since 3a68baa was 3a68baa, checked in by Miroslav Cimerman <mc@…>, 6 months ago

lib/device/hr: add INVALID state

  • Property mode set to 100644
File size: 8.5 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 libdevice
30 * @{
31 */
32/**
33 * @file
34 */
35
36#include <abi/ipc/interfaces.h>
37#include <async.h>
38#include <hr.h>
39#include <ipc/hr.h>
40#include <ipc/services.h>
41#include <loc.h>
42#include <stdlib.h>
43#include <stdio.h>
44#include <str.h>
45
46errno_t hr_sess_init(hr_t **rhr)
47{
48 errno_t rc;
49 hr_t *hr = NULL;
50
51 if (rhr == NULL)
52 return EINVAL;
53
54 hr = calloc(1, sizeof(hr_t));
55 if (hr == NULL) {
56 rc = ENOMEM;
57 goto error;
58 }
59
60 service_id_t hr_svcid;
61
62 rc = loc_service_get_id(SERVICE_NAME_HR, &hr_svcid, 0);
63 if (rc != EOK)
64 goto error;
65
66 hr->sess = loc_service_connect(hr_svcid, INTERFACE_HR, 0);
67 if (hr->sess == NULL) {
68 rc = EIO;
69 goto error;
70 }
71
72 *rhr = hr;
73 return EOK;
74error:
75 if (hr != NULL)
76 free(hr);
77
78 return rc;
79}
80
81void hr_sess_destroy(hr_t *hr)
82{
83 if (hr == NULL)
84 return;
85
86 async_hangup(hr->sess);
87 free(hr);
88}
89
90errno_t hr_create(hr_t *hr, hr_config_t *hr_config, bool assemble)
91{
92 errno_t rc, retval;
93 async_exch_t *exch;
94 aid_t req;
95
96 exch = async_exchange_begin(hr->sess);
97 if (exch == NULL)
98 return EINVAL;
99
100 req = async_send_0(exch, assemble ? HR_ASSEMBLE : HR_CREATE, NULL);
101
102 rc = async_data_write_start(exch, hr_config, sizeof(hr_config_t));
103 if (rc != EOK) {
104 async_exchange_end(exch);
105 async_forget(req);
106 return rc;
107 }
108
109 async_exchange_end(exch);
110 async_wait_for(req, &retval);
111 if (retval != EOK)
112 return retval;
113
114 return EOK;
115}
116
117static errno_t print_vol_info(size_t index, hr_vol_info_t *vol_info)
118{
119 errno_t rc;
120 size_t i;
121 char *devname;
122 hr_extent_t *ext;
123
124 printf("--- vol %zu ---\n", index);
125
126 printf("svc_id: %lu\n", vol_info->svc_id);
127
128 rc = loc_service_get_name(vol_info->svc_id, &devname);
129 if (rc != EOK)
130 return rc;
131 printf("devname: %s\n", devname);
132
133 printf("status: %s\n", hr_get_vol_status_msg(vol_info->status));
134
135 printf("level: %d\n", vol_info->level);
136 if (vol_info->level == HR_LVL_4 || vol_info->level == HR_LVL_5) {
137 printf("layout: %s\n",
138 hr_get_layout_str(vol_info->level, vol_info->layout));
139 }
140 if (vol_info->level == HR_LVL_0 || vol_info->level == HR_LVL_4) {
141 if (vol_info->strip_size / 1024 < 1)
142 printf("strip size in bytes: %u\n",
143 vol_info->strip_size);
144 else
145 printf("strip size: %uK\n",
146 vol_info->strip_size / 1024);
147 }
148 printf("size in bytes: %luMiB\n",
149 vol_info->nblocks * vol_info->bsize / 1024 / 1024);
150 printf("size in blocks: %lu\n", vol_info->nblocks);
151 printf("block size: %zu\n", vol_info->bsize);
152
153 if (vol_info->level == HR_LVL_4)
154 printf("extents: [P] [status] [index] [devname]\n");
155 else
156 printf("extents: [status] [index] [devname]\n");
157 for (i = 0; i < vol_info->extent_no; i++) {
158 ext = &vol_info->extents[i];
159 if (ext->status == HR_EXT_MISSING) {
160 devname = (char *) "MISSING-devname";
161 } else {
162 rc = loc_service_get_name(ext->svc_id, &devname);
163 if (rc != EOK)
164 return rc;
165 }
166 if (vol_info->level == HR_LVL_4) {
167 if ((i == 0 && vol_info->layout == HR_RLQ_RAID4_0) ||
168 (i == vol_info->extent_no - 1 &&
169 vol_info->layout == HR_RLQ_RAID4_N))
170 printf(" P %s %zu %s\n", hr_get_ext_status_msg(ext->status), i, devname);
171 else
172 printf(" %s %zu %s\n", hr_get_ext_status_msg(ext->status), i, devname);
173 } else {
174 printf(" %s %zu %s\n", hr_get_ext_status_msg(ext->status), i, devname);
175 }
176 }
177
178 if (vol_info->hotspare_no == 0)
179 return EOK;
180
181 printf("hotspares: [status] [index] [devname]\n");
182 for (i = 0; i < vol_info->hotspare_no; i++) {
183 ext = &vol_info->hotspares[i];
184 if (ext->status == HR_EXT_MISSING) {
185 devname = (char *) "MISSING-devname";
186 } else {
187 rc = loc_service_get_name(ext->svc_id, &devname);
188 if (rc != EOK)
189 return rc;
190 }
191 printf(" %s %zu %s\n",
192 hr_get_ext_status_msg(ext->status), i, devname);
193 }
194
195 return EOK;
196}
197
198errno_t hr_stop(const char *devname, long extent)
199{
200 hr_t *hr;
201 errno_t rc;
202 async_exch_t *exch;
203 service_id_t svc_id;
204
205 rc = loc_service_get_id(devname, &svc_id, 0);
206 if (rc != EOK)
207 return rc;
208
209 rc = hr_sess_init(&hr);
210 if (rc != EOK)
211 return rc;
212
213 exch = async_exchange_begin(hr->sess);
214 if (exch == NULL) {
215 rc = EINVAL;
216 goto error;
217 }
218 rc = async_req_2_0(exch, HR_STOP, svc_id, extent);
219 async_exchange_end(exch);
220
221 if (rc != EOK)
222 goto error;
223error:
224 hr_sess_destroy(hr);
225 return rc;
226}
227
228errno_t hr_add_hotspare(service_id_t vol_svc_id, service_id_t hs_svc_id)
229{
230 hr_t *hr;
231 errno_t rc;
232 async_exch_t *exch;
233
234 rc = hr_sess_init(&hr);
235 if (rc != EOK)
236 return rc;
237
238 exch = async_exchange_begin(hr->sess);
239 if (exch == NULL) {
240 rc = EINVAL;
241 goto error;
242 }
243
244 rc = async_req_2_0(exch, HR_ADD_HOTSPARE, vol_svc_id, hs_svc_id);
245 async_exchange_end(exch);
246error:
247 hr_sess_destroy(hr);
248 return rc;
249}
250
251errno_t hr_print_status(void)
252{
253 hr_t *hr;
254 errno_t rc, retval;
255 async_exch_t *exch;
256 aid_t req;
257 size_t size, i;
258 hr_vol_info_t *vols = NULL;
259
260 rc = hr_sess_init(&hr);
261 if (rc != EOK)
262 return rc;
263
264 exch = async_exchange_begin(hr->sess);
265 if (exch == NULL) {
266 rc = EINVAL;
267 goto error;
268 }
269
270 req = async_send_0(exch, HR_STATUS, NULL);
271 rc = async_data_read_start(exch, &size, sizeof(size_t));
272 if (rc != EOK) {
273 async_exchange_end(exch);
274 async_forget(req);
275 return rc;
276 }
277
278 vols = calloc(size, sizeof(hr_vol_info_t));
279 if (vols == NULL) {
280 async_exchange_end(exch);
281 async_forget(req);
282 return ENOMEM;
283 }
284
285 for (i = 0; i < size; i++) {
286 rc = async_data_read_start(exch, &vols[i],
287 sizeof(hr_vol_info_t));
288 if (rc != EOK) {
289 async_exchange_end(exch);
290 async_forget(req);
291 goto error;
292 }
293 }
294
295 async_exchange_end(exch);
296 async_wait_for(req, &retval);
297 if (retval != EOK) {
298 rc = retval;
299 goto error;
300 }
301
302 if (size == 0) {
303 printf("no active arrays\n");
304 goto error;
305 }
306
307 for (i = 0; i < size; i++) {
308 rc = print_vol_info(i, &vols[i]);
309 if (rc != EOK)
310 goto error;
311 }
312
313error:
314 hr_sess_destroy(hr);
315 if (vols != NULL)
316 free(vols);
317 return rc;
318}
319
320const char *hr_get_vol_status_msg(hr_vol_status_t status)
321{
322 switch (status) {
323 case HR_VOL_INVALID:
324 return "INVALID";
325 case HR_VOL_ONLINE:
326 return "ONLINE";
327 case HR_VOL_FAULTY:
328 return "FAULTY";
329 case HR_VOL_DEGRADED:
330 return "DEGRADED";
331 case HR_VOL_REBUILD:
332 return "REBUILD";
333 default:
334 return "UNKNOWN";
335 }
336}
337
338const char *hr_get_ext_status_msg(hr_ext_status_t status)
339{
340 switch (status) {
341 case HR_EXT_INVALID:
342 return "INVALID";
343 case HR_EXT_ONLINE:
344 return "ONLINE";
345 case HR_EXT_MISSING:
346 return "MISSING";
347 case HR_EXT_FAILED:
348 return "FAILED";
349 case HR_EXT_REBUILD:
350 return "REBUILD";
351 case HR_EXT_HOTSPARE:
352 return "HOTSPARE";
353 default:
354 return "UNKNOWN";
355 }
356}
357
358const char *hr_get_layout_str(hr_level_t level, uint8_t layout)
359{
360 switch (level) {
361 case HR_LVL_4:
362 switch (layout) {
363 case HR_RLQ_RAID4_0:
364 return "RAID-4 Non-Rotating Parity 0";
365 case HR_RLQ_RAID4_N:
366 return "RAID-4 Non-Rotating Parity N";
367 default:
368 return "RAID-4 INVALID";
369 }
370 case HR_LVL_5:
371 switch (layout) {
372 case HR_RLQ_RAID5_0R:
373 return "RAID-5 Rotating Parity 0 with Data Restart";
374 case HR_RLQ_RAID5_NR:
375 return "RAID-5 Rotating Parity N with Data Restart";
376 case HR_RLQ_RAID5_NC:
377 return "RAID-5 Rotating Parity N with Data Continuation";
378 default:
379 return "RAID-5 INVALID";
380 }
381 default:
382 return "INVALID";
383 }
384}
385
386/** @}
387 */
Note: See TracBrowser for help on using the repository browser.