.. | .. |
---|
| 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 */ |
---|