source: mainline/uspace/lib/device/src/hr.c@ 7d25273

Last change on this file since 7d25273 was 37a9c1e, checked in by Miroslav Cimerman <mc@…>, 7 months ago

hr: hr_volume_t: rename RLQ → layout

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