Changeset 50603405 in mainline


Ignore:
Timestamp:
2025-04-20T10:09:26Z (4 weeks ago)
Author:
Miroslav Cimerman <mc@…>
Children:
14394141
Parents:
6f41c21f
git-author:
Miroslav Cimerman <mc@…> (2025-04-20 09:56:29)
git-committer:
Miroslav Cimerman <mc@…> (2025-04-20 10:09:26)
Message:

hr: metadata format agnostic superblock ops

Put metadata specific code behind a new hr_superblock_ops_t
interface, that allows to easily add support for new metadata
formats.

Location:
uspace/srv/bd/hr
Files:
2 added
10 edited

Legend:

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

    r6f41c21f r50603405  
    7979        size_t i, size;
    8080        hr_config_t *cfg;
    81         hr_volume_t *new_volume;
     81        hr_volume_t *vol;
    8282        ipc_call_t call;
    8383
     
    127127        }
    128128
    129         rc = hr_create_vol_struct(&new_volume, cfg->level, cfg->devname);
     129        rc = hr_create_vol_struct(&vol, cfg->level, cfg->devname,
     130            HR_METADATA_NATIVE);
    130131        if (rc != EOK) {
    131132                free(cfg);
     
    134135        }
    135136
    136         rc = hr_init_extents_from_cfg(new_volume, cfg);
    137         if (rc != EOK)
    138                 goto error;
    139 
    140         new_volume->hr_ops.init(new_volume);
    141         if (rc != EOK)
    142                 goto error;
    143 
    144         rc = hr_metadata_init(new_volume, new_volume->in_mem_md);
    145         if (rc != EOK)
    146                 goto error;
    147 
    148         rc = new_volume->hr_ops.create(new_volume);
    149         if (rc != EOK)
    150                 goto error;
    151 
    152         rc = hr_metadata_save(new_volume, WITH_STATE_CALLBACK);
    153         if (rc != EOK)
    154                 goto error;
    155 
    156         rc = hr_register_volume(new_volume);
     137        rc = hr_init_extents_from_cfg(vol, cfg);
     138        if (rc != EOK)
     139                goto error;
     140
     141        vol->hr_ops.init(vol);
     142        if (rc != EOK)
     143                goto error;
     144
     145        rc = vol->meta_ops->init_vol2meta(vol, vol->in_mem_md);
     146        if (rc != EOK)
     147                goto error;
     148
     149        rc = vol->hr_ops.create(vol);
     150        if (rc != EOK)
     151                goto error;
     152
     153        rc = vol->meta_ops->save(vol, WITH_STATE_CALLBACK);
     154        if (rc != EOK)
     155                goto error;
     156
     157        rc = hr_register_volume(vol);
    157158        if (rc != EOK)
    158159                goto error;
    159160
    160161        fibril_rwlock_write_lock(&hr_volumes_lock);
    161         list_append(&new_volume->lvolumes, &hr_volumes);
     162        list_append(&vol->lvolumes, &hr_volumes);
    162163        fibril_rwlock_write_unlock(&hr_volumes_lock);
    163164
    164         HR_DEBUG("created volume \"%s\" (%" PRIun ")\n", new_volume->devname,
    165             new_volume->svc_id);
     165        HR_DEBUG("created volume \"%s\" (%" PRIun ")\n", vol->devname,
     166            vol->svc_id);
    166167
    167168        free(cfg);
     
    170171error:
    171172        free(cfg);
    172         hr_destroy_vol_struct(new_volume);
     173        hr_destroy_vol_struct(vol);
    173174        async_answer_0(icall, rc);
    174175}
  • uspace/srv/bd/hr/meson.build

    r6f41c21f r50603405  
    3232            'hr.c',
    3333            'io.c',
     34            'metadata/native.c',
    3435            'raid0.c',
    3536            'raid1.c',
  • uspace/srv/bd/hr/raid0.c

    r6f41c21f r50603405  
    124124        vol->truncated_blkno = truncated_blkno;
    125125        vol->nblocks = total_blkno;
    126         vol->data_offset = HR_DATA_OFF;
     126        vol->data_offset = vol->meta_ops->get_data_offset();
    127127
    128128        vol->data_blkno = total_blkno;
    129         vol->data_blkno -= HR_META_SIZE * vol->extent_no; /* count md blocks */
     129        /* count md blocks */
     130        vol->data_blkno -= vol->meta_ops->get_size() * vol->extent_no;
    130131
    131132        vol->strip_size = HR_STRIP_SIZE;
     
    200201        fibril_mutex_lock(&vol->md_lock);
    201202
    202         /* XXX: will be wrapped in md specific fcn ptrs */
    203         vol->in_mem_md->counter++;
     203        vol->meta_ops->inc_counter(vol->in_mem_md);
     204        /* TODO: save right away */
    204205
    205206        fibril_mutex_unlock(&vol->md_lock);
  • uspace/srv/bd/hr/raid1.c

    r6f41c21f r50603405  
    3434 */
    3535
     36#include <abi/ipc/ipc.h>
    3637#include <bd_srv.h>
    3738#include <block.h>
     
    137138        vol->truncated_blkno = truncated_blkno;
    138139        vol->nblocks = truncated_blkno;
    139         vol->data_offset = HR_DATA_OFF;
    140         vol->data_blkno = truncated_blkno - HR_META_SIZE;
     140        vol->data_offset = vol->meta_ops->get_data_offset();
     141        vol->data_blkno = truncated_blkno - vol->meta_ops->get_size();
    141142        vol->strip_size = 0;
    142143
     
    227228        fibril_mutex_lock(&vol->md_lock);
    228229
    229         /* XXX: will be wrapped in md specific fcn ptrs */
    230         vol->in_mem_md->counter++;
     230        vol->meta_ops->inc_counter(vol->in_mem_md);
     231        /* XXX: save right away */
    231232
    232233        fibril_mutex_unlock(&vol->md_lock);
     
    550551        fibril_rwlock_write_unlock(&vol->states_lock);
    551552
    552         rc = hr_metadata_save(vol, WITH_STATE_CALLBACK);
     553        rc = vol->meta_ops->save(vol, WITH_STATE_CALLBACK);
    553554
    554555end:
  • uspace/srv/bd/hr/raid5.c

    r6f41c21f r50603405  
    139139        vol->truncated_blkno = truncated_blkno;
    140140        vol->nblocks = total_blkno;
    141         vol->data_offset = HR_DATA_OFF;
     141        vol->data_offset = vol->meta_ops->get_data_offset();
    142142
    143143        vol->data_blkno = total_blkno;
    144         vol->data_blkno -= HR_META_SIZE * vol->extent_no; /* count md blocks */
     144        /* count md blocks */
     145        vol->data_blkno -= vol->meta_ops->get_size() * vol->extent_no;
    145146        vol->data_blkno -= truncated_blkno; /* count parity */
    146147
     
    845846        hr_update_ext_status(vol, bad, HR_EXT_ONLINE);
    846847
    847         rc = hr_metadata_save(vol, WITH_STATE_CALLBACK);
     848        rc = vol->meta_ops->save(vol, WITH_STATE_CALLBACK);
    848849
    849850end:
  • uspace/srv/bd/hr/superblock.c

    r6f41c21f r50603405  
    4545#include <stdio.h>
    4646#include <str.h>
    47 #include <types/uuid.h>
    4847
     48#include "metadata/native.h"
    4949#include "superblock.h"
    5050#include "util.h"
    5151#include "var.h"
    5252
    53 errno_t hr_metadata_init(hr_volume_t *vol, hr_metadata_t *md)
     53extern hr_superblock_ops_t metadata_native_ops;
     54
     55static hr_superblock_ops_t *hr_superblock_ops_all[] = {
     56        [HR_METADATA_NATIVE] = &metadata_native_ops
     57};
     58
     59hr_superblock_ops_t *get_type_ops(metadata_type_t type)
    5460{
    55         HR_DEBUG("%s()", __func__);
     61        assert(type >= HR_METADATA_NATIVE && type < HR_METADATA_LAST_DUMMY);
    5662
    57         str_cpy(md->magic, HR_MAGIC_SIZE, HR_MAGIC_STR);
    58 
    59         md->version = HR_METADATA_VERSION;
    60         vol->metadata_version = md->version;
    61 
    62         md->counter = 0;
    63 
    64         uuid_t uuid;
    65         /* rndgen */
    66         fibril_usleep(1000);
    67         errno_t rc = uuid_generate(&uuid);
    68         if (rc != EOK)
    69                 return rc;
    70 
    71         /* XXX: for now we just copy byte by byte as "encoding" */
    72         memcpy(md->uuid, &uuid, HR_UUID_LEN);
    73         /* uuid_encode(&uuid, metadata->uuid); */
    74 
    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;
     63        return hr_superblock_ops_all[type];
    8764}
    8865
    89 /*
    90  * XXX: finish this fcn documentation
    91  *
    92  * Returns ENOMEM else EOK
    93  */
    94 errno_t hr_metadata_save(hr_volume_t *vol, bool with_state_callback)
    95 {
    96         HR_DEBUG("%s()", __func__);
    97 
    98         errno_t rc = EOK;
    99 
    100         void *md_block = calloc(1, vol->bsize);
    101         if (md_block == NULL)
    102                 return ENOMEM;
    103 
    104         fibril_rwlock_read_lock(&vol->extents_lock);
    105 
    106         fibril_mutex_lock(&vol->md_lock);
    107 
    108         for (size_t i = 0; i < vol->extent_no; i++) {
    109                 hr_extent_t *ext = &vol->extents[i];
    110 
    111                 fibril_rwlock_read_lock(&vol->states_lock);
    112 
    113                 /* TODO: special case for REBUILD */
    114                 if (ext->status != HR_EXT_ONLINE)
    115                         continue;
    116 
    117                 fibril_rwlock_read_unlock(&vol->states_lock);
    118 
    119                 vol->in_mem_md->index = i;
    120                 hr_encode_metadata_to_block(vol->in_mem_md, md_block);
    121                 rc = hr_write_metadata_block(ext->svc_id, md_block);
    122                 if (with_state_callback && rc != EOK)
    123                         vol->state_callback(vol, i, rc);
    124         }
    125 
    126         fibril_mutex_unlock(&vol->md_lock);
    127 
    128         fibril_rwlock_read_unlock(&vol->extents_lock);
    129 
    130         if (with_state_callback)
    131                 vol->hr_ops.status_event(vol);
    132 
    133         free(md_block);
    134         return EOK;
    135 }
    136 
    137 bool hr_valid_md_magic(const hr_metadata_t *md)
    138 {
    139         HR_DEBUG("%s()", __func__);
    140 
    141         if (str_lcmp(md->magic, HR_MAGIC_STR, HR_MAGIC_SIZE) != 0)
    142                 return false;
    143 
    144         return true;
    145 }
    146 
    147 errno_t hr_write_metadata_block(service_id_t dev, const void *block)
     66errno_t find_metadata(service_id_t svc_id, void **rmetadata,
     67    metadata_type_t *rtype)
    14868{
    14969        HR_DEBUG("%s()", __func__);
    15070
    15171        errno_t rc;
    152         uint64_t blkno;
    153         size_t bsize;
     72        hr_superblock_ops_t *meta_ops;
     73        void *meta_block;
     74        void *metadata_struct;
    15475
    155         rc = block_get_bsize(dev, &bsize);
    156         if (rc != EOK)
    157                 return rc;
    158 
    159         if (bsize < sizeof(hr_metadata_t))
     76        if (rmetadata == NULL)
     77                return EINVAL;
     78        if (rtype == NULL)
    16079                return EINVAL;
    16180
    162         rc = block_get_nblocks(dev, &blkno);
    163         if (rc != EOK)
    164                 return rc;
     81        volatile metadata_type_t type = HR_METADATA_NATIVE;
     82        for (; type < HR_METADATA_LAST_DUMMY; type++) {
     83                meta_ops = hr_superblock_ops_all[type];
    16584
    166         if (blkno < HR_META_SIZE)
    167                 return EINVAL;
     85                metadata_struct = meta_ops->alloc_struct();
     86                if (metadata_struct == NULL)
     87                        return ENOMEM;
    16888
    169         rc = block_write_direct(dev, blkno - 1, HR_META_SIZE, block);
     89                rc = meta_ops->get_block(svc_id, &meta_block);
     90                if (rc == ENOMEM)
     91                        return ENOMEM;
     92                if (rc != EOK)
     93                        continue;
    17094
    171         return rc;
    172 }
     95                meta_ops->decode(meta_block, metadata_struct);
    17396
    174 errno_t hr_get_metadata_block(service_id_t dev, void **rblock)
    175 {
    176         HR_DEBUG("%s()", __func__);
     97                free(meta_block);
    17798
    178         errno_t rc;
    179         uint64_t blkno;
    180         size_t bsize;
    181         void *block;
     99                if (!meta_ops->has_valid_magic(metadata_struct)) {
     100                        free(metadata_struct);
     101                        continue;
     102                }
    182103
    183         rc = block_get_bsize(dev, &bsize);
    184         if (rc != EOK)
    185                 return rc;
    186 
    187         if (bsize < sizeof(hr_metadata_t))
    188                 return EINVAL;
    189 
    190         rc = block_get_nblocks(dev, &blkno);
    191         if (rc != EOK)
    192                 return rc;
    193 
    194         if (blkno < HR_META_SIZE)
    195                 return EINVAL;
    196 
    197         block = malloc(bsize);
    198         if (block == NULL)
    199                 return ENOMEM;
    200 
    201         rc = block_read_direct(dev, blkno - 1, HR_META_SIZE, block);
    202         /*
    203          * XXX: here maybe call vol status event or the state callback...
    204          *
    205          * but need to pass vol pointer
    206          */
    207         if (rc != EOK) {
    208                 free(block);
    209                 return rc;
     104                *rmetadata = metadata_struct;
     105                *rtype = type;
     106                return EOK;
    210107        }
    211108
    212         if (rblock == NULL) {
    213                 free(block);
    214                 return EINVAL;
    215         }
    216 
    217         *rblock = block;
    218         return EOK;
    219 }
    220 
    221 void hr_encode_metadata_to_block(const hr_metadata_t *metadata, void *block)
    222 {
    223         HR_DEBUG("%s()", __func__);
    224 
    225         /*
    226          * Use scratch metadata for easier encoding without the need
    227          * for manualy specifying offsets.
    228          */
    229         hr_metadata_t scratch_md;
    230 
    231         memcpy(scratch_md.magic, metadata->magic, HR_MAGIC_SIZE);
    232         memcpy(scratch_md.uuid, metadata->uuid, HR_UUID_LEN);
    233         /* uuid_decode((uint8_t *)scratch_md.uuid, (uuid_t *)metadata->uuid); */
    234 
    235         scratch_md.nblocks = host2uint64_t_le(metadata->nblocks);
    236         scratch_md.data_blkno = host2uint64_t_le(metadata->data_blkno);
    237         scratch_md.truncated_blkno = host2uint64_t_le(
    238             metadata->truncated_blkno);
    239         scratch_md.data_offset = host2uint64_t_le(metadata->data_offset);
    240         scratch_md.counter = host2uint64_t_le(metadata->counter);
    241         scratch_md.version = host2uint32_t_le(metadata->version);
    242         scratch_md.extent_no = host2uint32_t_le(metadata->extent_no);
    243         scratch_md.index = host2uint32_t_le(metadata->index);
    244         scratch_md.level = host2uint32_t_le(metadata->level);
    245         scratch_md.layout = host2uint32_t_le(metadata->layout);
    246         scratch_md.strip_size = host2uint32_t_le(metadata->strip_size);
    247         scratch_md.bsize = host2uint32_t_le(metadata->bsize);
    248         memcpy(scratch_md.devname, metadata->devname, HR_DEVNAME_LEN);
    249 
    250         memcpy(block, &scratch_md, sizeof(hr_metadata_t));
    251 }
    252 
    253 void hr_decode_metadata_from_block(const void *block, hr_metadata_t *metadata)
    254 {
    255         HR_DEBUG("%s()", __func__);
    256 
    257         /*
    258          * Use scratch metadata for easier decoding without the need
    259          * for manualy specifying offsets.
    260          */
    261         hr_metadata_t scratch_md;
    262         memcpy(&scratch_md, block, sizeof(hr_metadata_t));
    263 
    264         memcpy(metadata->magic, scratch_md.magic, HR_MAGIC_SIZE);
    265         memcpy(metadata->uuid, scratch_md.uuid, HR_UUID_LEN);
    266         /* uuid_decode((uint8_t *)scratch_md.uuid, (uuid_t *)metadata->uuid); */
    267 
    268         metadata->nblocks = uint64_t_le2host(scratch_md.nblocks);
    269         metadata->data_blkno = uint64_t_le2host(scratch_md.data_blkno);
    270         metadata->truncated_blkno = uint64_t_le2host(
    271             scratch_md.truncated_blkno);
    272         metadata->data_offset = uint64_t_le2host(scratch_md.data_offset);
    273         metadata->counter = uint64_t_le2host(scratch_md.counter);
    274         metadata->version = uint32_t_le2host(scratch_md.version);
    275         metadata->extent_no = uint32_t_le2host(scratch_md.extent_no);
    276         metadata->index = uint32_t_le2host(scratch_md.index);
    277         metadata->level = uint32_t_le2host(scratch_md.level);
    278         metadata->layout = uint32_t_le2host(scratch_md.layout);
    279         metadata->strip_size = uint32_t_le2host(scratch_md.strip_size);
    280         metadata->bsize = uint32_t_le2host(scratch_md.bsize);
    281         memcpy(metadata->devname, scratch_md.devname, HR_DEVNAME_LEN);
    282 }
    283 
    284 void hr_metadata_dump(const hr_metadata_t *metadata)
    285 {
    286         HR_DEBUG("%s()", __func__);
    287 
    288         printf("\tmagic: %s\n", metadata->magic);
    289         printf("\tUUID: ");
    290         for (size_t i = 0; i < HR_UUID_LEN; ++i) {
    291                 printf("%.2X", metadata->uuid[i]);
    292                 if (i + 1 < HR_UUID_LEN)
    293                         printf(" ");
    294         }
    295         printf("\n");
    296         printf("\tnblocks: %" PRIu64 "\n", metadata->nblocks);
    297         printf("\tdata_blkno: %" PRIu64 "\n", metadata->data_blkno);
    298         printf("\ttruncated_blkno: %" PRIu64 "\n", metadata->truncated_blkno);
    299         printf("\tdata_offset: %" PRIu64 "\n", metadata->data_offset);
    300         printf("\tcounter: %" PRIu64 "\n", metadata->counter);
    301         printf("\tversion: %" PRIu32 "\n", metadata->version);
    302         printf("\textent_no: %" PRIu32 "\n", metadata->extent_no);
    303         printf("\tindex: %" PRIu32 "\n", metadata->index);
    304         printf("\tlevel: %" PRIu32 "\n", metadata->level);
    305         printf("\tlayout: %" PRIu32 "\n", metadata->layout);
    306         printf("\tstrip_size: %" PRIu32 "\n", metadata->strip_size);
    307         printf("\tbsize: %" PRIu32 "\n", metadata->bsize);
    308         printf("\tdevname: %s\n", metadata->devname);
     109        return ENOFS;
    309110}
    310111
  • uspace/srv/bd/hr/superblock.h

    r6f41c21f r50603405  
    3939#include "var.h"
    4040
    41 /*
    42  * Metadata is stored on the last block of an extent.
    43  */
    44 #define HR_META_SIZE            1       /* in blocks */
    45 #define HR_DATA_OFF             0
    46 
    47 #define HR_MAGIC_STR            "HelenRAID"
    48 #define HR_MAGIC_SIZE           16
    49 #define HR_UUID_LEN             16
    50 #define HR_METADATA_VERSION     1
    51 
    52 typedef struct hr_metadata hr_metadata_t;
    5341typedef struct hr_volume hr_volume_t;
    5442
    55 struct hr_metadata {
    56         char            magic[HR_MAGIC_SIZE];
     43typedef enum {
     44        HR_METADATA_NATIVE      = 0,
     45        HR_METADATA_LAST_DUMMY  = 1
     46} metadata_type_t;
    5747
    58         uint8_t         uuid[HR_UUID_LEN];
     48#define HR_METADATA_HOTSPARE_SUPPORT 0x01
    5949
    60         /* TODO: change to blkno */
    61         uint64_t        nblocks;                /* all blocks */
    62         uint64_t        data_blkno;             /* usable blocks */
     50typedef struct hr_superblock_ops {
     51        void            *(*alloc_struct)(void);
     52        errno_t          (*init_vol2meta)(const hr_volume_t *, void *);
     53        errno_t          (*init_meta2vol)(const list_t *, hr_volume_t *);
     54        void             (*encode)(const void *, void *);
     55        void             (*decode)(const void *, void *);
     56        errno_t          (*get_block)(service_id_t, void **);
     57        errno_t          (*write_block)(service_id_t, const void *);
     58        bool             (*has_valid_magic)(const void *);
     59        bool             (*compare_uuids)(const void *, const void *);
     60        void             (*inc_counter)(void *);
     61        errno_t          (*save)(hr_volume_t *, bool);
     62        const char      *(*get_devname)(const void *);
     63        hr_level_t       (*get_level)(const void *);
     64        uint64_t         (*get_data_offset)(void);
     65        size_t           (*get_size)(void);
     66        uint8_t          (*get_flags)(void);
     67        metadata_type_t  (*get_type)(void);
     68        void             (*dump)(const void *);
     69} hr_superblock_ops_t;
    6370
    64         uint64_t        truncated_blkno;        /* usable blocks */
    65         uint64_t        data_offset;
    66 
    67         uint64_t        counter;                /* XXX: yet unused */
    68         uint32_t        version;                /* XXX: yet unused */
    69         uint32_t        extent_no;
    70 
    71         uint32_t        index;                  /* index of extent in volume */
    72         uint32_t        level;
    73         uint32_t        layout;
    74         uint32_t        strip_size;
    75 
    76         uint32_t        bsize;
    77 
    78         char            devname[HR_DEVNAME_LEN];
    79 } __attribute__((packed));
    80 
    81 extern errno_t  hr_metadata_init(hr_volume_t *, hr_metadata_t *);
    82 extern errno_t  hr_metadata_save(hr_volume_t *, bool);
    83 extern errno_t  hr_write_metadata_block(service_id_t, const void *);
    84 extern errno_t  hr_get_metadata_block(service_id_t, void **);
    85 extern void     hr_encode_metadata_to_block(const hr_metadata_t *, void *);
    86 extern void     hr_decode_metadata_from_block(const void *, hr_metadata_t *);
    87 extern void     hr_metadata_dump(const hr_metadata_t *);
    88 extern bool     hr_valid_md_magic(const hr_metadata_t *);
     71hr_superblock_ops_t *get_type_ops(metadata_type_t);
     72extern errno_t  find_metadata(service_id_t, void **, metadata_type_t *);
    8973
    9074#endif
  • uspace/srv/bd/hr/util.c

    r6f41c21f r50603405  
    5555#include "var.h"
    5656
    57 struct svc_id_linked;
    58 
    5957static bool     hr_range_lock_overlap(hr_range_lock_t *, hr_range_lock_t *);
    6058static errno_t  hr_add_svc_linked_to_list(list_t *, service_id_t, bool,
    61     hr_metadata_t *);
    62 static void     free_svc_id_linked(struct svc_id_linked *);
     59    void *);
     60static void     free_dev_list_member(struct dev_list_member *);
    6361static void     free_svc_id_list(list_t *);
    6462static errno_t  hr_fill_disk_part_svcs_list(list_t *);
     
    6664static void     block_fini_dev_list(list_t *);
    6765static errno_t  hr_util_get_matching_md_svcs_list(list_t *, list_t *,
    68     service_id_t, hr_metadata_t *);
    69 static errno_t  hr_util_assemble_from_matching_list(list_t *);
     66    service_id_t, metadata_type_t, void *);
     67static errno_t  hr_util_assemble_from_matching_list(list_t *, metadata_type_t);
    7068static errno_t  hr_fill_svcs_list_from_cfg(hr_config_t *, list_t *);
    7169
    72 #define HR_RL_LIST_LOCK(vol) (fibril_mutex_lock(&vol->range_lock_list_lock))
     70#define HR_RL_LIST_LOCK(vol) (fibril_mutex_lock(&(vol)->range_lock_list_lock))
    7371#define HR_RL_LIST_UNLOCK(vol) \
    74     (fibril_mutex_unlock(&vol->range_lock_list_lock))
    75 
    76 struct svc_id_linked {
    77         link_t           link;
    78         service_id_t     svc_id;
    79         hr_metadata_t   *md;
    80         bool             inited;
    81         bool             md_present;
    82 };
     72    (fibril_mutex_unlock(&(vol)->range_lock_list_lock))
    8373
    8474extern loc_srv_t *hr_srv;
     
    8777
    8878errno_t hr_create_vol_struct(hr_volume_t **rvol, hr_level_t level,
    89     const char *devname)
     79    const char *devname, metadata_type_t metadata_type)
    9080{
    9181        errno_t rc;
     
    9888        vol->level = level;
    9989
     90        vol->meta_ops = get_type_ops(metadata_type);
     91
    10092        switch (level) {
    101         case HR_LVL_1:
    102                 vol->hr_ops.create = hr_raid1_create;
    103                 vol->hr_ops.init = hr_raid1_init;
    104                 vol->hr_ops.status_event = hr_raid1_status_event;
    105                 vol->hr_ops.add_hotspare = hr_raid1_add_hotspare;
    106                 break;
    10793        case HR_LVL_0:
    10894                vol->hr_ops.create = hr_raid0_create;
     
    11096                vol->hr_ops.status_event = hr_raid0_status_event;
    11197                break;
     98        case HR_LVL_1:
     99                vol->hr_ops.create = hr_raid1_create;
     100                vol->hr_ops.init = hr_raid1_init;
     101                vol->hr_ops.status_event = hr_raid1_status_event;
     102                if (vol->meta_ops->get_flags() & HR_METADATA_HOTSPARE_SUPPORT)
     103                        vol->hr_ops.add_hotspare = hr_raid1_add_hotspare;
     104                break;
    112105        case HR_LVL_4:
    113106                vol->hr_ops.create = hr_raid5_create;
    114107                vol->hr_ops.init = hr_raid5_init;
    115108                vol->hr_ops.status_event = hr_raid5_status_event;
    116                 vol->hr_ops.add_hotspare = hr_raid5_add_hotspare;
     109                if (vol->meta_ops->get_flags() & HR_METADATA_HOTSPARE_SUPPORT)
     110                        vol->hr_ops.add_hotspare = hr_raid5_add_hotspare;
    117111                break;
    118112        case HR_LVL_5:
     
    120114                vol->hr_ops.init = hr_raid5_init;
    121115                vol->hr_ops.status_event = hr_raid5_status_event;
    122                 vol->hr_ops.add_hotspare = hr_raid5_add_hotspare;
     116                if (vol->meta_ops->get_flags() & HR_METADATA_HOTSPARE_SUPPORT)
     117                        vol->hr_ops.add_hotspare = hr_raid5_add_hotspare;
    123118                break;
    124119        default:
     
    134129        }
    135130
    136         vol->in_mem_md = calloc(1, sizeof(hr_metadata_t));
     131        vol->in_mem_md = vol->meta_ops->alloc_struct();
    137132        if (vol->in_mem_md == NULL) {
    138133                free(vol->fge);
     
    221216                        fibril_rwlock_write_unlock(&hr_volumes_lock);
    222217
    223                         hr_metadata_save(vol, NO_STATE_CALLBACK);
     218                        vol->meta_ops->save(vol, NO_STATE_CALLBACK);
    224219
    225220                        hr_destroy_vol_struct(vol);
     
    584579
    585580static errno_t hr_add_svc_linked_to_list(list_t *list, service_id_t svc_id,
    586     bool inited, hr_metadata_t *md)
    587 {
     581    bool inited, void *md)
     582{
     583        HR_DEBUG("%s()", __func__);
     584
    588585        errno_t rc = EOK;
    589         struct svc_id_linked *to_add;
    590 
    591         to_add = malloc(sizeof(struct svc_id_linked));
     586        struct dev_list_member *to_add;
     587
     588        if (list == NULL)
     589                return EINVAL;
     590
     591        to_add = malloc(sizeof(struct dev_list_member));
    592592        if (to_add == NULL) {
    593593                rc = ENOMEM;
    594594                goto error;
    595595        }
     596
    596597        to_add->svc_id = svc_id;
    597598        to_add->inited = inited;
    598599
    599600        if (md != NULL) {
    600                 to_add->md = malloc(sizeof(hr_metadata_t));
    601                 if (to_add->md == NULL) {
    602                         rc = ENOMEM;
    603                         goto error;
    604                 }
     601                to_add->md = md;
    605602                to_add->md_present = true;
    606                 memcpy(to_add->md, md, sizeof(*md));
    607603        } else {
    608604                to_add->md_present = false;
     
    615611}
    616612
    617 static void free_svc_id_linked(struct svc_id_linked *p)
    618 {
     613static void free_dev_list_member(struct dev_list_member *p)
     614{
     615        HR_DEBUG("%s()", __func__);
     616
    619617        if (p->md_present)
    620618                free(p->md);
     
    624622static void free_svc_id_list(list_t *list)
    625623{
    626         struct svc_id_linked *dev_id;
     624        HR_DEBUG("%s()", __func__);
     625
     626        struct dev_list_member *dev_id;
    627627        while (!list_empty(list)) {
    628                 dev_id = list_pop(list, struct svc_id_linked, link);
    629                 free_svc_id_linked(dev_id);
     628                dev_id = list_pop(list, struct dev_list_member, link);
     629                free_dev_list_member(dev_id);
    630630        }
    631631}
     
    633633static errno_t hr_fill_disk_part_svcs_list(list_t *list)
    634634{
     635        HR_DEBUG("%s()", __func__);
     636
    635637        errno_t rc;
    636638        size_t disk_count;
     
    653655
    654656                if (disk_info.ltype == lt_none) {
    655                         rc = hr_add_svc_linked_to_list(list, disk_svcs[i], false, NULL);
     657                        rc = hr_add_svc_linked_to_list(list, disk_svcs[i],
     658                            false, NULL);
    656659                        if (rc != EOK)
    657660                                goto error;
     
    659662                        size_t part_count;
    660663                        service_id_t *part_ids = NULL;
    661                         rc = vbd_label_get_parts(vbd, disk_svcs[i], &part_ids, &part_count);
     664                        rc = vbd_label_get_parts(vbd, disk_svcs[i], &part_ids,
     665                            &part_count);
    662666                        if (rc != EOK)
    663667                                goto error;
     
    665669                        for (size_t j = 0; j < part_count; j++) {
    666670                                vbd_part_info_t part_info;
    667                                 rc = vbd_part_get_info(vbd, part_ids[j], &part_info);
     671                                rc = vbd_part_get_info(vbd, part_ids[j],
     672                                    &part_info);
    668673                                if (rc != EOK) {
    669674                                        free(part_ids);
     
    697702static errno_t block_init_dev_list(list_t *list)
    698703{
     704        HR_DEBUG("%s()", __func__);
     705
    699706        list_foreach_safe(*list, cur_link, next_link) {
    700                 struct svc_id_linked *iter;
    701                 iter = list_get_instance(cur_link, struct svc_id_linked, link);
     707                struct dev_list_member *iter;
     708                iter = list_get_instance(cur_link, struct dev_list_member,
     709                    link);
    702710
    703711                if (iter->inited)
     
    710718                if (rc == EEXIST) {
    711719                        list_remove(cur_link);
    712                         free_svc_id_linked(iter);
     720                        free_dev_list_member(iter);
    713721                        continue;
    714722                }
     
    725733static void block_fini_dev_list(list_t *list)
    726734{
    727         list_foreach(*list, link, struct svc_id_linked, iter) {
     735        HR_DEBUG("%s()", __func__);
     736
     737        list_foreach(*list, link, struct dev_list_member, iter) {
    728738                if (iter->inited) {
    729739                        block_fini(iter->svc_id);
     
    733743}
    734744
    735 static errno_t hr_util_get_matching_md_svcs_list(list_t *rlist, list_t *devlist,
    736     service_id_t svc_id, hr_metadata_t *md_main)
    737 {
     745static errno_t hr_util_get_matching_md_svcs_list(list_t *rlist, list_t *list,
     746    service_id_t svc_id, metadata_type_t type, void *metadata_struct_main)
     747{
     748        HR_DEBUG("%s()", __func__);
     749
    738750        errno_t rc = EOK;
    739751
    740         list_foreach(*devlist, link, struct svc_id_linked, iter) {
     752        list_foreach(*list, link, struct dev_list_member, iter) {
    741753                if (iter->svc_id == svc_id)
    742754                        continue;
    743                 void *md_block;
    744                 hr_metadata_t md;
    745                 rc = hr_get_metadata_block(iter->svc_id, &md_block);
     755
     756                void *metadata_struct;
     757                metadata_type_t type;
     758
     759                rc = find_metadata(iter->svc_id, &metadata_struct, &type);
     760                if (rc == ENOFS)
     761                        continue;
    746762                if (rc != EOK)
    747763                        goto error;
    748                 hr_decode_metadata_from_block(md_block, &md);
    749 
    750                 free(md_block);
    751 
    752                 if (!hr_valid_md_magic(&md))
     764
     765                hr_superblock_ops_t *meta_ops = get_type_ops(type);
     766
     767                if (!meta_ops->compare_uuids(metadata_struct_main,
     768                    metadata_struct)) {
     769                        free(metadata_struct);
    753770                        continue;
    754 
    755                 if (memcmp(md_main->uuid, md.uuid, HR_UUID_LEN) != 0)
    756                         continue;
    757 
    758                 /*
    759                  * XXX: can I assume bsize and everything is fine when
    760                  * UUID matches?
    761                  */
    762 
    763                 rc = hr_add_svc_linked_to_list(rlist, iter->svc_id, true, &md);
     771                }
     772
     773                rc = hr_add_svc_linked_to_list(rlist, iter->svc_id, true,
     774                    metadata_struct);
    764775                if (rc != EOK)
    765776                        goto error;
     
    772783}
    773784
    774 static errno_t hr_util_assemble_from_matching_list(list_t *list)
     785static errno_t hr_util_assemble_from_matching_list(list_t *list,
     786    metadata_type_t type)
    775787{
    776788        HR_DEBUG("%s()", __func__);
     
    778790        errno_t rc = EOK;
    779791
    780         hr_metadata_t *main_md = NULL;
    781         size_t max_counter_val = 0;
    782 
    783         list_foreach(*list, link, struct svc_id_linked, iter) {
    784                 /* hr_metadata_dump(iter->md); */
    785                 if (iter->md->counter >= max_counter_val) {
    786                         max_counter_val = iter->md->counter;
    787                         main_md = iter->md;
    788                 }
    789         }
    790 
    791         assert(main_md != NULL);
     792        hr_superblock_ops_t *meta_ops = get_type_ops(type);
     793
     794        link_t *memb_l = list_first(list);
     795        struct dev_list_member *memb = list_get_instance(memb_l,
     796            struct dev_list_member, link);
     797
     798        hr_level_t level = meta_ops->get_level(memb->md);
     799        const char *devname = meta_ops->get_devname(memb->md);
    792800
    793801        hr_volume_t *vol;
    794         rc = hr_create_vol_struct(&vol, (hr_level_t)main_md->level,
    795             main_md->devname);
     802        rc = hr_create_vol_struct(&vol, level, devname, type);
    796803        if (rc != EOK)
    797804                goto error;
    798805
    799         vol->nblocks = main_md->nblocks;
    800         vol->data_blkno = main_md->data_blkno;
    801         vol->truncated_blkno = main_md->truncated_blkno;
    802         vol->data_offset = main_md->data_offset;
    803         vol->metadata_version = main_md->version;
    804         vol->extent_no = main_md->extent_no;
    805         /* vol->level = main_md->level; */
    806         vol->layout = main_md->layout;
    807         vol->strip_size = main_md->strip_size;
    808         vol->bsize = main_md->bsize;
    809         /* memcpy(vol->devname, main_md->devname, HR_DEVNAME_LEN); */
    810 
    811         memcpy(vol->in_mem_md, main_md, sizeof(hr_metadata_t));
    812 
    813         list_foreach(*list, link, struct svc_id_linked, iter) {
    814                 vol->extents[iter->md->index].svc_id = iter->svc_id;
    815 
    816                 uint64_t blkno;
    817                 rc = block_get_nblocks(iter->svc_id, &blkno);
    818                 if (rc != EOK)
    819                         goto error;
    820                 vol->extents[iter->md->index].blkno = blkno;
    821 
    822                 if (iter->md->counter == max_counter_val)
    823                         vol->extents[iter->md->index].status = HR_EXT_ONLINE;
    824                 else
    825                         vol->extents[iter->md->index].status = HR_EXT_INVALID;
    826         }
    827 
    828         for (size_t i = 0; i < vol->extent_no; i++) {
    829                 if (vol->extents[i].status == HR_EXT_NONE)
    830                         vol->extents[i].status = HR_EXT_MISSING;
    831         }
     806        meta_ops->init_meta2vol(list, vol);
    832807
    833808        /*
     
    845820         * write... but for now leave it here
    846821         */
    847         vol->in_mem_md->counter++;
     822        (void)vol->meta_ops->inc_counter(vol->in_mem_md);
    848823
    849824        rc = vol->hr_ops.create(vol);
     
    851826                goto error;
    852827
    853         hr_metadata_save(vol, WITH_STATE_CALLBACK);
    854 
    855828        fibril_rwlock_write_lock(&hr_volumes_lock);
    856 
    857         list_foreach(hr_volumes, lvolumes, hr_volume_t, other) {
    858                 uint8_t *our_uuid = vol->in_mem_md->uuid;
    859                 uint8_t *other_uuid = other->in_mem_md->uuid;
    860                 if (memcmp(our_uuid, other_uuid, HR_UUID_LEN) == 0) {
    861                         rc = EEXIST;
    862                         fibril_rwlock_write_unlock(&hr_volumes_lock);
    863                         goto error;
    864                 }
    865         }
    866829
    867830        /*
     
    884847        }
    885848
     849        (void)vol->meta_ops->save(vol, WITH_STATE_CALLBACK);
     850
    886851        list_append(&vol->lvolumes, &hr_volumes);
    887852
     
    896861static errno_t hr_fill_svcs_list_from_cfg(hr_config_t *cfg, list_t *list)
    897862{
     863        HR_DEBUG("%s()", __func__);
     864
    898865        errno_t rc = EOK;
    899866        for (size_t i = 0; i < cfg->dev_no; ++i) {
    900                 rc = hr_add_svc_linked_to_list(list, cfg->devs[i], false, NULL);
     867                rc = hr_add_svc_linked_to_list(list, cfg->devs[i], false,
     868                    NULL);
    901869                if (rc != EOK)
    902870                        goto error;
     
    944912                goto error;
    945913
    946         struct svc_id_linked *iter;
     914        struct dev_list_member *iter;
    947915        while (!list_empty(&dev_id_list)) {
    948                 iter = list_pop(&dev_id_list, struct svc_id_linked, link);
    949 
    950                 void *metadata_block;
    951                 hr_metadata_t metadata;
    952 
    953                 rc = hr_get_metadata_block(iter->svc_id, &metadata_block);
     916                iter = list_pop(&dev_id_list, struct dev_list_member, link);
     917
     918                void *metadata_struct_main;
     919                metadata_type_t type;
     920
     921                rc = find_metadata(iter->svc_id, &metadata_struct_main, &type);
     922                if (rc == ENOFS) {
     923                        block_fini(iter->svc_id);
     924                        free_dev_list_member(iter);
     925                        rc = EOK;
     926                        continue;
     927                }
     928
    954929                if (rc != EOK)
    955930                        goto error;
    956 
    957                 hr_decode_metadata_from_block(metadata_block, &metadata);
    958 
    959                 free(metadata_block);
    960 
    961                 if (!hr_valid_md_magic(&metadata)) {
    962                         block_fini(iter->svc_id);
    963                         free_svc_id_linked(iter);
    964                         continue;
    965                 }
    966 
    967                 /* hr_metadata_dump(&metadata); */
    968931
    969932                char *svc_name = NULL;
     
    981944
    982945                rc = hr_util_get_matching_md_svcs_list(&matching_svcs_list,
    983                     &dev_id_list, iter->svc_id, &metadata);
     946                    &dev_id_list, iter->svc_id, type, metadata_struct_main);
    984947                if (rc != EOK)
    985948                        goto error;
     
    987950                /* add current iter to list as well */
    988951                rc = hr_add_svc_linked_to_list(&matching_svcs_list,
    989                     iter->svc_id, true, &metadata);
     952                    iter->svc_id, true, metadata_struct_main);
    990953                if (rc != EOK) {
    991954                        free_svc_id_list(&matching_svcs_list);
     
    994957
    995958                /* remove matching list members from dev_id_list */
    996                 list_foreach(matching_svcs_list, link, struct svc_id_linked,
     959                list_foreach(matching_svcs_list, link, struct dev_list_member,
    997960                    iter2) {
    998                         struct svc_id_linked *to_remove;
     961                        struct dev_list_member *to_remove;
    999962                        list_foreach_safe(dev_id_list, cur_link, next_link) {
    1000963                                to_remove = list_get_instance(cur_link,
    1001                                     struct svc_id_linked, link);
     964                                    struct dev_list_member, link);
    1002965                                if (to_remove->svc_id == iter2->svc_id) {
    1003966                                        list_remove(cur_link);
    1004                                         free_svc_id_linked(to_remove);
     967                                        free_dev_list_member(to_remove);
    1005968                                }
    1006969                        }
    1007970                }
    1008971
    1009                 rc = hr_util_assemble_from_matching_list(&matching_svcs_list);
     972                rc = hr_util_assemble_from_matching_list(&matching_svcs_list,
     973                    type);
    1010974                switch (rc) {
    1011975                case EOK:
     
    10651029        }
    10661030
    1067         /*
    1068          * TODO: make more flexible, when will have foreign md, the calculation
    1069          * will differ, maybe something new like vol->md_hs_blkno will be enough
    1070          */
    1071         if (hs_blkno < vol->truncated_blkno - HR_META_SIZE) {
     1031        if (hs_blkno < vol->truncated_blkno - vol->meta_ops->get_size()) {
    10721032                rc = EINVAL;
    10731033                block_fini(hotspare);
  • uspace/srv/bd/hr/util.h

    r6f41c21f r50603405  
    3737#define _HR_UTIL_H
    3838
     39#include <adt/list.h>
    3940#include <errno.h>
    4041#include <hr.h>
    4142#include <io/log.h>
    4243
     44#include "superblock.h"
    4345#include "var.h"
     46
     47struct dev_list_member {
     48        link_t           link;
     49        service_id_t     svc_id;
     50        void            *md;
     51        bool             inited;
     52        bool             md_present;
     53};
    4454
    4555#define HR_DEBUG(format, ...) \
     
    5464
    5565extern errno_t           hr_create_vol_struct(hr_volume_t **, hr_level_t,
    56     const char *);
     66    const char *, metadata_type_t);
    5767extern void              hr_destroy_vol_struct(hr_volume_t *);
    5868extern hr_volume_t      *hr_get_volume(service_id_t);
  • uspace/srv/bd/hr/var.h

    r6f41c21f r50603405  
    5353typedef struct hr_volume hr_volume_t;
    5454typedef struct hr_metadata hr_metadata_t;
     55typedef struct hr_superblock_ops hr_superblock_ops_t;
    5556
    5657typedef struct hr_ops {
     
    7273        hr_fpool_t      *fge;                   /* fibril pool */
    7374
    74         /*
    75          * TODO: also print in info, doesn't have
    76          * to be part of hr_volume_t but just the info
    77          * that is passed to be printed
    78          *
    79          * Probably just defer this decition until foreign md
    80          * will be handled.
    81          */
    82         uint32_t         metadata_version;
     75        void            *in_mem_md;
     76        fibril_mutex_t   md_lock;               /* lock protecting in_mem_md */
    8377
    84         hr_metadata_t   *in_mem_md;
    85         fibril_mutex_t   md_lock;               /* lock protecting in_mem_md */
     78        hr_superblock_ops_t *meta_ops;
    8679
    8780        /* invariants */
Note: See TracChangeset for help on using the changeset viewer.