Changeset 8b51009 in mainline


Ignore:
Timestamp:
2025-03-28T23:37:16Z (3 months ago)
Author:
Miroslav Cimerman <mc@…>
Children:
0437dd5
Parents:
7bfe468
git-author:
Miroslav Cimerman <mc@…> (2025-03-28 23:25:57)
git-committer:
Miroslav Cimerman <mc@…> (2025-03-28 23:37:16)
Message:

hr: auto assembly, refactor

Added automatic assembly (with hrctl -A). All disks or their partitions
are scanned for HelenRAID metadata and assembly is attempted.

Main volume list is now locked with RW lock. The volume list
manipulation functions are moved into util.c.

hr_{create,destroy}_vol_struct() are implemented for better reusability
and modularity.

Volume destroy/stop (hrctl -D) now returns EBUSY if someone has still
the volume open()-ed.

Location:
uspace
Files:
10 edited

Legend:

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

    r7bfe468 r8b51009  
    11/*
    2  * Copyright (c) 2024 Miroslav Cimerman
     2 * Copyright (c) 2025 Miroslav Cimerman
    33 * All rights reserved.
    44 *
     
    4545#define HRCTL_SAMPLE_CONFIG_PATH "/cfg/sample_hr_config.sif"
    4646
    47 static void usage(void);
    48 static errno_t fill_config_devs(int, char **, int, hr_config_t *);
    49 static errno_t load_config(const char *, hr_config_t *);
     47static void     usage(void);
     48static errno_t  fill_config_devs(int, char **, int, hr_config_t *);
     49static errno_t  load_config(const char *, hr_config_t *);
    5050
    5151static const char usage_str[] =
     
    5353    "\n"
    5454    "Options:\n"
    55     "  -h, --help                display this help and exit\n"
     55    "  -h, --help                display this message and exit\n"
    5656    "  -C, --create-file=PATH    create an array from file,\n"
    5757    "                            sample file at: " HRCTL_SAMPLE_CONFIG_PATH "\n"
    58     "  -A, --assemble-file=PATH  create an array from file\n"
     58    "  -A, --auto-assemble       try to auto assemble all valid arrays\n"
    5959    "  -s, --status              display status of active arrays\n"
    6060    "  -H, --hotspare=DEV        add hotspare extent\n"
     
    6262    "  -F, --fail-extent         fail an extent, use with -D and set it before\n"
    6363    "  -c, --create=NAME         create new array\n"
    64     "  -a, --assemble=NAME       assemble an existing array\n"
     64    "  -a, --assemble=NAME       assemble from specified extents\n"
    6565    "  -n                        non-zero number of devices\n"
    6666    "  -l, --level=LEVEL         set the RAID level,\n"
     
    9595        { "level", required_argument, 0, 'l' },
    9696        { "create-file", required_argument, 0, 'C' },
    97         { "assemble-file", required_argument, 0, 'A' },
     97        { "auto-assemble", no_argument, 0, 'A' },
    9898        { "destroy", required_argument, 0, 'D' },
    9999        { "fail-extent", required_argument, 0, 'F' },
     
    253253
    254254        while (c != -1) {
    255                 c = getopt_long(argc, argv, "hsC:c:A:a:l:0145Ln:D:F:H:",
     255                c = getopt_long(argc, argv, "hsC:c:Aa:l:0145Ln:D:F:H:",
    256256                    long_options, NULL);
    257257                switch (c) {
     
    282282                        break;
    283283                case 'A':
    284                         rc = load_config(optarg, cfg);
    285                         if (rc != EOK) {
    286                                 printf("hrctl: failed to load config\n");
    287                                 free(cfg);
    288                                 return 1;
    289                         }
    290                         assemble = true;
    291                         goto skip;
     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 %lu volumes\n",
     292                                    cnt);
     293                        }
     294                        return rc;
    292295                case 'a':
    293296                        if (str_size(optarg) > sizeof(cfg->devname) - 1) {
     
    303306                        free(cfg);
    304307                        if (rc != EOK) {
    305                                 if (rc == ENOENT)
    306                                         printf("hrctl: service named \"%s\" does not exist\n",
    307                                             optarg);
    308                                 return 1;
     308                                printf("hrctl: got %s\n", str_error(rc));
     309                                return rc;
    309310                        }
    310311                        return 0;
  • uspace/lib/device/include/hr.h

    r7bfe468 r8b51009  
    118118extern void              hr_sess_destroy(hr_t *);
    119119extern errno_t           hr_create(hr_t *, hr_config_t *, bool);
     120extern errno_t           hr_auto_assemble(size_t *);
    120121extern errno_t           hr_stop(const char *, long);
    121122extern errno_t           hr_add_hotspare(service_id_t, service_id_t);
  • uspace/lib/device/include/ipc/hr.h

    r7bfe468 r8b51009  
    11/*
    2  * Copyright (c) 2024 Miroslav Cimerman
     2 * Copyright (c) 2025 Miroslav Cimerman
    33 * All rights reserved.
    44 *
     
    4141        HR_CREATE = IPC_FIRST_USER_METHOD,
    4242        HR_ASSEMBLE,
     43        HR_AUTO_ASSEMBLE,
    4344        HR_STOP,
    4445        HR_ADD_HOTSPARE,
  • uspace/lib/device/src/hr.c

    r7bfe468 r8b51009  
    115115}
    116116
     117errno_t hr_auto_assemble(size_t *rassembled_cnt)
     118{
     119        hr_t *hr;
     120        errno_t rc;
     121        size_t assembled_cnt;
     122
     123        rc = hr_sess_init(&hr);
     124        if (rc != EOK)
     125                return rc;
     126
     127        async_exch_t *exch = async_exchange_begin(hr->sess);
     128        if (exch == NULL) {
     129                rc = EINVAL;
     130                goto error;
     131        }
     132
     133        aid_t req = async_send_0(exch, HR_AUTO_ASSEMBLE, NULL);
     134
     135        rc = async_data_read_start(exch, &assembled_cnt, sizeof(size_t));
     136        if (rc != EOK) {
     137                async_exchange_end(exch);
     138                async_forget(req);
     139                return rc;
     140        }
     141
     142        async_exchange_end(exch);
     143        async_wait_for(req, &rc);
     144
     145        if (rassembled_cnt != NULL)
     146                *rassembled_cnt = assembled_cnt;
     147error:
     148        hr_sess_destroy(hr);
     149        return rc;
     150}
     151
    117152static errno_t print_vol_info(size_t index, hr_vol_info_t *vol_info)
    118153{
     
    218253        rc = async_req_2_0(exch, HR_STOP, svc_id, extent);
    219254        async_exchange_end(exch);
    220 
    221         if (rc != EOK)
    222                 goto error;
    223255error:
    224256        hr_sess_destroy(hr);
  • uspace/srv/bd/hr/hr.c

    r7bfe468 r8b51009  
    5959
    6060loc_srv_t *hr_srv;
    61 
    62 static fibril_mutex_t hr_volumes_lock;
    63 static list_t hr_volumes;
     61list_t hr_volumes;
     62fibril_rwlock_t hr_volumes_lock;
    6463
    6564static service_id_t ctl_sid;
    6665
    67 static hr_volume_t *hr_get_volume(service_id_t svc_id)
    68 {
    69         HR_DEBUG("hr_get_volume(): (%" PRIun ")\n", svc_id);
    70 
    71         fibril_mutex_lock(&hr_volumes_lock);
    72         list_foreach(hr_volumes, lvolumes, hr_volume_t, vol) {
    73                 if (vol->svc_id == svc_id) {
    74                         fibril_mutex_unlock(&hr_volumes_lock);
    75                         return vol;
    76                 }
    77         }
    78 
    79         fibril_mutex_unlock(&hr_volumes_lock);
    80         return NULL;
    81 }
    82 
    83 static errno_t hr_remove_volume(service_id_t svc_id)
    84 {
    85         HR_DEBUG("hr_remove_volume(): (%" PRIun ")\n", svc_id);
    86 
    87         fibril_mutex_lock(&hr_volumes_lock);
    88         list_foreach(hr_volumes, lvolumes, hr_volume_t, vol) {
    89                 if (vol->svc_id == svc_id) {
    90                         hr_fpool_destroy(vol->fge);
    91                         hr_fini_devs(vol);
    92                         list_remove(&vol->lvolumes);
    93                         free(vol);
    94                         fibril_mutex_unlock(&hr_volumes_lock);
    95                         return EOK;
    96                 }
    97         }
    98 
    99         fibril_mutex_unlock(&hr_volumes_lock);
    100         return ENOENT;
     66static void hr_auto_assemble_srv(ipc_call_t *icall)
     67{
     68        HR_DEBUG("%s()", __func__);
     69
     70        errno_t rc;
     71        size_t size;
     72        size_t assembled_cnt = 0;
     73        ipc_call_t call;
     74
     75        if (!async_data_read_receive(&call, &size)) {
     76                async_answer_0(icall, EREFUSED);
     77                return;
     78        }
     79
     80        if (size != sizeof(size_t)) {
     81                async_answer_0(icall, EINVAL);
     82                return;
     83        }
     84
     85        rc = hr_util_try_auto_assemble(&assembled_cnt);
     86        if (rc != EOK) {
     87                async_answer_0(&call, rc);
     88                async_answer_0(icall, rc);
     89                return;
     90        }
     91
     92        rc = async_data_read_finalize(&call, &assembled_cnt, size);
     93        if (rc != EOK) {
     94                async_answer_0(&call, rc);
     95                async_answer_0(icall, rc);
     96                return;
     97        }
     98
     99        async_answer_0(icall, EOK);
    101100}
    102101
     
    154153        }
    155154
    156         new_volume = calloc(1, sizeof(hr_volume_t));
    157         if (new_volume == NULL) {
     155        rc = hr_create_vol_struct(&new_volume, cfg->level);
     156        if (rc != EOK) {
    158157                free(cfg);
    159                 async_answer_0(icall, ENOMEM);
    160                 return;
    161         }
    162 
    163         hr_fpool_t *fge = hr_fpool_create(16, 32, sizeof(hr_io_t));
    164         if (fge == NULL) {
    165                 free(new_volume);
    166                 free(cfg);
    167                 async_answer_0(icall, ENOMEM);
    168                 return;
    169         }
    170         new_volume->fge = fge;
     158                async_answer_0(icall, rc);
     159                return;
     160        }
    171161
    172162        str_cpy(new_volume->devname, HR_DEVNAME_LEN, cfg->devname);
     
    176166        new_volume->extent_no = cfg->dev_no;
    177167
    178         if (assemble) {
    179                 if (cfg->level != HR_LVL_UNKNOWN)
    180                         HR_WARN("level manually set when assembling, ingoring");
    181                 new_volume->level = HR_LVL_UNKNOWN;
    182         }
    183 
    184168        rc = hr_init_devs(new_volume);
    185169        if (rc != EOK) {
     
    188172                async_answer_0(icall, rc);
    189173                return;
     174        }
     175
     176        if (assemble) {
     177                if (cfg->level != HR_LVL_UNKNOWN)
     178                        HR_DEBUG("level manually set when assembling, ingoring");
     179                new_volume->level = HR_LVL_UNKNOWN;
    190180        }
    191181
     
    201191        }
    202192
    203         switch (new_volume->level) {
    204         case HR_LVL_1:
    205                 if (!assemble)
    206                         new_volume->layout = 0x00; /* XXX: yet unused */
    207                 new_volume->hr_ops.create = hr_raid1_create;
    208                 new_volume->hr_ops.init = hr_raid1_init;
    209                 new_volume->hr_ops.status_event = hr_raid1_status_event;
    210                 new_volume->hr_ops.add_hotspare = hr_raid1_add_hotspare;
    211                 break;
    212         case HR_LVL_0:
    213                 if (!assemble)
    214                         new_volume->layout = 0x00;
    215                 new_volume->hr_ops.create = hr_raid0_create;
    216                 new_volume->hr_ops.init = hr_raid0_init;
    217                 new_volume->hr_ops.status_event = hr_raid0_status_event;
    218                 break;
    219         case HR_LVL_4:
    220                 if (!assemble)
    221                         new_volume->layout = HR_RLQ_RAID4_N;
    222                 new_volume->hr_ops.create = hr_raid5_create;
    223                 new_volume->hr_ops.init = hr_raid5_init;
    224                 new_volume->hr_ops.status_event = hr_raid5_status_event;
    225                 new_volume->hr_ops.add_hotspare = hr_raid5_add_hotspare;
    226                 break;
    227         case HR_LVL_5:
    228                 if (!assemble)
    229                         new_volume->layout = HR_RLQ_RAID5_NR;
    230                 new_volume->hr_ops.create = hr_raid5_create;
    231                 new_volume->hr_ops.init = hr_raid5_init;
    232                 new_volume->hr_ops.status_event = hr_raid5_status_event;
    233                 new_volume->hr_ops.add_hotspare = hr_raid5_add_hotspare;
    234                 break;
    235         default:
    236                 HR_DEBUG("unkown level: %d, aborting\n", new_volume->level);
    237                 rc = EINVAL;
    238                 goto error;
    239         }
    240 
    241193        if (!assemble) {
    242194                new_volume->hr_ops.init(new_volume);
     
    249201        }
    250202
    251         fibril_mutex_initialize(&new_volume->lock); /* XXX: will remove this */
    252 
    253         fibril_rwlock_initialize(&new_volume->extents_lock);
    254         fibril_rwlock_initialize(&new_volume->states_lock);
    255 
    256         fibril_mutex_initialize(&new_volume->hotspare_lock);
    257 
    258         list_initialize(&new_volume->range_lock_list);
    259         fibril_mutex_initialize(&new_volume->range_lock_list_lock);
    260 
    261         atomic_init(&new_volume->rebuild_blk, 0);
    262         atomic_init(&new_volume->state_dirty, false);
    263 
    264203        rc = new_volume->hr_ops.create(new_volume);
    265204        if (rc != EOK)
    266205                goto error;
    267206
    268         fibril_mutex_lock(&hr_volumes_lock);
     207        fibril_rwlock_write_lock(&hr_volumes_lock);
    269208        list_append(&new_volume->lvolumes, &hr_volumes);
    270         fibril_mutex_unlock(&hr_volumes_lock);
     209        fibril_rwlock_write_unlock(&hr_volumes_lock);
    271210
    272211        if (assemble) {
     
    283222error:
    284223        free(cfg);
    285         free(fge);
    286         hr_fini_devs(new_volume);
    287         free(new_volume);
     224        hr_destroy_vol_struct(new_volume);
    288225        async_answer_0(icall, rc);
    289226}
     
    313250                        return;
    314251                }
    315                 rc = loc_service_unregister(hr_srv, svc_id);
    316252        } else {
    317253                fibril_rwlock_write_lock(&vol->states_lock);
     
    370306        size_t size;
    371307
    372         fibril_mutex_lock(&hr_volumes_lock);
     308        fibril_rwlock_read_lock(&hr_volumes_lock);
    373309
    374310        vol_cnt = list_count(&hr_volumes);
     
    419355        }
    420356
    421         fibril_mutex_unlock(&hr_volumes_lock);
     357        fibril_rwlock_read_unlock(&hr_volumes_lock);
    422358        async_answer_0(icall, EOK);
    423359        return;
    424360error:
    425         fibril_mutex_unlock(&hr_volumes_lock);
     361        fibril_rwlock_read_unlock(&hr_volumes_lock);
    426362        async_answer_0(&call, rc);
    427363        async_answer_0(icall, rc);
     
    450386                case HR_ASSEMBLE:
    451387                        hr_create_srv(&call, true);
     388                        break;
     389                case HR_AUTO_ASSEMBLE:
     390                        hr_auto_assemble_srv(&call);
    452391                        break;
    453392                case HR_STOP:
     
    497436        }
    498437
    499         fibril_mutex_initialize(&hr_volumes_lock);
     438        fibril_rwlock_initialize(&hr_volumes_lock);
    500439        list_initialize(&hr_volumes);
    501440
  • uspace/srv/bd/hr/superblock.c

    r7bfe468 r8b51009  
    5252static errno_t read_metadata(service_id_t, hr_metadata_t *);
    5353static errno_t hr_fill_meta_from_vol(hr_volume_t *, hr_metadata_t *);
    54 static errno_t validate_meta(hr_metadata_t *);
    5554
    5655errno_t hr_write_meta_to_vol(hr_volume_t *vol)
     
    7170                goto error;
    7271
     72        /* rndgen */
     73        fibril_usleep(1000);
     74        rc = uuid_generate(&uuid);
     75        if (rc != EOK)
     76                goto error;
     77
     78        /* XXX: for now we just copy byte by byte as "encoding" */
     79        memcpy(metadata->uuid, &uuid, sizeof(HR_UUID_LEN));
     80        /* uuid_encode(&uuid, metadata->uuid); */
     81
    7382        for (i = 0; i < vol->extent_no; i++) {
    7483                metadata->index = host2uint32_t_le(i);
    75 
    76                 rc = uuid_generate(&uuid);
    77                 if (rc != EOK)
    78                         goto error;
    79                 uuid_encode(&uuid, metadata->uuid);
    8084
    8185                rc = block_write_direct(vol->extents[i].svc_id, HR_META_OFF,
     
    8488                        goto error;
    8589
    86                 /* rndgen */
    87                 fibril_usleep(1000);
    8890        }
    8991error:
     
    100102        uuid_t uuid;
    101103
     104        /* XXX: use scratchpad */
    102105        metadata = calloc(1, HR_META_SIZE * vol->bsize);
    103106        if (metadata == NULL)
     
    152155        }
    153156
    154         metadata->magic = host2uint64_t_le(HR_MAGIC);
    155         metadata->version = host2uint32_t_le(~(0U)); /* unused */
     157        /* XXX: use scratchpad */
     158        str_cpy(metadata->magic, HR_MAGIC_SIZE, HR_MAGIC_STR);
     159        metadata->nblocks = host2uint64_t_le(vol->nblocks);
     160        metadata->data_blkno = host2uint64_t_le(vol->data_blkno);
     161        metadata->truncated_blkno = host2uint64_t_le(vol->truncated_blkno);
     162        metadata->data_offset = host2uint64_t_le(vol->data_offset);
     163        metadata->counter = host2uint64_t_le(~(0UL)); /* XXX: unused */
     164        metadata->version = host2uint32_t_le(~(0U)); /* XXX: unused */
    156165        metadata->extent_no = host2uint32_t_le(vol->extent_no);
    157166        /* index filled separately for each extent */
     
    159168        metadata->layout = host2uint32_t_le(vol->layout);
    160169        metadata->strip_size = host2uint32_t_le(vol->strip_size);
    161         metadata->nblocks = host2uint64_t_le(vol->nblocks);
    162         metadata->data_blkno = host2uint64_t_le(vol->data_blkno);
    163         metadata->data_offset = host2uint64_t_le(vol->data_offset);
    164         metadata->counter = host2uint64_t_le(~(0UL)); /* unused */
    165         /* UUID generated separately for each extent */
     170        metadata->bsize = host2uint32_t_le(vol->bsize);
    166171        str_cpy(metadata->devname, HR_DEVNAME_LEN, vol->devname);
    167172
     
    169174}
    170175
    171 static errno_t validate_meta(hr_metadata_t *md)
    172 {
    173         if (uint64_t_le2host(md->magic) != HR_MAGIC) {
    174                 HR_ERROR("invalid magic\n");
    175                 return EINVAL;
    176         }
    177         return EOK;
     176bool hr_valid_md_magic(hr_metadata_t *md)
     177{
     178        if (str_lcmp(md->magic, HR_MAGIC_STR, HR_MAGIC_SIZE) != 0)
     179                return false;
     180
     181        return true;
    178182}
    179183
     
    203207                if (rc != EOK)
    204208                        goto end;
    205                 rc = validate_meta(metadata);
    206                 if (rc != EOK)
     209                if (!hr_valid_md_magic(metadata))
    207210                        goto end;
    208211                md_order_indices[i] = uint32_t_le2host(metadata->index);
     
    244247        vol->data_blkno = uint64_t_le2host(metadata->data_blkno);
    245248        vol->data_offset = uint64_t_le2host(metadata->data_offset);
     249        vol->bsize = uint32_t_le2host(metadata->bsize);
    246250        vol->counter = uint64_t_le2host(0x00); /* unused */
    247251
     
    274278}
    275279
     280errno_t hr_get_metadata_block(service_id_t dev, void **rblock)
     281{
     282        HR_DEBUG("%s()", __func__);
     283        errno_t rc;
     284        uint64_t blkno;
     285        size_t bsize;
     286        void *block;
     287
     288        rc = block_get_bsize(dev, &bsize);
     289        if (rc != EOK)
     290                return rc;
     291
     292        if (bsize < sizeof(hr_metadata_t))
     293                return EINVAL;
     294
     295        rc = block_get_nblocks(dev, &blkno);
     296        if (rc != EOK)
     297                return rc;
     298
     299        if (blkno < HR_META_OFF + HR_META_SIZE)
     300                return EINVAL;
     301
     302        block = malloc(bsize);
     303        if (block == NULL)
     304                return ENOMEM;
     305
     306        rc = block_read_direct(dev, HR_META_OFF, HR_META_SIZE, block);
     307        if (rc != EOK) {
     308                free(block);
     309                return rc;
     310        }
     311
     312        if (rblock == NULL) {
     313                free(block);
     314                return EINVAL;
     315        }
     316
     317        *rblock = block;
     318        return EOK;
     319}
     320
     321void hr_decode_metadata_from_block(void *block, hr_metadata_t *metadata)
     322{
     323        /*
     324         * Use scratch metadata for easier decoding without the need
     325         * for manualy specifying offsets.
     326         */
     327        hr_metadata_t scratch_md;
     328        memcpy(&scratch_md, block, sizeof(hr_metadata_t));
     329
     330        memcpy(metadata->magic, scratch_md.magic, HR_MAGIC_SIZE);
     331        memcpy(metadata->uuid, scratch_md.uuid, HR_UUID_LEN);
     332        metadata->nblocks = uint64_t_le2host(scratch_md.nblocks);
     333        metadata->data_blkno = uint64_t_le2host(scratch_md.data_blkno);
     334        metadata->truncated_blkno = uint64_t_le2host(
     335            scratch_md.truncated_blkno);
     336        metadata->data_offset = uint64_t_le2host(scratch_md.data_offset);
     337        metadata->counter = uint64_t_le2host(scratch_md.counter);
     338        metadata->version = uint32_t_le2host(scratch_md.version);
     339        metadata->extent_no = uint32_t_le2host(scratch_md.extent_no);
     340        metadata->index = uint32_t_le2host(scratch_md.index);
     341        metadata->level = uint32_t_le2host(scratch_md.level);
     342        metadata->layout = uint32_t_le2host(scratch_md.layout);
     343        metadata->strip_size = uint32_t_le2host(scratch_md.strip_size);
     344        metadata->bsize = uint64_t_le2host(scratch_md.bsize);
     345        memcpy(metadata->devname, scratch_md.devname, HR_DEVNAME_LEN);
     346}
     347
     348void hr_metadata_dump(hr_metadata_t *metadata)
     349{
     350        printf("\tmagic: %s\n", metadata->magic);
     351        printf("\tUUID: ");
     352        for (size_t i = 0; i < HR_UUID_LEN; ++i) {
     353                printf("%.2X", metadata->uuid[i]);
     354                if (i + 1 < HR_UUID_LEN)
     355                        printf(" ");
     356        }
     357        printf("\n");
     358        printf("\tnblocks: %lu\n", metadata->nblocks);
     359        printf("\tdata_blkno: %lu\n", metadata->data_blkno);
     360        printf("\ttruncated_blkno: %lu\n", metadata->truncated_blkno);
     361        printf("\tdata_offset: %lu\n", metadata->data_offset);
     362        printf("\tcounter: %lu\n", metadata->counter);
     363        printf("\tversion: %u\n", metadata->version);
     364        printf("\textent_no: %u\n", metadata->extent_no);
     365        printf("\tindex: %u\n", metadata->index);
     366        printf("\tlevel: %u\n", metadata->level);
     367        printf("\tlayout: %u\n", metadata->layout);
     368        printf("\tstrip_size: %u\n", metadata->strip_size);
     369        printf("\tdevname: %s\n", metadata->devname);
     370}
     371
    276372/** @}
    277373 */
  • uspace/srv/bd/hr/superblock.h

    r7bfe468 r8b51009  
    11/*
    2  * Copyright (c) 2024 Miroslav Cimerman
     2 * Copyright (c) 2025 Miroslav Cimerman
    33 * All rights reserved.
    44 *
     
    3939#include "var.h"
    4040
    41 #define HR_META_SIZE 1  /* in blocks */
    42 #define HR_META_OFF 7   /* in blocks */
    43 #define HR_DATA_OFF (HR_META_SIZE + HR_META_OFF)
     41#define HR_META_SIZE            1       /* in blocks */
     42#define HR_META_OFF             7       /* in blocks */
     43#define HR_DATA_OFF             (HR_META_OFF + HR_META_SIZE)
    4444
    45 #define HR_MAGIC 0x4420492041205248LLU
    46 #define HR_UUID_LEN 16
     45#define HR_MAGIC_STR            "HelenRAID"
     46#define HR_MAGIC_SIZE           16
     47#define HR_UUID_LEN             16
     48/* #define HR_METADATA_VERSION 0 */
    4749
    48 typedef struct hr_metadata {
    49         uint64_t magic;
    50         uint32_t version;       /* unused XXX */
    51         uint32_t extent_no;
     50typedef struct hr_metadata hr_metadata_t;
     51typedef struct hr_volume hr_volume_t;
    5252
    53         uint32_t index;         /* index of disk in array */
    54         uint32_t level;
    55         uint32_t layout;
    56         uint32_t strip_size;
     53struct hr_metadata {
     54        char            magic[HR_MAGIC_SIZE];
    5755
    58         uint64_t nblocks;       /* all blocks */
    59         uint64_t data_blkno;    /* usable blocks */
     56        uint8_t         uuid[HR_UUID_LEN];
    6057
    61         uint64_t data_offset;   /* block where data starts */
     58        /* TODO: change to blkno */
     59        uint64_t        nblocks;                /* all blocks */
     60        uint64_t        data_blkno;             /* usable blocks */
    6261
    63         uint64_t counter; /* unused */
     62        uint64_t        truncated_blkno;        /* usable blocks */
     63        uint64_t        data_offset;
    6464
    65         uint8_t uuid[HR_UUID_LEN];
     65        uint64_t        counter;                /* yet unused */
     66        uint32_t        version;                /* yet unused */
     67        uint32_t        extent_no;
    6668
    67         char devname[HR_DEVNAME_LEN];
    68 } hr_metadata_t;
     69        uint32_t        index;                  /* index of extent in volume */
     70        uint32_t        level;
     71        uint32_t        layout;
     72        uint32_t        strip_size;
    6973
    70 extern errno_t hr_write_meta_to_vol(hr_volume_t *);
    71 extern errno_t hr_write_meta_to_ext(hr_volume_t *, size_t);
    72 extern errno_t hr_fill_vol_from_meta(hr_volume_t *);
     74        uint32_t        bsize;
     75
     76        char            devname[HR_DEVNAME_LEN];
     77};
     78
     79extern errno_t  hr_write_meta_to_vol(hr_volume_t *);
     80extern errno_t  hr_write_meta_to_ext(hr_volume_t *, size_t);
     81extern errno_t  hr_fill_vol_from_meta(hr_volume_t *);
     82extern errno_t  hr_get_metadata_block(service_id_t, void **);
     83extern void     hr_decode_metadata_from_block(void *, hr_metadata_t *);
     84extern void     hr_metadata_dump(hr_metadata_t *);
     85extern bool     hr_valid_md_magic(hr_metadata_t *);
    7386
    7487#endif
  • uspace/srv/bd/hr/util.c

    r7bfe468 r8b51009  
    4141#include <io/log.h>
    4242#include <loc.h>
     43#include <mem.h>
    4344#include <stdatomic.h>
    4445#include <stdlib.h>
    4546#include <stdio.h>
    4647#include <str_error.h>
    47 
     48#include <vbd.h>
     49
     50#include "io.h"
     51#include "superblock.h"
    4852#include "util.h"
    4953#include "var.h"
     
    5660
    5761extern loc_srv_t *hr_srv;
     62extern list_t hr_volumes;
     63extern fibril_rwlock_t hr_volumes_lock;
     64
     65errno_t hr_create_vol_struct(hr_volume_t **rvol, hr_level_t level)
     66{
     67        errno_t rc;
     68
     69        hr_volume_t *vol = calloc(1, sizeof(hr_volume_t));
     70        if (vol == NULL)
     71                return ENOMEM;
     72
     73        vol->level = level;
     74
     75        switch (level) {
     76        case HR_LVL_1:
     77                vol->hr_ops.create = hr_raid1_create;
     78                vol->hr_ops.init = hr_raid1_init;
     79                vol->hr_ops.status_event = hr_raid1_status_event;
     80                vol->hr_ops.add_hotspare = hr_raid1_add_hotspare;
     81                break;
     82        case HR_LVL_0:
     83                vol->hr_ops.create = hr_raid0_create;
     84                vol->hr_ops.init = hr_raid0_init;
     85                vol->hr_ops.status_event = hr_raid0_status_event;
     86                break;
     87        case HR_LVL_4:
     88                vol->hr_ops.create = hr_raid5_create;
     89                vol->hr_ops.init = hr_raid5_init;
     90                vol->hr_ops.status_event = hr_raid5_status_event;
     91                vol->hr_ops.add_hotspare = hr_raid5_add_hotspare;
     92                break;
     93        case HR_LVL_5:
     94                vol->hr_ops.create = hr_raid5_create;
     95                vol->hr_ops.init = hr_raid5_init;
     96                vol->hr_ops.status_event = hr_raid5_status_event;
     97                vol->hr_ops.add_hotspare = hr_raid5_add_hotspare;
     98                break;
     99        default:
     100                HR_DEBUG("unkown level: %d, aborting\n", vol->level);
     101                rc = EINVAL;
     102                goto error;
     103        }
     104
     105        vol->fge = hr_fpool_create(16, 32, sizeof(hr_io_t));
     106        if (vol->fge == NULL) {
     107                rc = ENOMEM;
     108                goto error;
     109        }
     110
     111        vol->status = HR_VOL_NONE;
     112
     113        for (size_t i = 0; i < HR_MAX_EXTENTS; ++i)
     114                vol->extents[i].status = HR_EXT_MISSING;
     115
     116        for (size_t i = 0; i < HR_MAX_HOTSPARES; ++i)
     117                vol->extents[i].status = HR_EXT_MISSING;
     118
     119        fibril_mutex_initialize(&vol->lock); /* XXX: will remove this */
     120
     121        fibril_rwlock_initialize(&vol->extents_lock);
     122        fibril_rwlock_initialize(&vol->states_lock);
     123
     124        fibril_mutex_initialize(&vol->hotspare_lock);
     125
     126        list_initialize(&vol->range_lock_list);
     127        fibril_mutex_initialize(&vol->range_lock_list_lock);
     128
     129        atomic_init(&vol->rebuild_blk, 0);
     130        atomic_init(&vol->state_dirty, false);
     131        atomic_init(&vol->open_cnt, 0);
     132
     133        *rvol = vol;
     134
     135        return EOK;
     136error:
     137        free(vol);
     138        return rc;
     139}
     140
     141void hr_destroy_vol_struct(hr_volume_t *vol)
     142{
     143        if (vol == NULL)
     144                return;
     145
     146        hr_fpool_destroy(vol->fge);
     147        hr_fini_devs(vol);
     148        free(vol->in_mem_md);
     149        free(vol);
     150}
     151
     152hr_volume_t *hr_get_volume(service_id_t svc_id)
     153{
     154        HR_DEBUG("hr_get_volume(): (%" PRIun ")\n", svc_id);
     155
     156        hr_volume_t *rvol = NULL;
     157
     158        fibril_rwlock_read_lock(&hr_volumes_lock);
     159        list_foreach(hr_volumes, lvolumes, hr_volume_t, iter) {
     160                if (iter->svc_id == svc_id) {
     161                        rvol = iter;
     162                        break;
     163                }
     164        }
     165
     166        fibril_rwlock_read_unlock(&hr_volumes_lock);
     167        return rvol;
     168}
     169
     170errno_t hr_remove_volume(service_id_t svc_id)
     171{
     172        HR_DEBUG("hr_remove_volume(): (%" PRIun ")\n", svc_id);
     173
     174        errno_t rc;
     175
     176        fibril_rwlock_write_lock(&hr_volumes_lock);
     177        list_foreach(hr_volumes, lvolumes, hr_volume_t, vol) {
     178                if (vol->svc_id == svc_id) {
     179                        int open_cnt = atomic_load_explicit(&vol->open_cnt,
     180                            memory_order_relaxed);
     181                        /*
     182                         * The "atomicity" of this if condition is provided
     183                         * by the write lock - no new bd connection can
     184                         * come, because we need to get the bd_srvs_t from
     185                         * volume, which we get from the list.
     186                         * (see hr_client_conn() in hr.c)
     187                         */
     188                        if (open_cnt > 0) {
     189                                fibril_rwlock_write_unlock(&hr_volumes_lock);
     190                                return EBUSY;
     191                        }
     192                        list_remove(&vol->lvolumes);
     193                        fibril_rwlock_write_unlock(&hr_volumes_lock);
     194
     195                        hr_destroy_vol_struct(vol);
     196
     197                        rc = loc_service_unregister(hr_srv, svc_id);
     198                        return rc;
     199                }
     200        }
     201
     202        fibril_rwlock_write_unlock(&hr_volumes_lock);
     203        return ENOENT;
     204}
    58205
    59206errno_t hr_init_devs(hr_volume_t *vol)
     
    419566}
    420567
     568struct svc_id_linked {
     569        link_t link;
     570        service_id_t svc_id;
     571        hr_metadata_t *md;
     572        bool inited;
     573        bool md_present;
     574};
     575
     576static errno_t hr_add_svc_linked_to_list(list_t *list, service_id_t svc_id,
     577    bool inited, hr_metadata_t *md)
     578{
     579        errno_t rc = EOK;
     580        struct svc_id_linked *to_add;
     581
     582        to_add = malloc(sizeof(struct svc_id_linked));
     583        if (to_add == NULL) {
     584                rc = ENOMEM;
     585                goto error;
     586        }
     587        to_add->svc_id = svc_id;
     588        to_add->inited = inited;
     589
     590        if (md != NULL) {
     591                to_add->md = malloc(sizeof(hr_metadata_t));
     592                if (to_add->md == NULL) {
     593                        rc = ENOMEM;
     594                        goto error;
     595                }
     596                to_add->md_present = true;
     597                memcpy(to_add->md, md, sizeof(*md));
     598        } else {
     599                to_add->md_present = false;
     600        }
     601
     602        list_append(&to_add->link, list);
     603
     604error:
     605        return rc;
     606}
     607
     608static void free_svc_id_linked(struct svc_id_linked *p)
     609{
     610        if (p->md_present)
     611                free(p->md);
     612        free(p);
     613}
     614
     615static void free_svc_id_list(list_t *list)
     616{
     617        struct svc_id_linked *dev_id;
     618        while (!list_empty(list)) {
     619                dev_id = list_pop(list, struct svc_id_linked, link);
     620                free_svc_id_linked(dev_id);
     621        }
     622}
     623
     624static errno_t hr_fill_disk_part_svcs_list(list_t *list)
     625{
     626        errno_t rc;
     627        size_t disk_count;
     628        service_id_t *disk_svcs = NULL;
     629        vbd_t *vbd = NULL;
     630
     631        rc = vbd_create(&vbd);
     632        if (rc != EOK)
     633                goto error;
     634
     635        rc = vbd_get_disks(vbd, &disk_svcs, &disk_count);
     636        if (rc != EOK)
     637                goto error;
     638
     639        for (size_t i = 0; i < disk_count; i++) {
     640                vbd_disk_info_t disk_info;
     641                rc = vbd_disk_info(vbd, disk_svcs[i], &disk_info);
     642                if (rc != EOK)
     643                        goto error;
     644
     645                if (disk_info.ltype == lt_none) {
     646                        rc = hr_add_svc_linked_to_list(list, disk_svcs[i], false, NULL);
     647                        if (rc != EOK)
     648                                goto error;
     649                } else {
     650                        size_t part_count;
     651                        service_id_t *part_ids = NULL;
     652                        rc = vbd_label_get_parts(vbd, disk_svcs[i], &part_ids, &part_count);
     653                        if (rc != EOK)
     654                                goto error;
     655
     656                        for (size_t j = 0; j < part_count; j++) {
     657                                vbd_part_info_t part_info;
     658                                rc = vbd_part_get_info(vbd, part_ids[j], &part_info);
     659                                if (rc != EOK) {
     660                                        free(part_ids);
     661                                        goto error;
     662                                }
     663
     664                                rc = hr_add_svc_linked_to_list(list,
     665                                    part_info.svc_id, false, NULL);
     666                                if (rc != EOK) {
     667                                        free(part_ids);
     668                                        goto error;
     669                                }
     670                        }
     671
     672                        free(part_ids);
     673                }
     674        }
     675
     676        free(disk_svcs);
     677        vbd_destroy(vbd);
     678        return EOK;
     679error:
     680        free_svc_id_list(list);
     681        if (disk_svcs != NULL)
     682                free(disk_svcs);
     683        vbd_destroy(vbd);
     684
     685        return rc;
     686}
     687
     688static errno_t block_init_dev_list(list_t *list)
     689{
     690        list_foreach_safe(*list, cur_link, next_link) {
     691                struct svc_id_linked *iter;
     692                iter = list_get_instance(cur_link, struct svc_id_linked, link);
     693
     694                if (iter->inited)
     695                        continue;
     696
     697                errno_t rc = block_init(iter->svc_id);
     698
     699                /* already used as an extent of active volume */
     700                /* XXX: figure out how it is with hotspares too */
     701                if (rc == EEXIST) {
     702                        list_remove(cur_link);
     703                        free_svc_id_linked(iter);
     704                        continue;
     705                }
     706
     707                if (rc != EOK)
     708                        return rc;
     709
     710                iter->inited = true;
     711        }
     712
     713        return EOK;
     714}
     715
     716static void block_fini_dev_list(list_t *list)
     717{
     718        list_foreach(*list, link, struct svc_id_linked, iter) {
     719                if (iter->inited) {
     720                        block_fini(iter->svc_id);
     721                        iter->inited = false;
     722                }
     723        }
     724}
     725
     726static errno_t hr_util_get_matching_md_svcs_list(list_t *rlist, list_t *devlist,
     727    service_id_t svc_id, hr_metadata_t *md_main)
     728{
     729        errno_t rc = EOK;
     730
     731        list_foreach(*devlist, link, struct svc_id_linked, iter) {
     732                if (iter->svc_id == svc_id)
     733                        continue;
     734                void *md_block;
     735                hr_metadata_t md;
     736                rc = hr_get_metadata_block(iter->svc_id, &md_block);
     737                if (rc != EOK)
     738                        goto error;
     739                hr_decode_metadata_from_block(md_block, &md);
     740
     741                free(md_block);
     742
     743                if (!hr_valid_md_magic(&md))
     744                        continue;
     745
     746                if (memcmp(md_main->uuid, md.uuid, HR_UUID_LEN) != 0)
     747                        continue;
     748
     749                /*
     750                 * XXX: can I assume bsize and everything is fine when
     751                 * UUID matches?
     752                 */
     753
     754                rc = hr_add_svc_linked_to_list(rlist, iter->svc_id, true, &md);
     755                if (rc != EOK)
     756                        goto error;
     757        }
     758
     759        return  EOK;
     760error:
     761        free_svc_id_list(rlist);
     762        return rc;
     763}
     764
     765static errno_t hr_util_assemble_from_matching_list(list_t *list)
     766{
     767        HR_DEBUG("%s()", __func__);
     768
     769        errno_t rc = EOK;
     770
     771        hr_metadata_t *main_md = NULL;
     772        size_t max_counter_val = 0;
     773
     774        list_foreach(*list, link, struct svc_id_linked, iter) {
     775                hr_metadata_dump(iter->md);
     776                if (iter->md->counter >= max_counter_val) {
     777                        max_counter_val = iter->md->counter;
     778                        main_md = iter->md;
     779                }
     780        }
     781
     782        assert(main_md != NULL);
     783
     784        hr_volume_t *vol;
     785        rc = hr_create_vol_struct(&vol, (hr_level_t)main_md->level);
     786        if (rc != EOK)
     787                goto error;
     788
     789        vol->nblocks = main_md->nblocks;
     790        vol->data_blkno = main_md->data_blkno;
     791        vol->truncated_blkno = main_md->truncated_blkno;
     792        vol->data_offset = main_md->data_offset;
     793        vol->counter = main_md->counter;
     794        vol->metadata_version = main_md->version;
     795        vol->extent_no = main_md->extent_no;
     796        vol->level = main_md->level;
     797        vol->layout = main_md->layout;
     798        vol->strip_size = main_md->strip_size;
     799        vol->bsize = main_md->bsize;
     800        memcpy(vol->devname, main_md->devname, HR_DEVNAME_LEN);
     801
     802        list_foreach(*list, link, struct svc_id_linked, iter) {
     803                vol->extents[iter->md->index].svc_id = iter->svc_id;
     804                if (iter->md->counter == max_counter_val)
     805                        vol->extents[iter->md->index].status = HR_EXT_ONLINE;
     806                else
     807                        vol->extents[iter->md->index].status = HR_EXT_INVALID;
     808        }
     809
     810        rc = vol->hr_ops.create(vol);
     811        if (rc != EOK)
     812                goto error;
     813
     814        fibril_rwlock_write_lock(&hr_volumes_lock);
     815
     816        list_foreach(hr_volumes, lvolumes, hr_volume_t, other) {
     817                uint8_t *our_uuid = vol->in_mem_md->uuid;
     818                uint8_t *other_uuid = other->in_mem_md->uuid;
     819                if (memcmp(our_uuid, other_uuid, HR_UUID_LEN) == 0) {
     820                        rc = EEXIST;
     821                        fibril_rwlock_write_unlock(&hr_volumes_lock);
     822                        goto error;
     823                }
     824        }
     825
     826        /*
     827         * XXX: register it here
     828         * ... if it fails on EEXIST try different name... like + 1 on the end
     829         */
     830
     831        list_append(&vol->lvolumes, &hr_volumes);
     832
     833        fibril_rwlock_write_unlock(&hr_volumes_lock);
     834
     835        return EOK;
     836error:
     837        hr_destroy_vol_struct(vol);
     838        return rc;
     839}
     840
     841errno_t hr_util_try_auto_assemble(size_t *rassembled_cnt)
     842{
     843        HR_DEBUG("%s()", __func__);
     844
     845        /*
     846         * scan partitions or disks:
     847         *
     848         * When we find a metadata block with valid
     849         * magic, take UUID and try to find other matching
     850         * UUIDs.
     851         *
     852         * We ignore extents that are a part of already
     853         * active volumes. (even when the counter is lower
     854         * on active volumes... XXX: use timestamp as initial counter value
     855         * when assembling, or writing dirty metadata?)
     856         */
     857
     858        size_t asm_cnt = 0;
     859        errno_t rc;
     860        list_t dev_id_list;
     861
     862        list_initialize(&dev_id_list);
     863        rc = hr_fill_disk_part_svcs_list(&dev_id_list);
     864        if (rc != EOK)
     865                goto error;
     866
     867        rc = block_init_dev_list(&dev_id_list);
     868        if (rc != EOK)
     869                goto error;
     870
     871        struct svc_id_linked *iter;
     872        while (!list_empty(&dev_id_list)) {
     873                iter = list_pop(&dev_id_list, struct svc_id_linked, link);
     874
     875                printf("svc_id: %lu\n", iter->svc_id);
     876
     877                void *metadata_block;
     878                hr_metadata_t metadata;
     879
     880                rc = hr_get_metadata_block(iter->svc_id, &metadata_block);
     881                if (rc != EOK)
     882                        goto error;
     883
     884                hr_decode_metadata_from_block(metadata_block, &metadata);
     885
     886                free(metadata_block);
     887
     888                if (!hr_valid_md_magic(&metadata)) {
     889                        printf("BAD magic\n");
     890                        block_fini(iter->svc_id);
     891                        free_svc_id_linked(iter);
     892                        continue;
     893                }
     894
     895                hr_metadata_dump(&metadata);
     896
     897                char *svc_name = NULL;
     898                rc = loc_service_get_name(iter->svc_id, &svc_name);
     899                if (rc != EOK)
     900                        goto error;
     901
     902                HR_DEBUG("found valid metadata on %s, "
     903                    "will try to match other extents\n", svc_name);
     904
     905                free(svc_name);
     906
     907                list_t matching_svcs_list;
     908                list_initialize(&matching_svcs_list);
     909
     910                rc = hr_util_get_matching_md_svcs_list(&matching_svcs_list,
     911                    &dev_id_list, iter->svc_id, &metadata);
     912                if (rc != EOK)
     913                        goto error;
     914
     915                /* add current iter to list as well */
     916                rc = hr_add_svc_linked_to_list(&matching_svcs_list,
     917                    iter->svc_id, true, &metadata);
     918                if (rc != EOK) {
     919                        free_svc_id_list(&matching_svcs_list);
     920                        goto error;
     921                }
     922
     923                /* remove matching list members from dev_id_list */
     924                list_foreach(matching_svcs_list, link, struct svc_id_linked,
     925                    iter2) {
     926                        printf("matching svc_id: %lu\n", iter2->svc_id);
     927                        struct svc_id_linked *to_remove;
     928                        list_foreach_safe(dev_id_list, cur_link, next_link) {
     929                                to_remove = list_get_instance(cur_link,
     930                                    struct svc_id_linked, link);
     931                                if (to_remove->svc_id == iter2->svc_id) {
     932                                        list_remove(cur_link);
     933                                        free_svc_id_linked(to_remove);
     934                                }
     935                        }
     936                }
     937
     938                rc = hr_util_assemble_from_matching_list(&matching_svcs_list);
     939                switch (rc) {
     940                case EOK:
     941                        asm_cnt++;
     942                        break;
     943                case EEXIST:
     944                        /*
     945                         * A race is detected this way, because we don't want
     946                         * to hold the hr_volumes list lock for a long time,
     947                         * for all assembly attempts. XXX: discuss...
     948                         */
     949                        rc = EOK;
     950                        break;
     951                default:
     952                        block_fini_dev_list(&matching_svcs_list);
     953                        free_svc_id_list(&matching_svcs_list);
     954                        goto error;
     955                }
     956
     957                free_svc_id_list(&matching_svcs_list);
     958        }
     959
     960error:
     961        if (rassembled_cnt != NULL)
     962                *rassembled_cnt = asm_cnt;
     963
     964        block_fini_dev_list(&dev_id_list);
     965        free_svc_id_list(&dev_id_list);
     966
     967        return rc;
     968}
     969
    421970/** @}
    422971 */
  • uspace/srv/bd/hr/util.h

    r7bfe468 r8b51009  
    5151    log_msg(LOG_DEFAULT, LVL_ERROR, format, ##__VA_ARGS__)
    5252
    53 extern errno_t hr_init_devs(hr_volume_t *);
    54 extern void hr_fini_devs(hr_volume_t *);
    55 extern errno_t hr_register_volume(hr_volume_t *);
    56 extern errno_t hr_check_devs(hr_volume_t *, uint64_t *, size_t *);
    57 extern errno_t hr_check_ba_range(hr_volume_t *, size_t, uint64_t);
    58 extern void hr_add_ba_offset(hr_volume_t *, uint64_t *);
    59 extern void hr_update_ext_status(hr_volume_t *, size_t, hr_ext_status_t);
    60 extern void hr_update_hotspare_status(hr_volume_t *, size_t, hr_ext_status_t);
    61 extern void hr_update_vol_status(hr_volume_t *, hr_vol_status_t);
    62 extern void hr_update_ext_svc_id(hr_volume_t *, size_t, service_id_t);
    63 extern void hr_update_hotspare_svc_id(hr_volume_t *, size_t, service_id_t);
    64 extern void hr_sync_all_extents(hr_volume_t *);
    65 extern size_t hr_count_extents(hr_volume_t *, hr_ext_status_t);
    66 extern hr_range_lock_t *hr_range_lock_acquire(hr_volume_t *, uint64_t,
     53
     54extern errno_t           hr_create_vol_struct(hr_volume_t **, hr_level_t);
     55extern void              hr_destroy_vol_struct(hr_volume_t *);
     56extern hr_volume_t      *hr_get_volume(service_id_t);
     57extern errno_t           hr_remove_volume(service_id_t);
     58extern errno_t           hr_init_devs(hr_volume_t *);
     59extern void              hr_fini_devs(hr_volume_t *);
     60extern errno_t           hr_register_volume(hr_volume_t *);
     61extern errno_t           hr_check_devs(hr_volume_t *, uint64_t *, size_t *);
     62extern errno_t           hr_check_ba_range(hr_volume_t *, size_t, uint64_t);
     63extern void              hr_add_ba_offset(hr_volume_t *, uint64_t *);
     64extern void              hr_update_ext_status(hr_volume_t *, size_t,
     65    hr_ext_status_t);
     66extern void              hr_update_hotspare_status(hr_volume_t *, size_t,
     67    hr_ext_status_t);
     68extern void              hr_update_vol_status(hr_volume_t *, hr_vol_status_t);
     69extern void              hr_update_ext_svc_id(hr_volume_t *, size_t,
     70    service_id_t);
     71extern void              hr_update_hotspare_svc_id(hr_volume_t *, size_t,
     72    service_id_t);
     73extern void              hr_sync_all_extents(hr_volume_t *);
     74extern size_t            hr_count_extents(hr_volume_t *, hr_ext_status_t);
     75extern void              hr_mark_vol_state_dirty(hr_volume_t *);
     76extern void              hr_range_lock_release(hr_range_lock_t *);
     77extern hr_range_lock_t  *hr_range_lock_acquire(hr_volume_t *, uint64_t,
    6778    uint64_t);
    68 extern void hr_range_lock_release(hr_range_lock_t *);
    69 extern void hr_mark_vol_state_dirty(hr_volume_t *);
     79extern errno_t           hr_util_try_auto_assemble(size_t *);
    7080
    7181#endif
  • uspace/srv/bd/hr/var.h

    r7bfe468 r8b51009  
    4242#include <fibril_synch.h>
    4343#include <hr.h>
     44#include <stdatomic.h>
    4445
    4546#include "fge.h"
     47#include "superblock.h"
    4648
    4749#define NAME            "hr"
     
    5052struct hr_volume;
    5153typedef struct hr_volume hr_volume_t;
     54typedef struct hr_metadata hr_metadata_t;
    5255
    5356typedef struct hr_ops {
     
    6972        hr_fpool_t      *fge;                   /* fibril pool */
    7073
     74        uint32_t         metadata_version; /* XXX: yet unused */
     75
     76        hr_metadata_t   *in_mem_md; /* TODO: implement */
     77
    7178        /* invariants */
    7279        size_t           extent_no;             /* number of extents */
    7380        size_t           bsize;                 /* block size */
    7481        uint64_t         nblocks;               /* no. of all usable blocks */
     82        uint64_t         truncated_blkno;       /* blkno per extent */
    7583        uint64_t         data_blkno;            /* no. of user usable blocks */
    7684        uint64_t         data_offset;           /* user data offset in blocks */
     
    9199        _Atomic bool     state_dirty;           /* dirty state */
    92100
    93         /*
    94          * XXX: unportable for 32-bit?
    95          *
    96          * Add macros for locking or atomic increment depending
    97          * on the platform?
    98          */
     101        /* XXX: atomic_uint_least64_t? */
    99102        _Atomic uint64_t rebuild_blk;           /* rebuild position */
     103        _Atomic int      open_cnt;              /* open/close() counter */
    100104        uint64_t         counter;               /* TODO: metadata syncing */
    101105        hr_vol_status_t  status;                /* volume status */
Note: See TracChangeset for help on using the changeset viewer.