Changeset d1d355f in mainline


Ignore:
Timestamp:
2025-05-06T21:30:30Z (5 weeks ago)
Author:
Miroslav Cimerman <mc@…>
Children:
c2f0160
Parents:
40f56a4
Message:

hr: refactor hrctl and some hr IPC methods

Location:
uspace
Files:
7 edited

Legend:

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

    r40f56a4 rd1d355f  
    4343#include <str_error.h>
    4444
    45 #define HRCTL_SAMPLE_CONFIG_PATH "/cfg/sample_hr_config.sif"
     45/* #define HRCTL_SAMPLE_CONFIG_PATH "/cfg/sample_hr_config.sif" */
     46
     47#define NAME "hrctl"
    4648
    4749static void     usage(void);
    48 static errno_t  fill_config_devs(int, char **, int, hr_config_t *);
     50static errno_t  fill_config_devs(int, char **, hr_config_t *);
    4951static errno_t  load_config(const char *, hr_config_t *);
    5052
    5153static const char usage_str[] =
    52     "Usage: hrctl [OPTION]... -n <dev_no> <devices>...\n"
     54    "Usage: hrctl [OPTION]...\n"
    5355    "\n"
    5456    "Options:\n"
    55     "  -h, --help                display this message and exit\n"
    56     "  -C, --create-file=PATH    create an array from file,\n"
    57     "                            sample file at: " HRCTL_SAMPLE_CONFIG_PATH "\n"
    58     "  -A, --auto-assemble       try to auto assemble all valid arrays\n"
    59     "  -s, --status              display status of active arrays\n"
    60     "  -H, --hotspare=DEV        add hotspare extent\n"
    61     "  -D, --destroy             destroy/disassemble an active array\n"
    62     "  -F, --fail-extent         fail an extent, use with -D and set it before\n"
    63     "  -c, --create=NAME         create new array\n"
    64     "  -a, --assemble            try to assemble from specified extents\n"
    65     "  -n                        non-zero number of devices\n"
    66     "  -l, --level=LEVEL         set the RAID level,\n"
    67     "                            valid values: 0, 1, 4, 5\n"
    68     "  -0                        striping\n"
    69     "  -1                        mirroring\n"
    70     "  -4                        parity on one extent\n"
    71     "  -5                        distributed parity\n"
    72     "\n"
    73     "When specifying name for creation or assembly, the device name\n"
    74     "is automatically prepended with \"devices/\" prefix.\n"
     57    "  -h, --help                                Display this message and exit.\n"
     58    "\n"
     59    "  -c, --create                              Create a volume, options:\n"
     60    "      name {-l , --level level} device...   manual device specification, or\n"
     61    "      -f configuration.sif                  create from configuration file.\n"
     62    "\n"
     63    "  -a, --assemble                            Assemble volume(s), options:\n"
     64    "      [device...]                           manual device specification, or\n"
     65    "      [-f configuration.sif]                assemble from configuration file, or\n"
     66    "                                            no option is automatic assembly.\n"
     67    "\n"
     68    "  -d, --disassemble                         Deactivate/disassemble, options:\n"
     69    "      [volume]                              specific volume, or\n"
     70    "                                            all volumes with no specified option.\n"
     71    "\n"
     72    "  -m, --modify volume                       Modify a volume, options:\n"
     73    "          -f, --fail index                  fail an extent, or\n"
     74    "          -h, --hotspare device             add hotspare.\n"
     75    "\n"
     76    "  -s, --status                              Display status of active volumes.\n"
    7577    "\n"
    7678    "Example usage:\n"
    77     "  hrctl --create hr0 -0 -n 2 devices/\\hw\\0 devices/\\hw\\1\n"
    78     "    - creates new mirroring RAID device named /hr0 consisting\n"
    79     "      of 2 drives\n"
    80     "  hrctl --assemble -n 2 devices/\\hw\\0 devices/\\hw\\1\n"
    81     "    - assembles RAID devices from specified extents,\n"
    82     "      that were previously in an (active) array\n"
    83     "  hrctl devices/hr0 --hotspare=devices/disk10\n"
    84     "    - adds \"devices/disk10\" as hotspare extent\n"
    85     "  hrctl -F 0 -D devices/hr0\n"
    86     "    - marks first extent as FAILED\n"
     79    "\t\thrctl --create hr0 --level 5 disk1 disk2 disk3\n"
     80    "\t\thrctl -c hr0 -l 5 disk1 disk2 disk3\n"
     81    "\t\thrctl -c -f cfg.sif\n"
     82    "\t\thrctl --assemble disk1 disk2 disk3\n"
     83    "\t\thrctl -a\n"
     84    "\t\thrctl -d devices/hr0\n"
     85    "\t\thrctl -d\n"
     86    "\t\thrctl --modify devices/hr0 --fail 0\n"
     87    "\t\thrctl --modify devices/hr0 --hotspare disk4\n"
     88    "\t\thrctl -s\n"
     89    "\n"
     90    "Volume service names are automatically prepended with \"devices/\" prefix.\n"
     91    "\n"
    8792    "Limitations:\n"
    88     "  - device name must be less than 32 characters in size\n";
    89 
    90 static struct option const long_options[] = {
    91         { "help", no_argument, 0, 'h' },
    92         { "status", no_argument, 0, 's' },
    93         { "assemble", no_argument, 0, 'a' },
    94         { "create", required_argument, 0, 'c' },
    95         { "level", required_argument, 0, 'l' },
    96         { "create-file", required_argument, 0, 'C' },
    97         { "auto-assemble", no_argument, 0, 'A' },
    98         { "destroy", required_argument, 0, 'D' },
    99         { "fail-extent", required_argument, 0, 'F' },
    100         { "hotspare", required_argument, 0, 'H' },
    101         { 0, 0, 0, 0 }
    102 };
     93    "\t- volume name must be shorter than 32 characters\n";
    10394
    10495static void usage(void)
     
    10798}
    10899
    109 static errno_t fill_config_devs(int argc, char **argv, int optind,
    110     hr_config_t *cfg)
     100static errno_t fill_config_devs(int argc, char **argv, hr_config_t *cfg)
    111101{
    112102        errno_t rc;
    113103        size_t i;
    114104
    115         for (i = 0; i < cfg->dev_no; i++) {
     105        for (i = 0; i < HR_MAX_EXTENTS; i++) {
    116106                rc = loc_service_get_id(argv[optind], &cfg->devs[i], 0);
    117107                if (rc == ENOENT) {
    118                         printf("hrctl: no device \"%s\", marking as missing\n",
     108                        printf(NAME ": device \"%s\" not found, aborting\n",
    119109                            argv[optind]);
    120                         cfg->devs[i] = 0;
     110                        return ENOENT;
    121111                } else if (rc != EOK) {
    122                         printf("hrctl: error resolving device \"%s\", aborting\n",
     112                        printf(NAME ": error resolving device \"%s\", aborting\n",
    123113                            argv[optind]);
    124114                        return EINVAL;
    125115                }
    126116
    127                 optind++;
    128         }
     117                if (++optind >= argc)
     118                        break;
     119        }
     120
     121        if (optind < argc) {
     122                printf(NAME ": too many devices specified, max = %u\n",
     123                    HR_MAX_EXTENTS);
     124                return ELIMIT;
     125        }
     126
     127        cfg->dev_no = i;
    129128
    130129        return EOK;
     
    226225}
    227226
     227static int handle_create(int argc, char **argv)
     228{
     229        if (optind >= argc) {
     230                printf(NAME ": no arguments to --create\n");
     231                return EXIT_FAILURE;
     232        }
     233
     234        hr_config_t *vol_config = calloc(1, sizeof(hr_config_t));
     235        if (vol_config == NULL) {
     236                printf(NAME ": not enough memory");
     237                return ENOMEM;
     238        }
     239
     240        if (str_cmp(argv[optind], "-f") == 0) {
     241                if (++optind >= argc) {
     242                        printf(NAME ": not enough arguments\n");
     243                        goto error;
     244                }
     245                const char *config_path = argv[optind++];
     246                errno_t rc = load_config(config_path, vol_config);
     247                if (rc != EOK) {
     248                        printf(NAME ": config parsing failed\n");
     249                        goto error;
     250                }
     251        } else {
     252                /* we need name + --level + arg + at least one extent */
     253                if (optind + 3 >= argc) {
     254                        printf(NAME ": not enough arguments\n");
     255                        goto error;
     256                }
     257
     258                const char *name = argv[optind++];
     259                if (str_size(name) >= HR_DEVNAME_LEN) {
     260                        printf(NAME ": devname must be less then 32 bytes.\n");
     261                        goto error;
     262                }
     263
     264                str_cpy(vol_config->devname, HR_DEVNAME_LEN, name);
     265
     266                const char *level_opt = argv[optind++];
     267                if (str_cmp(level_opt, "--level") != 0 &&
     268                    str_cmp(level_opt, "-l") != 0) {
     269                        printf(NAME ": unknown option \"%s\"\n", level_opt);
     270                        goto error;
     271                }
     272
     273                vol_config->level = strtol(argv[optind++], NULL, 10);
     274
     275                errno_t rc = fill_config_devs(argc, argv, vol_config);
     276                if (rc != EOK)
     277                        goto error;
     278        }
     279
     280        if (optind < argc) {
     281                printf(NAME ": unexpected arguments\n");
     282                goto error;
     283        }
     284
     285        hr_t *hr;
     286        errno_t rc = hr_sess_init(&hr);
     287        if (rc != EOK) {
     288                printf(NAME ": server session init failed: %s\n",
     289                    str_error(rc));
     290                goto error;
     291        }
     292
     293        rc = hr_create(hr, vol_config);
     294        if (rc != EOK) {
     295                printf(NAME ": creation failed: %s\n",
     296                    str_error(rc));
     297                goto error;
     298        }
     299
     300        hr_sess_destroy(hr);
     301
     302        free(vol_config);
     303        return EXIT_SUCCESS;
     304error:
     305        free(vol_config);
     306        return EXIT_FAILURE;
     307}
     308
     309static int handle_assemble(int argc, char **argv)
     310{
     311        if (optind >= argc) {
     312                size_t cnt;
     313                errno_t rc = hr_auto_assemble(&cnt);
     314                if (rc != EOK) {
     315                        /* XXX: here have own error codes */
     316                        printf("hrctl: auto assemble rc: %s\n", str_error(rc));
     317                        return EXIT_FAILURE;
     318                }
     319
     320                printf(NAME ": auto assembled %zu volumes\n", cnt);
     321                return EXIT_SUCCESS;
     322        }
     323
     324        hr_config_t *vol_config = calloc(1, sizeof(hr_config_t));
     325        if (vol_config == NULL) {
     326                printf(NAME ": not enough memory");
     327                return ENOMEM;
     328        }
     329
     330        if (str_cmp(argv[optind], "-f") == 0) {
     331                if (++optind >= argc) {
     332                        printf(NAME ": not enough arguments\n");
     333                        goto error;
     334                }
     335                const char *config_path = argv[optind++];
     336                errno_t rc = load_config(config_path, vol_config);
     337                if (rc != EOK) {
     338                        printf(NAME ": config parsing failed\n");
     339                        goto error;
     340                }
     341                if (optind < argc) {
     342                        printf(NAME ": unexpected arguments\n");
     343                        goto error;
     344                }
     345        } else {
     346                errno_t rc = fill_config_devs(argc, argv, vol_config);
     347                if (rc != EOK)
     348                        goto error;
     349        }
     350
     351        hr_t *hr;
     352        errno_t rc = hr_sess_init(&hr);
     353        if (rc != EOK) {
     354                printf(NAME ": server session init failed: %s\n",
     355                    str_error(rc));
     356                goto error;
     357        }
     358
     359        size_t cnt;
     360        rc = hr_assemble(hr, vol_config, &cnt);
     361        if (rc != EOK) {
     362                printf(NAME ": assmeble failed: %s\n", str_error(rc));
     363                goto error;
     364        }
     365
     366        printf("hrctl: auto assembled %zu volumes\n", cnt);
     367
     368        hr_sess_destroy(hr);
     369
     370        free(vol_config);
     371        return EXIT_SUCCESS;
     372error:
     373        free(vol_config);
     374        return EXIT_FAILURE;
     375}
     376
     377static int handle_disassemble(int argc, char **argv)
     378{
     379        if (optind >= argc) {
     380                errno_t rc = hr_stop_all();
     381                if (rc != EOK) {
     382                        printf(NAME ": stopping some volumes failed: %s\n",
     383                            str_error(rc));
     384                        return EXIT_FAILURE;
     385                }
     386                return EXIT_SUCCESS;
     387        }
     388
     389        if (optind + 1 < argc) {
     390                printf(NAME ": only 1 device can be manually specified\n");
     391                return EXIT_FAILURE;
     392        }
     393
     394        const char *devname = argv[optind++];
     395
     396        errno_t rc = hr_stop(devname);
     397        if (rc != EOK) {
     398                printf(NAME ": disassembly of device \"%s\" failed: %s\n",
     399                    devname, str_error(rc));
     400                return EXIT_FAILURE;
     401        }
     402
     403        return EXIT_SUCCESS;
     404}
     405
     406static int handle_modify(int argc, char **argv)
     407{
     408        if (optind >= argc) {
     409                printf(NAME ": no arguments to --modify\n");
     410                return EXIT_FAILURE;
     411        }
     412
     413        const char *volname = argv[optind++];
     414
     415        /* at least 1 option and its agument */
     416        if (optind + 1 >= argc) {
     417                printf(NAME ": not enough arguments\n");
     418                return EXIT_FAILURE;
     419        }
     420
     421        if (optind + 2 < argc) {
     422                printf(NAME ": unexpected arguments\n");
     423                return EXIT_FAILURE;
     424        }
     425
     426        if (str_cmp(argv[optind], "--fail") == 0 ||
     427            str_cmp(argv[optind], "-f") == 0) {
     428                optind++;
     429                unsigned long extent = strtol(argv[optind++], NULL, 10);
     430                errno_t rc = hr_fail_extent(volname, extent);
     431                if (rc != EOK) {
     432                        printf(NAME ": failing extent failed: %s\n",
     433                            str_error(rc));
     434                        return EXIT_FAILURE;
     435                }
     436        } else if (str_cmp(argv[optind], "--hotspare") == 0 ||
     437            str_cmp(argv[optind], "-h") == 0) {
     438                optind++;
     439                errno_t rc = hr_add_hotspare(volname, argv[optind++]);
     440                if (rc != EOK) {
     441                        printf(NAME ": adding hotspare failed: %s\n",
     442                            str_error(rc));
     443                        return EXIT_FAILURE;
     444                }
     445        } else {
     446                printf(NAME ": unknown argument\n");
     447                return EXIT_FAILURE;
     448        }
     449
     450        return EXIT_SUCCESS;
     451}
     452
     453static int handle_status(int argc, char **argv)
     454{
     455        (void)argc;
     456        (void)argv;
     457
     458        errno_t rc = hr_print_status();
     459        if (rc != EOK) {
     460                printf(NAME ": status printing failed: %s\n", str_error(rc));
     461                return EXIT_FAILURE;
     462        }
     463
     464        return EXIT_SUCCESS;
     465}
     466
    228467int main(int argc, char **argv)
    229468{
    230         errno_t rc;
    231         int retval, c;
    232         bool create, assemble;
    233         long fail_extent = -1;
    234         hr_t *hr = NULL;
    235         hr_config_t *cfg;
    236 
    237         cfg = calloc(1, sizeof(hr_config_t));
    238         if (cfg == NULL)
    239                 return 1;
    240 
    241         retval = 0;
    242         cfg->level = HR_LVL_UNKNOWN;
    243         cfg->dev_no = 0;
    244         create = assemble = false;
     469        int rc = EXIT_SUCCESS;
     470        int c;
    245471
    246472        if (argc < 2) {
    247                 goto bad;
     473                rc = EXIT_FAILURE;
     474                goto end;
    248475        }
    249476
     
    252479        optind = 0;
    253480
     481        struct option const top_level_opts[] = {
     482                { "help",               no_argument, 0, 'h' },
     483                { "create",             no_argument, 0, 'c' },
     484                { "assemble",           no_argument, 0, 'a' },
     485                { "disassemble",        no_argument, 0, 'd' },
     486                { "modify",             no_argument, 0, 'm' },
     487                { "status",             no_argument, 0, 's' },
     488                { 0, 0, 0, 0 }
     489        };
     490
    254491        while (c != -1) {
    255                 c = getopt_long(argc, argv, "hsC:c:Aal:0145Ln:D:F:H:",
    256                     long_options, NULL);
     492                c = getopt_long(argc, argv, "hcadms", top_level_opts, NULL);
    257493                switch (c) {
     494                case 'h':
     495                        usage();
     496                        return EXIT_SUCCESS;
     497                case 'c':
     498                        rc = handle_create(argc, argv);
     499                        goto end;
     500                case 'a':
     501                        rc = handle_assemble(argc, argv);
     502                        goto end;
     503                case 'd':
     504                        rc = handle_disassemble(argc, argv);
     505                        goto end;
     506                case 'm':
     507                        rc = handle_modify(argc, argv);
     508                        goto end;
    258509                case 's':
    259                         free(cfg);
    260                         rc = hr_print_status();
    261                         if (rc != EOK)
    262                                 return 1;
    263                         return 0;
    264                 case 'C':
    265                         /* only support 1 array inside config for now XXX */
    266                         rc = load_config(optarg, cfg);
    267                         if (rc != EOK) {
    268                                 printf("hrctl: failed to load config\n");
    269                                 free(cfg);
    270                                 return 1;
    271                         }
    272                         create = true;
    273                         goto skip;
    274                 case 'c':
    275                         if (str_size(optarg) > sizeof(cfg->devname) - 1) {
    276                                 printf("hrctl: device name too long\n");
    277                                 free(cfg);
    278                                 return 1;
    279                         }
    280                         str_cpy(cfg->devname, sizeof(cfg->devname), optarg);
    281                         create = true;
    282                         break;
    283                 case 'A':
    284                         size_t cnt;
    285                         rc = hr_auto_assemble(&cnt);
    286                         if (rc != EOK) {
    287                                 /* XXX: here have own error codes */
    288                                 printf("hrctl: auto assemble rc: %s\n",
    289                                     str_error(rc));
    290                         } else {
    291                                 printf("hrctl: auto assembled %zu volumes\n",
    292                                     cnt);
    293                         }
    294                         return rc;
    295                 case 'a':
    296                         /*
    297                          * XXX: redo this, no devname, only svc ids...
    298                          *
    299                          * find some other way to rename the arrays...,
    300                          *
    301                          * some metadata editation tool... something like
    302                          * fdisk but can only change devnames on inactive
    303                          * extents...
    304                          */
    305 
    306                         /*
    307                          * XXX: remake whole parsing, don't allow -a
    308                          * to have any levels set or anything
    309                          */
    310                         assemble = true;
    311                         break;
    312                 case 'D':
    313                         rc = hr_stop(optarg, fail_extent);
    314                         free(cfg);
    315                         if (rc != EOK) {
    316                                 printf("hrctl: got %s\n", str_error(rc));
    317                                 return rc;
    318                         }
    319                         return 0;
    320                 case 'F':
    321                         fail_extent = strtol(optarg, NULL, 10);
    322                         break;
    323                 case 'l':
    324                         if (cfg->level != HR_LVL_UNKNOWN)
    325                                 goto bad;
    326                         cfg->level = strtol(optarg, NULL, 10);
    327                         break;
    328                 case '0':
    329                         if (cfg->level != HR_LVL_UNKNOWN)
    330                                 goto bad;
    331                         cfg->level = HR_LVL_0;
    332                         break;
    333                 case '1':
    334                         if (cfg->level != HR_LVL_UNKNOWN)
    335                                 goto bad;
    336                         cfg->level = HR_LVL_1;
    337                         break;
    338                 case '4':
    339                         if (cfg->level != HR_LVL_UNKNOWN)
    340                                 goto bad;
    341                         cfg->level = HR_LVL_4;
    342                         break;
    343                 case '5':
    344                         if (cfg->level != HR_LVL_UNKNOWN)
    345                                 goto bad;
    346                         cfg->level = HR_LVL_5;
    347                         break;
    348                 case 'n':
    349                         cfg->dev_no = strtol(optarg, NULL, 10);
    350                         if ((int)cfg->dev_no + optind != argc)
    351                                 goto bad;
    352                         rc = fill_config_devs(argc, argv, optind, cfg);
    353                         if (rc != EOK) {
    354                                 free(cfg);
    355                                 return 1;
    356                         }
    357                         goto skip;
    358                 case 'H':
    359                         if (optind != 3 && argc != 4)
    360                                 goto bad;
    361 
    362                         service_id_t hotspare;
    363                         service_id_t vol_svc_id;
    364 
    365                         rc = loc_service_get_id(argv[1], &vol_svc_id, 0);
    366                         if (rc != EOK) {
    367                                 printf("hrctl: error resolving volume \"%s\", "
    368                                     "aborting extent addition\n", argv[1]);
    369                                 goto bad;
    370                         }
    371 
    372                         rc = loc_service_get_id(optarg, &hotspare, 0);
    373                         if (rc != EOK) {
    374                                 printf("hrctl: error resolving device \"%s\", "
    375                                     "aborting extent addition\n", optarg);
    376                                 goto bad;
    377                         }
    378 
    379                         rc = hr_add_hotspare(vol_svc_id, hotspare);
    380                         if (rc != EOK)
    381                                 printf("hrctl: hr_add_hotspare() rc: %s\n",
    382                                     str_error(rc));
    383 
    384                         free(cfg);
    385                         if (rc != EOK)
    386                                 return 1;
    387                         else
    388                                 return 0;
    389                 case 'h':
     510                        rc = handle_status(argc, argv);
     511                        goto end;
    390512                default:
    391                         usage();
    392                         free(cfg);
    393                         return 0;
    394                 }
    395         }
    396 
    397 skip:
    398         if ((create && assemble) || (!create && !assemble))
    399                 goto bad;
    400 
    401         if (create && cfg->level == HR_LVL_UNKNOWN) {
    402                 printf("hrctl: invalid level, exiting\n");
    403                 goto bad;
    404         }
    405 
    406         if (cfg->dev_no > HR_MAX_EXTENTS) {
    407                 printf("hrctl: too many devices, exiting\n");
    408                 goto bad;
    409         }
    410 
    411         if (cfg->dev_no == 0) {
    412                 printf("hrctl: invalid number of devices, exiting\n");
    413                 goto bad;
    414         }
    415 
    416         rc = hr_sess_init(&hr);
    417         if (rc != EOK) {
    418                 printf("hrctl: hr_sess_init() rc: %s\n", str_error(rc));
    419                 retval = 1;
    420                 goto end;
    421         }
    422 
    423         if (create) {
    424                 rc = hr_create(hr, cfg);
    425                 printf("hrctl: hr_create() rc: %s\n", str_error(rc));
    426         } else if (assemble) {
    427                 size_t assembled_cnt = 0;
    428                 rc = hr_assemble(hr, cfg, &assembled_cnt);
    429                 if (rc != EOK) {
    430                         /* XXX: here have own error codes */
    431                         printf("hrctl: auto assemble rc: %s\n", str_error(rc));
    432                 } else {
    433                         printf("hrctl: auto assembled %zu volumes\n",
    434                             assembled_cnt);
    435                 }
    436 
     513                        goto end;
     514                }
    437515        }
    438516
    439517end:
    440         free(cfg);
    441         hr_sess_destroy(hr);
    442         return retval;
    443 bad:
    444         free(cfg);
    445         printf("hrctl: bad usage, try hrctl --help\n");
    446         return 1;
     518        if (rc != EXIT_SUCCESS)
     519                printf(NAME ": use --help to see usage\n");
     520        return rc;
    447521}
    448522
  • uspace/lib/device/include/hr.h

    r40f56a4 rd1d355f  
    125125extern errno_t           hr_assemble(hr_t *, hr_config_t *, size_t *);
    126126extern errno_t           hr_auto_assemble(size_t *);
    127 extern errno_t           hr_stop(const char *, long);
    128 extern errno_t           hr_add_hotspare(service_id_t, service_id_t);
     127extern errno_t           hr_stop(const char *);
     128extern errno_t           hr_stop_all(void);
     129extern errno_t           hr_fail_extent(const char *, unsigned long);
     130extern errno_t           hr_add_hotspare(const char *, const char *);
    129131extern errno_t           hr_print_status(void);
    130132extern const char       *hr_get_vol_status_msg(hr_vol_status_t);
  • uspace/lib/device/include/ipc/hr.h

    r40f56a4 rd1d355f  
    4343        HR_AUTO_ASSEMBLE,
    4444        HR_STOP,
     45        HR_STOP_ALL,
     46        HR_FAIL_EXTENT,
    4547        HR_ADD_HOTSPARE,
    4648        HR_STATUS
  • uspace/lib/device/src/hr.c

    r40f56a4 rd1d355f  
    109109        async_exchange_end(exch);
    110110        async_wait_for(req, &retval);
    111         if (retval != EOK)
    112                 return retval;
    113 
    114         return EOK;
     111        return retval;
    115112}
    116113
     
    269266}
    270267
    271 errno_t hr_stop(const char *devname, long extent)
     268errno_t hr_stop(const char *devname)
    272269{
    273270        hr_t *hr;
     
    289286                goto error;
    290287        }
    291         rc = async_req_2_0(exch, HR_STOP, svc_id, extent);
     288
     289        rc = async_req_1_0(exch, HR_STOP, svc_id);
    292290        async_exchange_end(exch);
    293291error:
     
    296294}
    297295
    298 errno_t hr_add_hotspare(service_id_t vol_svc_id, service_id_t hs_svc_id)
     296errno_t hr_stop_all(void)
    299297{
    300298        hr_t *hr;
    301         errno_t rc;
    302         async_exch_t *exch;
     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);
     341        async_exchange_end(exch);
     342error:
     343        hr_sess_destroy(hr);
     344        return rc;
     345}
     346
     347errno_t hr_add_hotspare(const char *volume_name, const char *hotspare)
     348{
     349        hr_t *hr;
     350        errno_t rc;
     351        async_exch_t *exch;
     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;
    303361
    304362        rc = hr_sess_init(&hr);
  • uspace/srv/bd/hr/hr.c

    r40f56a4 rd1d355f  
    6161static void hr_auto_assemble_srv(ipc_call_t *);
    6262static void hr_stop_srv(ipc_call_t *);
     63static void hr_stop_all_srv(ipc_call_t *);
    6364static void hr_add_hotspare_srv(ipc_call_t *);
    6465static void hr_print_status_srv(ipc_call_t *);
     
    163164        fibril_rwlock_write_unlock(&hr_volumes_lock);
    164165
    165         HR_DEBUG("created volume \"%s\" (%" PRIun ")\n", vol->devname,
    166             vol->svc_id);
     166        HR_NOTE("created volume \"%s\"\n", vol->devname);
    167167
    168168        free(cfg);
     
    275275        errno_t rc = EOK;
    276276        service_id_t svc_id;
    277         long fail_extent;
    278277        hr_volume_t *vol;
    279278
    280279        svc_id = ipc_get_arg1(icall);
    281         fail_extent = (long)ipc_get_arg2(icall);
    282280
    283281        vol = hr_get_volume(svc_id);
     
    287285        }
    288286
    289         if (fail_extent == -1) {
    290                 rc = hr_remove_volume(svc_id);
    291                 if (rc != EOK) {
    292                         async_answer_0(icall, rc);
    293                         return;
     287        rc = hr_remove_volume(vol);
     288
     289        async_answer_0(icall, rc);
     290}
     291
     292static void hr_stop_all_srv(ipc_call_t *icall)
     293{
     294        HR_DEBUG("%s()", __func__);
     295
     296        hr_volume_t *vol;
     297        errno_t rc = EOK;
     298
     299        while (true) {
     300                fibril_rwlock_write_lock(&hr_volumes_lock);
     301                if (list_empty(&hr_volumes)) {
     302                        fibril_rwlock_write_unlock(&hr_volumes_lock);
     303                        break;
    294304                }
    295         } else {
    296                 fibril_rwlock_write_lock(&vol->states_lock);
    297                 fibril_rwlock_read_lock(&vol->extents_lock);
    298 
    299                 /* TODO: maybe expose extent state callbacks */
    300                 hr_update_ext_status(vol, fail_extent, HR_EXT_FAILED);
    301                 hr_mark_vol_state_dirty(vol);
    302 
    303                 fibril_rwlock_read_unlock(&vol->extents_lock);
    304                 fibril_rwlock_write_unlock(&vol->states_lock);
    305 
    306                 vol->hr_ops.status_event(vol);
    307         }
    308         async_answer_0(icall, rc);
     305
     306                vol = list_pop(&hr_volumes, hr_volume_t, lvolumes);
     307
     308                fibril_rwlock_write_unlock(&hr_volumes_lock);
     309
     310                rc = hr_remove_volume(vol);
     311                if (rc != EOK)
     312                        break;
     313        }
     314
     315        async_answer_0(icall, rc);
     316}
     317
     318static void hr_fail_extent_srv(ipc_call_t *icall)
     319{
     320        HR_DEBUG("%s()", __func__);
     321
     322        service_id_t svc_id;
     323        size_t fail_extent;
     324        hr_volume_t *vol;
     325
     326        svc_id = (service_id_t)ipc_get_arg1(icall);
     327        fail_extent = (size_t)ipc_get_arg2(icall);
     328
     329        vol = hr_get_volume(svc_id);
     330        if (vol == NULL) {
     331                async_answer_0(icall, ENOENT);
     332                return;
     333        }
     334
     335        fibril_rwlock_write_lock(&vol->states_lock);
     336        fibril_rwlock_read_lock(&vol->extents_lock);
     337
     338        hr_update_ext_status(vol, fail_extent, HR_EXT_FAILED);
     339        hr_mark_vol_state_dirty(vol);
     340
     341        fibril_rwlock_read_unlock(&vol->extents_lock);
     342        fibril_rwlock_write_unlock(&vol->states_lock);
     343
     344        vol->hr_ops.status_event(vol);
     345
     346        async_answer_0(icall, EOK);
    309347}
    310348
     
    438476                        hr_stop_srv(&call);
    439477                        break;
     478                case HR_STOP_ALL:
     479                        hr_stop_all_srv(&call);
     480                        break;
     481                case HR_FAIL_EXTENT:
     482                        hr_fail_extent_srv(&call);
     483                        break;
    440484                case HR_ADD_HOTSPARE:
    441485                        hr_add_hotspare_srv(&call);
  • uspace/srv/bd/hr/util.c

    r40f56a4 rd1d355f  
    162162void hr_destroy_vol_struct(hr_volume_t *vol)
    163163{
     164        HR_DEBUG("%s()", __func__);
     165
    164166        if (vol == NULL)
    165167                return;
     
    173175hr_volume_t *hr_get_volume(service_id_t svc_id)
    174176{
    175         HR_DEBUG("hr_get_volume(): (%" PRIun ")\n", svc_id);
     177        HR_DEBUG("%s()", __func__);
    176178
    177179        hr_volume_t *rvol = NULL;
     
    189191}
    190192
    191 errno_t hr_remove_volume(service_id_t svc_id)
    192 {
    193         HR_DEBUG("hr_remove_volume(): (%" PRIun ")\n", svc_id);
    194 
    195         errno_t rc;
     193errno_t hr_remove_volume(hr_volume_t *vol)
     194{
     195        HR_DEBUG("%s()", __func__);
    196196
    197197        fibril_rwlock_write_lock(&hr_volumes_lock);
    198         list_foreach(hr_volumes, lvolumes, hr_volume_t, vol) {
    199                 if (vol->svc_id == svc_id) {
    200                         int open_cnt = atomic_load_explicit(&vol->open_cnt,
    201                             memory_order_relaxed);
    202                         /*
    203                          * The "atomicity" of this if condition is provided
    204                          * by the write lock - no new bd connection can
    205                          * come, because we need to get the bd_srvs_t from
    206                          * volume, which we get from the list.
    207                          * (see hr_client_conn() in hr.c)
    208                          */
    209                         if (open_cnt > 0) {
    210                                 fibril_rwlock_write_unlock(&hr_volumes_lock);
    211                                 return EBUSY;
    212                         }
    213                         list_remove(&vol->lvolumes);
    214                         fibril_rwlock_write_unlock(&hr_volumes_lock);
    215 
    216                         vol->meta_ops->save(vol, NO_STATE_CALLBACK);
    217 
    218                         hr_destroy_vol_struct(vol);
    219 
    220                         rc = loc_service_unregister(hr_srv, svc_id);
    221                         return rc;
    222                 }
    223         }
     198
     199        int open_cnt = atomic_load_explicit(&vol->open_cnt,
     200            memory_order_relaxed);
     201        /*
     202         * The atomicity of this if condition (and this whole
     203         * operation) is provided by the write lock - no new
     204         * bd connection can come, because we need to get the
     205         * bd_srvs_t from the volume, which we get from the list.
     206         * (see hr_client_conn() in hr.c)
     207         */
     208        if (open_cnt > 0) {
     209                fibril_rwlock_write_unlock(&hr_volumes_lock);
     210                return EBUSY;
     211        }
     212
     213        list_remove(&vol->lvolumes);
    224214
    225215        fibril_rwlock_write_unlock(&hr_volumes_lock);
    226         return ENOENT;
     216
     217        /* save metadata, but we don't care about states anymore */
     218        (void)vol->meta_ops->save(vol, NO_STATE_CALLBACK);
     219
     220        service_id_t svc_id = vol->svc_id;
     221
     222        HR_NOTE("deactivating volume \"%s\"\n", vol->devname);
     223
     224        hr_destroy_vol_struct(vol);
     225
     226        errno_t rc = loc_service_unregister(hr_srv, svc_id);
     227        return rc;
    227228}
    228229
     
    836837                goto error;
    837838
    838         fibril_rwlock_write_lock(&hr_volumes_lock);
    839 
    840839        /*
    841840         * XXX: register it here
     
    852851         */
    853852        rc = hr_register_volume(vol);
    854         if (rc != EOK) {
    855                 fibril_rwlock_write_unlock(&hr_volumes_lock);
    856                 goto error;
    857         }
     853        if (rc != EOK)
     854                goto error;
    858855
    859856        (void)vol->meta_ops->save(vol, WITH_STATE_CALLBACK);
    860857
     858        fibril_rwlock_write_lock(&hr_volumes_lock);
    861859        list_append(&vol->lvolumes, &hr_volumes);
    862 
    863860        fibril_rwlock_write_unlock(&hr_volumes_lock);
     861
     862        HR_NOTE("assembled volume \"%s\"\n", vol->devname);
    864863
    865864        return EOK;
  • uspace/srv/bd/hr/util.h

    r40f56a4 rd1d355f  
    7171extern void              hr_destroy_vol_struct(hr_volume_t *);
    7272extern hr_volume_t      *hr_get_volume(service_id_t);
    73 extern errno_t           hr_remove_volume(service_id_t);
     73extern errno_t           hr_remove_volume(hr_volume_t *);
    7474extern errno_t           hr_init_extents_from_cfg(hr_volume_t *, hr_config_t *);
    7575extern void              hr_fini_devs(hr_volume_t *);
Note: See TracChangeset for help on using the changeset viewer.