source: mainline/uspace/lib/device/src/hr.c@ 44da6c8

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

hr: fix printing extent states with invalid service id

  • Property mode set to 100644
File size: 9.9 KB
RevLine 
[94d84a0]1/*
[d082801]2 * Copyright (c) 2025 Miroslav Cimerman
[94d84a0]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;
[40be7eb]49 hr_t *hr = NULL;
[94d84a0]50
[40be7eb]51 if (rhr == NULL)
52 return EINVAL;
53
54 hr = calloc(1, sizeof(hr_t));
[94d84a0]55 if (hr == NULL) {
56 rc = ENOMEM;
57 goto error;
58 }
59
60 service_id_t hr_svcid;
61
[6784abc]62 rc = loc_service_get_id(SERVICE_NAME_HR, &hr_svcid, 0);
[40be7eb]63 if (rc != EOK)
[94d84a0]64 goto error;
65
[6784abc]66 hr->sess = loc_service_connect(hr_svcid, INTERFACE_HR, 0);
[94d84a0]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);
[40be7eb]77
[94d84a0]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
[d082801]90errno_t hr_create(hr_t *hr, hr_config_t *hr_config)
[94d84a0]91{
92 errno_t rc, retval;
93 async_exch_t *exch;
94 aid_t req;
95
96 exch = async_exchange_begin(hr->sess);
[68e357e]97 if (exch == NULL)
[94d84a0]98 return EINVAL;
99
[d082801]100 req = async_send_0(exch, HR_CREATE, NULL);
[b0f1366]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
[d082801]117errno_t hr_assemble(hr_t *hr, hr_config_t *hr_config, size_t *rassembled_cnt)
118{
119 errno_t rc;
120 async_exch_t *exch;
121 aid_t req;
122 size_t assembled_cnt;
123
124 exch = async_exchange_begin(hr->sess);
125 if (exch == NULL)
126 return EINVAL;
127
128 req = async_send_0(exch, HR_ASSEMBLE, NULL);
129
130 rc = async_data_write_start(exch, hr_config, sizeof(hr_config_t));
131 if (rc != EOK) {
132 async_exchange_end(exch);
133 async_forget(req);
134 return rc;
135 }
136
137 rc = async_data_read_start(exch, &assembled_cnt, sizeof(size_t));
138 if (rc != EOK) {
139 async_exchange_end(exch);
140 async_forget(req);
141 return rc;
142 }
143
144 async_exchange_end(exch);
145 async_wait_for(req, &rc);
146
147 if (rassembled_cnt != NULL)
148 *rassembled_cnt = assembled_cnt;
149
150 return rc;
151}
152
[8b51009]153errno_t hr_auto_assemble(size_t *rassembled_cnt)
154{
155 hr_t *hr;
156 errno_t rc;
157 size_t assembled_cnt;
158
159 rc = hr_sess_init(&hr);
160 if (rc != EOK)
161 return rc;
162
163 async_exch_t *exch = async_exchange_begin(hr->sess);
164 if (exch == NULL) {
165 rc = EINVAL;
166 goto error;
167 }
168
169 aid_t req = async_send_0(exch, HR_AUTO_ASSEMBLE, NULL);
170
171 rc = async_data_read_start(exch, &assembled_cnt, sizeof(size_t));
172 if (rc != EOK) {
173 async_exchange_end(exch);
174 async_forget(req);
175 return rc;
176 }
177
178 async_exchange_end(exch);
179 async_wait_for(req, &rc);
180
181 if (rassembled_cnt != NULL)
182 *rassembled_cnt = assembled_cnt;
183error:
184 hr_sess_destroy(hr);
185 return rc;
186}
187
[095a989]188static errno_t print_vol_info(size_t index, hr_vol_info_t *vol_info)
189{
190 errno_t rc;
191 size_t i;
192 char *devname;
[dbd91da]193 hr_extent_t *ext;
[095a989]194
195 printf("--- vol %zu ---\n", index);
196
197 printf("svc_id: %lu\n", vol_info->svc_id);
198
199 rc = loc_service_get_name(vol_info->svc_id, &devname);
200 if (rc != EOK)
201 return rc;
202 printf("devname: %s\n", devname);
203
[e47a032]204 printf("status: %s\n", hr_get_vol_status_msg(vol_info->status));
205
[095a989]206 printf("level: %d\n", vol_info->level);
[4066371]207 if (vol_info->level == HR_LVL_4 || vol_info->level == HR_LVL_5) {
208 printf("layout: %s\n",
[37a9c1e]209 hr_get_layout_str(vol_info->level, vol_info->layout));
[4066371]210 }
[50bed55d]211 if (vol_info->level == HR_LVL_0 || vol_info->level == HR_LVL_4) {
[9c1cf34c]212 if (vol_info->strip_size / 1024 < 1)
213 printf("strip size in bytes: %u\n",
214 vol_info->strip_size);
215 else
216 printf("strip size: %uK\n",
217 vol_info->strip_size / 1024);
218 }
219 printf("size in bytes: %luMiB\n",
220 vol_info->nblocks * vol_info->bsize / 1024 / 1024);
221 printf("size in blocks: %lu\n", vol_info->nblocks);
222 printf("block size: %zu\n", vol_info->bsize);
223
[50bed55d]224 if (vol_info->level == HR_LVL_4)
[dbd91da]225 printf("extents: [P] [status] [index] [devname]\n");
226 else
227 printf("extents: [status] [index] [devname]\n");
[095a989]228 for (i = 0; i < vol_info->extent_no; i++) {
[dbd91da]229 ext = &vol_info->extents[i];
[4200735]230 if (ext->status == HR_EXT_MISSING || ext->status == HR_EXT_NONE) {
[e47a032]231 devname = (char *) "MISSING-devname";
232 } else {
233 rc = loc_service_get_name(ext->svc_id, &devname);
[4200735]234 if (rc != EOK) {
235 printf("loc_service_get_name() failed, skipping...\n");
236 continue;
237 }
[e47a032]238 }
[4066371]239 if (vol_info->level == HR_LVL_4) {
[37a9c1e]240 if ((i == 0 && vol_info->layout == HR_RLQ_RAID4_0) ||
[4066371]241 (i == vol_info->extent_no - 1 &&
[37a9c1e]242 vol_info->layout == HR_RLQ_RAID4_N))
[4066371]243 printf(" P %s %zu %s\n", hr_get_ext_status_msg(ext->status), i, devname);
244 else
245 printf(" %s %zu %s\n", hr_get_ext_status_msg(ext->status), i, devname);
246 } else {
[e47a032]247 printf(" %s %zu %s\n", hr_get_ext_status_msg(ext->status), i, devname);
[4066371]248 }
[095a989]249 }
[5b320ac]250
251 if (vol_info->hotspare_no == 0)
252 return EOK;
253
254 printf("hotspares: [status] [index] [devname]\n");
255 for (i = 0; i < vol_info->hotspare_no; i++) {
256 ext = &vol_info->hotspares[i];
257 if (ext->status == HR_EXT_MISSING) {
258 devname = (char *) "MISSING-devname";
259 } else {
260 rc = loc_service_get_name(ext->svc_id, &devname);
261 if (rc != EOK)
262 return rc;
263 }
264 printf(" %s %zu %s\n",
265 hr_get_ext_status_msg(ext->status), i, devname);
266 }
267
[095a989]268 return EOK;
269}
270
[cf28ffd3]271errno_t hr_stop(const char *devname, long extent)
[a19d7fc4]272{
273 hr_t *hr;
274 errno_t rc;
275 async_exch_t *exch;
276 service_id_t svc_id;
277
278 rc = loc_service_get_id(devname, &svc_id, 0);
279 if (rc != EOK)
280 return rc;
281
282 rc = hr_sess_init(&hr);
283 if (rc != EOK)
284 return rc;
285
286 exch = async_exchange_begin(hr->sess);
287 if (exch == NULL) {
288 rc = EINVAL;
289 goto error;
290 }
[cf28ffd3]291 rc = async_req_2_0(exch, HR_STOP, svc_id, extent);
[a19d7fc4]292 async_exchange_end(exch);
293error:
294 hr_sess_destroy(hr);
295 return rc;
296}
297
[5b320ac]298errno_t hr_add_hotspare(service_id_t vol_svc_id, service_id_t hs_svc_id)
299{
300 hr_t *hr;
301 errno_t rc;
302 async_exch_t *exch;
303
304 rc = hr_sess_init(&hr);
305 if (rc != EOK)
306 return rc;
307
308 exch = async_exchange_begin(hr->sess);
309 if (exch == NULL) {
310 rc = EINVAL;
311 goto error;
312 }
313
314 rc = async_req_2_0(exch, HR_ADD_HOTSPARE, vol_svc_id, hs_svc_id);
315 async_exchange_end(exch);
316error:
317 hr_sess_destroy(hr);
318 return rc;
319}
320
[095a989]321errno_t hr_print_status(void)
322{
323 hr_t *hr;
324 errno_t rc, retval;
325 async_exch_t *exch;
326 aid_t req;
327 size_t size, i;
[a19d7fc4]328 hr_vol_info_t *vols = NULL;
[095a989]329
330 rc = hr_sess_init(&hr);
331 if (rc != EOK)
332 return rc;
333
334 exch = async_exchange_begin(hr->sess);
[a19d7fc4]335 if (exch == NULL) {
336 rc = EINVAL;
337 goto error;
338 }
[095a989]339
340 req = async_send_0(exch, HR_STATUS, NULL);
341 rc = async_data_read_start(exch, &size, sizeof(size_t));
342 if (rc != EOK) {
343 async_exchange_end(exch);
344 async_forget(req);
345 return rc;
346 }
347
348 vols = calloc(size, sizeof(hr_vol_info_t));
349 if (vols == NULL) {
350 async_exchange_end(exch);
351 async_forget(req);
352 return ENOMEM;
353 }
354
355 for (i = 0; i < size; i++) {
356 rc = async_data_read_start(exch, &vols[i],
357 sizeof(hr_vol_info_t));
358 if (rc != EOK) {
359 async_exchange_end(exch);
360 async_forget(req);
361 goto error;
362 }
363 }
364
365 async_exchange_end(exch);
366 async_wait_for(req, &retval);
367 if (retval != EOK) {
368 rc = retval;
369 goto error;
370 }
371
[a19d7fc4]372 if (size == 0) {
373 printf("no active arrays\n");
374 goto error;
375 }
376
[095a989]377 for (i = 0; i < size; i++) {
378 rc = print_vol_info(i, &vols[i]);
379 if (rc != EOK)
380 goto error;
381 }
382
383error:
[a19d7fc4]384 hr_sess_destroy(hr);
[095a989]385 if (vols != NULL)
386 free(vols);
387 return rc;
388}
389
[e47a032]390const char *hr_get_vol_status_msg(hr_vol_status_t status)
391{
392 switch (status) {
[e24c064]393 case HR_VOL_NONE:
394 return "NONE/UNKNOWN";
[e47a032]395 case HR_VOL_ONLINE:
396 return "ONLINE";
397 case HR_VOL_FAULTY:
398 return "FAULTY";
[13ce552]399 case HR_VOL_DEGRADED:
400 return "DEGRADED";
[5b320ac]401 case HR_VOL_REBUILD:
402 return "REBUILD";
[e47a032]403 default:
[e24c064]404 return "Invalid state value";
[e47a032]405 }
406}
407
408const char *hr_get_ext_status_msg(hr_ext_status_t status)
409{
410 switch (status) {
[e24c064]411 case HR_EXT_NONE:
412 return "NONE/UNKNOWN";
[3a68baa]413 case HR_EXT_INVALID:
414 return "INVALID";
[e47a032]415 case HR_EXT_ONLINE:
416 return "ONLINE";
417 case HR_EXT_MISSING:
418 return "MISSING";
419 case HR_EXT_FAILED:
420 return "FAILED";
[5b320ac]421 case HR_EXT_REBUILD:
422 return "REBUILD";
423 case HR_EXT_HOTSPARE:
424 return "HOTSPARE";
[e47a032]425 default:
[e24c064]426 return "Invalid state value";
[e47a032]427 }
428}
429
[37a9c1e]430const char *hr_get_layout_str(hr_level_t level, uint8_t layout)
[4066371]431{
432 switch (level) {
433 case HR_LVL_4:
[37a9c1e]434 switch (layout) {
[4066371]435 case HR_RLQ_RAID4_0:
436 return "RAID-4 Non-Rotating Parity 0";
437 case HR_RLQ_RAID4_N:
438 return "RAID-4 Non-Rotating Parity N";
439 default:
[e24c064]440 return "Invalid RAID 4 layout";
[4066371]441 }
442 case HR_LVL_5:
[37a9c1e]443 switch (layout) {
[4066371]444 case HR_RLQ_RAID5_0R:
445 return "RAID-5 Rotating Parity 0 with Data Restart";
446 case HR_RLQ_RAID5_NR:
447 return "RAID-5 Rotating Parity N with Data Restart";
448 case HR_RLQ_RAID5_NC:
449 return "RAID-5 Rotating Parity N with Data Continuation";
450 default:
[e24c064]451 return "Invalid RAID 5 layout";
[4066371]452 }
453 default:
[e24c064]454 return "Invalid RAID level";
[4066371]455 }
456}
457
[94d84a0]458/** @}
459 */
Note: See TracBrowser for help on using the repository browser.