Changeset 0277ec2 in mainline


Ignore:
Timestamp:
2025-04-01T08:51:52Z (6 weeks ago)
Author:
Miroslav Cimerman <mc@…>
Children:
4200735
Parents:
a5ec426
Message:

hr: refactor metadata handling

Location:
uspace/srv/bd/hr
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/bd/hr/hr.c

    ra5ec426 r0277ec2  
    142142                goto error;
    143143
    144         rc = hr_write_meta_to_vol(new_volume);
     144        rc = hr_metadata_init(new_volume, new_volume->in_mem_md);
     145        if (rc != EOK)
     146                goto error;
     147
     148        rc = hr_metadata_save(new_volume);
    145149        if (rc != EOK)
    146150                goto error;
  • uspace/srv/bd/hr/raid1.c

    ra5ec426 r0277ec2  
    540540        fibril_rwlock_write_unlock(&vol->states_lock);
    541541
    542         /*
    543          * For now write metadata at the end, because
    544          * we don't sync metada accross extents yet.
    545          */
    546         hr_write_meta_to_ext(vol, rebuild_idx);
     542        rc = hr_metadata_save(vol);
     543
    547544end:
    548545        if (rc != EOK) {
  • uspace/srv/bd/hr/raid5.c

    ra5ec426 r0277ec2  
    842842
    843843        hr_update_ext_status(vol, bad, HR_EXT_ONLINE);
    844         /*
    845          * For now write metadata at the end, because
    846          * we don't sync metada accross extents yet.
    847          */
    848         hr_write_meta_to_ext(vol, bad);
     844
     845        rc = hr_metadata_save(vol);
     846
    849847end:
    850848        (void)hr_raid5_update_vol_status(vol);
  • uspace/srv/bd/hr/superblock.c

    ra5ec426 r0277ec2  
    5050#include "var.h"
    5151
    52 static errno_t read_metadata(service_id_t, hr_metadata_t *);
    53 static errno_t hr_fill_meta_from_vol(hr_volume_t *, hr_metadata_t *);
    54 
    55 errno_t hr_write_meta_to_vol(hr_volume_t *vol)
    56 {
    57         HR_DEBUG("%s()", __func__);
    58 
    59         errno_t rc;
    60         size_t i;
    61         hr_metadata_t *metadata;
     52errno_t hr_metadata_init(hr_volume_t *vol, hr_metadata_t *md)
     53{
     54        HR_DEBUG("%s()", __func__);
     55
     56        str_cpy(md->magic, HR_MAGIC_SIZE, HR_MAGIC_STR);
     57
     58        md->version = HR_METADATA_VERSION;
     59        vol->metadata_version = md->version;
     60
     61        md->counter = 0;
     62        vol->counter = md->counter;
     63
    6264        uuid_t uuid;
    63 
    64         metadata = calloc(1, HR_META_SIZE * vol->bsize);
    65         if (metadata == NULL)
    66                 return ENOMEM;
    67 
    68         rc = hr_fill_meta_from_vol(vol, metadata);
    69         if (rc != EOK)
    70                 goto error;
    71 
    7265        /* rndgen */
    7366        fibril_usleep(1000);
    74         rc = uuid_generate(&uuid);
    75         if (rc != EOK)
    76                 goto error;
     67        errno_t rc = uuid_generate(&uuid);
     68        if (rc != EOK)
     69                return rc;
    7770
    7871        /* XXX: for now we just copy byte by byte as "encoding" */
    79         memcpy(metadata->uuid, &uuid, HR_UUID_LEN);
     72        memcpy(md->uuid, &uuid, HR_UUID_LEN);
    8073        /* uuid_encode(&uuid, metadata->uuid); */
    8174
    82         for (i = 0; i < vol->extent_no; i++) {
    83                 metadata->index = host2uint32_t_le(i);
    84 
    85                 rc = block_write_direct(vol->extents[i].svc_id,
    86                     vol->extents[i].blkno - 1, HR_META_SIZE, metadata);
     75        md->nblocks = vol->nblocks;
     76        md->data_blkno = vol->data_blkno;
     77        md->truncated_blkno = vol->truncated_blkno;
     78        md->data_offset = vol->data_offset;
     79        md->extent_no = vol->extent_no;
     80        md->level = vol->level;
     81        md->layout = vol->layout;
     82        md->strip_size = vol->strip_size;
     83        md->bsize = vol->bsize;
     84        memcpy(md->devname, vol->devname, HR_DEVNAME_LEN);
     85
     86        return EOK;
     87}
     88
     89errno_t hr_metadata_save(hr_volume_t *vol)
     90{
     91        HR_DEBUG("%s()", __func__);
     92
     93        errno_t rc = EOK;
     94
     95        void *md_block = calloc(1, vol->bsize);
     96        if (md_block == NULL)
     97                return ENOMEM;
     98
     99        for (size_t i = 0; i < vol->extent_no; i++) {
     100                hr_extent_t *ext = &vol->extents[i];
     101
     102                /* TODO: special case for REBUILD */
     103                if (ext->status != HR_EXT_ONLINE)
     104                        continue;
     105
     106                vol->in_mem_md->index = i;
     107                hr_encode_metadata_to_block(vol->in_mem_md, md_block);
     108                rc = hr_write_metadata_block(ext->svc_id, md_block);
     109                /*
     110                 * XXX: here maybe call vol status event or the state
     111                 * callback inside, same with read_block...
     112                 *
     113                 * also think about using FGE here... maybe a bit more
     114                 * code, but faster and gratis state callback :-)
     115                 */
    87116                if (rc != EOK)
    88117                        goto error;
    89 
    90118        }
    91119
    92         memcpy(vol->in_mem_md, metadata, sizeof(hr_metadata_t));
    93120error:
    94         free(metadata);
     121        free(md_block);
    95122        return rc;
    96123}
    97124
    98 errno_t hr_write_meta_to_ext(hr_volume_t *vol, size_t ext)
    99 {
    100         HR_DEBUG("%s()", __func__);
    101 
    102         errno_t rc;
    103         hr_metadata_t *metadata;
    104 
    105         /* XXX: use scratchpad */
    106         metadata = calloc(1, HR_META_SIZE * vol->bsize);
    107         if (metadata == NULL)
    108                 return ENOMEM;
    109 
    110         rc = hr_fill_meta_from_vol(vol, metadata);
    111         if (rc != EOK)
    112                 goto error;
    113 
    114         metadata->index = host2uint32_t_le(ext);
    115 
    116         rc = block_write_direct(vol->extents[ext].svc_id,
    117             vol->extents[ext].blkno - 1, HR_META_SIZE, metadata);
    118         if (rc != EOK)
    119                 goto error;
    120 
    121 error:
    122         free(metadata);
    123         return rc;
    124 }
    125 
    126 /*
    127  * Fill metadata members from
    128  * specified volume.
    129  *
    130  * Does not fill extent index and UUID.
    131  */
    132 static errno_t hr_fill_meta_from_vol(hr_volume_t *vol, hr_metadata_t *metadata)
    133 {
    134         HR_DEBUG("%s()", __func__);
    135 
    136         size_t meta_blkno = HR_META_SIZE;
    137 
    138         if (vol->level != HR_LVL_1)
    139                 meta_blkno *= vol->extent_no;
    140 
    141         if (vol->nblocks < meta_blkno) {
    142                 HR_ERROR("hr_fill_meta_from_vol(): volume \"%s\" does not "
    143                     " have enough space to store metada, aborting\n",
    144                     vol->devname);
    145                 return EINVAL;
    146         } else if (vol->nblocks == meta_blkno) {
    147                 HR_ERROR("hr_fill_meta_from_vol(): volume \"%s\" would have "
    148                     "zero data blocks after writing metadata, aborting\n",
    149                     vol->devname);
    150                 return EINVAL;
    151         }
    152 
    153         /* XXX: use scratchpad */
    154         str_cpy(metadata->magic, HR_MAGIC_SIZE, HR_MAGIC_STR);
    155         metadata->nblocks = host2uint64_t_le(vol->nblocks);
    156         metadata->data_blkno = host2uint64_t_le(vol->data_blkno);
    157         metadata->truncated_blkno = host2uint64_t_le(vol->truncated_blkno);
    158         metadata->data_offset = host2uint64_t_le(vol->data_offset);
    159         metadata->counter = host2uint64_t_le(~(0UL)); /* XXX: unused */
    160         metadata->version = host2uint32_t_le(~(0U)); /* XXX: unused */
    161         metadata->extent_no = host2uint32_t_le(vol->extent_no);
    162         /* index filled separately for each extent */
    163         metadata->level = host2uint32_t_le(vol->level);
    164         metadata->layout = host2uint32_t_le(vol->layout);
    165         metadata->strip_size = host2uint32_t_le(vol->strip_size);
    166         metadata->bsize = host2uint32_t_le(vol->bsize);
    167         str_cpy(metadata->devname, HR_DEVNAME_LEN, vol->devname);
    168 
    169         return EOK;
    170 }
    171 
    172125bool hr_valid_md_magic(hr_metadata_t *md)
    173126{
     127        HR_DEBUG("%s()", __func__);
     128
    174129        if (str_lcmp(md->magic, HR_MAGIC_STR, HR_MAGIC_SIZE) != 0)
    175130                return false;
     
    178133}
    179134
    180 errno_t hr_fill_vol_from_meta(hr_volume_t *vol)
     135errno_t hr_write_metadata_block(service_id_t dev, const void *block)
    181136{
    182137        HR_DEBUG("%s()", __func__);
    183138
    184139        errno_t rc;
    185         hr_metadata_t *metadata;
    186 
    187         metadata = calloc(1, HR_META_SIZE * vol->bsize);
    188         if (metadata == NULL)
    189                 return ENOMEM;
    190 
    191         service_id_t assembly_svc_id_order[HR_MAX_EXTENTS] = { 0 };
    192         for (size_t i = 0; i < vol->extent_no; i++)
    193                 assembly_svc_id_order[i] = vol->extents[i].svc_id;
    194 
     140        uint64_t blkno;
     141        size_t bsize;
     142
     143        rc = block_get_bsize(dev, &bsize);
     144        if (rc != EOK)
     145                return rc;
     146
     147        if (bsize < sizeof(hr_metadata_t))
     148                return EINVAL;
     149
     150        rc = block_get_nblocks(dev, &blkno);
     151        if (rc != EOK)
     152                return rc;
     153
     154        if (blkno < HR_META_SIZE)
     155                return EINVAL;
     156
     157        rc = block_write_direct(dev, blkno - 1, HR_META_SIZE, block);
    195158        /*
    196          * XXX: sanitize metadata, for example if truncated_blkno <= extent.blkno
    197          * or bsize == extent.bsize
     159         * XXX: here maybe call vol status event or the state callback...
     160         *
     161         * but need to pass vol pointer
    198162         */
    199163
    200         size_t md_order_indices[HR_MAX_EXTENTS] = { 0 };
    201         for (size_t i = 0; i < vol->extent_no; i++) {
    202                 if (assembly_svc_id_order[i] == 0) {
    203                         /* set invalid index */
    204                         md_order_indices[i] = vol->extent_no;
    205                         continue;
    206                 }
    207                 rc = read_metadata(assembly_svc_id_order[i], metadata);
    208                 if (rc != EOK)
    209                         goto end;
    210                 if (!hr_valid_md_magic(metadata))
    211                         goto end;
    212                 md_order_indices[i] = uint32_t_le2host(metadata->index);
    213         }
    214 
    215         for (size_t i = 0; i < vol->extent_no; i++) {
    216                 vol->extents[i].svc_id = 0;
    217                 vol->extents[i].status = HR_EXT_MISSING;
    218         }
    219 
    220         /* sort */
    221         for (size_t i = 0; i < vol->extent_no; i++) {
    222                 for (size_t j = 0; j < vol->extent_no; j++) {
    223                         if (i == md_order_indices[j]) {
    224                                 vol->extents[i].svc_id =
    225                                     assembly_svc_id_order[j];
    226                                 vol->extents[i].status = HR_EXT_ONLINE;
    227                         }
    228                 }
    229         }
    230 
    231         /*
    232          * still assume metadata are in sync across extents
    233          */
    234 
    235         if (vol->extent_no != uint32_t_le2host(metadata->extent_no)) {
    236                 HR_ERROR("number of divices in array differ: specified %zu, "
    237                     "metadata states %u",
    238                     vol->extent_no, uint32_t_le2host(metadata->extent_no));
    239                 rc = EINVAL;
    240                 goto end;
    241         }
    242 
    243         /* TODO: handle version */
    244         vol->level = uint32_t_le2host(metadata->level);
    245         vol->layout = (uint8_t)uint32_t_le2host(metadata->layout);
    246         vol->strip_size = uint32_t_le2host(metadata->strip_size);
    247         vol->nblocks = uint64_t_le2host(metadata->nblocks);
    248         vol->data_blkno = uint64_t_le2host(metadata->data_blkno);
    249         vol->data_offset = uint64_t_le2host(metadata->data_offset);
    250         vol->bsize = uint32_t_le2host(metadata->bsize);
    251         vol->counter = uint64_t_le2host(0x00); /* unused */
    252 
    253         if (str_cmp(metadata->devname, vol->devname) != 0) {
    254                 HR_WARN("devname on metadata (%s) and config (%s) differ, "
    255                     "using config", metadata->devname, vol->devname);
    256         }
    257 end:
    258         free(metadata);
    259164        return rc;
    260165}
    261166
    262 /* XXX: rewrite with read_metadata_block() */
    263 static errno_t read_metadata(service_id_t dev, hr_metadata_t *metadata)
    264 {
    265         errno_t rc;
    266         uint64_t nblocks;
    267 
    268         rc = block_get_nblocks(dev, &nblocks);
    269         if (rc != EOK)
    270                 return rc;
    271 
    272         if (nblocks < HR_META_SIZE)
    273                 return EINVAL;
    274 
    275         rc = block_read_direct(dev, nblocks - 1, HR_META_SIZE, metadata);
    276         if (rc != EOK)
    277                 return rc;
    278 
    279         return EOK;
    280 }
    281 
    282167errno_t hr_get_metadata_block(service_id_t dev, void **rblock)
    283168{
    284169        HR_DEBUG("%s()", __func__);
     170
    285171        errno_t rc;
    286172        uint64_t blkno;
     
    307193
    308194        rc = block_read_direct(dev, blkno - 1, HR_META_SIZE, block);
     195        /*
     196         * XXX: here maybe call vol status event or the state callback...
     197         *
     198         * but need to pass vol pointer
     199         */
    309200        if (rc != EOK) {
    310201                free(block);
     
    321212}
    322213
    323 void hr_decode_metadata_from_block(void *block, hr_metadata_t *metadata)
    324 {
     214void hr_encode_metadata_to_block(hr_metadata_t *metadata, void *block)
     215{
     216        HR_DEBUG("%s()", __func__);
     217
     218        /*
     219         * Use scratch metadata for easier encoding without the need
     220         * for manualy specifying offsets.
     221         */
     222        hr_metadata_t scratch_md;
     223
     224        memcpy(scratch_md.magic, metadata->magic, HR_MAGIC_SIZE);
     225        memcpy(scratch_md.uuid, metadata->uuid, HR_UUID_LEN);
     226        /* uuid_decode((uint8_t *)scratch_md.uuid, (uuid_t *)metadata->uuid); */
     227
     228        scratch_md.nblocks = host2uint64_t_le(metadata->nblocks);
     229        scratch_md.data_blkno = host2uint64_t_le(metadata->data_blkno);
     230        scratch_md.truncated_blkno = host2uint64_t_le(
     231            metadata->truncated_blkno);
     232        scratch_md.data_offset = host2uint64_t_le(metadata->data_offset);
     233        scratch_md.counter = host2uint64_t_le(metadata->counter);
     234        scratch_md.version = host2uint32_t_le(metadata->version);
     235        scratch_md.extent_no = host2uint32_t_le(metadata->extent_no);
     236        scratch_md.index = host2uint32_t_le(metadata->index);
     237        scratch_md.level = host2uint32_t_le(metadata->level);
     238        scratch_md.layout = host2uint32_t_le(metadata->layout);
     239        scratch_md.strip_size = host2uint32_t_le(metadata->strip_size);
     240        scratch_md.bsize = host2uint32_t_le(metadata->bsize);
     241        memcpy(scratch_md.devname, metadata->devname, HR_DEVNAME_LEN);
     242
     243        memcpy(block, &scratch_md, sizeof(hr_metadata_t));
     244}
     245
     246void hr_decode_metadata_from_block(const void *block, hr_metadata_t *metadata)
     247{
     248        HR_DEBUG("%s()", __func__);
     249
    325250        /*
    326251         * Use scratch metadata for easier decoding without the need
     
    352277void hr_metadata_dump(hr_metadata_t *metadata)
    353278{
     279        HR_DEBUG("%s()", __func__);
     280
    354281        printf("\tmagic: %s\n", metadata->magic);
    355282        printf("\tUUID: ");
  • uspace/srv/bd/hr/superblock.h

    ra5ec426 r0277ec2  
    4848#define HR_MAGIC_SIZE           16
    4949#define HR_UUID_LEN             16
    50 /* #define HR_METADATA_VERSION 0 */
     50#define HR_METADATA_VERSION     1
    5151
    5252typedef struct hr_metadata hr_metadata_t;
     
    7979} __attribute__((packed));
    8080
    81 extern errno_t  hr_write_meta_to_vol(hr_volume_t *);
    82 extern errno_t  hr_write_meta_to_ext(hr_volume_t *, size_t);
    83 extern errno_t  hr_fill_vol_from_meta(hr_volume_t *);
     81extern errno_t  hr_metadata_init(hr_volume_t *, hr_metadata_t *);
     82extern errno_t  hr_metadata_save(hr_volume_t *);
     83extern errno_t  hr_write_metadata_block(service_id_t, const void *);
    8484extern errno_t  hr_get_metadata_block(service_id_t, void **);
    85 extern void     hr_decode_metadata_from_block(void *, hr_metadata_t *);
     85extern void     hr_encode_metadata_to_block(hr_metadata_t *, void *);
     86extern void     hr_decode_metadata_from_block(const void *, hr_metadata_t *);
    8687extern void     hr_metadata_dump(hr_metadata_t *);
    8788extern bool     hr_valid_md_magic(hr_metadata_t *);
  • uspace/srv/bd/hr/util.c

    ra5ec426 r0277ec2  
    773773
    774774        list_foreach(*list, link, struct svc_id_linked, iter) {
    775                 hr_metadata_dump(iter->md);
     775                /* hr_metadata_dump(iter->md); */
    776776                if (iter->md->counter >= max_counter_val) {
    777777                        max_counter_val = iter->md->counter;
Note: See TracChangeset for help on using the changeset viewer.