| 1 | /*
 | 
|---|
| 2 |  * Copyright (c) 2025 Miroslav Cimerman
 | 
|---|
| 3 |  * All rights reserved.
 | 
|---|
| 4 |  *
 | 
|---|
| 5 |  * Redistribution and use in source and binary forms, with or without
 | 
|---|
| 6 |  * modification, are permitted provided that the following conditions
 | 
|---|
| 7 |  * are met:
 | 
|---|
| 8 |  *
 | 
|---|
| 9 |  * - Redistributions of source code must retain the above copyright
 | 
|---|
| 10 |  *   notice, this list of conditions and the following disclaimer.
 | 
|---|
| 11 |  * - Redistributions in binary form must reproduce the above copyright
 | 
|---|
| 12 |  *   notice, this list of conditions and the following disclaimer in the
 | 
|---|
| 13 |  *   documentation and/or other materials provided with the distribution.
 | 
|---|
| 14 |  * - The name of the author may not be used to endorse or promote products
 | 
|---|
| 15 |  *   derived from this software without specific prior written permission.
 | 
|---|
| 16 |  *
 | 
|---|
| 17 |  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 | 
|---|
| 18 |  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 | 
|---|
| 19 |  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 | 
|---|
| 20 |  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
|---|
| 21 |  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | 
|---|
| 22 |  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
|---|
| 23 |  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
|---|
| 24 |  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
|---|
| 25 |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 | 
|---|
| 26 |  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
|---|
| 27 |  */
 | 
|---|
| 28 | 
 | 
|---|
| 29 | /** @addtogroup hr
 | 
|---|
| 30 |  * @{
 | 
|---|
| 31 |  */
 | 
|---|
| 32 | /**
 | 
|---|
| 33 |  * @file
 | 
|---|
| 34 |  */
 | 
|---|
| 35 | 
 | 
|---|
| 36 | #ifndef _HR_VAR_H
 | 
|---|
| 37 | #define _HR_VAR_H
 | 
|---|
| 38 | 
 | 
|---|
| 39 | #include <adt/list.h>
 | 
|---|
| 40 | #include <bd_srv.h>
 | 
|---|
| 41 | #include <errno.h>
 | 
|---|
| 42 | #include <fibril_synch.h>
 | 
|---|
| 43 | #include <hr.h>
 | 
|---|
| 44 | 
 | 
|---|
| 45 | #include "fge.h"
 | 
|---|
| 46 | 
 | 
|---|
| 47 | #define NAME "hr"
 | 
|---|
| 48 | 
 | 
|---|
| 49 | #define HR_STRIP_SIZE DATA_XFER_LIMIT
 | 
|---|
| 50 | 
 | 
|---|
| 51 | struct hr_volume;
 | 
|---|
| 52 | typedef struct hr_volume hr_volume_t;
 | 
|---|
| 53 | 
 | 
|---|
| 54 | typedef struct hr_ops {
 | 
|---|
| 55 |         errno_t (*create)(hr_volume_t *);
 | 
|---|
| 56 |         errno_t (*init)(hr_volume_t *);
 | 
|---|
| 57 |         void    (*status_event)(hr_volume_t *);
 | 
|---|
| 58 |         errno_t (*add_hotspare)(hr_volume_t *, service_id_t);
 | 
|---|
| 59 | } hr_ops_t;
 | 
|---|
| 60 | 
 | 
|---|
| 61 | typedef struct hr_deferred_invalidation {
 | 
|---|
| 62 |         link_t link;
 | 
|---|
| 63 |         size_t index;
 | 
|---|
| 64 |         service_id_t svc_id;
 | 
|---|
| 65 | } hr_deferred_invalidation_t;
 | 
|---|
| 66 | 
 | 
|---|
| 67 | typedef struct hr_volume {
 | 
|---|
| 68 |         hr_ops_t hr_ops;
 | 
|---|
| 69 |         bd_srvs_t hr_bds;
 | 
|---|
| 70 | 
 | 
|---|
| 71 |         link_t lvolumes; /* protected by static hr_volumes_lock in hr.c */
 | 
|---|
| 72 | 
 | 
|---|
| 73 |         /*
 | 
|---|
| 74 |          * XXX: will be gone after all paralelization, but still used
 | 
|---|
| 75 |          * in yet-unparallelized levels
 | 
|---|
| 76 |          */
 | 
|---|
| 77 |         fibril_mutex_t lock;
 | 
|---|
| 78 | 
 | 
|---|
| 79 |         list_t range_lock_list;
 | 
|---|
| 80 |         fibril_mutex_t range_lock_list_lock;
 | 
|---|
| 81 | 
 | 
|---|
| 82 |         hr_fpool_t *fge;
 | 
|---|
| 83 | 
 | 
|---|
| 84 |         /* after assembly, these are invariant */
 | 
|---|
| 85 |         size_t extent_no;
 | 
|---|
| 86 |         size_t bsize;
 | 
|---|
| 87 |         uint64_t nblocks;
 | 
|---|
| 88 |         uint64_t data_blkno;
 | 
|---|
| 89 |         uint64_t data_offset; /* in blocks */
 | 
|---|
| 90 |         uint32_t strip_size;
 | 
|---|
| 91 |         hr_level_t level;
 | 
|---|
| 92 |         uint8_t layout; /* RAID Level Qualifier */
 | 
|---|
| 93 |         service_id_t svc_id;
 | 
|---|
| 94 |         char devname[HR_DEVNAME_LEN];
 | 
|---|
| 95 | 
 | 
|---|
| 96 |         size_t hotspare_no;
 | 
|---|
| 97 |         hr_extent_t hotspares[HR_MAX_HOTSPARES + HR_MAX_EXTENTS];
 | 
|---|
| 98 | 
 | 
|---|
| 99 |         /* protects hotspares (hotspares.{svc_id,status}, hotspare_no) */
 | 
|---|
| 100 |         fibril_mutex_t hotspare_lock;
 | 
|---|
| 101 | 
 | 
|---|
| 102 |         hr_extent_t extents[HR_MAX_EXTENTS];
 | 
|---|
| 103 |         /* protects extents ordering (extents.svc_id) */
 | 
|---|
| 104 |         fibril_rwlock_t extents_lock;
 | 
|---|
| 105 |         /* protects states (extents.status, hr_volume_t.status) */
 | 
|---|
| 106 |         fibril_rwlock_t states_lock;
 | 
|---|
| 107 | 
 | 
|---|
| 108 |         /* for halting IO requests when a REBUILD start waits */
 | 
|---|
| 109 |         bool halt_please;
 | 
|---|
| 110 |         fibril_mutex_t halt_lock;
 | 
|---|
| 111 | 
 | 
|---|
| 112 |         /*
 | 
|---|
| 113 |          * For deferring invalidations of extents. Used when
 | 
|---|
| 114 |          * an extent has to be invalidated (got ENOMEM on a WRITE),
 | 
|---|
| 115 |          * but workers - therefore state callbacks cannot lock
 | 
|---|
| 116 |          * extents for writing (they are readers), so invalidations
 | 
|---|
| 117 |          * are harvested later when we are able to.
 | 
|---|
| 118 |          */
 | 
|---|
| 119 |         _Atomic bool pending_invalidation;
 | 
|---|
| 120 |         fibril_mutex_t deferred_list_lock;
 | 
|---|
| 121 |         list_t deferred_invalidations_list;
 | 
|---|
| 122 |         hr_deferred_invalidation_t deferred_inval[HR_MAX_EXTENTS];
 | 
|---|
| 123 | 
 | 
|---|
| 124 |         _Atomic bool state_changed;
 | 
|---|
| 125 |         _Atomic uint64_t rebuild_blk;
 | 
|---|
| 126 |         uint64_t counter; /* metadata syncing */
 | 
|---|
| 127 |         hr_vol_status_t status;
 | 
|---|
| 128 | } hr_volume_t;
 | 
|---|
| 129 | 
 | 
|---|
| 130 | typedef enum {
 | 
|---|
| 131 |         HR_BD_SYNC,
 | 
|---|
| 132 |         HR_BD_READ,
 | 
|---|
| 133 |         HR_BD_WRITE
 | 
|---|
| 134 | } hr_bd_op_type_t;
 | 
|---|
| 135 | 
 | 
|---|
| 136 | typedef struct hr_range_lock {
 | 
|---|
| 137 |         fibril_mutex_t lock;
 | 
|---|
| 138 |         link_t link;
 | 
|---|
| 139 |         hr_volume_t *vol;
 | 
|---|
| 140 |         uint64_t off;
 | 
|---|
| 141 |         uint64_t len;
 | 
|---|
| 142 |         size_t pending; /* protected by vol->range_lock_list_lock */
 | 
|---|
| 143 |         bool ignore; /* protected by vol->range_lock_list_lock */
 | 
|---|
| 144 | } hr_range_lock_t;
 | 
|---|
| 145 | 
 | 
|---|
| 146 | extern errno_t hr_init_devs(hr_volume_t *);
 | 
|---|
| 147 | extern void hr_fini_devs(hr_volume_t *);
 | 
|---|
| 148 | 
 | 
|---|
| 149 | extern errno_t hr_raid0_create(hr_volume_t *);
 | 
|---|
| 150 | extern errno_t hr_raid1_create(hr_volume_t *);
 | 
|---|
| 151 | extern errno_t hr_raid5_create(hr_volume_t *);
 | 
|---|
| 152 | 
 | 
|---|
| 153 | extern errno_t hr_raid0_init(hr_volume_t *);
 | 
|---|
| 154 | extern errno_t hr_raid1_init(hr_volume_t *);
 | 
|---|
| 155 | extern errno_t hr_raid5_init(hr_volume_t *);
 | 
|---|
| 156 | 
 | 
|---|
| 157 | extern void hr_raid0_status_event(hr_volume_t *);
 | 
|---|
| 158 | extern void hr_raid1_status_event(hr_volume_t *);
 | 
|---|
| 159 | extern void hr_raid5_status_event(hr_volume_t *);
 | 
|---|
| 160 | 
 | 
|---|
| 161 | extern errno_t hr_raid1_add_hotspare(hr_volume_t *, service_id_t);
 | 
|---|
| 162 | extern errno_t hr_raid5_add_hotspare(hr_volume_t *, service_id_t);
 | 
|---|
| 163 | 
 | 
|---|
| 164 | #endif
 | 
|---|
| 165 | 
 | 
|---|
| 166 | /** @}
 | 
|---|
| 167 |  */
 | 
|---|