Changeset e5ea5f8 in mainline for uspace/app/hrctl/hrctl.c


Ignore:
Timestamp:
2025-05-07T18:54:11Z (5 weeks ago)
Author:
Miroslav Cimerman <mc@…>
Children:
1cfce3f
Parents:
ed41962
Message:

hrctl: finalize parsing, add new sample sif config

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/hrctl/hrctl.c

    red41962 re5ea5f8  
    5050static void     usage(void);
    5151static errno_t  fill_config_devs(int, char **, hr_config_t *);
    52 static errno_t  load_config(const char *, hr_config_t *);
     52static errno_t get_vol_configs_from_sif(const char *, hr_config_t **, size_t *);
    5353
    5454static const char usage_str[] =
     
    9494    "  metadata as dirty in other healthy extents, and therefore invalidates\n"
    9595    "  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"
    9698    "\n"
    9799    "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";
    99102
    100103static void usage(void)
     
    133136}
    134137
    135 static errno_t load_config(const char *path, hr_config_t *cfg)
     138static errno_t get_vol_configs_from_sif(const char *path, hr_config_t **rcfgs,
     139    size_t *rcount)
    136140{
    137141        errno_t rc;
    138         size_t i;
    139142        sif_doc_t *doc = NULL;
    140         sif_node_t *narrays;
    141         sif_node_t *rnode;
    142         sif_node_t *narray;
     143        sif_node_t *hrconfig_node;
     144        sif_node_t *root_node;
     145        sif_node_t *volume_node;
    143146        sif_node_t *nextent;
    144147        const char *ntype;
    145148        const char *devname;
    146149        const char *level_str;
    147         const char *dev_no_str;
    148150        const char *extent_devname;
     151        hr_config_t *vol_configs = NULL;
    149152
    150153        rc = sif_load(path, &doc);
     
    152155                goto error;
    153156
    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) {
    193171                        rc = EINVAL;
    194172                        goto error;
    195173                }
    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;
    200181                        goto error;
    201182                }
    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        }
    224240error:
    225241        if (doc != NULL)
    226242                sif_delete(doc);
     243        if (rc != EOK) {
     244                if (vol_configs)
     245                        free(vol_configs);
     246        }
    227247        return rc;
    228248}
    229249
    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");
     250static 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
     277static 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");
    234282                return EXIT_FAILURE;
    235283        }
     
    237285        hr_config_t *vol_config = calloc(1, sizeof(hr_config_t));
    238286        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;
    254322        } 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);
    299325        }
    300326
     
    306332}
    307333
     334static 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
     365static 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
     389static 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;
     412error:
     413        free(vol_config);
     414        return EXIT_FAILURE;
     415}
     416
    308417static int handle_assemble(hr_t *hr, int argc, char **argv)
    309418{
     419        int rc;
     420
    310421        if (optind >= argc) {
    311422                size_t cnt;
     
    321432        }
    322433
    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 
    329434        if (str_cmp(argv[optind], "-f") == 0) {
    330435                if (++optind >= argc) {
    331436                        printf(NAME ": not enough arguments\n");
    332                         goto error;
     437                        return EXIT_FAILURE;
    333438                }
    334439                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
    340441                if (optind < argc) {
    341442                        printf(NAME ": unexpected arguments\n");
    342                         goto error;
    343                 }
     443                        return EXIT_FAILURE;
     444                }
     445
     446                rc = assemble_from_config(hr, config_path);
    344447        } 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;
    364452}
    365453
     
    464552        }
    465553
    466         if (hr_sess_init(&hr) != EOK) {
     554        rc = hr_sess_init(&hr);
     555        if (rc != EOK) {
    467556                printf(NAME ": hr server session init failed: %s\n",
    468557                    str_error(rc));
Note: See TracChangeset for help on using the changeset viewer.