Changeset e5ea5f8 in mainline for uspace/app/hrctl/hrctl.c
- Timestamp:
- 2025-05-07T18:54:11Z (5 weeks ago)
- Children:
- 1cfce3f
- Parents:
- ed41962
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/hrctl/hrctl.c
red41962 re5ea5f8 50 50 static void usage(void); 51 51 static errno_t fill_config_devs(int, char **, hr_config_t *); 52 static errno_t load_config(const char *, hr_config_t *);52 static errno_t get_vol_configs_from_sif(const char *, hr_config_t **, size_t *); 53 53 54 54 static const char usage_str[] = … … 94 94 " metadata as dirty in other healthy extents, and therefore invalidates\n" 95 95 " the specified extent.\n" 96 " Nested levels have to be created manually, or from config file, but need to\n" 97 " be specified as separate volumes.\n" 96 98 "\n" 97 99 "Limitations:\n" 98 "\t- volume name must be shorter than 32 characters\n"; 100 "\t- volume name must be shorter than 32 characters\n" 101 "\t- automatic assembly and disassembly on nested volumes is UNDEFINED!\n"; 99 102 100 103 static void usage(void) … … 133 136 } 134 137 135 static errno_t load_config(const char *path, hr_config_t *cfg) 138 static errno_t get_vol_configs_from_sif(const char *path, hr_config_t **rcfgs, 139 size_t *rcount) 136 140 { 137 141 errno_t rc; 138 size_t i;139 142 sif_doc_t *doc = NULL; 140 sif_node_t * narrays;141 sif_node_t *r node;142 sif_node_t * narray;143 sif_node_t *hrconfig_node; 144 sif_node_t *root_node; 145 sif_node_t *volume_node; 143 146 sif_node_t *nextent; 144 147 const char *ntype; 145 148 const char *devname; 146 149 const char *level_str; 147 const char *dev_no_str;148 150 const char *extent_devname; 151 hr_config_t *vol_configs = NULL; 149 152 150 153 rc = sif_load(path, &doc); … … 152 155 goto error; 153 156 154 rnode = sif_get_root(doc); 155 156 narrays = sif_node_first_child(rnode); 157 ntype = sif_node_get_type(narrays); 158 if (str_cmp(ntype, "arrays") != 0) { 159 rc = EIO; 160 goto error; 161 } 162 163 narray = sif_node_first_child(narrays); 164 ntype = sif_node_get_type(narray); 165 if (str_cmp(ntype, "array") != 0) { 166 rc = EIO; 167 goto error; 168 } 169 170 devname = sif_node_get_attr(narray, "devname"); 171 if (devname == NULL) { 172 rc = EIO; 173 goto error; 174 } 175 str_cpy(cfg->devname, sizeof(cfg->devname), devname); 176 177 level_str = sif_node_get_attr(narray, "level"); 178 if (level_str == NULL) 179 cfg->level = HR_LVL_UNKNOWN; 180 else 181 cfg->level = strtol(level_str, NULL, 10); 182 183 dev_no_str = sif_node_get_attr(narray, "n"); 184 if (dev_no_str == NULL) { 185 rc = EIO; 186 goto error; 187 } 188 cfg->dev_no = strtol(dev_no_str, NULL, 10); 189 190 nextent = sif_node_first_child(narray); 191 for (i = 0; i < cfg->dev_no; i++) { 192 if (nextent == NULL) { 157 root_node = sif_get_root(doc); 158 159 hrconfig_node = sif_node_first_child(root_node); 160 ntype = sif_node_get_type(hrconfig_node); 161 if (str_cmp(ntype, "hrconfig") != 0) { 162 rc = EINVAL; 163 goto error; 164 } 165 166 size_t vol_count = 0; 167 volume_node = sif_node_first_child(hrconfig_node); 168 while (volume_node) { 169 ntype = sif_node_get_type(volume_node); 170 if (str_cmp(ntype, "volume") != 0) { 193 171 rc = EINVAL; 194 172 goto error; 195 173 } 196 197 ntype = sif_node_get_type(nextent); 198 if (str_cmp(ntype, "extent") != 0) { 199 rc = EIO; 174 vol_configs = realloc(vol_configs, 175 (vol_count + 1) * sizeof(hr_config_t)); 176 hr_config_t *cfg = vol_configs + vol_count; 177 178 devname = sif_node_get_attr(volume_node, "devname"); 179 if (devname == NULL) { 180 rc = EINVAL; 200 181 goto error; 201 182 } 202 203 extent_devname = sif_node_get_attr(nextent, "devname"); 204 if (extent_devname == NULL) { 205 rc = EIO; 206 goto error; 207 } 208 209 rc = loc_service_get_id(extent_devname, &cfg->devs[i], 0); 210 if (rc == ENOENT) { 211 printf("hrctl: no device \"%s\", marking as missing\n", 212 extent_devname); 213 cfg->devs[i] = 0; 214 rc = EOK; 215 } else if (rc != EOK) { 216 printf("hrctl: error resolving device \"%s\", aborting\n", 217 extent_devname); 218 return EINVAL; 219 } 220 221 nextent = sif_node_next_child(nextent); 222 } 223 183 str_cpy(cfg->devname, sizeof(cfg->devname), devname); 184 185 level_str = sif_node_get_attr(volume_node, "level"); 186 if (level_str == NULL) 187 cfg->level = HR_LVL_UNKNOWN; 188 else 189 cfg->level = strtol(level_str, NULL, 10); 190 191 nextent = sif_node_first_child(volume_node); 192 size_t i = 0; 193 while (nextent && i < HR_MAX_EXTENTS) { 194 ntype = sif_node_get_type(nextent); 195 if (str_cmp(ntype, "extent") != 0) { 196 rc = EINVAL; 197 goto error; 198 } 199 200 extent_devname = sif_node_get_attr(nextent, "devname"); 201 if (extent_devname == NULL) { 202 rc = EINVAL; 203 goto error; 204 } 205 206 rc = loc_service_get_id(extent_devname, &cfg->devs[i], 0); 207 if (rc == ENOENT) { 208 printf(NAME ": no device \"%s\", marking as missing\n", 209 extent_devname); 210 cfg->devs[i] = 0; 211 rc = EOK; 212 } else if (rc != EOK) { 213 printf(NAME ": error resolving device \"%s\", aborting\n", 214 extent_devname); 215 goto error; 216 } 217 218 nextent = sif_node_next_child(nextent); 219 i++; 220 } 221 222 if (i > HR_MAX_EXTENTS) { 223 printf(NAME ": too many devices specified in volume \"%s\", " 224 "skipping\n", devname); 225 memset(&vol_configs[vol_count], 0, sizeof(hr_config_t)); 226 } else { 227 cfg->dev_no = i; 228 vol_count++; 229 } 230 231 volume_node = sif_node_next_child(volume_node); 232 } 233 234 if (rc == EOK) { 235 if (rcount) 236 *rcount = vol_count; 237 if (rcfgs) 238 *rcfgs = vol_configs; 239 } 224 240 error: 225 241 if (doc != NULL) 226 242 sif_delete(doc); 243 if (rc != EOK) { 244 if (vol_configs) 245 free(vol_configs); 246 } 227 247 return rc; 228 248 } 229 249 230 static int handle_create(hr_t *hr, int argc, char **argv) 231 { 232 if (optind >= argc) { 233 printf(NAME ": no arguments to --create\n"); 250 static int create_from_config(hr_t *hr, const char *config_path) 251 { 252 hr_config_t *vol_configs = NULL; 253 size_t vol_count = 0; 254 errno_t rc = get_vol_configs_from_sif(config_path, &vol_configs, 255 &vol_count); 256 if (rc != EOK) { 257 printf(NAME ": config parsing failed\n"); 258 return EXIT_FAILURE; 259 } 260 261 for (size_t i = 0; i < vol_count; i++) { 262 rc = hr_create(hr, &vol_configs[i]); 263 if (rc != EOK) { 264 printf(NAME ": creation of volume \"%s\" failed: %s, " 265 "but continuing\n", 266 vol_configs[i].devname, str_error(rc)); 267 } else { 268 printf(NAME ": volume \"%s\" successfully created\n", 269 vol_configs[i].devname); 270 } 271 } 272 273 free(vol_configs); 274 return EXIT_SUCCESS; 275 } 276 277 static int create_from_argv(hr_t *hr, int argc, char **argv) 278 { 279 /* we need name + --level + arg + at least one extent */ 280 if (optind + 3 >= argc) { 281 printf(NAME ": not enough arguments\n"); 234 282 return EXIT_FAILURE; 235 283 } … … 237 285 hr_config_t *vol_config = calloc(1, sizeof(hr_config_t)); 238 286 if (vol_config == NULL) { 239 printf(NAME ": not enough memory"); 240 return ENOMEM; 241 } 242 243 if (str_cmp(argv[optind], "-f") == 0) { 244 if (++optind >= argc) { 245 printf(NAME ": not enough arguments\n"); 246 goto error; 247 } 248 const char *config_path = argv[optind++]; 249 errno_t rc = load_config(config_path, vol_config); 250 if (rc != EOK) { 251 printf(NAME ": config parsing failed\n"); 252 goto error; 253 } 287 printf(NAME ": not enough memory\n"); 288 return EXIT_FAILURE; 289 } 290 291 const char *name = argv[optind++]; 292 if (str_size(name) >= HR_DEVNAME_LEN) { 293 printf(NAME ": devname must be less then 32 bytes.\n"); 294 goto error; 295 } 296 297 str_cpy(vol_config->devname, HR_DEVNAME_LEN, name); 298 299 const char *level_opt = argv[optind++]; 300 if (str_cmp(level_opt, "--level") != 0 && 301 str_cmp(level_opt, "-l") != 0) { 302 printf(NAME ": unknown option \"%s\"\n", level_opt); 303 goto error; 304 } 305 306 const char *level_str = argv[optind++]; 307 if (str_size(level_str) != 1 && !isdigit(level_str[0])) { 308 printf(NAME ": unknown level \"%s\"\n", level_str); 309 goto error; 310 } 311 312 vol_config->level = strtol(level_str, NULL, 10); 313 314 errno_t rc = fill_config_devs(argc, argv, vol_config); 315 if (rc != EOK) 316 goto error; 317 318 rc = hr_create(hr, vol_config); 319 if (rc != EOK) { 320 printf(NAME ": creation failed: %s\n", str_error(rc)); 321 goto error; 254 322 } else { 255 /* we need name + --level + arg + at least one extent */ 256 if (optind + 3 >= argc) { 257 printf(NAME ": not enough arguments\n"); 258 goto error; 259 } 260 261 const char *name = argv[optind++]; 262 if (str_size(name) >= HR_DEVNAME_LEN) { 263 printf(NAME ": devname must be less then 32 bytes.\n"); 264 goto error; 265 } 266 267 str_cpy(vol_config->devname, HR_DEVNAME_LEN, name); 268 269 const char *level_opt = argv[optind++]; 270 if (str_cmp(level_opt, "--level") != 0 && 271 str_cmp(level_opt, "-l") != 0) { 272 printf(NAME ": unknown option \"%s\"\n", level_opt); 273 goto error; 274 } 275 276 const char *level_str = argv[optind++]; 277 if (str_size(level_str) != 1 && !isdigit(level_str[0])) { 278 printf(NAME ": unknown level \"%s\"\n", level_str); 279 goto error; 280 } 281 282 vol_config->level = strtol(level_str, NULL, 10); 283 284 errno_t rc = fill_config_devs(argc, argv, vol_config); 285 if (rc != EOK) 286 goto error; 287 } 288 289 if (optind < argc) { 290 printf(NAME ": unexpected arguments\n"); 291 goto error; 292 } 293 294 errno_t rc = hr_create(hr, vol_config); 295 if (rc != EOK) { 296 printf(NAME ": creation failed: %s\n", 297 str_error(rc)); 298 goto error; 323 printf(NAME ": volume \"%s\" successfully created\n", 324 vol_config->devname); 299 325 } 300 326 … … 306 332 } 307 333 334 static int handle_create(hr_t *hr, int argc, char **argv) 335 { 336 int rc; 337 338 if (optind >= argc) { 339 printf(NAME ": no arguments to --create\n"); 340 return EXIT_FAILURE; 341 } 342 343 if (str_cmp(argv[optind], "-f") == 0) { 344 optind++; 345 if (optind >= argc) { 346 printf(NAME ": not enough arguments\n"); 347 return EXIT_FAILURE; 348 } 349 350 const char *config_path = argv[optind++]; 351 352 if (optind < argc) { 353 printf(NAME ": unexpected arguments\n"); 354 return EXIT_FAILURE; 355 } 356 357 rc = create_from_config(hr, config_path); 358 } else { 359 rc = create_from_argv(hr, argc, argv); 360 } 361 362 return rc; 363 } 364 365 static int assemble_from_config(hr_t *hr, const char *config_path) 366 { 367 hr_config_t *vol_configs = NULL; 368 size_t vol_count = 0; 369 errno_t rc = get_vol_configs_from_sif(config_path, &vol_configs, 370 &vol_count); 371 if (rc != EOK) { 372 printf(NAME ": config parsing failed\n"); 373 return EXIT_FAILURE; 374 } 375 376 size_t cnt = 0; 377 for (size_t i = 0; i < vol_count; i++) { 378 size_t tmpcnt = 0; 379 (void)hr_assemble(hr, &vol_configs[i], &tmpcnt); 380 cnt += tmpcnt; 381 } 382 383 printf(NAME ": assembled %zu volumes\n", cnt); 384 385 free(vol_configs); 386 return EXIT_SUCCESS; 387 } 388 389 static int assemble_from_argv(hr_t *hr, int argc, char **argv) 390 { 391 hr_config_t *vol_config = calloc(1, sizeof(hr_config_t)); 392 if (vol_config == NULL) { 393 printf(NAME ": not enough memory\n"); 394 return ENOMEM; 395 } 396 397 errno_t rc = fill_config_devs(argc, argv, vol_config); 398 if (rc != EOK) 399 goto error; 400 401 size_t cnt; 402 rc = hr_assemble(hr, vol_config, &cnt); 403 if (rc != EOK) { 404 printf(NAME ": assmeble failed: %s\n", str_error(rc)); 405 goto error; 406 } 407 408 printf("hrctl: assembled %zu volumes\n", cnt); 409 410 free(vol_config); 411 return EXIT_SUCCESS; 412 error: 413 free(vol_config); 414 return EXIT_FAILURE; 415 } 416 308 417 static int handle_assemble(hr_t *hr, int argc, char **argv) 309 418 { 419 int rc; 420 310 421 if (optind >= argc) { 311 422 size_t cnt; … … 321 432 } 322 433 323 hr_config_t *vol_config = calloc(1, sizeof(hr_config_t));324 if (vol_config == NULL) {325 printf(NAME ": not enough memory");326 return ENOMEM;327 }328 329 434 if (str_cmp(argv[optind], "-f") == 0) { 330 435 if (++optind >= argc) { 331 436 printf(NAME ": not enough arguments\n"); 332 goto error;437 return EXIT_FAILURE; 333 438 } 334 439 const char *config_path = argv[optind++]; 335 errno_t rc = load_config(config_path, vol_config); 336 if (rc != EOK) { 337 printf(NAME ": config parsing failed\n"); 338 goto error; 339 } 440 340 441 if (optind < argc) { 341 442 printf(NAME ": unexpected arguments\n"); 342 goto error; 343 } 443 return EXIT_FAILURE; 444 } 445 446 rc = assemble_from_config(hr, config_path); 344 447 } else { 345 errno_t rc = fill_config_devs(argc, argv, vol_config); 346 if (rc != EOK) 347 goto error; 348 } 349 350 size_t cnt; 351 errno_t rc = hr_assemble(hr, vol_config, &cnt); 352 if (rc != EOK) { 353 printf(NAME ": assmeble failed: %s\n", str_error(rc)); 354 goto error; 355 } 356 357 printf("hrctl: auto assembled %zu volumes\n", cnt); 358 359 free(vol_config); 360 return EXIT_SUCCESS; 361 error: 362 free(vol_config); 363 return EXIT_FAILURE; 448 rc = assemble_from_argv(hr, argc, argv); 449 } 450 451 return rc; 364 452 } 365 453 … … 464 552 } 465 553 466 if (hr_sess_init(&hr) != EOK) { 554 rc = hr_sess_init(&hr); 555 if (rc != EOK) { 467 556 printf(NAME ": hr server session init failed: %s\n", 468 557 str_error(rc));
Note:
See TracChangeset
for help on using the changeset viewer.