source: mainline/uspace/lib/device/src/hr.c@ 31eb568

Last change on this file since 31eb568 was d1d355f, checked in by Miroslav Cimerman <mc@…>, 10 months ago

hr: refactor hrctl and some hr IPC methods

  • Property mode set to 100644
File size: 11.1 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);
[d1d355f]111 return retval;
[b0f1366]112}
113
[d082801]114errno_t hr_assemble(hr_t *hr, hr_config_t *hr_config, size_t *rassembled_cnt)
115{
116 errno_t rc;
117 async_exch_t *exch;
118 aid_t req;
119 size_t assembled_cnt;
120
121 exch = async_exchange_begin(hr->sess);
122 if (exch == NULL)
123 return EINVAL;
124
125 req = async_send_0(exch, HR_ASSEMBLE, NULL);
126
127 rc = async_data_write_start(exch, hr_config, sizeof(hr_config_t));
128 if (rc != EOK) {
129 async_exchange_end(exch);
130 async_forget(req);
131 return rc;
132 }
133
134 rc = async_data_read_start(exch, &assembled_cnt, sizeof(size_t));
135 if (rc != EOK) {
136 async_exchange_end(exch);
137 async_forget(req);
138 return rc;
139 }
140
141 async_exchange_end(exch);
142 async_wait_for(req, &rc);
143
144 if (rassembled_cnt != NULL)
145 *rassembled_cnt = assembled_cnt;
146
147 return rc;
148}
149
[8b51009]150errno_t hr_auto_assemble(size_t *rassembled_cnt)
151{
152 hr_t *hr;
153 errno_t rc;
154 size_t assembled_cnt;
155
156 rc = hr_sess_init(&hr);
157 if (rc != EOK)
158 return rc;
159
160 async_exch_t *exch = async_exchange_begin(hr->sess);
161 if (exch == NULL) {
162 rc = EINVAL;
163 goto error;
164 }
165
166 aid_t req = async_send_0(exch, HR_AUTO_ASSEMBLE, NULL);
167
168 rc = async_data_read_start(exch, &assembled_cnt, sizeof(size_t));
169 if (rc != EOK) {
170 async_exchange_end(exch);
171 async_forget(req);
172 return rc;
173 }
174
175 async_exchange_end(exch);
176 async_wait_for(req, &rc);
177
178 if (rassembled_cnt != NULL)
179 *rassembled_cnt = assembled_cnt;
180error:
181 hr_sess_destroy(hr);
182 return rc;
183}
184
[095a989]185static errno_t print_vol_info(size_t index, hr_vol_info_t *vol_info)
186{
187 errno_t rc;
188 size_t i;
189 char *devname;
[dbd91da]190 hr_extent_t *ext;
[095a989]191
192 printf("--- vol %zu ---\n", index);
193
[ca7fa5b]194 printf("svc_id: %" PRIun "\n", vol_info->svc_id);
[095a989]195
196 rc = loc_service_get_name(vol_info->svc_id, &devname);
197 if (rc != EOK)
198 return rc;
199 printf("devname: %s\n", devname);
200
[e47a032]201 printf("status: %s\n", hr_get_vol_status_msg(vol_info->status));
202
[095a989]203 printf("level: %d\n", vol_info->level);
[4066371]204 if (vol_info->level == HR_LVL_4 || vol_info->level == HR_LVL_5) {
205 printf("layout: %s\n",
[fb06476f]206 hr_get_layout_str(vol_info->layout));
[4066371]207 }
[50bed55d]208 if (vol_info->level == HR_LVL_0 || vol_info->level == HR_LVL_4) {
[9c1cf34c]209 if (vol_info->strip_size / 1024 < 1)
[ca7fa5b]210 printf("strip size in bytes: %" PRIu32 "\n",
[9c1cf34c]211 vol_info->strip_size);
212 else
[ca7fa5b]213 printf("strip size: %" PRIu32 "K\n",
[9c1cf34c]214 vol_info->strip_size / 1024);
215 }
[ca7fa5b]216 printf("size in bytes: %" PRIu64 "MiB\n",
[9c1cf34c]217 vol_info->nblocks * vol_info->bsize / 1024 / 1024);
[ca7fa5b]218 printf("size in blocks: %" PRIu64 "\n", vol_info->nblocks);
[9c1cf34c]219 printf("block size: %zu\n", vol_info->bsize);
220
[50bed55d]221 if (vol_info->level == HR_LVL_4)
[dbd91da]222 printf("extents: [P] [status] [index] [devname]\n");
223 else
224 printf("extents: [status] [index] [devname]\n");
[095a989]225 for (i = 0; i < vol_info->extent_no; i++) {
[dbd91da]226 ext = &vol_info->extents[i];
[4200735]227 if (ext->status == HR_EXT_MISSING || ext->status == HR_EXT_NONE) {
[e47a032]228 devname = (char *) "MISSING-devname";
229 } else {
230 rc = loc_service_get_name(ext->svc_id, &devname);
[4200735]231 if (rc != EOK) {
232 printf("loc_service_get_name() failed, skipping...\n");
233 continue;
234 }
[e47a032]235 }
[4066371]236 if (vol_info->level == HR_LVL_4) {
[37a9c1e]237 if ((i == 0 && vol_info->layout == HR_RLQ_RAID4_0) ||
[4066371]238 (i == vol_info->extent_no - 1 &&
[37a9c1e]239 vol_info->layout == HR_RLQ_RAID4_N))
[4066371]240 printf(" P %s %zu %s\n", hr_get_ext_status_msg(ext->status), i, devname);
241 else
242 printf(" %s %zu %s\n", hr_get_ext_status_msg(ext->status), i, devname);
243 } else {
[e47a032]244 printf(" %s %zu %s\n", hr_get_ext_status_msg(ext->status), i, devname);
[4066371]245 }
[095a989]246 }
[5b320ac]247
248 if (vol_info->hotspare_no == 0)
249 return EOK;
250
251 printf("hotspares: [status] [index] [devname]\n");
252 for (i = 0; i < vol_info->hotspare_no; i++) {
253 ext = &vol_info->hotspares[i];
254 if (ext->status == HR_EXT_MISSING) {
255 devname = (char *) "MISSING-devname";
256 } else {
257 rc = loc_service_get_name(ext->svc_id, &devname);
258 if (rc != EOK)
259 return rc;
260 }
261 printf(" %s %zu %s\n",
262 hr_get_ext_status_msg(ext->status), i, devname);
263 }
264
[095a989]265 return EOK;
266}
267
[d1d355f]268errno_t hr_stop(const char *devname)
[a19d7fc4]269{
270 hr_t *hr;
271 errno_t rc;
272 async_exch_t *exch;
273 service_id_t svc_id;
274
275 rc = loc_service_get_id(devname, &svc_id, 0);
276 if (rc != EOK)
277 return rc;
278
279 rc = hr_sess_init(&hr);
280 if (rc != EOK)
281 return rc;
282
283 exch = async_exchange_begin(hr->sess);
284 if (exch == NULL) {
285 rc = EINVAL;
286 goto error;
287 }
[d1d355f]288
289 rc = async_req_1_0(exch, HR_STOP, svc_id);
290 async_exchange_end(exch);
291error:
292 hr_sess_destroy(hr);
293 return rc;
294}
295
296errno_t hr_stop_all(void)
297{
298 hr_t *hr;
299 async_exch_t *exch;
300 errno_t rc;
301
302 rc = hr_sess_init(&hr);
303 if (rc != EOK)
304 return rc;
305
306 exch = async_exchange_begin(hr->sess);
307 if (exch == NULL) {
308 rc = EINVAL;
309 goto error;
310 }
311
312 rc = async_req_0_0(exch, HR_STOP_ALL);
313 async_exchange_end(exch);
314error:
315 hr_sess_destroy(hr);
316 return rc;
317}
318
319errno_t hr_fail_extent(const char *volume_name, unsigned long extent)
320{
321 hr_t *hr;
322 errno_t rc;
323 async_exch_t *exch;
324 service_id_t vol_svc_id;
325
326 rc = loc_service_get_id(volume_name, &vol_svc_id, 0);
327 if (rc != EOK)
328 return rc;
329
330 rc = hr_sess_init(&hr);
331 if (rc != EOK)
332 return rc;
333
334 exch = async_exchange_begin(hr->sess);
335 if (exch == NULL) {
336 rc = EINVAL;
337 goto error;
338 }
339
340 rc = async_req_2_0(exch, HR_FAIL_EXTENT, vol_svc_id, extent);
[a19d7fc4]341 async_exchange_end(exch);
342error:
343 hr_sess_destroy(hr);
344 return rc;
345}
346
[d1d355f]347errno_t hr_add_hotspare(const char *volume_name, const char *hotspare)
[5b320ac]348{
349 hr_t *hr;
350 errno_t rc;
351 async_exch_t *exch;
[d1d355f]352 service_id_t vol_svc_id, hs_svc_id;
353
354 rc = loc_service_get_id(volume_name, &vol_svc_id, 0);
355 if (rc != EOK)
356 return rc;
357
358 rc = loc_service_get_id(hotspare, &hs_svc_id, 0);
359 if (rc != EOK)
360 return rc;
[5b320ac]361
362 rc = hr_sess_init(&hr);
363 if (rc != EOK)
364 return rc;
365
366 exch = async_exchange_begin(hr->sess);
367 if (exch == NULL) {
368 rc = EINVAL;
369 goto error;
370 }
371
372 rc = async_req_2_0(exch, HR_ADD_HOTSPARE, vol_svc_id, hs_svc_id);
373 async_exchange_end(exch);
374error:
375 hr_sess_destroy(hr);
376 return rc;
377}
378
[095a989]379errno_t hr_print_status(void)
380{
381 hr_t *hr;
382 errno_t rc, retval;
383 async_exch_t *exch;
384 aid_t req;
385 size_t size, i;
[a19d7fc4]386 hr_vol_info_t *vols = NULL;
[095a989]387
388 rc = hr_sess_init(&hr);
389 if (rc != EOK)
390 return rc;
391
392 exch = async_exchange_begin(hr->sess);
[a19d7fc4]393 if (exch == NULL) {
394 rc = EINVAL;
395 goto error;
396 }
[095a989]397
398 req = async_send_0(exch, HR_STATUS, NULL);
399 rc = async_data_read_start(exch, &size, sizeof(size_t));
400 if (rc != EOK) {
401 async_exchange_end(exch);
402 async_forget(req);
403 return rc;
404 }
405
406 vols = calloc(size, sizeof(hr_vol_info_t));
407 if (vols == NULL) {
408 async_exchange_end(exch);
409 async_forget(req);
410 return ENOMEM;
411 }
412
413 for (i = 0; i < size; i++) {
414 rc = async_data_read_start(exch, &vols[i],
415 sizeof(hr_vol_info_t));
416 if (rc != EOK) {
417 async_exchange_end(exch);
418 async_forget(req);
419 goto error;
420 }
421 }
422
423 async_exchange_end(exch);
424 async_wait_for(req, &retval);
425 if (retval != EOK) {
426 rc = retval;
427 goto error;
428 }
429
[a19d7fc4]430 if (size == 0) {
431 printf("no active arrays\n");
432 goto error;
433 }
434
[095a989]435 for (i = 0; i < size; i++) {
436 rc = print_vol_info(i, &vols[i]);
437 if (rc != EOK)
438 goto error;
439 }
440
441error:
[a19d7fc4]442 hr_sess_destroy(hr);
[095a989]443 if (vols != NULL)
444 free(vols);
445 return rc;
446}
447
[e47a032]448const char *hr_get_vol_status_msg(hr_vol_status_t status)
449{
450 switch (status) {
[e24c064]451 case HR_VOL_NONE:
452 return "NONE/UNKNOWN";
[e47a032]453 case HR_VOL_ONLINE:
454 return "ONLINE";
455 case HR_VOL_FAULTY:
456 return "FAULTY";
[13ce552]457 case HR_VOL_DEGRADED:
458 return "DEGRADED";
[5b320ac]459 case HR_VOL_REBUILD:
460 return "REBUILD";
[e47a032]461 default:
[e24c064]462 return "Invalid state value";
[e47a032]463 }
464}
465
466const char *hr_get_ext_status_msg(hr_ext_status_t status)
467{
468 switch (status) {
[e24c064]469 case HR_EXT_NONE:
470 return "NONE/UNKNOWN";
[3a68baa]471 case HR_EXT_INVALID:
472 return "INVALID";
[e47a032]473 case HR_EXT_ONLINE:
474 return "ONLINE";
475 case HR_EXT_MISSING:
476 return "MISSING";
477 case HR_EXT_FAILED:
478 return "FAILED";
[5b320ac]479 case HR_EXT_REBUILD:
480 return "REBUILD";
481 case HR_EXT_HOTSPARE:
482 return "HOTSPARE";
[e47a032]483 default:
[e24c064]484 return "Invalid state value";
[e47a032]485 }
486}
487
[fb06476f]488const char *hr_get_layout_str(hr_layout_t layout)
[4066371]489{
[fb06476f]490 switch (layout) {
491 case HR_RLQ_NONE:
492 return "RAID layout not set";
493 case HR_RLQ_RAID4_0:
494 return "RAID-4 Non-Rotating Parity 0";
495 case HR_RLQ_RAID4_N:
496 return "RAID-4 Non-Rotating Parity N";
497 case HR_RLQ_RAID5_0R:
498 return "RAID-5 Rotating Parity 0 with Data Restart";
499 case HR_RLQ_RAID5_NR:
500 return "RAID-5 Rotating Parity N with Data Restart";
501 case HR_RLQ_RAID5_NC:
502 return "RAID-5 Rotating Parity N with Data Continuation";
[4066371]503 default:
[fb06476f]504 return "Invalid RAID layout";
[4066371]505 }
506}
507
[b883aa8]508const char *hr_get_metadata_type_str(hr_metadata_type_t type)
509{
510 switch (type) {
511 case HR_METADATA_NATIVE:
512 return "Native HelenRAID metadata";
513 case HR_METADATA_GEOM_MIRROR:
514 return "GEOM::MIRROR";
515 case HR_METADATA_GEOM_STRIPE:
516 return "GEOM::STRIPE";
517 default:
518 return "Invalid metadata type value";
519 }
520}
521
[94d84a0]522/** @}
523 */
Note: See TracBrowser for help on using the repository browser.