Changeset e0bbecb in mainline
- Timestamp:
- 2025-06-09T20:01:03Z (7 days ago)
- Children:
- e2a8fd2
- Parents:
- 431b513
- Location:
- uspace
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/hrctl/hrctl.c
r431b513 re0bbecb 34 34 */ 35 35 36 #include <capa.h> 36 37 #include <ctype.h> 37 38 #include <errno.h> … … 51 52 static errno_t fill_config_devs(int, char **, hr_config_t *); 52 53 static errno_t get_vol_configs_from_sif(const char *, hr_config_t **, size_t *); 54 static int create_from_config(hr_t *, const char *); 55 static int create_from_argv(hr_t *, int, char **); 56 static int handle_create(hr_t *, int, char **); 57 static int assemble_from_config(hr_t *, const char *); 58 static int assemble_from_argv(hr_t *, int, char **); 59 static int handle_assemble(hr_t *, int, char **); 60 static int handle_disassemble(hr_t *, int, char **); 61 static int handle_modify(hr_t *, int, char **); 62 static errno_t print_vol_info(hr_vol_info_t *); 63 static int handle_state(hr_t *, int, char **); 53 64 54 65 static const char usage_str[] = … … 76 87 " -h, --hotspare device add hotspare.\n" 77 88 "\n" 78 " -s, --state Display state of active volumes.\n"89 " -s, --state [volume] Display state of active volume(s).\n" 79 90 "\n" 80 91 "level can be one of:\n" … … 107 118 "\t- volume name must be shorter than 32 characters\n" 108 119 "\t- automatic assembly and disassembly on nested volumes is UNDEFINED!\n"; 109 110 static void usage(void)111 {112 printf("%s", usage_str);113 }114 115 static errno_t fill_config_devs(int argc, char **argv, hr_config_t *cfg)116 {117 errno_t rc;118 size_t i;119 120 for (i = 0; i < HR_MAX_EXTENTS && optind < argc; i++) {121 rc = loc_service_get_id(argv[optind], &cfg->devs[i], 0);122 if (rc == ENOENT) {123 printf(NAME ": device \"%s\" not found, aborting\n",124 argv[optind]);125 return ENOENT;126 } else if (rc != EOK) {127 printf(NAME ": error resolving device \"%s\", aborting\n",128 argv[optind]);129 return EINVAL;130 }131 optind++;132 }133 134 if (optind < argc) {135 printf(NAME ": too many devices specified, max = %u\n",136 HR_MAX_EXTENTS);137 return ELIMIT;138 }139 140 cfg->dev_no = i;141 142 return EOK;143 }144 145 static errno_t get_vol_configs_from_sif(const char *path, hr_config_t **rcfgs,146 size_t *rcount)147 {148 errno_t rc;149 sif_doc_t *doc = NULL;150 sif_node_t *hrconfig_node;151 sif_node_t *root_node;152 sif_node_t *volume_node;153 sif_node_t *nextent;154 const char *ntype;155 const char *devname;156 const char *level_str;157 const char *extent_devname;158 hr_config_t *vol_configs = NULL;159 160 rc = sif_load(path, &doc);161 if (rc != EOK)162 goto error;163 164 root_node = sif_get_root(doc);165 166 hrconfig_node = sif_node_first_child(root_node);167 ntype = sif_node_get_type(hrconfig_node);168 if (str_cmp(ntype, "hrconfig") != 0) {169 rc = EINVAL;170 goto error;171 }172 173 size_t vol_count = 0;174 volume_node = sif_node_first_child(hrconfig_node);175 while (volume_node) {176 ntype = sif_node_get_type(volume_node);177 if (str_cmp(ntype, "volume") != 0) {178 rc = EINVAL;179 goto error;180 }181 vol_configs = realloc(vol_configs,182 (vol_count + 1) * sizeof(hr_config_t));183 if (vol_configs == NULL) {184 rc = ENOMEM;185 goto error;186 }187 188 hr_config_t *cfg = vol_configs + vol_count;189 190 devname = sif_node_get_attr(volume_node, "devname");191 if (devname == NULL) {192 rc = EINVAL;193 goto error;194 }195 str_cpy(cfg->devname, sizeof(cfg->devname), devname);196 197 level_str = sif_node_get_attr(volume_node, "level");198 if (level_str == NULL)199 cfg->level = HR_LVL_UNKNOWN;200 else201 cfg->level = strtol(level_str, NULL, 10);202 203 nextent = sif_node_first_child(volume_node);204 size_t i = 0;205 while (nextent && i < HR_MAX_EXTENTS) {206 ntype = sif_node_get_type(nextent);207 if (str_cmp(ntype, "extent") != 0) {208 rc = EINVAL;209 goto error;210 }211 212 extent_devname = sif_node_get_attr(nextent, "devname");213 if (extent_devname == NULL) {214 rc = EINVAL;215 goto error;216 }217 218 rc = loc_service_get_id(extent_devname, &cfg->devs[i], 0);219 if (rc == ENOENT) {220 printf(NAME ": no device \"%s\", marking as missing\n",221 extent_devname);222 cfg->devs[i] = 0;223 rc = EOK;224 } else if (rc != EOK) {225 printf(NAME ": error resolving device \"%s\", aborting\n",226 extent_devname);227 goto error;228 }229 230 nextent = sif_node_next_child(nextent);231 i++;232 }233 234 if (i > HR_MAX_EXTENTS) {235 printf(NAME ": too many devices specified in volume \"%s\", "236 "skipping\n", devname);237 memset(&vol_configs[vol_count], 0, sizeof(hr_config_t));238 } else {239 cfg->dev_no = i;240 vol_count++;241 }242 243 volume_node = sif_node_next_child(volume_node);244 }245 246 if (rc == EOK) {247 if (rcount)248 *rcount = vol_count;249 if (rcfgs)250 *rcfgs = vol_configs;251 }252 error:253 if (doc != NULL)254 sif_delete(doc);255 if (rc != EOK) {256 if (vol_configs)257 free(vol_configs);258 }259 return rc;260 }261 262 static int create_from_config(hr_t *hr, const char *config_path)263 {264 hr_config_t *vol_configs = NULL;265 size_t vol_count = 0;266 errno_t rc = get_vol_configs_from_sif(config_path, &vol_configs,267 &vol_count);268 if (rc != EOK) {269 printf(NAME ": config parsing failed\n");270 return EXIT_FAILURE;271 }272 273 for (size_t i = 0; i < vol_count; i++) {274 rc = hr_create(hr, &vol_configs[i]);275 if (rc != EOK) {276 printf(NAME ": creation of volume \"%s\" failed: %s, "277 "but continuing\n",278 vol_configs[i].devname, str_error(rc));279 } else {280 printf(NAME ": volume \"%s\" successfully created\n",281 vol_configs[i].devname);282 }283 }284 285 free(vol_configs);286 return EXIT_SUCCESS;287 }288 289 static int create_from_argv(hr_t *hr, int argc, char **argv)290 {291 /* we need name + --level + arg + at least one extent */292 if (optind + 3 >= argc) {293 printf(NAME ": not enough arguments\n");294 return EXIT_FAILURE;295 }296 297 hr_config_t *vol_config = calloc(1, sizeof(hr_config_t));298 if (vol_config == NULL) {299 printf(NAME ": not enough memory\n");300 return EXIT_FAILURE;301 }302 303 const char *name = argv[optind++];304 if (str_size(name) >= HR_DEVNAME_LEN) {305 printf(NAME ": devname must be less then 32 bytes.\n");306 goto error;307 }308 309 str_cpy(vol_config->devname, HR_DEVNAME_LEN, name);310 311 const char *level_opt = argv[optind++];312 if (str_cmp(level_opt, "--level") != 0 &&313 str_cmp(level_opt, "-l") != 0) {314 printf(NAME ": unknown option \"%s\"\n", level_opt);315 goto error;316 }317 318 const char *level_str = argv[optind++];319 if (str_size(level_str) == 1 && isdigit(level_str[0])) {320 vol_config->level = strtol(level_str, NULL, 10);321 } else {322 if (str_cmp(level_str, "mirror") == 0 ||323 str_cmp(level_str, "mirroring") == 0) {324 vol_config->level = HR_LVL_1;325 } else if (str_cmp(level_str, "stripe") == 0 ||326 str_cmp(level_str, "striping") == 0) {327 vol_config->level = HR_LVL_0;328 } else if (str_cmp(level_str, "parity") == 0 ||329 str_cmp(level_str, "parity_distributed") == 0) {330 vol_config->level = HR_LVL_5;331 } else if (str_cmp(level_str, "parity_dedicated") == 0) {332 vol_config->level = HR_LVL_4;333 } else {334 printf(NAME ": unknown level \"%s\"\n", level_str);335 goto error;336 }337 }338 339 errno_t rc = fill_config_devs(argc, argv, vol_config);340 if (rc != EOK)341 goto error;342 343 rc = hr_create(hr, vol_config);344 if (rc != EOK) {345 printf(NAME ": creation failed: %s\n", str_error(rc));346 goto error;347 } else {348 printf(NAME ": volume \"%s\" successfully created\n",349 vol_config->devname);350 }351 352 free(vol_config);353 return EXIT_SUCCESS;354 error:355 free(vol_config);356 return EXIT_FAILURE;357 }358 359 static int handle_create(hr_t *hr, int argc, char **argv)360 {361 int rc;362 363 if (optind >= argc) {364 printf(NAME ": no arguments to --create\n");365 return EXIT_FAILURE;366 }367 368 if (str_cmp(argv[optind], "-f") == 0) {369 optind++;370 if (optind >= argc) {371 printf(NAME ": not enough arguments\n");372 return EXIT_FAILURE;373 }374 375 const char *config_path = argv[optind++];376 377 if (optind < argc) {378 printf(NAME ": unexpected arguments\n");379 return EXIT_FAILURE;380 }381 382 rc = create_from_config(hr, config_path);383 } else {384 rc = create_from_argv(hr, argc, argv);385 }386 387 return rc;388 }389 390 static int assemble_from_config(hr_t *hr, const char *config_path)391 {392 hr_config_t *vol_configs = NULL;393 size_t vol_count = 0;394 errno_t rc = get_vol_configs_from_sif(config_path, &vol_configs,395 &vol_count);396 if (rc != EOK) {397 printf(NAME ": config parsing failed\n");398 return EXIT_FAILURE;399 }400 401 size_t cnt = 0;402 for (size_t i = 0; i < vol_count; i++) {403 size_t tmpcnt = 0;404 (void)hr_assemble(hr, &vol_configs[i], &tmpcnt);405 cnt += tmpcnt;406 }407 408 printf(NAME ": assembled %zu volumes\n", cnt);409 410 free(vol_configs);411 return EXIT_SUCCESS;412 }413 414 static int assemble_from_argv(hr_t *hr, int argc, char **argv)415 {416 hr_config_t *vol_config = calloc(1, sizeof(hr_config_t));417 if (vol_config == NULL) {418 printf(NAME ": not enough memory\n");419 return ENOMEM;420 }421 422 errno_t rc = fill_config_devs(argc, argv, vol_config);423 if (rc != EOK)424 goto error;425 426 size_t cnt;427 rc = hr_assemble(hr, vol_config, &cnt);428 if (rc != EOK) {429 printf(NAME ": assmeble failed: %s\n", str_error(rc));430 goto error;431 }432 433 printf("hrctl: assembled %zu volumes\n", cnt);434 435 free(vol_config);436 return EXIT_SUCCESS;437 error:438 free(vol_config);439 return EXIT_FAILURE;440 }441 442 static int handle_assemble(hr_t *hr, int argc, char **argv)443 {444 int rc;445 446 if (optind >= argc) {447 size_t cnt;448 errno_t rc = hr_auto_assemble(hr, &cnt);449 if (rc != EOK) {450 /* XXX: here have own error codes */451 printf("hrctl: auto assemble rc: %s\n", str_error(rc));452 return EXIT_FAILURE;453 }454 455 printf(NAME ": auto assembled %zu volumes\n", cnt);456 return EXIT_SUCCESS;457 }458 459 if (str_cmp(argv[optind], "-f") == 0) {460 if (++optind >= argc) {461 printf(NAME ": not enough arguments\n");462 return EXIT_FAILURE;463 }464 const char *config_path = argv[optind++];465 466 if (optind < argc) {467 printf(NAME ": unexpected arguments\n");468 return EXIT_FAILURE;469 }470 471 rc = assemble_from_config(hr, config_path);472 } else {473 rc = assemble_from_argv(hr, argc, argv);474 }475 476 return rc;477 }478 479 static int handle_disassemble(hr_t *hr, int argc, char **argv)480 {481 if (optind >= argc) {482 errno_t rc = hr_stop_all(hr);483 if (rc != EOK) {484 printf(NAME ": stopping some volumes failed: %s\n",485 str_error(rc));486 return EXIT_FAILURE;487 }488 return EXIT_SUCCESS;489 }490 491 if (optind + 1 < argc) {492 printf(NAME ": only 1 device can be manually specified\n");493 return EXIT_FAILURE;494 }495 496 const char *devname = argv[optind++];497 498 errno_t rc = hr_stop(hr, devname);499 if (rc != EOK) {500 printf(NAME ": disassembly of device \"%s\" failed: %s\n",501 devname, str_error(rc));502 return EXIT_FAILURE;503 }504 505 return EXIT_SUCCESS;506 }507 508 static int handle_modify(hr_t *hr, int argc, char **argv)509 {510 if (optind >= argc) {511 printf(NAME ": no arguments to --modify\n");512 return EXIT_FAILURE;513 }514 515 const char *volname = argv[optind++];516 517 /* at least 1 option and its agument */518 if (optind + 1 >= argc) {519 printf(NAME ": not enough arguments\n");520 return EXIT_FAILURE;521 }522 523 if (optind + 2 < argc) {524 printf(NAME ": unexpected arguments\n");525 return EXIT_FAILURE;526 }527 528 if (str_cmp(argv[optind], "--fail") == 0 ||529 str_cmp(argv[optind], "-f") == 0) {530 optind++;531 unsigned long extent = strtol(argv[optind++], NULL, 10);532 errno_t rc = hr_fail_extent(hr, volname, extent);533 if (rc != EOK) {534 printf(NAME ": failing extent failed: %s\n",535 str_error(rc));536 return EXIT_FAILURE;537 }538 } else if (str_cmp(argv[optind], "--hotspare") == 0 ||539 str_cmp(argv[optind], "-h") == 0) {540 optind++;541 errno_t rc = hr_add_hotspare(hr, volname, argv[optind++]);542 if (rc != EOK) {543 printf(NAME ": adding hotspare failed: %s\n",544 str_error(rc));545 return EXIT_FAILURE;546 }547 } else {548 printf(NAME ": unknown argument\n");549 return EXIT_FAILURE;550 }551 552 return EXIT_SUCCESS;553 }554 555 static int handle_state(hr_t *hr, int argc, char **argv)556 {557 (void)argc;558 (void)argv;559 560 errno_t rc = hr_print_state(hr);561 if (rc != EOK) {562 printf(NAME ": state printing failed: %s\n", str_error(rc));563 return EXIT_FAILURE;564 }565 566 return EXIT_SUCCESS;567 }568 120 569 121 int main(int argc, char **argv) … … 629 181 } 630 182 183 static void usage(void) 184 { 185 printf("%s", usage_str); 186 } 187 188 static errno_t fill_config_devs(int argc, char **argv, hr_config_t *cfg) 189 { 190 errno_t rc; 191 size_t i; 192 193 for (i = 0; i < HR_MAX_EXTENTS && optind < argc; i++) { 194 rc = loc_service_get_id(argv[optind], &cfg->devs[i], 0); 195 if (rc == ENOENT) { 196 printf(NAME ": device \"%s\" not found, aborting\n", 197 argv[optind]); 198 return ENOENT; 199 } else if (rc != EOK) { 200 printf(NAME ": error resolving device \"%s\", aborting\n", 201 argv[optind]); 202 return EINVAL; 203 } 204 optind++; 205 } 206 207 if (optind < argc) { 208 printf(NAME ": too many devices specified, max = %u\n", 209 HR_MAX_EXTENTS); 210 return ELIMIT; 211 } 212 213 cfg->dev_no = i; 214 215 return EOK; 216 } 217 218 static errno_t get_vol_configs_from_sif(const char *path, hr_config_t **rcfgs, 219 size_t *rcount) 220 { 221 errno_t rc; 222 sif_doc_t *doc = NULL; 223 sif_node_t *hrconfig_node; 224 sif_node_t *root_node; 225 sif_node_t *volume_node; 226 sif_node_t *nextent; 227 const char *ntype; 228 const char *devname; 229 const char *level_str; 230 const char *extent_devname; 231 hr_config_t *vol_configs = NULL; 232 233 rc = sif_load(path, &doc); 234 if (rc != EOK) 235 goto error; 236 237 root_node = sif_get_root(doc); 238 239 hrconfig_node = sif_node_first_child(root_node); 240 ntype = sif_node_get_type(hrconfig_node); 241 if (str_cmp(ntype, "hrconfig") != 0) { 242 rc = EINVAL; 243 goto error; 244 } 245 246 size_t vol_count = 0; 247 volume_node = sif_node_first_child(hrconfig_node); 248 while (volume_node) { 249 ntype = sif_node_get_type(volume_node); 250 if (str_cmp(ntype, "volume") != 0) { 251 rc = EINVAL; 252 goto error; 253 } 254 vol_configs = realloc(vol_configs, 255 (vol_count + 1) * sizeof(hr_config_t)); 256 if (vol_configs == NULL) { 257 rc = ENOMEM; 258 goto error; 259 } 260 261 hr_config_t *cfg = vol_configs + vol_count; 262 263 devname = sif_node_get_attr(volume_node, "devname"); 264 if (devname == NULL) { 265 rc = EINVAL; 266 goto error; 267 } 268 str_cpy(cfg->devname, sizeof(cfg->devname), devname); 269 270 level_str = sif_node_get_attr(volume_node, "level"); 271 if (level_str == NULL) 272 cfg->level = HR_LVL_UNKNOWN; 273 else 274 cfg->level = strtol(level_str, NULL, 10); 275 276 nextent = sif_node_first_child(volume_node); 277 size_t i = 0; 278 while (nextent && i < HR_MAX_EXTENTS) { 279 ntype = sif_node_get_type(nextent); 280 if (str_cmp(ntype, "extent") != 0) { 281 rc = EINVAL; 282 goto error; 283 } 284 285 extent_devname = sif_node_get_attr(nextent, "devname"); 286 if (extent_devname == NULL) { 287 rc = EINVAL; 288 goto error; 289 } 290 291 rc = loc_service_get_id(extent_devname, &cfg->devs[i], 0); 292 if (rc == ENOENT) { 293 printf(NAME ": no device \"%s\", marking as missing\n", 294 extent_devname); 295 cfg->devs[i] = 0; 296 rc = EOK; 297 } else if (rc != EOK) { 298 printf(NAME ": error resolving device \"%s\", aborting\n", 299 extent_devname); 300 goto error; 301 } 302 303 nextent = sif_node_next_child(nextent); 304 i++; 305 } 306 307 if (i > HR_MAX_EXTENTS) { 308 printf(NAME ": too many devices specified in volume \"%s\", " 309 "skipping\n", devname); 310 memset(&vol_configs[vol_count], 0, sizeof(hr_config_t)); 311 } else { 312 cfg->dev_no = i; 313 vol_count++; 314 } 315 316 volume_node = sif_node_next_child(volume_node); 317 } 318 319 if (rc == EOK) { 320 if (rcount) 321 *rcount = vol_count; 322 if (rcfgs) 323 *rcfgs = vol_configs; 324 } 325 error: 326 if (doc != NULL) 327 sif_delete(doc); 328 if (rc != EOK) { 329 if (vol_configs) 330 free(vol_configs); 331 } 332 return rc; 333 } 334 335 static int create_from_config(hr_t *hr, const char *config_path) 336 { 337 hr_config_t *vol_configs = NULL; 338 size_t vol_count = 0; 339 errno_t rc = get_vol_configs_from_sif(config_path, &vol_configs, 340 &vol_count); 341 if (rc != EOK) { 342 printf(NAME ": config parsing failed\n"); 343 return EXIT_FAILURE; 344 } 345 346 for (size_t i = 0; i < vol_count; i++) { 347 rc = hr_create(hr, &vol_configs[i]); 348 if (rc != EOK) { 349 printf(NAME ": creation of volume \"%s\" failed: %s, " 350 "but continuing\n", 351 vol_configs[i].devname, str_error(rc)); 352 } else { 353 printf(NAME ": volume \"%s\" successfully created\n", 354 vol_configs[i].devname); 355 } 356 } 357 358 free(vol_configs); 359 return EXIT_SUCCESS; 360 } 361 362 static int create_from_argv(hr_t *hr, int argc, char **argv) 363 { 364 /* we need name + --level + arg + at least one extent */ 365 if (optind + 3 >= argc) { 366 printf(NAME ": not enough arguments\n"); 367 return EXIT_FAILURE; 368 } 369 370 hr_config_t *vol_config = calloc(1, sizeof(hr_config_t)); 371 if (vol_config == NULL) { 372 printf(NAME ": not enough memory\n"); 373 return EXIT_FAILURE; 374 } 375 376 const char *name = argv[optind++]; 377 if (str_size(name) >= HR_DEVNAME_LEN) { 378 printf(NAME ": devname must be less then 32 bytes.\n"); 379 goto error; 380 } 381 382 str_cpy(vol_config->devname, HR_DEVNAME_LEN, name); 383 384 const char *level_opt = argv[optind++]; 385 if (str_cmp(level_opt, "--level") != 0 && 386 str_cmp(level_opt, "-l") != 0) { 387 printf(NAME ": unknown option \"%s\"\n", level_opt); 388 goto error; 389 } 390 391 const char *level_str = argv[optind++]; 392 if (str_size(level_str) == 1 && isdigit(level_str[0])) { 393 vol_config->level = strtol(level_str, NULL, 10); 394 } else { 395 if (str_cmp(level_str, "mirror") == 0 || 396 str_cmp(level_str, "mirroring") == 0) { 397 vol_config->level = HR_LVL_1; 398 } else if (str_cmp(level_str, "stripe") == 0 || 399 str_cmp(level_str, "striping") == 0) { 400 vol_config->level = HR_LVL_0; 401 } else if (str_cmp(level_str, "parity") == 0 || 402 str_cmp(level_str, "parity_distributed") == 0) { 403 vol_config->level = HR_LVL_5; 404 } else if (str_cmp(level_str, "parity_dedicated") == 0) { 405 vol_config->level = HR_LVL_4; 406 } else { 407 printf(NAME ": unknown level \"%s\"\n", level_str); 408 goto error; 409 } 410 } 411 412 errno_t rc = fill_config_devs(argc, argv, vol_config); 413 if (rc != EOK) 414 goto error; 415 416 rc = hr_create(hr, vol_config); 417 if (rc != EOK) { 418 printf(NAME ": creation failed: %s\n", str_error(rc)); 419 goto error; 420 } else { 421 printf(NAME ": volume \"%s\" successfully created\n", 422 vol_config->devname); 423 } 424 425 free(vol_config); 426 return EXIT_SUCCESS; 427 error: 428 free(vol_config); 429 return EXIT_FAILURE; 430 } 431 432 static int handle_create(hr_t *hr, int argc, char **argv) 433 { 434 int rc; 435 436 if (optind >= argc) { 437 printf(NAME ": no arguments to --create\n"); 438 return EXIT_FAILURE; 439 } 440 441 if (str_cmp(argv[optind], "-f") == 0) { 442 optind++; 443 if (optind >= argc) { 444 printf(NAME ": not enough arguments\n"); 445 return EXIT_FAILURE; 446 } 447 448 const char *config_path = argv[optind++]; 449 450 if (optind < argc) { 451 printf(NAME ": unexpected arguments\n"); 452 return EXIT_FAILURE; 453 } 454 455 rc = create_from_config(hr, config_path); 456 } else { 457 rc = create_from_argv(hr, argc, argv); 458 } 459 460 return rc; 461 } 462 463 static int assemble_from_config(hr_t *hr, const char *config_path) 464 { 465 hr_config_t *vol_configs = NULL; 466 size_t vol_count = 0; 467 errno_t rc = get_vol_configs_from_sif(config_path, &vol_configs, 468 &vol_count); 469 if (rc != EOK) { 470 printf(NAME ": config parsing failed\n"); 471 return EXIT_FAILURE; 472 } 473 474 size_t cnt = 0; 475 for (size_t i = 0; i < vol_count; i++) { 476 size_t tmpcnt = 0; 477 (void)hr_assemble(hr, &vol_configs[i], &tmpcnt); 478 cnt += tmpcnt; 479 } 480 481 printf(NAME ": assembled %zu volumes\n", cnt); 482 483 free(vol_configs); 484 return EXIT_SUCCESS; 485 } 486 487 static int assemble_from_argv(hr_t *hr, int argc, char **argv) 488 { 489 hr_config_t *vol_config = calloc(1, sizeof(hr_config_t)); 490 if (vol_config == NULL) { 491 printf(NAME ": not enough memory\n"); 492 return ENOMEM; 493 } 494 495 errno_t rc = fill_config_devs(argc, argv, vol_config); 496 if (rc != EOK) 497 goto error; 498 499 size_t cnt; 500 rc = hr_assemble(hr, vol_config, &cnt); 501 if (rc != EOK) { 502 printf(NAME ": assmeble failed: %s\n", str_error(rc)); 503 goto error; 504 } 505 506 printf("hrctl: assembled %zu volumes\n", cnt); 507 508 free(vol_config); 509 return EXIT_SUCCESS; 510 error: 511 free(vol_config); 512 return EXIT_FAILURE; 513 } 514 515 static int handle_assemble(hr_t *hr, int argc, char **argv) 516 { 517 int rc; 518 519 if (optind >= argc) { 520 size_t cnt; 521 errno_t rc = hr_auto_assemble(hr, &cnt); 522 if (rc != EOK) { 523 /* XXX: here have own error codes */ 524 printf("hrctl: auto assemble rc: %s\n", str_error(rc)); 525 return EXIT_FAILURE; 526 } 527 528 printf(NAME ": auto assembled %zu volumes\n", cnt); 529 return EXIT_SUCCESS; 530 } 531 532 if (str_cmp(argv[optind], "-f") == 0) { 533 if (++optind >= argc) { 534 printf(NAME ": not enough arguments\n"); 535 return EXIT_FAILURE; 536 } 537 const char *config_path = argv[optind++]; 538 539 if (optind < argc) { 540 printf(NAME ": unexpected arguments\n"); 541 return EXIT_FAILURE; 542 } 543 544 rc = assemble_from_config(hr, config_path); 545 } else { 546 rc = assemble_from_argv(hr, argc, argv); 547 } 548 549 return rc; 550 } 551 552 static int handle_disassemble(hr_t *hr, int argc, char **argv) 553 { 554 if (optind >= argc) { 555 errno_t rc = hr_stop_all(hr); 556 if (rc != EOK) { 557 printf(NAME ": stopping some volumes failed: %s\n", 558 str_error(rc)); 559 return EXIT_FAILURE; 560 } 561 return EXIT_SUCCESS; 562 } 563 564 if (optind + 1 < argc) { 565 printf(NAME ": only 1 device can be manually specified\n"); 566 return EXIT_FAILURE; 567 } 568 569 const char *devname = argv[optind++]; 570 571 errno_t rc = hr_stop(hr, devname); 572 if (rc != EOK) { 573 printf(NAME ": disassembly of device \"%s\" failed: %s\n", 574 devname, str_error(rc)); 575 return EXIT_FAILURE; 576 } 577 578 return EXIT_SUCCESS; 579 } 580 581 static int handle_modify(hr_t *hr, int argc, char **argv) 582 { 583 if (optind >= argc) { 584 printf(NAME ": no arguments to --modify\n"); 585 return EXIT_FAILURE; 586 } 587 588 const char *volname = argv[optind++]; 589 590 /* at least 1 option and its agument */ 591 if (optind + 1 >= argc) { 592 printf(NAME ": not enough arguments\n"); 593 return EXIT_FAILURE; 594 } 595 596 if (optind + 2 < argc) { 597 printf(NAME ": unexpected arguments\n"); 598 return EXIT_FAILURE; 599 } 600 601 if (str_cmp(argv[optind], "--fail") == 0 || 602 str_cmp(argv[optind], "-f") == 0) { 603 optind++; 604 unsigned long extent = strtol(argv[optind++], NULL, 10); 605 errno_t rc = hr_fail_extent(hr, volname, extent); 606 if (rc != EOK) { 607 printf(NAME ": failing extent failed: %s\n", 608 str_error(rc)); 609 return EXIT_FAILURE; 610 } 611 } else if (str_cmp(argv[optind], "--hotspare") == 0 || 612 str_cmp(argv[optind], "-h") == 0) { 613 optind++; 614 errno_t rc = hr_add_hotspare(hr, volname, argv[optind++]); 615 if (rc != EOK) { 616 printf(NAME ": adding hotspare failed: %s\n", 617 str_error(rc)); 618 return EXIT_FAILURE; 619 } 620 } else { 621 printf(NAME ": unknown argument\n"); 622 return EXIT_FAILURE; 623 } 624 625 return EXIT_SUCCESS; 626 } 627 628 static errno_t print_vol_info(hr_vol_info_t *info) 629 { 630 errno_t rc; 631 size_t i; 632 hr_extent_t *ext; 633 const char *devname; 634 635 printf("volume: \"%s\" (%" PRIun ")\n", info->devname, info->svc_id); 636 637 printf("| metadata type: %s\n", 638 hr_get_metadata_type_str(info->meta_type)); 639 printf("| level: %s\n", hr_get_level_str(info->level)); 640 if (info->layout != HR_RLQ_NONE) 641 printf("| layout: %s\n", 642 hr_get_layout_str(info->layout)); 643 644 if (info->strip_size > 0) { 645 if (info->strip_size < 1024) { 646 printf("| strip size: %" PRIu32 "B\n", 647 info->strip_size); 648 } else { 649 printf("| strip size: %" PRIu32 "KiB\n", 650 info->strip_size / 1024); 651 } 652 } 653 654 printf("| no. of extents: %zu\n", info->extent_no); 655 printf("|no. of hotspares: %zu\n", info->hotspare_no); 656 printf("|number of blocks: %" PRIu64 "\n", info->data_blkno); 657 printf("| block size: %zuB\n", info->bsize); 658 659 capa_spec_t capa; 660 char *scapa = NULL; 661 capa_from_blocks(info->data_blkno, info->bsize, &capa); 662 capa_simplify(&capa); 663 rc = capa_format(&capa, &scapa); 664 if (rc != EOK) { 665 printf(NAME ": failed to format capacity: %s\n", str_error(rc)); 666 return rc; 667 } 668 669 printf("| volume capacity: %s\n", scapa); 670 671 free(scapa); 672 673 printf("| state: %s\n", hr_get_vol_state_str(info->state)); 674 printf("| extents:\n"); 675 676 for (i = 0; i < info->extent_no; i++) { 677 ext = &info->extents[i]; 678 char *tmpname = NULL; 679 if (ext->state == HR_EXT_MISSING || ext->state == HR_EXT_NONE) { 680 devname = "MISSING"; 681 } else { 682 rc = loc_service_get_name(ext->svc_id, &tmpname); 683 if (rc != EOK) 684 devname = "MISSING"; 685 else 686 devname = tmpname; 687 } 688 printf("| %zu %s\n", i, hr_get_ext_state_str(ext->state)); 689 printf("| %s\n", devname); 690 if (tmpname != NULL) 691 free(tmpname); 692 } 693 694 if (info->hotspare_no == 0) 695 return EOK; 696 697 printf("| hotspares:\n"); 698 for (i = 0; i < info->hotspare_no; i++) { 699 ext = &info->hotspares[i]; 700 char *tmpname; 701 if (ext->state == HR_EXT_MISSING || ext->state == HR_EXT_NONE) { 702 devname = "MISSING"; 703 } else { 704 rc = loc_service_get_name(ext->svc_id, &tmpname); 705 if (rc != EOK) 706 devname = "MISSING"; 707 else 708 devname = tmpname; 709 } 710 printf("| %zu %s\n", i, hr_get_ext_state_str(ext->state)); 711 printf("| %s\n", devname); 712 if (tmpname != NULL) 713 free(tmpname); 714 } 715 716 return EOK; 717 } 718 719 static int handle_state(hr_t *hr, int argc, char **argv) 720 { 721 errno_t rc; 722 size_t cnt; 723 hr_pair_vol_state_t *pairs = NULL; 724 char *devname; 725 726 /* print state of all volumes */ 727 if (optind >= argc) { 728 rc = hr_get_vol_states(hr, &pairs, &cnt); 729 if (rc != EOK) { 730 printf(NAME ": failed getting state of volumes: %s\n", 731 str_error(rc)); 732 return EXIT_FAILURE; 733 } 734 735 if (cnt == 0) { 736 printf(NAME ": no active volumes\n"); 737 return EXIT_SUCCESS; 738 } 739 740 for (size_t i = 0; i < cnt; i++) { 741 service_id_t svc_id = pairs[i].svc_id; 742 hr_vol_state_t state = pairs[i].state; 743 rc = loc_service_get_name(svc_id, &devname); 744 if (rc != EOK) { 745 printf(NAME ": getting service name failed: " 746 "%s\n", str_error(rc)); 747 return EXIT_FAILURE; 748 } 749 printf("volume \"%s\" (%" PRIun ") %s\n", devname, 750 svc_id, hr_get_vol_state_str(state)); 751 752 free(devname); 753 } 754 free(pairs); 755 756 return EXIT_SUCCESS; 757 } 758 759 /* print volume info of requested volumes */ 760 while (optind < argc) { 761 service_id_t svc_id; 762 devname = argv[optind++]; 763 rc = loc_service_get_id(devname, &svc_id, 0); 764 if (rc != EOK) { 765 printf(NAME ": getting service id of \"%s\" failed: " 766 "%s\n", devname, str_error(rc)); 767 return EXIT_FAILURE; 768 } 769 770 hr_vol_info_t info; 771 rc = hr_get_vol_info(hr, svc_id, &info); 772 if (rc != EOK) { 773 printf(NAME ": getting volume info failed: %s\n", 774 str_error(rc)); 775 return EXIT_FAILURE; 776 } 777 778 rc = print_vol_info(&info); 779 if (rc != EOK) { 780 printf(NAME ": volume info printing failed: %s\n", 781 str_error(rc)); 782 return EXIT_FAILURE; 783 } 784 } 785 786 return EXIT_SUCCESS; 787 } 788 631 789 /** @} 632 790 */ -
uspace/app/hrctl/meson.build
r431b513 re0bbecb 1 1 # 2 # Copyright (c) 202 4Miroslav Cimerman2 # Copyright (c) 2025 Miroslav Cimerman 3 3 # All rights reserved. 4 4 # -
uspace/lib/device/include/hr.h
r431b513 re0bbecb 82 82 } hr_ext_state_t; 83 83 84 typedef enum { 85 HR_METADATA_NATIVE = 0, 86 HR_METADATA_GEOM_MIRROR, 87 HR_METADATA_GEOM_STRIPE, 88 HR_METADATA_SOFTRAID, 89 HR_METADATA_LAST_DUMMY 90 } hr_metadata_type_t; 91 84 92 typedef struct hr { 85 93 async_sess_t *sess; … … 98 106 } hr_extent_t; 99 107 108 typedef struct hr_pair_vol_state { 109 service_id_t svc_id; 110 hr_vol_state_t state; 111 } hr_pair_vol_state_t; 112 100 113 typedef struct hr_vol_info { 114 char devname[HR_DEVNAME_LEN]; 115 service_id_t svc_id; 116 hr_level_t level; 101 117 hr_extent_t extents[HR_MAX_EXTENTS]; 102 118 hr_extent_t hotspares[HR_MAX_HOTSPARES]; 103 119 size_t extent_no; 104 120 size_t hotspare_no; 105 service_id_t svc_id; 106 hr_level_t level; 107 uint64_t nblocks; 121 uint64_t data_blkno; 108 122 uint32_t strip_size; 109 123 size_t bsize; 110 124 hr_vol_state_t state; 111 uint8_t layout; 125 hr_layout_t layout; 126 hr_metadata_type_t meta_type; 127 /* TODO: add rebuild pos */ 112 128 } hr_vol_info_t; 113 114 typedef enum {115 HR_METADATA_NATIVE = 0,116 HR_METADATA_GEOM_MIRROR,117 HR_METADATA_GEOM_STRIPE,118 HR_METADATA_SOFTRAID,119 HR_METADATA_LAST_DUMMY120 } hr_metadata_type_t;121 129 122 130 extern errno_t hr_sess_init(hr_t **); … … 129 137 extern errno_t hr_fail_extent(hr_t *, const char *, unsigned long); 130 138 extern errno_t hr_add_hotspare(hr_t *, const char *, const char *); 131 extern errno_t hr_print_state(hr_t *); 139 extern errno_t hr_get_vol_states(hr_t *, hr_pair_vol_state_t **, size_t *); 140 extern errno_t hr_get_vol_info(hr_t *, service_id_t, hr_vol_info_t *); 132 141 extern const char *hr_get_vol_state_str(hr_vol_state_t); 133 142 extern const char *hr_get_ext_state_str(hr_ext_state_t); 134 143 extern const char *hr_get_layout_str(hr_layout_t); 144 extern const char *hr_get_level_str(hr_level_t); 135 145 extern const char *hr_get_metadata_type_str(hr_metadata_type_t); 136 146 -
uspace/lib/device/include/ipc/hr.h
r431b513 re0bbecb 46 46 HR_FAIL_EXTENT, 47 47 HR_ADD_HOTSPARE, 48 HR_STATUS 48 HR_GET_VOL_STATES, 49 HR_GET_VOL_INFO 49 50 } hr_request_t; 50 51 -
uspace/lib/device/src/hr.c
r431b513 re0bbecb 209 209 } 210 210 211 static errno_t print_vol_info(size_t index, hr_vol_info_t *vol_info)212 {213 errno_t rc;214 size_t i;215 char *devname;216 hr_extent_t *ext;217 218 printf("--- vol %zu ---\n", index);219 220 printf("svc_id: %" PRIun "\n", vol_info->svc_id);221 222 rc = loc_service_get_name(vol_info->svc_id, &devname);223 if (rc != EOK)224 return rc;225 printf("devname: %s\n", devname);226 227 printf("state: %s\n", hr_get_vol_state_str(vol_info->state));228 229 printf("level: %d\n", vol_info->level);230 if (vol_info->level == HR_LVL_4 || vol_info->level == HR_LVL_5) {231 printf("layout: %s\n",232 hr_get_layout_str(vol_info->layout));233 }234 if (vol_info->level == HR_LVL_0 || vol_info->level == HR_LVL_4) {235 if (vol_info->strip_size / 1024 < 1)236 printf("strip size in bytes: %" PRIu32 "\n",237 vol_info->strip_size);238 else239 printf("strip size: %" PRIu32 "K\n",240 vol_info->strip_size / 1024);241 }242 printf("size in bytes: %" PRIu64 "MiB\n",243 vol_info->nblocks * vol_info->bsize / 1024 / 1024);244 printf("size in blocks: %" PRIu64 "\n", vol_info->nblocks);245 printf("block size: %zu\n", vol_info->bsize);246 247 if (vol_info->level == HR_LVL_4)248 printf("extents: [P] [state] [index] [devname]\n");249 else250 printf("extents: [state] [index] [devname]\n");251 for (i = 0; i < vol_info->extent_no; i++) {252 ext = &vol_info->extents[i];253 if (ext->state == HR_EXT_MISSING || ext->state == HR_EXT_NONE) {254 devname = (char *) "MISSING-devname";255 } else {256 rc = loc_service_get_name(ext->svc_id, &devname);257 if (rc != EOK) {258 printf("loc_service_get_name() failed, skipping...\n");259 continue;260 }261 }262 if (vol_info->level == HR_LVL_4) {263 if ((i == 0 && vol_info->layout == HR_RLQ_RAID4_0) ||264 (i == vol_info->extent_no - 1 &&265 vol_info->layout == HR_RLQ_RAID4_N))266 printf(" P %s %zu %s\n", hr_get_ext_state_str(ext->state), i, devname);267 else268 printf(" %s %zu %s\n", hr_get_ext_state_str(ext->state), i, devname);269 } else {270 printf(" %s %zu %s\n", hr_get_ext_state_str(ext->state), i, devname);271 }272 }273 274 if (vol_info->hotspare_no == 0)275 return EOK;276 277 printf("hotspares: [state] [index] [devname]\n");278 for (i = 0; i < vol_info->hotspare_no; i++) {279 ext = &vol_info->hotspares[i];280 if (ext->state == HR_EXT_MISSING) {281 devname = (char *) "MISSING-devname";282 } else {283 rc = loc_service_get_name(ext->svc_id, &devname);284 if (rc != EOK)285 return rc;286 }287 printf(" %s %zu %s\n",288 hr_get_ext_state_str(ext->state), i, devname);289 }290 291 return EOK;292 }293 294 211 /** Stop/deactivate volume. 295 212 * … … 408 325 } 409 326 410 /** Print state of volumes. 411 * 412 * @param hr Server session 413 * 414 * @return EOK on success or an error code 415 */ 416 errno_t hr_print_state(hr_t *hr) 327 /** Get state of volumes. 328 * 329 * @param hr Server session 330 * @param rpairs Place to store pointer to (service id, vol state) pairs 331 * @param rcnt Place to store pair count 332 * 333 * @return EOK on success or an error code 334 */ 335 errno_t hr_get_vol_states(hr_t *hr, hr_pair_vol_state_t **rpairs, size_t *rcnt) 417 336 { 418 337 errno_t rc, retval; 419 338 async_exch_t *exch; 420 339 aid_t req; 421 size_t size, i;422 hr_ vol_info_t *vols = NULL;423 424 exch = async_exchange_begin(hr->sess); 425 if (exch == NULL) { 426 rc = EINVAL; 427 goto error; 428 } 429 430 req = async_send_0(exch, HR_ STATUS, NULL);431 rc = async_data_read_start(exch, & size, sizeof(size_t));432 if (rc != EOK) { 433 async_exchange_end(exch); 434 async_forget(req); 435 return rc; 436 } 437 438 vols = calloc(size, sizeof(hr_vol_info_t));439 if ( vols == NULL) {340 size_t cnt, i; 341 hr_pair_vol_state_t *pairs = NULL; 342 343 exch = async_exchange_begin(hr->sess); 344 if (exch == NULL) { 345 rc = EINVAL; 346 goto error; 347 } 348 349 req = async_send_0(exch, HR_GET_VOL_STATES, NULL); 350 rc = async_data_read_start(exch, &cnt, sizeof(size_t)); 351 if (rc != EOK) { 352 async_exchange_end(exch); 353 async_forget(req); 354 return rc; 355 } 356 357 pairs = calloc(cnt, sizeof(*pairs)); 358 if (pairs == NULL) { 440 359 async_exchange_end(exch); 441 360 async_forget(req); … … 443 362 } 444 363 445 for (i = 0; i < size; i++) { 446 rc = async_data_read_start(exch, &vols[i], 447 sizeof(hr_vol_info_t)); 364 for (i = 0; i < cnt; i++) { 365 rc = async_data_read_start(exch, &pairs[i], sizeof(*pairs)); 448 366 if (rc != EOK) { 449 367 async_exchange_end(exch); … … 460 378 } 461 379 462 if (size == 0) { 463 printf("no active volumes\n"); 464 goto error; 465 } 466 467 for (i = 0; i < size; i++) { 468 rc = print_vol_info(i, &vols[i]); 469 if (rc != EOK) 470 goto error; 471 } 472 473 error: 474 if (vols != NULL) 475 free(vols); 380 if (rpairs != NULL) 381 *rpairs = pairs; 382 if (rcnt != NULL) 383 *rcnt = cnt; 384 return EOK; 385 386 error: 387 if (pairs != NULL) 388 free(pairs); 389 return rc; 390 } 391 392 /** Get volume info. 393 * 394 * @param hr Server session 395 * @param svc_id Service id of volume 396 * @param rinfo Place to store volume info 397 * 398 * @return EOK on success or an error code 399 */ 400 errno_t hr_get_vol_info(hr_t *hr, service_id_t svc_id, hr_vol_info_t *rinfo) 401 { 402 errno_t rc, retval; 403 async_exch_t *exch; 404 aid_t req; 405 406 exch = async_exchange_begin(hr->sess); 407 if (exch == NULL) { 408 rc = EINVAL; 409 goto error; 410 } 411 412 req = async_send_0(exch, HR_GET_VOL_INFO, NULL); 413 rc = async_data_write_start(exch, &svc_id, sizeof(svc_id)); 414 if (rc != EOK) { 415 async_exchange_end(exch); 416 async_forget(req); 417 return rc; 418 } 419 420 rc = async_data_read_start(exch, rinfo, sizeof(*rinfo)); 421 async_exchange_end(exch); 422 if (rc != EOK) { 423 async_forget(req); 424 goto error; 425 } 426 427 async_wait_for(req, &retval); 428 if (retval != EOK) { 429 rc = retval; 430 goto error; 431 } 432 433 error: 476 434 return rc; 477 435 } … … 555 513 } 556 514 515 /** Get volume level string. 516 * 517 * @param level Levelvalue 518 * 519 * @return Level string 520 */ 521 const char *hr_get_level_str(hr_level_t level) 522 { 523 switch (level) { 524 case HR_LVL_0: 525 return "stripe (RAID 0)"; 526 case HR_LVL_1: 527 return "mirror (RAID 1)"; 528 case HR_LVL_4: 529 return "dedicated parity (RAID 4)"; 530 case HR_LVL_5: 531 return "distributed parity (RAID 5)"; 532 default: 533 return "Invalid RAID level"; 534 } 535 } 536 557 537 /** Get volume metadata type string. 558 538 * -
uspace/srv/bd/hr/hr.c
r431b513 re0bbecb 59 59 static void hr_stop_all_srv(ipc_call_t *); 60 60 static void hr_add_hotspare_srv(ipc_call_t *); 61 static void hr_ print_state_srv(ipc_call_t *);61 static void hr_get_vol_states_srv(ipc_call_t *); 62 62 static void hr_ctl_conn(ipc_call_t *); 63 63 static void hr_client_conn(ipc_call_t *, void *); … … 416 416 } 417 417 418 /** Volume state printing (server).419 * 420 * Prints info about all active volumes.421 */ 422 static void hr_ print_state_srv(ipc_call_t *icall)418 /** Send volume states. 419 * 420 * Sends the client pairs of (volume service_id, state). 421 */ 422 static void hr_get_vol_states_srv(ipc_call_t *icall) 423 423 { 424 424 HR_DEBUG("%s()", __func__); … … 426 426 errno_t rc; 427 427 size_t vol_cnt = 0; 428 hr_ vol_info_t info;428 hr_pair_vol_state_t pair; 429 429 ipc_call_t call; 430 430 size_t size; … … 439 439 } 440 440 441 if (size != sizeof( size_t)) {441 if (size != sizeof(vol_cnt)) { 442 442 rc = EINVAL; 443 443 goto error; … … 449 449 450 450 list_foreach(hr_volumes, lvolumes, hr_volume_t, vol) { 451 memcpy(info.extents, vol->extents, 452 sizeof(hr_extent_t) * HR_MAX_EXTENTS); 453 memcpy(info.hotspares, vol->hotspares, 454 sizeof(hr_extent_t) * HR_MAX_HOTSPARES); 455 info.svc_id = vol->svc_id; 456 info.extent_no = vol->extent_no; 457 info.hotspare_no = vol->hotspare_no; 458 info.level = vol->level; 459 /* print usable number of blocks */ 460 /* TODO: change to data_blkno */ 461 info.nblocks = vol->data_blkno; 462 info.strip_size = vol->strip_size; 463 info.bsize = vol->bsize; 464 info.state = vol->state; 465 info.layout = vol->layout; 451 pair.svc_id = vol->svc_id; 452 pair.state = vol->state; 466 453 467 454 if (!async_data_read_receive(&call, &size)) { … … 470 457 } 471 458 472 if (size != sizeof( hr_vol_info_t)) {459 if (size != sizeof(pair)) { 473 460 rc = EINVAL; 474 461 goto error; 475 462 } 476 463 477 rc = async_data_read_finalize(&call, & info, size);464 rc = async_data_read_finalize(&call, &pair, size); 478 465 if (rc != EOK) 479 466 goto error; … … 489 476 } 490 477 478 /** Send volume info. 479 * 480 * Sends the client volume info. 481 */ 482 static void hr_get_vol_info_srv(ipc_call_t *icall) 483 { 484 HR_DEBUG("%s()", __func__); 485 486 errno_t rc; 487 size_t size; 488 ipc_call_t call; 489 service_id_t svc_id; 490 hr_vol_info_t info; 491 hr_volume_t *vol; 492 493 if (!async_data_write_receive(&call, &size)) { 494 rc = EREFUSED; 495 goto error; 496 } 497 498 if (size != sizeof(service_id_t)) { 499 rc = EINVAL; 500 goto error; 501 } 502 503 rc = async_data_write_finalize(&call, &svc_id, size); 504 if (rc != EOK) 505 goto error; 506 507 vol = hr_get_volume(svc_id); 508 if (vol == NULL) { 509 rc = ENOENT; 510 goto error; 511 } 512 513 memcpy(info.extents, vol->extents, 514 sizeof(hr_extent_t) * HR_MAX_EXTENTS); 515 memcpy(info.hotspares, vol->hotspares, 516 sizeof(hr_extent_t) * HR_MAX_HOTSPARES); 517 info.svc_id = vol->svc_id; 518 info.extent_no = vol->extent_no; 519 info.hotspare_no = vol->hotspare_no; 520 info.level = vol->level; 521 info.data_blkno = vol->data_blkno; 522 info.strip_size = vol->strip_size; 523 info.bsize = vol->bsize; 524 info.state = vol->state; 525 info.layout = vol->layout; 526 info.meta_type = vol->meta_ops->get_type(); 527 memcpy(info.devname, vol->devname, HR_DEVNAME_LEN); 528 529 if (!async_data_read_receive(&call, &size)) { 530 rc = EREFUSED; 531 goto error; 532 } 533 534 if (size != sizeof(info)) { 535 rc = EINVAL; 536 goto error; 537 } 538 539 rc = async_data_read_finalize(&call, &info, size); 540 if (rc != EOK) 541 goto error; 542 543 async_answer_0(icall, EOK); 544 return; 545 error: 546 async_answer_0(&call, rc); 547 async_answer_0(icall, rc); 548 } 549 491 550 /** HelenRAID server control IPC methods crossroad. 492 551 */ … … 529 588 hr_add_hotspare_srv(&call); 530 589 break; 531 case HR_STATUS: 532 hr_print_state_srv(&call); 590 case HR_GET_VOL_STATES: 591 hr_get_vol_states_srv(&call); 592 break; 593 case HR_GET_VOL_INFO: 594 hr_get_vol_info_srv(&call); 533 595 break; 534 596 default:
Note:
See TracChangeset
for help on using the changeset viewer.