| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2017 Western Digital Corporation or its affiliates. |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 44 | 45 | #define dmz_bio_block(bio) dmz_sect2blk((bio)->bi_iter.bi_sector) |
|---|
| 45 | 46 | #define dmz_bio_blocks(bio) dmz_sect2blk(bio_sectors(bio)) |
|---|
| 46 | 47 | |
|---|
| 48 | +struct dmz_metadata; |
|---|
| 49 | +struct dmz_reclaim; |
|---|
| 50 | + |
|---|
| 47 | 51 | /* |
|---|
| 48 | 52 | * Zoned block device information. |
|---|
| 49 | 53 | */ |
|---|
| 50 | 54 | struct dmz_dev { |
|---|
| 51 | 55 | struct block_device *bdev; |
|---|
| 56 | + struct dmz_metadata *metadata; |
|---|
| 57 | + struct dmz_reclaim *reclaim; |
|---|
| 52 | 58 | |
|---|
| 53 | 59 | char name[BDEVNAME_SIZE]; |
|---|
| 60 | + uuid_t uuid; |
|---|
| 54 | 61 | |
|---|
| 55 | 62 | sector_t capacity; |
|---|
| 56 | 63 | |
|---|
| 64 | + unsigned int dev_idx; |
|---|
| 65 | + |
|---|
| 57 | 66 | unsigned int nr_zones; |
|---|
| 67 | + unsigned int zone_offset; |
|---|
| 58 | 68 | |
|---|
| 59 | 69 | unsigned int flags; |
|---|
| 60 | 70 | |
|---|
| 61 | 71 | sector_t zone_nr_sectors; |
|---|
| 62 | | - unsigned int zone_nr_sectors_shift; |
|---|
| 63 | 72 | |
|---|
| 64 | | - sector_t zone_nr_blocks; |
|---|
| 65 | | - sector_t zone_nr_blocks_shift; |
|---|
| 73 | + unsigned int nr_rnd; |
|---|
| 74 | + atomic_t unmap_nr_rnd; |
|---|
| 75 | + struct list_head unmap_rnd_list; |
|---|
| 76 | + struct list_head map_rnd_list; |
|---|
| 77 | + |
|---|
| 78 | + unsigned int nr_seq; |
|---|
| 79 | + atomic_t unmap_nr_seq; |
|---|
| 80 | + struct list_head unmap_seq_list; |
|---|
| 81 | + struct list_head map_seq_list; |
|---|
| 66 | 82 | }; |
|---|
| 67 | 83 | |
|---|
| 68 | | -#define dmz_bio_chunk(dev, bio) ((bio)->bi_iter.bi_sector >> \ |
|---|
| 69 | | - (dev)->zone_nr_sectors_shift) |
|---|
| 70 | | -#define dmz_chunk_block(dev, b) ((b) & ((dev)->zone_nr_blocks - 1)) |
|---|
| 84 | +#define dmz_bio_chunk(zmd, bio) ((bio)->bi_iter.bi_sector >> \ |
|---|
| 85 | + dmz_zone_nr_sectors_shift(zmd)) |
|---|
| 86 | +#define dmz_chunk_block(zmd, b) ((b) & (dmz_zone_nr_blocks(zmd) - 1)) |
|---|
| 71 | 87 | |
|---|
| 72 | 88 | /* Device flags. */ |
|---|
| 73 | 89 | #define DMZ_BDEV_DYING (1 << 0) |
|---|
| 74 | 90 | #define DMZ_CHECK_BDEV (2 << 0) |
|---|
| 91 | +#define DMZ_BDEV_REGULAR (4 << 0) |
|---|
| 75 | 92 | |
|---|
| 76 | 93 | /* |
|---|
| 77 | 94 | * Zone descriptor. |
|---|
| .. | .. |
|---|
| 80 | 97 | /* For listing the zone depending on its state */ |
|---|
| 81 | 98 | struct list_head link; |
|---|
| 82 | 99 | |
|---|
| 100 | + /* Device containing this zone */ |
|---|
| 101 | + struct dmz_dev *dev; |
|---|
| 102 | + |
|---|
| 83 | 103 | /* Zone type and state */ |
|---|
| 84 | 104 | unsigned long flags; |
|---|
| 85 | 105 | |
|---|
| 86 | 106 | /* Zone activation reference count */ |
|---|
| 87 | 107 | atomic_t refcount; |
|---|
| 108 | + |
|---|
| 109 | + /* Zone id */ |
|---|
| 110 | + unsigned int id; |
|---|
| 88 | 111 | |
|---|
| 89 | 112 | /* Zone write pointer block (relative to the zone start block) */ |
|---|
| 90 | 113 | unsigned int wp_block; |
|---|
| .. | .. |
|---|
| 108 | 131 | */ |
|---|
| 109 | 132 | enum { |
|---|
| 110 | 133 | /* Zone write type */ |
|---|
| 134 | + DMZ_CACHE, |
|---|
| 111 | 135 | DMZ_RND, |
|---|
| 112 | 136 | DMZ_SEQ, |
|---|
| 113 | 137 | |
|---|
| .. | .. |
|---|
| 119 | 143 | DMZ_META, |
|---|
| 120 | 144 | DMZ_DATA, |
|---|
| 121 | 145 | DMZ_BUF, |
|---|
| 146 | + DMZ_RESERVED, |
|---|
| 122 | 147 | |
|---|
| 123 | 148 | /* Zone internal state */ |
|---|
| 124 | 149 | DMZ_RECLAIM, |
|---|
| 125 | 150 | DMZ_SEQ_WRITE_ERR, |
|---|
| 151 | + DMZ_RECLAIM_TERMINATE, |
|---|
| 126 | 152 | }; |
|---|
| 127 | 153 | |
|---|
| 128 | 154 | /* |
|---|
| 129 | 155 | * Zone data accessors. |
|---|
| 130 | 156 | */ |
|---|
| 157 | +#define dmz_is_cache(z) test_bit(DMZ_CACHE, &(z)->flags) |
|---|
| 131 | 158 | #define dmz_is_rnd(z) test_bit(DMZ_RND, &(z)->flags) |
|---|
| 132 | 159 | #define dmz_is_seq(z) test_bit(DMZ_SEQ, &(z)->flags) |
|---|
| 133 | 160 | #define dmz_is_empty(z) ((z)->wp_block == 0) |
|---|
| 134 | 161 | #define dmz_is_offline(z) test_bit(DMZ_OFFLINE, &(z)->flags) |
|---|
| 135 | 162 | #define dmz_is_readonly(z) test_bit(DMZ_READ_ONLY, &(z)->flags) |
|---|
| 136 | 163 | #define dmz_in_reclaim(z) test_bit(DMZ_RECLAIM, &(z)->flags) |
|---|
| 164 | +#define dmz_is_reserved(z) test_bit(DMZ_RESERVED, &(z)->flags) |
|---|
| 137 | 165 | #define dmz_seq_write_err(z) test_bit(DMZ_SEQ_WRITE_ERR, &(z)->flags) |
|---|
| 166 | +#define dmz_reclaim_should_terminate(z) \ |
|---|
| 167 | + test_bit(DMZ_RECLAIM_TERMINATE, &(z)->flags) |
|---|
| 138 | 168 | |
|---|
| 139 | 169 | #define dmz_is_meta(z) test_bit(DMZ_META, &(z)->flags) |
|---|
| 140 | 170 | #define dmz_is_buf(z) test_bit(DMZ_BUF, &(z)->flags) |
|---|
| .. | .. |
|---|
| 157 | 187 | #define dmz_dev_debug(dev, format, args...) \ |
|---|
| 158 | 188 | DMDEBUG("(%s): " format, (dev)->name, ## args) |
|---|
| 159 | 189 | |
|---|
| 160 | | -struct dmz_metadata; |
|---|
| 161 | | -struct dmz_reclaim; |
|---|
| 162 | | - |
|---|
| 163 | 190 | /* |
|---|
| 164 | 191 | * Functions defined in dm-zoned-metadata.c |
|---|
| 165 | 192 | */ |
|---|
| 166 | | -int dmz_ctr_metadata(struct dmz_dev *dev, struct dmz_metadata **zmd); |
|---|
| 193 | +int dmz_ctr_metadata(struct dmz_dev *dev, int num_dev, |
|---|
| 194 | + struct dmz_metadata **zmd, const char *devname); |
|---|
| 167 | 195 | void dmz_dtr_metadata(struct dmz_metadata *zmd); |
|---|
| 168 | 196 | int dmz_resume_metadata(struct dmz_metadata *zmd); |
|---|
| 169 | 197 | |
|---|
| .. | .. |
|---|
| 174 | 202 | void dmz_lock_flush(struct dmz_metadata *zmd); |
|---|
| 175 | 203 | void dmz_unlock_flush(struct dmz_metadata *zmd); |
|---|
| 176 | 204 | int dmz_flush_metadata(struct dmz_metadata *zmd); |
|---|
| 205 | +const char *dmz_metadata_label(struct dmz_metadata *zmd); |
|---|
| 177 | 206 | |
|---|
| 178 | | -unsigned int dmz_id(struct dmz_metadata *zmd, struct dm_zone *zone); |
|---|
| 179 | 207 | sector_t dmz_start_sect(struct dmz_metadata *zmd, struct dm_zone *zone); |
|---|
| 180 | 208 | sector_t dmz_start_block(struct dmz_metadata *zmd, struct dm_zone *zone); |
|---|
| 181 | 209 | unsigned int dmz_nr_chunks(struct dmz_metadata *zmd); |
|---|
| 182 | 210 | |
|---|
| 183 | | -#define DMZ_ALLOC_RND 0x01 |
|---|
| 184 | | -#define DMZ_ALLOC_RECLAIM 0x02 |
|---|
| 211 | +bool dmz_check_dev(struct dmz_metadata *zmd); |
|---|
| 212 | +bool dmz_dev_is_dying(struct dmz_metadata *zmd); |
|---|
| 185 | 213 | |
|---|
| 186 | | -struct dm_zone *dmz_alloc_zone(struct dmz_metadata *zmd, unsigned long flags); |
|---|
| 214 | +#define DMZ_ALLOC_RND 0x01 |
|---|
| 215 | +#define DMZ_ALLOC_CACHE 0x02 |
|---|
| 216 | +#define DMZ_ALLOC_SEQ 0x04 |
|---|
| 217 | +#define DMZ_ALLOC_RECLAIM 0x10 |
|---|
| 218 | + |
|---|
| 219 | +struct dm_zone *dmz_alloc_zone(struct dmz_metadata *zmd, |
|---|
| 220 | + unsigned int dev_idx, unsigned long flags); |
|---|
| 187 | 221 | void dmz_free_zone(struct dmz_metadata *zmd, struct dm_zone *zone); |
|---|
| 188 | 222 | |
|---|
| 189 | 223 | void dmz_map_zone(struct dmz_metadata *zmd, struct dm_zone *zone, |
|---|
| 190 | 224 | unsigned int chunk); |
|---|
| 191 | 225 | void dmz_unmap_zone(struct dmz_metadata *zmd, struct dm_zone *zone); |
|---|
| 192 | | -unsigned int dmz_nr_rnd_zones(struct dmz_metadata *zmd); |
|---|
| 193 | | -unsigned int dmz_nr_unmap_rnd_zones(struct dmz_metadata *zmd); |
|---|
| 226 | +unsigned int dmz_nr_zones(struct dmz_metadata *zmd); |
|---|
| 227 | +unsigned int dmz_nr_cache_zones(struct dmz_metadata *zmd); |
|---|
| 228 | +unsigned int dmz_nr_unmap_cache_zones(struct dmz_metadata *zmd); |
|---|
| 229 | +unsigned int dmz_nr_rnd_zones(struct dmz_metadata *zmd, int idx); |
|---|
| 230 | +unsigned int dmz_nr_unmap_rnd_zones(struct dmz_metadata *zmd, int idx); |
|---|
| 231 | +unsigned int dmz_nr_seq_zones(struct dmz_metadata *zmd, int idx); |
|---|
| 232 | +unsigned int dmz_nr_unmap_seq_zones(struct dmz_metadata *zmd, int idx); |
|---|
| 233 | +unsigned int dmz_zone_nr_blocks(struct dmz_metadata *zmd); |
|---|
| 234 | +unsigned int dmz_zone_nr_blocks_shift(struct dmz_metadata *zmd); |
|---|
| 235 | +unsigned int dmz_zone_nr_sectors(struct dmz_metadata *zmd); |
|---|
| 236 | +unsigned int dmz_zone_nr_sectors_shift(struct dmz_metadata *zmd); |
|---|
| 194 | 237 | |
|---|
| 195 | 238 | /* |
|---|
| 196 | 239 | * Activate a zone (increment its reference count). |
|---|
| .. | .. |
|---|
| 200 | 243 | atomic_inc(&zone->refcount); |
|---|
| 201 | 244 | } |
|---|
| 202 | 245 | |
|---|
| 203 | | -/* |
|---|
| 204 | | - * Deactivate a zone. This decrement the zone reference counter |
|---|
| 205 | | - * indicating that all BIOs to the zone have completed when the count is 0. |
|---|
| 206 | | - */ |
|---|
| 207 | | -static inline void dmz_deactivate_zone(struct dm_zone *zone) |
|---|
| 208 | | -{ |
|---|
| 209 | | - atomic_dec(&zone->refcount); |
|---|
| 210 | | -} |
|---|
| 211 | | - |
|---|
| 212 | | -/* |
|---|
| 213 | | - * Test if a zone is active, that is, has a refcount > 0. |
|---|
| 214 | | - */ |
|---|
| 215 | | -static inline bool dmz_is_active(struct dm_zone *zone) |
|---|
| 216 | | -{ |
|---|
| 217 | | - return atomic_read(&zone->refcount); |
|---|
| 218 | | -} |
|---|
| 219 | | - |
|---|
| 220 | 246 | int dmz_lock_zone_reclaim(struct dm_zone *zone); |
|---|
| 221 | 247 | void dmz_unlock_zone_reclaim(struct dm_zone *zone); |
|---|
| 222 | | -struct dm_zone *dmz_get_zone_for_reclaim(struct dmz_metadata *zmd); |
|---|
| 248 | +struct dm_zone *dmz_get_zone_for_reclaim(struct dmz_metadata *zmd, |
|---|
| 249 | + unsigned int dev_idx, bool idle); |
|---|
| 223 | 250 | |
|---|
| 224 | 251 | struct dm_zone *dmz_get_chunk_mapping(struct dmz_metadata *zmd, |
|---|
| 225 | 252 | unsigned int chunk, int op); |
|---|
| .. | .. |
|---|
| 243 | 270 | /* |
|---|
| 244 | 271 | * Functions defined in dm-zoned-reclaim.c |
|---|
| 245 | 272 | */ |
|---|
| 246 | | -int dmz_ctr_reclaim(struct dmz_dev *dev, struct dmz_metadata *zmd, |
|---|
| 247 | | - struct dmz_reclaim **zrc); |
|---|
| 273 | +int dmz_ctr_reclaim(struct dmz_metadata *zmd, struct dmz_reclaim **zrc, int idx); |
|---|
| 248 | 274 | void dmz_dtr_reclaim(struct dmz_reclaim *zrc); |
|---|
| 249 | 275 | void dmz_suspend_reclaim(struct dmz_reclaim *zrc); |
|---|
| 250 | 276 | void dmz_resume_reclaim(struct dmz_reclaim *zrc); |
|---|
| .. | .. |
|---|
| 257 | 283 | bool dmz_bdev_is_dying(struct dmz_dev *dmz_dev); |
|---|
| 258 | 284 | bool dmz_check_bdev(struct dmz_dev *dmz_dev); |
|---|
| 259 | 285 | |
|---|
| 286 | +/* |
|---|
| 287 | + * Deactivate a zone. This decrement the zone reference counter |
|---|
| 288 | + * indicating that all BIOs to the zone have completed when the count is 0. |
|---|
| 289 | + */ |
|---|
| 290 | +static inline void dmz_deactivate_zone(struct dm_zone *zone) |
|---|
| 291 | +{ |
|---|
| 292 | + dmz_reclaim_bio_acc(zone->dev->reclaim); |
|---|
| 293 | + atomic_dec(&zone->refcount); |
|---|
| 294 | +} |
|---|
| 295 | + |
|---|
| 296 | +/* |
|---|
| 297 | + * Test if a zone is active, that is, has a refcount > 0. |
|---|
| 298 | + */ |
|---|
| 299 | +static inline bool dmz_is_active(struct dm_zone *zone) |
|---|
| 300 | +{ |
|---|
| 301 | + return atomic_read(&zone->refcount); |
|---|
| 302 | +} |
|---|
| 303 | + |
|---|
| 260 | 304 | #endif /* DM_ZONED_H */ |
|---|