.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2017 Western Digital Corporation or its affiliates. |
---|
3 | 4 | * |
---|
.. | .. |
---|
8 | 9 | |
---|
9 | 10 | #include <linux/module.h> |
---|
10 | 11 | #include <linux/crc32.h> |
---|
| 12 | +#include <linux/sched/mm.h> |
---|
11 | 13 | |
---|
12 | 14 | #define DM_MSG_PREFIX "zoned metadata" |
---|
13 | 15 | |
---|
14 | 16 | /* |
---|
15 | 17 | * Metadata version. |
---|
16 | 18 | */ |
---|
17 | | -#define DMZ_META_VER 1 |
---|
| 19 | +#define DMZ_META_VER 2 |
---|
18 | 20 | |
---|
19 | 21 | /* |
---|
20 | 22 | * On-disk super block magic. |
---|
.. | .. |
---|
33 | 35 | * (1) Super block (1 block) |
---|
34 | 36 | * (2) Chunk mapping table (nr_map_blocks) |
---|
35 | 37 | * (3) Bitmap blocks (nr_bitmap_blocks) |
---|
36 | | - * All metadata blocks are stored in conventional zones, starting from the |
---|
| 38 | + * All metadata blocks are stored in conventional zones, starting from |
---|
37 | 39 | * the first conventional zone found on disk. |
---|
38 | 40 | */ |
---|
39 | 41 | struct dmz_super { |
---|
.. | .. |
---|
67 | 69 | /* Checksum */ |
---|
68 | 70 | __le32 crc; /* 48 */ |
---|
69 | 71 | |
---|
| 72 | + /* DM-Zoned label */ |
---|
| 73 | + u8 dmz_label[32]; /* 80 */ |
---|
| 74 | + |
---|
| 75 | + /* DM-Zoned UUID */ |
---|
| 76 | + u8 dmz_uuid[16]; /* 96 */ |
---|
| 77 | + |
---|
| 78 | + /* Device UUID */ |
---|
| 79 | + u8 dev_uuid[16]; /* 112 */ |
---|
| 80 | + |
---|
70 | 81 | /* Padding to full 512B sector */ |
---|
71 | | - u8 reserved[464]; /* 512 */ |
---|
| 82 | + u8 reserved[400]; /* 512 */ |
---|
72 | 83 | }; |
---|
73 | 84 | |
---|
74 | 85 | /* |
---|
.. | .. |
---|
120 | 131 | */ |
---|
121 | 132 | struct dmz_sb { |
---|
122 | 133 | sector_t block; |
---|
| 134 | + struct dmz_dev *dev; |
---|
123 | 135 | struct dmz_mblock *mblk; |
---|
124 | 136 | struct dmz_super *sb; |
---|
| 137 | + struct dm_zone *zone; |
---|
125 | 138 | }; |
---|
126 | 139 | |
---|
127 | 140 | /* |
---|
.. | .. |
---|
129 | 142 | */ |
---|
130 | 143 | struct dmz_metadata { |
---|
131 | 144 | struct dmz_dev *dev; |
---|
| 145 | + unsigned int nr_devs; |
---|
| 146 | + |
---|
| 147 | + char devname[BDEVNAME_SIZE]; |
---|
| 148 | + char label[BDEVNAME_SIZE]; |
---|
| 149 | + uuid_t uuid; |
---|
132 | 150 | |
---|
133 | 151 | sector_t zone_bitmap_size; |
---|
134 | 152 | unsigned int zone_nr_bitmap_blocks; |
---|
135 | 153 | unsigned int zone_bits_per_mblk; |
---|
136 | 154 | |
---|
| 155 | + sector_t zone_nr_blocks; |
---|
| 156 | + sector_t zone_nr_blocks_shift; |
---|
| 157 | + |
---|
| 158 | + sector_t zone_nr_sectors; |
---|
| 159 | + sector_t zone_nr_sectors_shift; |
---|
| 160 | + |
---|
137 | 161 | unsigned int nr_bitmap_blocks; |
---|
138 | 162 | unsigned int nr_map_blocks; |
---|
139 | 163 | |
---|
| 164 | + unsigned int nr_zones; |
---|
140 | 165 | unsigned int nr_useable_zones; |
---|
141 | 166 | unsigned int nr_meta_blocks; |
---|
142 | 167 | unsigned int nr_meta_zones; |
---|
143 | 168 | unsigned int nr_data_zones; |
---|
| 169 | + unsigned int nr_cache_zones; |
---|
144 | 170 | unsigned int nr_rnd_zones; |
---|
145 | 171 | unsigned int nr_reserved_seq; |
---|
146 | 172 | unsigned int nr_chunks; |
---|
147 | 173 | |
---|
148 | 174 | /* Zone information array */ |
---|
149 | | - struct dm_zone *zones; |
---|
| 175 | + struct xarray zones; |
---|
150 | 176 | |
---|
151 | | - struct dm_zone *sb_zone; |
---|
152 | 177 | struct dmz_sb sb[2]; |
---|
153 | 178 | unsigned int mblk_primary; |
---|
| 179 | + unsigned int sb_version; |
---|
154 | 180 | u64 sb_gen; |
---|
155 | 181 | unsigned int min_nr_mblks; |
---|
156 | 182 | unsigned int max_nr_mblks; |
---|
.. | .. |
---|
166 | 192 | /* Zone allocation management */ |
---|
167 | 193 | struct mutex map_lock; |
---|
168 | 194 | struct dmz_mblock **map_mblk; |
---|
169 | | - unsigned int nr_rnd; |
---|
170 | | - atomic_t unmap_nr_rnd; |
---|
171 | | - struct list_head unmap_rnd_list; |
---|
172 | | - struct list_head map_rnd_list; |
---|
173 | 195 | |
---|
174 | | - unsigned int nr_seq; |
---|
175 | | - atomic_t unmap_nr_seq; |
---|
176 | | - struct list_head unmap_seq_list; |
---|
177 | | - struct list_head map_seq_list; |
---|
| 196 | + unsigned int nr_cache; |
---|
| 197 | + atomic_t unmap_nr_cache; |
---|
| 198 | + struct list_head unmap_cache_list; |
---|
| 199 | + struct list_head map_cache_list; |
---|
178 | 200 | |
---|
179 | 201 | atomic_t nr_reserved_seq_zones; |
---|
180 | 202 | struct list_head reserved_seq_zones_list; |
---|
.. | .. |
---|
182 | 204 | wait_queue_head_t free_wq; |
---|
183 | 205 | }; |
---|
184 | 206 | |
---|
| 207 | +#define dmz_zmd_info(zmd, format, args...) \ |
---|
| 208 | + DMINFO("(%s): " format, (zmd)->label, ## args) |
---|
| 209 | + |
---|
| 210 | +#define dmz_zmd_err(zmd, format, args...) \ |
---|
| 211 | + DMERR("(%s): " format, (zmd)->label, ## args) |
---|
| 212 | + |
---|
| 213 | +#define dmz_zmd_warn(zmd, format, args...) \ |
---|
| 214 | + DMWARN("(%s): " format, (zmd)->label, ## args) |
---|
| 215 | + |
---|
| 216 | +#define dmz_zmd_debug(zmd, format, args...) \ |
---|
| 217 | + DMDEBUG("(%s): " format, (zmd)->label, ## args) |
---|
185 | 218 | /* |
---|
186 | 219 | * Various accessors |
---|
187 | 220 | */ |
---|
188 | | -unsigned int dmz_id(struct dmz_metadata *zmd, struct dm_zone *zone) |
---|
| 221 | +static unsigned int dmz_dev_zone_id(struct dmz_metadata *zmd, struct dm_zone *zone) |
---|
189 | 222 | { |
---|
190 | | - return ((unsigned int)(zone - zmd->zones)); |
---|
| 223 | + if (WARN_ON(!zone)) |
---|
| 224 | + return 0; |
---|
| 225 | + |
---|
| 226 | + return zone->id - zone->dev->zone_offset; |
---|
191 | 227 | } |
---|
192 | 228 | |
---|
193 | 229 | sector_t dmz_start_sect(struct dmz_metadata *zmd, struct dm_zone *zone) |
---|
194 | 230 | { |
---|
195 | | - return (sector_t)dmz_id(zmd, zone) << zmd->dev->zone_nr_sectors_shift; |
---|
| 231 | + unsigned int zone_id = dmz_dev_zone_id(zmd, zone); |
---|
| 232 | + |
---|
| 233 | + return (sector_t)zone_id << zmd->zone_nr_sectors_shift; |
---|
196 | 234 | } |
---|
197 | 235 | |
---|
198 | 236 | sector_t dmz_start_block(struct dmz_metadata *zmd, struct dm_zone *zone) |
---|
199 | 237 | { |
---|
200 | | - return (sector_t)dmz_id(zmd, zone) << zmd->dev->zone_nr_blocks_shift; |
---|
| 238 | + unsigned int zone_id = dmz_dev_zone_id(zmd, zone); |
---|
| 239 | + |
---|
| 240 | + return (sector_t)zone_id << zmd->zone_nr_blocks_shift; |
---|
| 241 | +} |
---|
| 242 | + |
---|
| 243 | +unsigned int dmz_zone_nr_blocks(struct dmz_metadata *zmd) |
---|
| 244 | +{ |
---|
| 245 | + return zmd->zone_nr_blocks; |
---|
| 246 | +} |
---|
| 247 | + |
---|
| 248 | +unsigned int dmz_zone_nr_blocks_shift(struct dmz_metadata *zmd) |
---|
| 249 | +{ |
---|
| 250 | + return zmd->zone_nr_blocks_shift; |
---|
| 251 | +} |
---|
| 252 | + |
---|
| 253 | +unsigned int dmz_zone_nr_sectors(struct dmz_metadata *zmd) |
---|
| 254 | +{ |
---|
| 255 | + return zmd->zone_nr_sectors; |
---|
| 256 | +} |
---|
| 257 | + |
---|
| 258 | +unsigned int dmz_zone_nr_sectors_shift(struct dmz_metadata *zmd) |
---|
| 259 | +{ |
---|
| 260 | + return zmd->zone_nr_sectors_shift; |
---|
| 261 | +} |
---|
| 262 | + |
---|
| 263 | +unsigned int dmz_nr_zones(struct dmz_metadata *zmd) |
---|
| 264 | +{ |
---|
| 265 | + return zmd->nr_zones; |
---|
201 | 266 | } |
---|
202 | 267 | |
---|
203 | 268 | unsigned int dmz_nr_chunks(struct dmz_metadata *zmd) |
---|
.. | .. |
---|
205 | 270 | return zmd->nr_chunks; |
---|
206 | 271 | } |
---|
207 | 272 | |
---|
208 | | -unsigned int dmz_nr_rnd_zones(struct dmz_metadata *zmd) |
---|
| 273 | +unsigned int dmz_nr_rnd_zones(struct dmz_metadata *zmd, int idx) |
---|
209 | 274 | { |
---|
210 | | - return zmd->nr_rnd; |
---|
| 275 | + return zmd->dev[idx].nr_rnd; |
---|
211 | 276 | } |
---|
212 | 277 | |
---|
213 | | -unsigned int dmz_nr_unmap_rnd_zones(struct dmz_metadata *zmd) |
---|
| 278 | +unsigned int dmz_nr_unmap_rnd_zones(struct dmz_metadata *zmd, int idx) |
---|
214 | 279 | { |
---|
215 | | - return atomic_read(&zmd->unmap_nr_rnd); |
---|
| 280 | + return atomic_read(&zmd->dev[idx].unmap_nr_rnd); |
---|
| 281 | +} |
---|
| 282 | + |
---|
| 283 | +unsigned int dmz_nr_cache_zones(struct dmz_metadata *zmd) |
---|
| 284 | +{ |
---|
| 285 | + return zmd->nr_cache; |
---|
| 286 | +} |
---|
| 287 | + |
---|
| 288 | +unsigned int dmz_nr_unmap_cache_zones(struct dmz_metadata *zmd) |
---|
| 289 | +{ |
---|
| 290 | + return atomic_read(&zmd->unmap_nr_cache); |
---|
| 291 | +} |
---|
| 292 | + |
---|
| 293 | +unsigned int dmz_nr_seq_zones(struct dmz_metadata *zmd, int idx) |
---|
| 294 | +{ |
---|
| 295 | + return zmd->dev[idx].nr_seq; |
---|
| 296 | +} |
---|
| 297 | + |
---|
| 298 | +unsigned int dmz_nr_unmap_seq_zones(struct dmz_metadata *zmd, int idx) |
---|
| 299 | +{ |
---|
| 300 | + return atomic_read(&zmd->dev[idx].unmap_nr_seq); |
---|
| 301 | +} |
---|
| 302 | + |
---|
| 303 | +static struct dm_zone *dmz_get(struct dmz_metadata *zmd, unsigned int zone_id) |
---|
| 304 | +{ |
---|
| 305 | + return xa_load(&zmd->zones, zone_id); |
---|
| 306 | +} |
---|
| 307 | + |
---|
| 308 | +static struct dm_zone *dmz_insert(struct dmz_metadata *zmd, |
---|
| 309 | + unsigned int zone_id, struct dmz_dev *dev) |
---|
| 310 | +{ |
---|
| 311 | + struct dm_zone *zone = kzalloc(sizeof(struct dm_zone), GFP_KERNEL); |
---|
| 312 | + |
---|
| 313 | + if (!zone) |
---|
| 314 | + return ERR_PTR(-ENOMEM); |
---|
| 315 | + |
---|
| 316 | + if (xa_insert(&zmd->zones, zone_id, zone, GFP_KERNEL)) { |
---|
| 317 | + kfree(zone); |
---|
| 318 | + return ERR_PTR(-EBUSY); |
---|
| 319 | + } |
---|
| 320 | + |
---|
| 321 | + INIT_LIST_HEAD(&zone->link); |
---|
| 322 | + atomic_set(&zone->refcount, 0); |
---|
| 323 | + zone->id = zone_id; |
---|
| 324 | + zone->chunk = DMZ_MAP_UNMAPPED; |
---|
| 325 | + zone->dev = dev; |
---|
| 326 | + |
---|
| 327 | + return zone; |
---|
| 328 | +} |
---|
| 329 | + |
---|
| 330 | +const char *dmz_metadata_label(struct dmz_metadata *zmd) |
---|
| 331 | +{ |
---|
| 332 | + return (const char *)zmd->label; |
---|
| 333 | +} |
---|
| 334 | + |
---|
| 335 | +bool dmz_check_dev(struct dmz_metadata *zmd) |
---|
| 336 | +{ |
---|
| 337 | + unsigned int i; |
---|
| 338 | + |
---|
| 339 | + for (i = 0; i < zmd->nr_devs; i++) { |
---|
| 340 | + if (!dmz_check_bdev(&zmd->dev[i])) |
---|
| 341 | + return false; |
---|
| 342 | + } |
---|
| 343 | + return true; |
---|
| 344 | +} |
---|
| 345 | + |
---|
| 346 | +bool dmz_dev_is_dying(struct dmz_metadata *zmd) |
---|
| 347 | +{ |
---|
| 348 | + unsigned int i; |
---|
| 349 | + |
---|
| 350 | + for (i = 0; i < zmd->nr_devs; i++) { |
---|
| 351 | + if (dmz_bdev_is_dying(&zmd->dev[i])) |
---|
| 352 | + return true; |
---|
| 353 | + } |
---|
| 354 | + return false; |
---|
216 | 355 | } |
---|
217 | 356 | |
---|
218 | 357 | /* |
---|
.. | .. |
---|
233 | 372 | * Lock/unlock metadata access. This is a "read" lock on a semaphore |
---|
234 | 373 | * that prevents metadata flush from running while metadata are being |
---|
235 | 374 | * modified. The actual metadata write mutual exclusion is achieved with |
---|
236 | | - * the map lock and zone styate management (active and reclaim state are |
---|
| 375 | + * the map lock and zone state management (active and reclaim state are |
---|
237 | 376 | * mutually exclusive). |
---|
238 | 377 | */ |
---|
239 | 378 | void dmz_lock_metadata(struct dmz_metadata *zmd) |
---|
.. | .. |
---|
400 | 539 | { |
---|
401 | 540 | struct dmz_mblock *mblk, *m; |
---|
402 | 541 | sector_t block = zmd->sb[zmd->mblk_primary].block + mblk_no; |
---|
| 542 | + struct dmz_dev *dev = zmd->sb[zmd->mblk_primary].dev; |
---|
403 | 543 | struct bio *bio; |
---|
404 | 544 | |
---|
405 | | - if (dmz_bdev_is_dying(zmd->dev)) |
---|
| 545 | + if (dmz_bdev_is_dying(dev)) |
---|
406 | 546 | return ERR_PTR(-EIO); |
---|
407 | 547 | |
---|
408 | 548 | /* Get a new block and a BIO to read it */ |
---|
.. | .. |
---|
438 | 578 | |
---|
439 | 579 | /* Submit read BIO */ |
---|
440 | 580 | bio->bi_iter.bi_sector = dmz_blk2sect(block); |
---|
441 | | - bio_set_dev(bio, zmd->dev->bdev); |
---|
| 581 | + bio_set_dev(bio, dev->bdev); |
---|
442 | 582 | bio->bi_private = mblk; |
---|
443 | 583 | bio->bi_end_io = dmz_mblock_bio_end_io; |
---|
444 | 584 | bio_set_op_attrs(bio, REQ_OP_READ, REQ_META | REQ_PRIO); |
---|
.. | .. |
---|
535 | 675 | sector_t mblk_no) |
---|
536 | 676 | { |
---|
537 | 677 | struct dmz_mblock *mblk; |
---|
| 678 | + struct dmz_dev *dev = zmd->sb[zmd->mblk_primary].dev; |
---|
538 | 679 | |
---|
539 | 680 | /* Check rbtree */ |
---|
540 | 681 | spin_lock(&zmd->mblk_lock); |
---|
.. | .. |
---|
553 | 694 | TASK_UNINTERRUPTIBLE); |
---|
554 | 695 | if (test_bit(DMZ_META_ERROR, &mblk->state)) { |
---|
555 | 696 | dmz_release_mblock(zmd, mblk); |
---|
556 | | - dmz_check_bdev(zmd->dev); |
---|
| 697 | + dmz_check_bdev(dev); |
---|
557 | 698 | return ERR_PTR(-EIO); |
---|
558 | 699 | } |
---|
559 | 700 | |
---|
.. | .. |
---|
577 | 718 | static int dmz_write_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk, |
---|
578 | 719 | unsigned int set) |
---|
579 | 720 | { |
---|
| 721 | + struct dmz_dev *dev = zmd->sb[set].dev; |
---|
580 | 722 | sector_t block = zmd->sb[set].block + mblk->no; |
---|
581 | 723 | struct bio *bio; |
---|
582 | 724 | |
---|
583 | | - if (dmz_bdev_is_dying(zmd->dev)) |
---|
| 725 | + if (dmz_bdev_is_dying(dev)) |
---|
584 | 726 | return -EIO; |
---|
585 | 727 | |
---|
586 | 728 | bio = bio_alloc(GFP_NOIO, 1); |
---|
.. | .. |
---|
592 | 734 | set_bit(DMZ_META_WRITING, &mblk->state); |
---|
593 | 735 | |
---|
594 | 736 | bio->bi_iter.bi_sector = dmz_blk2sect(block); |
---|
595 | | - bio_set_dev(bio, zmd->dev->bdev); |
---|
| 737 | + bio_set_dev(bio, dev->bdev); |
---|
596 | 738 | bio->bi_private = mblk; |
---|
597 | 739 | bio->bi_end_io = dmz_mblock_bio_end_io; |
---|
598 | 740 | bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_META | REQ_PRIO); |
---|
.. | .. |
---|
605 | 747 | /* |
---|
606 | 748 | * Read/write a metadata block. |
---|
607 | 749 | */ |
---|
608 | | -static int dmz_rdwr_block(struct dmz_metadata *zmd, int op, sector_t block, |
---|
609 | | - struct page *page) |
---|
| 750 | +static int dmz_rdwr_block(struct dmz_dev *dev, int op, |
---|
| 751 | + sector_t block, struct page *page) |
---|
610 | 752 | { |
---|
611 | 753 | struct bio *bio; |
---|
612 | 754 | int ret; |
---|
613 | 755 | |
---|
614 | | - if (dmz_bdev_is_dying(zmd->dev)) |
---|
| 756 | + if (WARN_ON(!dev)) |
---|
| 757 | + return -EIO; |
---|
| 758 | + |
---|
| 759 | + if (dmz_bdev_is_dying(dev)) |
---|
615 | 760 | return -EIO; |
---|
616 | 761 | |
---|
617 | 762 | bio = bio_alloc(GFP_NOIO, 1); |
---|
.. | .. |
---|
619 | 764 | return -ENOMEM; |
---|
620 | 765 | |
---|
621 | 766 | bio->bi_iter.bi_sector = dmz_blk2sect(block); |
---|
622 | | - bio_set_dev(bio, zmd->dev->bdev); |
---|
| 767 | + bio_set_dev(bio, dev->bdev); |
---|
623 | 768 | bio_set_op_attrs(bio, op, REQ_SYNC | REQ_META | REQ_PRIO); |
---|
624 | 769 | bio_add_page(bio, page, DMZ_BLOCK_SIZE, 0); |
---|
625 | 770 | ret = submit_bio_wait(bio); |
---|
626 | 771 | bio_put(bio); |
---|
627 | 772 | |
---|
628 | 773 | if (ret) |
---|
629 | | - dmz_check_bdev(zmd->dev); |
---|
| 774 | + dmz_check_bdev(dev); |
---|
630 | 775 | return ret; |
---|
631 | 776 | } |
---|
632 | 777 | |
---|
.. | .. |
---|
635 | 780 | */ |
---|
636 | 781 | static int dmz_write_sb(struct dmz_metadata *zmd, unsigned int set) |
---|
637 | 782 | { |
---|
638 | | - sector_t block = zmd->sb[set].block; |
---|
639 | 783 | struct dmz_mblock *mblk = zmd->sb[set].mblk; |
---|
640 | 784 | struct dmz_super *sb = zmd->sb[set].sb; |
---|
| 785 | + struct dmz_dev *dev = zmd->sb[set].dev; |
---|
| 786 | + sector_t sb_block; |
---|
641 | 787 | u64 sb_gen = zmd->sb_gen + 1; |
---|
642 | 788 | int ret; |
---|
643 | 789 | |
---|
644 | 790 | sb->magic = cpu_to_le32(DMZ_MAGIC); |
---|
645 | | - sb->version = cpu_to_le32(DMZ_META_VER); |
---|
| 791 | + |
---|
| 792 | + sb->version = cpu_to_le32(zmd->sb_version); |
---|
| 793 | + if (zmd->sb_version > 1) { |
---|
| 794 | + BUILD_BUG_ON(UUID_SIZE != 16); |
---|
| 795 | + export_uuid(sb->dmz_uuid, &zmd->uuid); |
---|
| 796 | + memcpy(sb->dmz_label, zmd->label, BDEVNAME_SIZE); |
---|
| 797 | + export_uuid(sb->dev_uuid, &dev->uuid); |
---|
| 798 | + } |
---|
646 | 799 | |
---|
647 | 800 | sb->gen = cpu_to_le64(sb_gen); |
---|
648 | 801 | |
---|
649 | | - sb->sb_block = cpu_to_le64(block); |
---|
| 802 | + /* |
---|
| 803 | + * The metadata always references the absolute block address, |
---|
| 804 | + * ie relative to the entire block range, not the per-device |
---|
| 805 | + * block address. |
---|
| 806 | + */ |
---|
| 807 | + sb_block = zmd->sb[set].zone->id << zmd->zone_nr_blocks_shift; |
---|
| 808 | + sb->sb_block = cpu_to_le64(sb_block); |
---|
650 | 809 | sb->nr_meta_blocks = cpu_to_le32(zmd->nr_meta_blocks); |
---|
651 | 810 | sb->nr_reserved_seq = cpu_to_le32(zmd->nr_reserved_seq); |
---|
652 | 811 | sb->nr_chunks = cpu_to_le32(zmd->nr_chunks); |
---|
.. | .. |
---|
657 | 816 | sb->crc = 0; |
---|
658 | 817 | sb->crc = cpu_to_le32(crc32_le(sb_gen, (unsigned char *)sb, DMZ_BLOCK_SIZE)); |
---|
659 | 818 | |
---|
660 | | - ret = dmz_rdwr_block(zmd, REQ_OP_WRITE, block, mblk->page); |
---|
| 819 | + ret = dmz_rdwr_block(dev, REQ_OP_WRITE, zmd->sb[set].block, |
---|
| 820 | + mblk->page); |
---|
661 | 821 | if (ret == 0) |
---|
662 | | - ret = blkdev_issue_flush(zmd->dev->bdev, GFP_NOIO, NULL); |
---|
| 822 | + ret = blkdev_issue_flush(dev->bdev, GFP_NOIO); |
---|
663 | 823 | |
---|
664 | 824 | return ret; |
---|
665 | 825 | } |
---|
.. | .. |
---|
672 | 832 | unsigned int set) |
---|
673 | 833 | { |
---|
674 | 834 | struct dmz_mblock *mblk; |
---|
| 835 | + struct dmz_dev *dev = zmd->sb[set].dev; |
---|
675 | 836 | struct blk_plug plug; |
---|
676 | 837 | int ret = 0, nr_mblks_submitted = 0; |
---|
677 | 838 | |
---|
.. | .. |
---|
693 | 854 | TASK_UNINTERRUPTIBLE); |
---|
694 | 855 | if (test_bit(DMZ_META_ERROR, &mblk->state)) { |
---|
695 | 856 | clear_bit(DMZ_META_ERROR, &mblk->state); |
---|
696 | | - dmz_check_bdev(zmd->dev); |
---|
| 857 | + dmz_check_bdev(dev); |
---|
697 | 858 | ret = -EIO; |
---|
698 | 859 | } |
---|
699 | 860 | nr_mblks_submitted--; |
---|
.. | .. |
---|
701 | 862 | |
---|
702 | 863 | /* Flush drive cache (this will also sync data) */ |
---|
703 | 864 | if (ret == 0) |
---|
704 | | - ret = blkdev_issue_flush(zmd->dev->bdev, GFP_NOIO, NULL); |
---|
| 865 | + ret = blkdev_issue_flush(dev->bdev, GFP_NOIO); |
---|
705 | 866 | |
---|
706 | 867 | return ret; |
---|
707 | 868 | } |
---|
.. | .. |
---|
738 | 899 | { |
---|
739 | 900 | struct dmz_mblock *mblk; |
---|
740 | 901 | struct list_head write_list; |
---|
| 902 | + struct dmz_dev *dev; |
---|
741 | 903 | int ret; |
---|
742 | 904 | |
---|
743 | 905 | if (WARN_ON(!zmd)) |
---|
.. | .. |
---|
751 | 913 | * from modifying metadata. |
---|
752 | 914 | */ |
---|
753 | 915 | down_write(&zmd->mblk_sem); |
---|
| 916 | + dev = zmd->sb[zmd->mblk_primary].dev; |
---|
754 | 917 | |
---|
755 | 918 | /* |
---|
756 | 919 | * This is called from the target flush work and reclaim work. |
---|
.. | .. |
---|
758 | 921 | */ |
---|
759 | 922 | dmz_lock_flush(zmd); |
---|
760 | 923 | |
---|
761 | | - if (dmz_bdev_is_dying(zmd->dev)) { |
---|
| 924 | + if (dmz_bdev_is_dying(dev)) { |
---|
762 | 925 | ret = -EIO; |
---|
763 | 926 | goto out; |
---|
764 | 927 | } |
---|
.. | .. |
---|
770 | 933 | |
---|
771 | 934 | /* If there are no dirty metadata blocks, just flush the device cache */ |
---|
772 | 935 | if (list_empty(&write_list)) { |
---|
773 | | - ret = blkdev_issue_flush(zmd->dev->bdev, GFP_NOIO, NULL); |
---|
| 936 | + ret = blkdev_issue_flush(dev->bdev, GFP_NOIO); |
---|
774 | 937 | goto err; |
---|
775 | 938 | } |
---|
776 | 939 | |
---|
.. | .. |
---|
819 | 982 | list_splice(&write_list, &zmd->mblk_dirty_list); |
---|
820 | 983 | spin_unlock(&zmd->mblk_lock); |
---|
821 | 984 | } |
---|
822 | | - if (!dmz_check_bdev(zmd->dev)) |
---|
| 985 | + if (!dmz_check_bdev(dev)) |
---|
823 | 986 | ret = -EIO; |
---|
824 | 987 | goto out; |
---|
825 | 988 | } |
---|
.. | .. |
---|
827 | 990 | /* |
---|
828 | 991 | * Check super block. |
---|
829 | 992 | */ |
---|
830 | | -static int dmz_check_sb(struct dmz_metadata *zmd, struct dmz_super *sb) |
---|
| 993 | +static int dmz_check_sb(struct dmz_metadata *zmd, struct dmz_sb *dsb, |
---|
| 994 | + bool tertiary) |
---|
831 | 995 | { |
---|
| 996 | + struct dmz_super *sb = dsb->sb; |
---|
| 997 | + struct dmz_dev *dev = dsb->dev; |
---|
832 | 998 | unsigned int nr_meta_zones, nr_data_zones; |
---|
833 | | - struct dmz_dev *dev = zmd->dev; |
---|
834 | 999 | u32 crc, stored_crc; |
---|
835 | | - u64 gen; |
---|
| 1000 | + u64 gen, sb_block; |
---|
| 1001 | + |
---|
| 1002 | + if (le32_to_cpu(sb->magic) != DMZ_MAGIC) { |
---|
| 1003 | + dmz_dev_err(dev, "Invalid meta magic (needed 0x%08x, got 0x%08x)", |
---|
| 1004 | + DMZ_MAGIC, le32_to_cpu(sb->magic)); |
---|
| 1005 | + return -ENXIO; |
---|
| 1006 | + } |
---|
| 1007 | + |
---|
| 1008 | + zmd->sb_version = le32_to_cpu(sb->version); |
---|
| 1009 | + if (zmd->sb_version > DMZ_META_VER) { |
---|
| 1010 | + dmz_dev_err(dev, "Invalid meta version (needed %d, got %d)", |
---|
| 1011 | + DMZ_META_VER, zmd->sb_version); |
---|
| 1012 | + return -EINVAL; |
---|
| 1013 | + } |
---|
| 1014 | + if (zmd->sb_version < 2 && tertiary) { |
---|
| 1015 | + dmz_dev_err(dev, "Tertiary superblocks are not supported"); |
---|
| 1016 | + return -EINVAL; |
---|
| 1017 | + } |
---|
836 | 1018 | |
---|
837 | 1019 | gen = le64_to_cpu(sb->gen); |
---|
838 | 1020 | stored_crc = le32_to_cpu(sb->crc); |
---|
.. | .. |
---|
844 | 1026 | return -ENXIO; |
---|
845 | 1027 | } |
---|
846 | 1028 | |
---|
847 | | - if (le32_to_cpu(sb->magic) != DMZ_MAGIC) { |
---|
848 | | - dmz_dev_err(dev, "Invalid meta magic (needed 0x%08x, got 0x%08x)", |
---|
849 | | - DMZ_MAGIC, le32_to_cpu(sb->magic)); |
---|
850 | | - return -ENXIO; |
---|
| 1029 | + sb_block = le64_to_cpu(sb->sb_block); |
---|
| 1030 | + if (sb_block != (u64)dsb->zone->id << zmd->zone_nr_blocks_shift ) { |
---|
| 1031 | + dmz_dev_err(dev, "Invalid superblock position " |
---|
| 1032 | + "(is %llu expected %llu)", |
---|
| 1033 | + sb_block, |
---|
| 1034 | + (u64)dsb->zone->id << zmd->zone_nr_blocks_shift); |
---|
| 1035 | + return -EINVAL; |
---|
| 1036 | + } |
---|
| 1037 | + if (zmd->sb_version > 1) { |
---|
| 1038 | + uuid_t sb_uuid; |
---|
| 1039 | + |
---|
| 1040 | + import_uuid(&sb_uuid, sb->dmz_uuid); |
---|
| 1041 | + if (uuid_is_null(&sb_uuid)) { |
---|
| 1042 | + dmz_dev_err(dev, "NULL DM-Zoned uuid"); |
---|
| 1043 | + return -ENXIO; |
---|
| 1044 | + } else if (uuid_is_null(&zmd->uuid)) { |
---|
| 1045 | + uuid_copy(&zmd->uuid, &sb_uuid); |
---|
| 1046 | + } else if (!uuid_equal(&zmd->uuid, &sb_uuid)) { |
---|
| 1047 | + dmz_dev_err(dev, "mismatching DM-Zoned uuid, " |
---|
| 1048 | + "is %pUl expected %pUl", |
---|
| 1049 | + &sb_uuid, &zmd->uuid); |
---|
| 1050 | + return -ENXIO; |
---|
| 1051 | + } |
---|
| 1052 | + if (!strlen(zmd->label)) |
---|
| 1053 | + memcpy(zmd->label, sb->dmz_label, BDEVNAME_SIZE); |
---|
| 1054 | + else if (memcmp(zmd->label, sb->dmz_label, BDEVNAME_SIZE)) { |
---|
| 1055 | + dmz_dev_err(dev, "mismatching DM-Zoned label, " |
---|
| 1056 | + "is %s expected %s", |
---|
| 1057 | + sb->dmz_label, zmd->label); |
---|
| 1058 | + return -ENXIO; |
---|
| 1059 | + } |
---|
| 1060 | + import_uuid(&dev->uuid, sb->dev_uuid); |
---|
| 1061 | + if (uuid_is_null(&dev->uuid)) { |
---|
| 1062 | + dmz_dev_err(dev, "NULL device uuid"); |
---|
| 1063 | + return -ENXIO; |
---|
| 1064 | + } |
---|
| 1065 | + |
---|
| 1066 | + if (tertiary) { |
---|
| 1067 | + /* |
---|
| 1068 | + * Generation number should be 0, but it doesn't |
---|
| 1069 | + * really matter if it isn't. |
---|
| 1070 | + */ |
---|
| 1071 | + if (gen != 0) |
---|
| 1072 | + dmz_dev_warn(dev, "Invalid generation %llu", |
---|
| 1073 | + gen); |
---|
| 1074 | + return 0; |
---|
| 1075 | + } |
---|
851 | 1076 | } |
---|
852 | 1077 | |
---|
853 | | - if (le32_to_cpu(sb->version) != DMZ_META_VER) { |
---|
854 | | - dmz_dev_err(dev, "Invalid meta version (needed %d, got %d)", |
---|
855 | | - DMZ_META_VER, le32_to_cpu(sb->version)); |
---|
856 | | - return -ENXIO; |
---|
857 | | - } |
---|
858 | | - |
---|
859 | | - nr_meta_zones = (le32_to_cpu(sb->nr_meta_blocks) + dev->zone_nr_blocks - 1) |
---|
860 | | - >> dev->zone_nr_blocks_shift; |
---|
| 1078 | + nr_meta_zones = (le32_to_cpu(sb->nr_meta_blocks) + zmd->zone_nr_blocks - 1) |
---|
| 1079 | + >> zmd->zone_nr_blocks_shift; |
---|
861 | 1080 | if (!nr_meta_zones || |
---|
862 | | - nr_meta_zones >= zmd->nr_rnd_zones) { |
---|
| 1081 | + (zmd->nr_devs <= 1 && nr_meta_zones >= zmd->nr_rnd_zones) || |
---|
| 1082 | + (zmd->nr_devs > 1 && nr_meta_zones >= zmd->nr_cache_zones)) { |
---|
863 | 1083 | dmz_dev_err(dev, "Invalid number of metadata blocks"); |
---|
864 | 1084 | return -ENXIO; |
---|
865 | 1085 | } |
---|
.. | .. |
---|
893 | 1113 | /* |
---|
894 | 1114 | * Read the first or second super block from disk. |
---|
895 | 1115 | */ |
---|
896 | | -static int dmz_read_sb(struct dmz_metadata *zmd, unsigned int set) |
---|
| 1116 | +static int dmz_read_sb(struct dmz_metadata *zmd, struct dmz_sb *sb, int set) |
---|
897 | 1117 | { |
---|
898 | | - return dmz_rdwr_block(zmd, REQ_OP_READ, zmd->sb[set].block, |
---|
899 | | - zmd->sb[set].mblk->page); |
---|
| 1118 | + dmz_zmd_debug(zmd, "read superblock set %d dev %s block %llu", |
---|
| 1119 | + set, sb->dev->name, sb->block); |
---|
| 1120 | + |
---|
| 1121 | + return dmz_rdwr_block(sb->dev, REQ_OP_READ, |
---|
| 1122 | + sb->block, sb->mblk->page); |
---|
900 | 1123 | } |
---|
901 | 1124 | |
---|
902 | 1125 | /* |
---|
.. | .. |
---|
906 | 1129 | */ |
---|
907 | 1130 | static int dmz_lookup_secondary_sb(struct dmz_metadata *zmd) |
---|
908 | 1131 | { |
---|
909 | | - unsigned int zone_nr_blocks = zmd->dev->zone_nr_blocks; |
---|
| 1132 | + unsigned int zone_nr_blocks = zmd->zone_nr_blocks; |
---|
910 | 1133 | struct dmz_mblock *mblk; |
---|
| 1134 | + unsigned int zone_id = zmd->sb[0].zone->id; |
---|
911 | 1135 | int i; |
---|
912 | 1136 | |
---|
913 | 1137 | /* Allocate a block */ |
---|
.. | .. |
---|
920 | 1144 | |
---|
921 | 1145 | /* Bad first super block: search for the second one */ |
---|
922 | 1146 | zmd->sb[1].block = zmd->sb[0].block + zone_nr_blocks; |
---|
923 | | - for (i = 0; i < zmd->nr_rnd_zones - 1; i++) { |
---|
924 | | - if (dmz_read_sb(zmd, 1) != 0) |
---|
| 1147 | + zmd->sb[1].zone = dmz_get(zmd, zone_id + 1); |
---|
| 1148 | + zmd->sb[1].dev = zmd->sb[0].dev; |
---|
| 1149 | + for (i = 1; i < zmd->nr_rnd_zones; i++) { |
---|
| 1150 | + if (dmz_read_sb(zmd, &zmd->sb[1], 1) != 0) |
---|
925 | 1151 | break; |
---|
926 | 1152 | if (le32_to_cpu(zmd->sb[1].sb->magic) == DMZ_MAGIC) |
---|
927 | 1153 | return 0; |
---|
928 | 1154 | zmd->sb[1].block += zone_nr_blocks; |
---|
| 1155 | + zmd->sb[1].zone = dmz_get(zmd, zone_id + i); |
---|
929 | 1156 | } |
---|
930 | 1157 | |
---|
931 | 1158 | dmz_free_mblock(zmd, mblk); |
---|
932 | 1159 | zmd->sb[1].mblk = NULL; |
---|
| 1160 | + zmd->sb[1].zone = NULL; |
---|
| 1161 | + zmd->sb[1].dev = NULL; |
---|
933 | 1162 | |
---|
934 | 1163 | return -EIO; |
---|
935 | 1164 | } |
---|
936 | 1165 | |
---|
937 | 1166 | /* |
---|
938 | | - * Read the first or second super block from disk. |
---|
| 1167 | + * Read a super block from disk. |
---|
939 | 1168 | */ |
---|
940 | | -static int dmz_get_sb(struct dmz_metadata *zmd, unsigned int set) |
---|
| 1169 | +static int dmz_get_sb(struct dmz_metadata *zmd, struct dmz_sb *sb, int set) |
---|
941 | 1170 | { |
---|
942 | 1171 | struct dmz_mblock *mblk; |
---|
943 | 1172 | int ret; |
---|
.. | .. |
---|
947 | 1176 | if (!mblk) |
---|
948 | 1177 | return -ENOMEM; |
---|
949 | 1178 | |
---|
950 | | - zmd->sb[set].mblk = mblk; |
---|
951 | | - zmd->sb[set].sb = mblk->data; |
---|
| 1179 | + sb->mblk = mblk; |
---|
| 1180 | + sb->sb = mblk->data; |
---|
952 | 1181 | |
---|
953 | 1182 | /* Read super block */ |
---|
954 | | - ret = dmz_read_sb(zmd, set); |
---|
| 1183 | + ret = dmz_read_sb(zmd, sb, set); |
---|
955 | 1184 | if (ret) { |
---|
956 | 1185 | dmz_free_mblock(zmd, mblk); |
---|
957 | | - zmd->sb[set].mblk = NULL; |
---|
| 1186 | + sb->mblk = NULL; |
---|
958 | 1187 | return ret; |
---|
959 | 1188 | } |
---|
960 | 1189 | |
---|
.. | .. |
---|
970 | 1199 | struct page *page; |
---|
971 | 1200 | int i, ret; |
---|
972 | 1201 | |
---|
973 | | - dmz_dev_warn(zmd->dev, "Metadata set %u invalid: recovering", dst_set); |
---|
| 1202 | + dmz_dev_warn(zmd->sb[dst_set].dev, |
---|
| 1203 | + "Metadata set %u invalid: recovering", dst_set); |
---|
974 | 1204 | |
---|
975 | 1205 | if (dst_set == 0) |
---|
976 | | - zmd->sb[0].block = dmz_start_block(zmd, zmd->sb_zone); |
---|
977 | | - else { |
---|
978 | | - zmd->sb[1].block = zmd->sb[0].block + |
---|
979 | | - (zmd->nr_meta_zones << zmd->dev->zone_nr_blocks_shift); |
---|
980 | | - } |
---|
| 1206 | + zmd->sb[0].block = dmz_start_block(zmd, zmd->sb[0].zone); |
---|
| 1207 | + else |
---|
| 1208 | + zmd->sb[1].block = dmz_start_block(zmd, zmd->sb[1].zone); |
---|
981 | 1209 | |
---|
982 | 1210 | page = alloc_page(GFP_NOIO); |
---|
983 | 1211 | if (!page) |
---|
.. | .. |
---|
985 | 1213 | |
---|
986 | 1214 | /* Copy metadata blocks */ |
---|
987 | 1215 | for (i = 1; i < zmd->nr_meta_blocks; i++) { |
---|
988 | | - ret = dmz_rdwr_block(zmd, REQ_OP_READ, |
---|
| 1216 | + ret = dmz_rdwr_block(zmd->sb[src_set].dev, REQ_OP_READ, |
---|
989 | 1217 | zmd->sb[src_set].block + i, page); |
---|
990 | 1218 | if (ret) |
---|
991 | 1219 | goto out; |
---|
992 | | - ret = dmz_rdwr_block(zmd, REQ_OP_WRITE, |
---|
| 1220 | + ret = dmz_rdwr_block(zmd->sb[dst_set].dev, REQ_OP_WRITE, |
---|
993 | 1221 | zmd->sb[dst_set].block + i, page); |
---|
994 | 1222 | if (ret) |
---|
995 | 1223 | goto out; |
---|
.. | .. |
---|
1021 | 1249 | u64 sb_gen[2] = {0, 0}; |
---|
1022 | 1250 | int ret; |
---|
1023 | 1251 | |
---|
| 1252 | + if (!zmd->sb[0].zone) { |
---|
| 1253 | + dmz_zmd_err(zmd, "Primary super block zone not set"); |
---|
| 1254 | + return -ENXIO; |
---|
| 1255 | + } |
---|
| 1256 | + |
---|
1024 | 1257 | /* Read and check the primary super block */ |
---|
1025 | | - zmd->sb[0].block = dmz_start_block(zmd, zmd->sb_zone); |
---|
1026 | | - ret = dmz_get_sb(zmd, 0); |
---|
| 1258 | + zmd->sb[0].block = dmz_start_block(zmd, zmd->sb[0].zone); |
---|
| 1259 | + zmd->sb[0].dev = zmd->sb[0].zone->dev; |
---|
| 1260 | + ret = dmz_get_sb(zmd, &zmd->sb[0], 0); |
---|
1027 | 1261 | if (ret) { |
---|
1028 | | - dmz_dev_err(zmd->dev, "Read primary super block failed"); |
---|
| 1262 | + dmz_dev_err(zmd->sb[0].dev, "Read primary super block failed"); |
---|
1029 | 1263 | return ret; |
---|
1030 | 1264 | } |
---|
1031 | 1265 | |
---|
1032 | | - ret = dmz_check_sb(zmd, zmd->sb[0].sb); |
---|
| 1266 | + ret = dmz_check_sb(zmd, &zmd->sb[0], false); |
---|
1033 | 1267 | |
---|
1034 | 1268 | /* Read and check secondary super block */ |
---|
1035 | 1269 | if (ret == 0) { |
---|
1036 | 1270 | sb_good[0] = true; |
---|
1037 | | - zmd->sb[1].block = zmd->sb[0].block + |
---|
1038 | | - (zmd->nr_meta_zones << zmd->dev->zone_nr_blocks_shift); |
---|
1039 | | - ret = dmz_get_sb(zmd, 1); |
---|
| 1271 | + if (!zmd->sb[1].zone) { |
---|
| 1272 | + unsigned int zone_id = |
---|
| 1273 | + zmd->sb[0].zone->id + zmd->nr_meta_zones; |
---|
| 1274 | + |
---|
| 1275 | + zmd->sb[1].zone = dmz_get(zmd, zone_id); |
---|
| 1276 | + } |
---|
| 1277 | + zmd->sb[1].block = dmz_start_block(zmd, zmd->sb[1].zone); |
---|
| 1278 | + zmd->sb[1].dev = zmd->sb[0].dev; |
---|
| 1279 | + ret = dmz_get_sb(zmd, &zmd->sb[1], 1); |
---|
1040 | 1280 | } else |
---|
1041 | 1281 | ret = dmz_lookup_secondary_sb(zmd); |
---|
1042 | 1282 | |
---|
1043 | 1283 | if (ret) { |
---|
1044 | | - dmz_dev_err(zmd->dev, "Read secondary super block failed"); |
---|
| 1284 | + dmz_dev_err(zmd->sb[1].dev, "Read secondary super block failed"); |
---|
1045 | 1285 | return ret; |
---|
1046 | 1286 | } |
---|
1047 | 1287 | |
---|
1048 | | - ret = dmz_check_sb(zmd, zmd->sb[1].sb); |
---|
| 1288 | + ret = dmz_check_sb(zmd, &zmd->sb[1], false); |
---|
1049 | 1289 | if (ret == 0) |
---|
1050 | 1290 | sb_good[1] = true; |
---|
1051 | 1291 | |
---|
1052 | 1292 | /* Use highest generation sb first */ |
---|
1053 | 1293 | if (!sb_good[0] && !sb_good[1]) { |
---|
1054 | | - dmz_dev_err(zmd->dev, "No valid super block found"); |
---|
| 1294 | + dmz_zmd_err(zmd, "No valid super block found"); |
---|
1055 | 1295 | return -EIO; |
---|
1056 | 1296 | } |
---|
1057 | 1297 | |
---|
1058 | 1298 | if (sb_good[0]) |
---|
1059 | 1299 | sb_gen[0] = le64_to_cpu(zmd->sb[0].sb->gen); |
---|
1060 | | - else |
---|
| 1300 | + else { |
---|
1061 | 1301 | ret = dmz_recover_mblocks(zmd, 0); |
---|
| 1302 | + if (ret) { |
---|
| 1303 | + dmz_dev_err(zmd->sb[0].dev, |
---|
| 1304 | + "Recovery of superblock 0 failed"); |
---|
| 1305 | + return -EIO; |
---|
| 1306 | + } |
---|
| 1307 | + } |
---|
1062 | 1308 | |
---|
1063 | 1309 | if (sb_good[1]) |
---|
1064 | 1310 | sb_gen[1] = le64_to_cpu(zmd->sb[1].sb->gen); |
---|
1065 | | - else |
---|
| 1311 | + else { |
---|
1066 | 1312 | ret = dmz_recover_mblocks(zmd, 1); |
---|
1067 | 1313 | |
---|
1068 | | - if (ret) { |
---|
1069 | | - dmz_dev_err(zmd->dev, "Recovery failed"); |
---|
1070 | | - return -EIO; |
---|
| 1314 | + if (ret) { |
---|
| 1315 | + dmz_dev_err(zmd->sb[1].dev, |
---|
| 1316 | + "Recovery of superblock 1 failed"); |
---|
| 1317 | + return -EIO; |
---|
| 1318 | + } |
---|
1071 | 1319 | } |
---|
1072 | 1320 | |
---|
1073 | 1321 | if (sb_gen[0] >= sb_gen[1]) { |
---|
.. | .. |
---|
1078 | 1326 | zmd->mblk_primary = 1; |
---|
1079 | 1327 | } |
---|
1080 | 1328 | |
---|
1081 | | - dmz_dev_debug(zmd->dev, "Using super block %u (gen %llu)", |
---|
| 1329 | + dmz_dev_debug(zmd->sb[zmd->mblk_primary].dev, |
---|
| 1330 | + "Using super block %u (gen %llu)", |
---|
1082 | 1331 | zmd->mblk_primary, zmd->sb_gen); |
---|
1083 | 1332 | |
---|
1084 | | - return 0; |
---|
| 1333 | + if (zmd->sb_version > 1) { |
---|
| 1334 | + int i; |
---|
| 1335 | + struct dmz_sb *sb; |
---|
| 1336 | + |
---|
| 1337 | + sb = kzalloc(sizeof(struct dmz_sb), GFP_KERNEL); |
---|
| 1338 | + if (!sb) |
---|
| 1339 | + return -ENOMEM; |
---|
| 1340 | + for (i = 1; i < zmd->nr_devs; i++) { |
---|
| 1341 | + sb->block = 0; |
---|
| 1342 | + sb->zone = dmz_get(zmd, zmd->dev[i].zone_offset); |
---|
| 1343 | + sb->dev = &zmd->dev[i]; |
---|
| 1344 | + if (!dmz_is_meta(sb->zone)) { |
---|
| 1345 | + dmz_dev_err(sb->dev, |
---|
| 1346 | + "Tertiary super block zone %u not marked as metadata zone", |
---|
| 1347 | + sb->zone->id); |
---|
| 1348 | + ret = -EINVAL; |
---|
| 1349 | + goto out_kfree; |
---|
| 1350 | + } |
---|
| 1351 | + ret = dmz_get_sb(zmd, sb, i + 1); |
---|
| 1352 | + if (ret) { |
---|
| 1353 | + dmz_dev_err(sb->dev, |
---|
| 1354 | + "Read tertiary super block failed"); |
---|
| 1355 | + dmz_free_mblock(zmd, sb->mblk); |
---|
| 1356 | + goto out_kfree; |
---|
| 1357 | + } |
---|
| 1358 | + ret = dmz_check_sb(zmd, sb, true); |
---|
| 1359 | + dmz_free_mblock(zmd, sb->mblk); |
---|
| 1360 | + if (ret == -EINVAL) |
---|
| 1361 | + goto out_kfree; |
---|
| 1362 | + } |
---|
| 1363 | + out_kfree: |
---|
| 1364 | + kfree(sb); |
---|
| 1365 | + } |
---|
| 1366 | + return ret; |
---|
1085 | 1367 | } |
---|
1086 | 1368 | |
---|
1087 | 1369 | /* |
---|
1088 | 1370 | * Initialize a zone descriptor. |
---|
1089 | 1371 | */ |
---|
1090 | | -static int dmz_init_zone(struct dmz_metadata *zmd, struct dm_zone *zone, |
---|
1091 | | - struct blk_zone *blkz) |
---|
| 1372 | +static int dmz_init_zone(struct blk_zone *blkz, unsigned int num, void *data) |
---|
1092 | 1373 | { |
---|
1093 | | - struct dmz_dev *dev = zmd->dev; |
---|
| 1374 | + struct dmz_dev *dev = data; |
---|
| 1375 | + struct dmz_metadata *zmd = dev->metadata; |
---|
| 1376 | + int idx = num + dev->zone_offset; |
---|
| 1377 | + struct dm_zone *zone; |
---|
1094 | 1378 | |
---|
1095 | | - /* Ignore the eventual last runt (smaller) zone */ |
---|
1096 | | - if (blkz->len != dev->zone_nr_sectors) { |
---|
1097 | | - if (blkz->start + blkz->len == dev->capacity) |
---|
| 1379 | + zone = dmz_insert(zmd, idx, dev); |
---|
| 1380 | + if (IS_ERR(zone)) |
---|
| 1381 | + return PTR_ERR(zone); |
---|
| 1382 | + |
---|
| 1383 | + if (blkz->len != zmd->zone_nr_sectors) { |
---|
| 1384 | + if (zmd->sb_version > 1) { |
---|
| 1385 | + /* Ignore the eventual runt (smaller) zone */ |
---|
| 1386 | + set_bit(DMZ_OFFLINE, &zone->flags); |
---|
| 1387 | + return 0; |
---|
| 1388 | + } else if (blkz->start + blkz->len == dev->capacity) |
---|
1098 | 1389 | return 0; |
---|
1099 | 1390 | return -ENXIO; |
---|
1100 | 1391 | } |
---|
1101 | 1392 | |
---|
1102 | | - INIT_LIST_HEAD(&zone->link); |
---|
1103 | | - atomic_set(&zone->refcount, 0); |
---|
1104 | | - zone->chunk = DMZ_MAP_UNMAPPED; |
---|
1105 | | - |
---|
1106 | | - if (blkz->type == BLK_ZONE_TYPE_CONVENTIONAL) { |
---|
1107 | | - set_bit(DMZ_RND, &zone->flags); |
---|
1108 | | - } else if (blkz->type == BLK_ZONE_TYPE_SEQWRITE_REQ || |
---|
1109 | | - blkz->type == BLK_ZONE_TYPE_SEQWRITE_PREF) { |
---|
1110 | | - set_bit(DMZ_SEQ, &zone->flags); |
---|
1111 | | - } else |
---|
| 1393 | + /* |
---|
| 1394 | + * Devices that have zones with a capacity smaller than the zone size |
---|
| 1395 | + * (e.g. NVMe zoned namespaces) are not supported. |
---|
| 1396 | + */ |
---|
| 1397 | + if (blkz->capacity != blkz->len) |
---|
1112 | 1398 | return -ENXIO; |
---|
1113 | 1399 | |
---|
1114 | | - if (blkz->cond == BLK_ZONE_COND_OFFLINE) |
---|
1115 | | - set_bit(DMZ_OFFLINE, &zone->flags); |
---|
1116 | | - else if (blkz->cond == BLK_ZONE_COND_READONLY) |
---|
1117 | | - set_bit(DMZ_READ_ONLY, &zone->flags); |
---|
| 1400 | + switch (blkz->type) { |
---|
| 1401 | + case BLK_ZONE_TYPE_CONVENTIONAL: |
---|
| 1402 | + set_bit(DMZ_RND, &zone->flags); |
---|
| 1403 | + break; |
---|
| 1404 | + case BLK_ZONE_TYPE_SEQWRITE_REQ: |
---|
| 1405 | + case BLK_ZONE_TYPE_SEQWRITE_PREF: |
---|
| 1406 | + set_bit(DMZ_SEQ, &zone->flags); |
---|
| 1407 | + break; |
---|
| 1408 | + default: |
---|
| 1409 | + return -ENXIO; |
---|
| 1410 | + } |
---|
1118 | 1411 | |
---|
1119 | 1412 | if (dmz_is_rnd(zone)) |
---|
1120 | 1413 | zone->wp_block = 0; |
---|
1121 | 1414 | else |
---|
1122 | 1415 | zone->wp_block = dmz_sect2blk(blkz->wp - blkz->start); |
---|
1123 | 1416 | |
---|
1124 | | - if (!dmz_is_offline(zone) && !dmz_is_readonly(zone)) { |
---|
| 1417 | + if (blkz->cond == BLK_ZONE_COND_OFFLINE) |
---|
| 1418 | + set_bit(DMZ_OFFLINE, &zone->flags); |
---|
| 1419 | + else if (blkz->cond == BLK_ZONE_COND_READONLY) |
---|
| 1420 | + set_bit(DMZ_READ_ONLY, &zone->flags); |
---|
| 1421 | + else { |
---|
1125 | 1422 | zmd->nr_useable_zones++; |
---|
1126 | 1423 | if (dmz_is_rnd(zone)) { |
---|
1127 | 1424 | zmd->nr_rnd_zones++; |
---|
1128 | | - if (!zmd->sb_zone) { |
---|
1129 | | - /* Super block zone */ |
---|
1130 | | - zmd->sb_zone = zone; |
---|
| 1425 | + if (zmd->nr_devs == 1 && !zmd->sb[0].zone) { |
---|
| 1426 | + /* Primary super block zone */ |
---|
| 1427 | + zmd->sb[0].zone = zone; |
---|
1131 | 1428 | } |
---|
1132 | 1429 | } |
---|
| 1430 | + if (zmd->nr_devs > 1 && num == 0) { |
---|
| 1431 | + /* |
---|
| 1432 | + * Tertiary superblock zones are always at the |
---|
| 1433 | + * start of the zoned devices, so mark them |
---|
| 1434 | + * as metadata zone. |
---|
| 1435 | + */ |
---|
| 1436 | + set_bit(DMZ_META, &zone->flags); |
---|
| 1437 | + } |
---|
1133 | 1438 | } |
---|
| 1439 | + return 0; |
---|
| 1440 | +} |
---|
1134 | 1441 | |
---|
| 1442 | +static int dmz_emulate_zones(struct dmz_metadata *zmd, struct dmz_dev *dev) |
---|
| 1443 | +{ |
---|
| 1444 | + int idx; |
---|
| 1445 | + sector_t zone_offset = 0; |
---|
| 1446 | + |
---|
| 1447 | + for(idx = 0; idx < dev->nr_zones; idx++) { |
---|
| 1448 | + struct dm_zone *zone; |
---|
| 1449 | + |
---|
| 1450 | + zone = dmz_insert(zmd, idx, dev); |
---|
| 1451 | + if (IS_ERR(zone)) |
---|
| 1452 | + return PTR_ERR(zone); |
---|
| 1453 | + set_bit(DMZ_CACHE, &zone->flags); |
---|
| 1454 | + zone->wp_block = 0; |
---|
| 1455 | + zmd->nr_cache_zones++; |
---|
| 1456 | + zmd->nr_useable_zones++; |
---|
| 1457 | + if (dev->capacity - zone_offset < zmd->zone_nr_sectors) { |
---|
| 1458 | + /* Disable runt zone */ |
---|
| 1459 | + set_bit(DMZ_OFFLINE, &zone->flags); |
---|
| 1460 | + break; |
---|
| 1461 | + } |
---|
| 1462 | + zone_offset += zmd->zone_nr_sectors; |
---|
| 1463 | + } |
---|
1135 | 1464 | return 0; |
---|
1136 | 1465 | } |
---|
1137 | 1466 | |
---|
.. | .. |
---|
1140 | 1469 | */ |
---|
1141 | 1470 | static void dmz_drop_zones(struct dmz_metadata *zmd) |
---|
1142 | 1471 | { |
---|
1143 | | - kfree(zmd->zones); |
---|
1144 | | - zmd->zones = NULL; |
---|
1145 | | -} |
---|
| 1472 | + int idx; |
---|
1146 | 1473 | |
---|
1147 | | -/* |
---|
1148 | | - * The size of a zone report in number of zones. |
---|
1149 | | - * This results in 4096*64B=256KB report zones commands. |
---|
1150 | | - */ |
---|
1151 | | -#define DMZ_REPORT_NR_ZONES 4096 |
---|
| 1474 | + for(idx = 0; idx < zmd->nr_zones; idx++) { |
---|
| 1475 | + struct dm_zone *zone = xa_load(&zmd->zones, idx); |
---|
| 1476 | + |
---|
| 1477 | + kfree(zone); |
---|
| 1478 | + xa_erase(&zmd->zones, idx); |
---|
| 1479 | + } |
---|
| 1480 | + xa_destroy(&zmd->zones); |
---|
| 1481 | +} |
---|
1152 | 1482 | |
---|
1153 | 1483 | /* |
---|
1154 | 1484 | * Allocate and initialize zone descriptors using the zone |
---|
.. | .. |
---|
1156 | 1486 | */ |
---|
1157 | 1487 | static int dmz_init_zones(struct dmz_metadata *zmd) |
---|
1158 | 1488 | { |
---|
1159 | | - struct dmz_dev *dev = zmd->dev; |
---|
1160 | | - struct dm_zone *zone; |
---|
1161 | | - struct blk_zone *blkz; |
---|
1162 | | - unsigned int nr_blkz; |
---|
1163 | | - sector_t sector = 0; |
---|
1164 | | - int i, ret = 0; |
---|
| 1489 | + int i, ret; |
---|
| 1490 | + struct dmz_dev *zoned_dev = &zmd->dev[0]; |
---|
1165 | 1491 | |
---|
1166 | 1492 | /* Init */ |
---|
1167 | | - zmd->zone_bitmap_size = dev->zone_nr_blocks >> 3; |
---|
| 1493 | + zmd->zone_nr_sectors = zmd->dev[0].zone_nr_sectors; |
---|
| 1494 | + zmd->zone_nr_sectors_shift = ilog2(zmd->zone_nr_sectors); |
---|
| 1495 | + zmd->zone_nr_blocks = dmz_sect2blk(zmd->zone_nr_sectors); |
---|
| 1496 | + zmd->zone_nr_blocks_shift = ilog2(zmd->zone_nr_blocks); |
---|
| 1497 | + zmd->zone_bitmap_size = zmd->zone_nr_blocks >> 3; |
---|
1168 | 1498 | zmd->zone_nr_bitmap_blocks = |
---|
1169 | 1499 | max_t(sector_t, 1, zmd->zone_bitmap_size >> DMZ_BLOCK_SHIFT); |
---|
1170 | | - zmd->zone_bits_per_mblk = min_t(sector_t, dev->zone_nr_blocks, |
---|
| 1500 | + zmd->zone_bits_per_mblk = min_t(sector_t, zmd->zone_nr_blocks, |
---|
1171 | 1501 | DMZ_BLOCK_SIZE_BITS); |
---|
1172 | 1502 | |
---|
1173 | 1503 | /* Allocate zone array */ |
---|
1174 | | - zmd->zones = kcalloc(dev->nr_zones, sizeof(struct dm_zone), GFP_KERNEL); |
---|
1175 | | - if (!zmd->zones) |
---|
1176 | | - return -ENOMEM; |
---|
| 1504 | + zmd->nr_zones = 0; |
---|
| 1505 | + for (i = 0; i < zmd->nr_devs; i++) { |
---|
| 1506 | + struct dmz_dev *dev = &zmd->dev[i]; |
---|
1177 | 1507 | |
---|
1178 | | - dmz_dev_info(dev, "Using %zu B for zone information", |
---|
1179 | | - sizeof(struct dm_zone) * dev->nr_zones); |
---|
| 1508 | + dev->metadata = zmd; |
---|
| 1509 | + zmd->nr_zones += dev->nr_zones; |
---|
1180 | 1510 | |
---|
1181 | | - /* Get zone information */ |
---|
1182 | | - nr_blkz = DMZ_REPORT_NR_ZONES; |
---|
1183 | | - blkz = kcalloc(nr_blkz, sizeof(struct blk_zone), GFP_KERNEL); |
---|
1184 | | - if (!blkz) { |
---|
1185 | | - ret = -ENOMEM; |
---|
1186 | | - goto out; |
---|
| 1511 | + atomic_set(&dev->unmap_nr_rnd, 0); |
---|
| 1512 | + INIT_LIST_HEAD(&dev->unmap_rnd_list); |
---|
| 1513 | + INIT_LIST_HEAD(&dev->map_rnd_list); |
---|
| 1514 | + |
---|
| 1515 | + atomic_set(&dev->unmap_nr_seq, 0); |
---|
| 1516 | + INIT_LIST_HEAD(&dev->unmap_seq_list); |
---|
| 1517 | + INIT_LIST_HEAD(&dev->map_seq_list); |
---|
| 1518 | + } |
---|
| 1519 | + |
---|
| 1520 | + if (!zmd->nr_zones) { |
---|
| 1521 | + DMERR("(%s): No zones found", zmd->devname); |
---|
| 1522 | + return -ENXIO; |
---|
| 1523 | + } |
---|
| 1524 | + xa_init(&zmd->zones); |
---|
| 1525 | + |
---|
| 1526 | + DMDEBUG("(%s): Using %zu B for zone information", |
---|
| 1527 | + zmd->devname, sizeof(struct dm_zone) * zmd->nr_zones); |
---|
| 1528 | + |
---|
| 1529 | + if (zmd->nr_devs > 1) { |
---|
| 1530 | + ret = dmz_emulate_zones(zmd, &zmd->dev[0]); |
---|
| 1531 | + if (ret < 0) { |
---|
| 1532 | + DMDEBUG("(%s): Failed to emulate zones, error %d", |
---|
| 1533 | + zmd->devname, ret); |
---|
| 1534 | + dmz_drop_zones(zmd); |
---|
| 1535 | + return ret; |
---|
| 1536 | + } |
---|
| 1537 | + |
---|
| 1538 | + /* |
---|
| 1539 | + * Primary superblock zone is always at zone 0 when multiple |
---|
| 1540 | + * drives are present. |
---|
| 1541 | + */ |
---|
| 1542 | + zmd->sb[0].zone = dmz_get(zmd, 0); |
---|
| 1543 | + |
---|
| 1544 | + for (i = 1; i < zmd->nr_devs; i++) { |
---|
| 1545 | + zoned_dev = &zmd->dev[i]; |
---|
| 1546 | + |
---|
| 1547 | + ret = blkdev_report_zones(zoned_dev->bdev, 0, |
---|
| 1548 | + BLK_ALL_ZONES, |
---|
| 1549 | + dmz_init_zone, zoned_dev); |
---|
| 1550 | + if (ret < 0) { |
---|
| 1551 | + DMDEBUG("(%s): Failed to report zones, error %d", |
---|
| 1552 | + zmd->devname, ret); |
---|
| 1553 | + dmz_drop_zones(zmd); |
---|
| 1554 | + return ret; |
---|
| 1555 | + } |
---|
| 1556 | + } |
---|
| 1557 | + return 0; |
---|
1187 | 1558 | } |
---|
1188 | 1559 | |
---|
1189 | 1560 | /* |
---|
1190 | | - * Get zone information and initialize zone descriptors. |
---|
1191 | | - * At the same time, determine where the super block |
---|
1192 | | - * should be: first block of the first randomly writable |
---|
1193 | | - * zone. |
---|
| 1561 | + * Get zone information and initialize zone descriptors. At the same |
---|
| 1562 | + * time, determine where the super block should be: first block of the |
---|
| 1563 | + * first randomly writable zone. |
---|
1194 | 1564 | */ |
---|
1195 | | - zone = zmd->zones; |
---|
1196 | | - while (sector < dev->capacity) { |
---|
1197 | | - /* Get zone information */ |
---|
1198 | | - nr_blkz = DMZ_REPORT_NR_ZONES; |
---|
1199 | | - ret = blkdev_report_zones(dev->bdev, sector, blkz, |
---|
1200 | | - &nr_blkz, GFP_KERNEL); |
---|
1201 | | - if (ret) { |
---|
1202 | | - dmz_dev_err(dev, "Report zones failed %d", ret); |
---|
1203 | | - goto out; |
---|
1204 | | - } |
---|
1205 | | - |
---|
1206 | | - if (!nr_blkz) |
---|
1207 | | - break; |
---|
1208 | | - |
---|
1209 | | - /* Process report */ |
---|
1210 | | - for (i = 0; i < nr_blkz; i++) { |
---|
1211 | | - ret = dmz_init_zone(zmd, zone, &blkz[i]); |
---|
1212 | | - if (ret) |
---|
1213 | | - goto out; |
---|
1214 | | - sector += dev->zone_nr_sectors; |
---|
1215 | | - zone++; |
---|
1216 | | - } |
---|
1217 | | - } |
---|
1218 | | - |
---|
1219 | | - /* The entire zone configuration of the disk should now be known */ |
---|
1220 | | - if (sector < dev->capacity) { |
---|
1221 | | - dmz_dev_err(dev, "Failed to get correct zone information"); |
---|
1222 | | - ret = -ENXIO; |
---|
1223 | | - } |
---|
1224 | | -out: |
---|
1225 | | - kfree(blkz); |
---|
1226 | | - if (ret) |
---|
| 1565 | + ret = blkdev_report_zones(zoned_dev->bdev, 0, BLK_ALL_ZONES, |
---|
| 1566 | + dmz_init_zone, zoned_dev); |
---|
| 1567 | + if (ret < 0) { |
---|
| 1568 | + DMDEBUG("(%s): Failed to report zones, error %d", |
---|
| 1569 | + zmd->devname, ret); |
---|
1227 | 1570 | dmz_drop_zones(zmd); |
---|
| 1571 | + return ret; |
---|
| 1572 | + } |
---|
1228 | 1573 | |
---|
1229 | | - return ret; |
---|
| 1574 | + return 0; |
---|
| 1575 | +} |
---|
| 1576 | + |
---|
| 1577 | +static int dmz_update_zone_cb(struct blk_zone *blkz, unsigned int idx, |
---|
| 1578 | + void *data) |
---|
| 1579 | +{ |
---|
| 1580 | + struct dm_zone *zone = data; |
---|
| 1581 | + |
---|
| 1582 | + clear_bit(DMZ_OFFLINE, &zone->flags); |
---|
| 1583 | + clear_bit(DMZ_READ_ONLY, &zone->flags); |
---|
| 1584 | + if (blkz->cond == BLK_ZONE_COND_OFFLINE) |
---|
| 1585 | + set_bit(DMZ_OFFLINE, &zone->flags); |
---|
| 1586 | + else if (blkz->cond == BLK_ZONE_COND_READONLY) |
---|
| 1587 | + set_bit(DMZ_READ_ONLY, &zone->flags); |
---|
| 1588 | + |
---|
| 1589 | + if (dmz_is_seq(zone)) |
---|
| 1590 | + zone->wp_block = dmz_sect2blk(blkz->wp - blkz->start); |
---|
| 1591 | + else |
---|
| 1592 | + zone->wp_block = 0; |
---|
| 1593 | + return 0; |
---|
1230 | 1594 | } |
---|
1231 | 1595 | |
---|
1232 | 1596 | /* |
---|
.. | .. |
---|
1234 | 1598 | */ |
---|
1235 | 1599 | static int dmz_update_zone(struct dmz_metadata *zmd, struct dm_zone *zone) |
---|
1236 | 1600 | { |
---|
1237 | | - unsigned int nr_blkz = 1; |
---|
1238 | | - struct blk_zone blkz; |
---|
| 1601 | + struct dmz_dev *dev = zone->dev; |
---|
| 1602 | + unsigned int noio_flag; |
---|
1239 | 1603 | int ret; |
---|
1240 | 1604 | |
---|
1241 | | - /* Get zone information from disk */ |
---|
1242 | | - ret = blkdev_report_zones(zmd->dev->bdev, dmz_start_sect(zmd, zone), |
---|
1243 | | - &blkz, &nr_blkz, GFP_NOIO); |
---|
1244 | | - if (!nr_blkz) |
---|
| 1605 | + if (dev->flags & DMZ_BDEV_REGULAR) |
---|
| 1606 | + return 0; |
---|
| 1607 | + |
---|
| 1608 | + /* |
---|
| 1609 | + * Get zone information from disk. Since blkdev_report_zones() uses |
---|
| 1610 | + * GFP_KERNEL by default for memory allocations, set the per-task |
---|
| 1611 | + * PF_MEMALLOC_NOIO flag so that all allocations are done as if |
---|
| 1612 | + * GFP_NOIO was specified. |
---|
| 1613 | + */ |
---|
| 1614 | + noio_flag = memalloc_noio_save(); |
---|
| 1615 | + ret = blkdev_report_zones(dev->bdev, dmz_start_sect(zmd, zone), 1, |
---|
| 1616 | + dmz_update_zone_cb, zone); |
---|
| 1617 | + memalloc_noio_restore(noio_flag); |
---|
| 1618 | + |
---|
| 1619 | + if (ret == 0) |
---|
1245 | 1620 | ret = -EIO; |
---|
1246 | | - if (ret) { |
---|
1247 | | - dmz_dev_err(zmd->dev, "Get zone %u report failed", |
---|
1248 | | - dmz_id(zmd, zone)); |
---|
1249 | | - dmz_check_bdev(zmd->dev); |
---|
| 1621 | + if (ret < 0) { |
---|
| 1622 | + dmz_dev_err(dev, "Get zone %u report failed", |
---|
| 1623 | + zone->id); |
---|
| 1624 | + dmz_check_bdev(dev); |
---|
1250 | 1625 | return ret; |
---|
1251 | 1626 | } |
---|
1252 | | - |
---|
1253 | | - clear_bit(DMZ_OFFLINE, &zone->flags); |
---|
1254 | | - clear_bit(DMZ_READ_ONLY, &zone->flags); |
---|
1255 | | - if (blkz.cond == BLK_ZONE_COND_OFFLINE) |
---|
1256 | | - set_bit(DMZ_OFFLINE, &zone->flags); |
---|
1257 | | - else if (blkz.cond == BLK_ZONE_COND_READONLY) |
---|
1258 | | - set_bit(DMZ_READ_ONLY, &zone->flags); |
---|
1259 | | - |
---|
1260 | | - if (dmz_is_seq(zone)) |
---|
1261 | | - zone->wp_block = dmz_sect2blk(blkz.wp - blkz.start); |
---|
1262 | | - else |
---|
1263 | | - zone->wp_block = 0; |
---|
1264 | 1627 | |
---|
1265 | 1628 | return 0; |
---|
1266 | 1629 | } |
---|
.. | .. |
---|
1272 | 1635 | static int dmz_handle_seq_write_err(struct dmz_metadata *zmd, |
---|
1273 | 1636 | struct dm_zone *zone) |
---|
1274 | 1637 | { |
---|
| 1638 | + struct dmz_dev *dev = zone->dev; |
---|
1275 | 1639 | unsigned int wp = 0; |
---|
1276 | 1640 | int ret; |
---|
1277 | 1641 | |
---|
.. | .. |
---|
1280 | 1644 | if (ret) |
---|
1281 | 1645 | return ret; |
---|
1282 | 1646 | |
---|
1283 | | - dmz_dev_warn(zmd->dev, "Processing zone %u write error (zone wp %u/%u)", |
---|
1284 | | - dmz_id(zmd, zone), zone->wp_block, wp); |
---|
| 1647 | + dmz_dev_warn(dev, "Processing zone %u write error (zone wp %u/%u)", |
---|
| 1648 | + zone->id, zone->wp_block, wp); |
---|
1285 | 1649 | |
---|
1286 | 1650 | if (zone->wp_block < wp) { |
---|
1287 | 1651 | dmz_invalidate_blocks(zmd, zone, zone->wp_block, |
---|
.. | .. |
---|
1289 | 1653 | } |
---|
1290 | 1654 | |
---|
1291 | 1655 | return 0; |
---|
1292 | | -} |
---|
1293 | | - |
---|
1294 | | -static struct dm_zone *dmz_get(struct dmz_metadata *zmd, unsigned int zone_id) |
---|
1295 | | -{ |
---|
1296 | | - return &zmd->zones[zone_id]; |
---|
1297 | 1656 | } |
---|
1298 | 1657 | |
---|
1299 | 1658 | /* |
---|
.. | .. |
---|
1313 | 1672 | return 0; |
---|
1314 | 1673 | |
---|
1315 | 1674 | if (!dmz_is_empty(zone) || dmz_seq_write_err(zone)) { |
---|
1316 | | - struct dmz_dev *dev = zmd->dev; |
---|
| 1675 | + struct dmz_dev *dev = zone->dev; |
---|
1317 | 1676 | |
---|
1318 | | - ret = blkdev_reset_zones(dev->bdev, |
---|
1319 | | - dmz_start_sect(zmd, zone), |
---|
1320 | | - dev->zone_nr_sectors, GFP_NOIO); |
---|
| 1677 | + ret = blkdev_zone_mgmt(dev->bdev, REQ_OP_ZONE_RESET, |
---|
| 1678 | + dmz_start_sect(zmd, zone), |
---|
| 1679 | + zmd->zone_nr_sectors, GFP_NOIO); |
---|
1321 | 1680 | if (ret) { |
---|
1322 | 1681 | dmz_dev_err(dev, "Reset zone %u failed %d", |
---|
1323 | | - dmz_id(zmd, zone), ret); |
---|
| 1682 | + zone->id, ret); |
---|
1324 | 1683 | return ret; |
---|
1325 | 1684 | } |
---|
1326 | 1685 | } |
---|
.. | .. |
---|
1339 | 1698 | */ |
---|
1340 | 1699 | static int dmz_load_mapping(struct dmz_metadata *zmd) |
---|
1341 | 1700 | { |
---|
1342 | | - struct dmz_dev *dev = zmd->dev; |
---|
1343 | 1701 | struct dm_zone *dzone, *bzone; |
---|
1344 | 1702 | struct dmz_mblock *dmap_mblk = NULL; |
---|
1345 | 1703 | struct dmz_map *dmap; |
---|
.. | .. |
---|
1371 | 1729 | if (dzone_id == DMZ_MAP_UNMAPPED) |
---|
1372 | 1730 | goto next; |
---|
1373 | 1731 | |
---|
1374 | | - if (dzone_id >= dev->nr_zones) { |
---|
1375 | | - dmz_dev_err(dev, "Chunk %u mapping: invalid data zone ID %u", |
---|
| 1732 | + if (dzone_id >= zmd->nr_zones) { |
---|
| 1733 | + dmz_zmd_err(zmd, "Chunk %u mapping: invalid data zone ID %u", |
---|
1376 | 1734 | chunk, dzone_id); |
---|
1377 | 1735 | return -EIO; |
---|
1378 | 1736 | } |
---|
1379 | 1737 | |
---|
1380 | 1738 | dzone = dmz_get(zmd, dzone_id); |
---|
| 1739 | + if (!dzone) { |
---|
| 1740 | + dmz_zmd_err(zmd, "Chunk %u mapping: data zone %u not present", |
---|
| 1741 | + chunk, dzone_id); |
---|
| 1742 | + return -EIO; |
---|
| 1743 | + } |
---|
1381 | 1744 | set_bit(DMZ_DATA, &dzone->flags); |
---|
1382 | 1745 | dzone->chunk = chunk; |
---|
1383 | 1746 | dmz_get_zone_weight(zmd, dzone); |
---|
1384 | 1747 | |
---|
1385 | | - if (dmz_is_rnd(dzone)) |
---|
1386 | | - list_add_tail(&dzone->link, &zmd->map_rnd_list); |
---|
| 1748 | + if (dmz_is_cache(dzone)) |
---|
| 1749 | + list_add_tail(&dzone->link, &zmd->map_cache_list); |
---|
| 1750 | + else if (dmz_is_rnd(dzone)) |
---|
| 1751 | + list_add_tail(&dzone->link, &dzone->dev->map_rnd_list); |
---|
1387 | 1752 | else |
---|
1388 | | - list_add_tail(&dzone->link, &zmd->map_seq_list); |
---|
| 1753 | + list_add_tail(&dzone->link, &dzone->dev->map_seq_list); |
---|
1389 | 1754 | |
---|
1390 | 1755 | /* Check buffer zone */ |
---|
1391 | 1756 | bzone_id = le32_to_cpu(dmap[e].bzone_id); |
---|
1392 | 1757 | if (bzone_id == DMZ_MAP_UNMAPPED) |
---|
1393 | 1758 | goto next; |
---|
1394 | 1759 | |
---|
1395 | | - if (bzone_id >= dev->nr_zones) { |
---|
1396 | | - dmz_dev_err(dev, "Chunk %u mapping: invalid buffer zone ID %u", |
---|
| 1760 | + if (bzone_id >= zmd->nr_zones) { |
---|
| 1761 | + dmz_zmd_err(zmd, "Chunk %u mapping: invalid buffer zone ID %u", |
---|
1397 | 1762 | chunk, bzone_id); |
---|
1398 | 1763 | return -EIO; |
---|
1399 | 1764 | } |
---|
1400 | 1765 | |
---|
1401 | 1766 | bzone = dmz_get(zmd, bzone_id); |
---|
1402 | | - if (!dmz_is_rnd(bzone)) { |
---|
1403 | | - dmz_dev_err(dev, "Chunk %u mapping: invalid buffer zone %u", |
---|
| 1767 | + if (!bzone) { |
---|
| 1768 | + dmz_zmd_err(zmd, "Chunk %u mapping: buffer zone %u not present", |
---|
| 1769 | + chunk, bzone_id); |
---|
| 1770 | + return -EIO; |
---|
| 1771 | + } |
---|
| 1772 | + if (!dmz_is_rnd(bzone) && !dmz_is_cache(bzone)) { |
---|
| 1773 | + dmz_zmd_err(zmd, "Chunk %u mapping: invalid buffer zone %u", |
---|
1404 | 1774 | chunk, bzone_id); |
---|
1405 | 1775 | return -EIO; |
---|
1406 | 1776 | } |
---|
.. | .. |
---|
1411 | 1781 | bzone->bzone = dzone; |
---|
1412 | 1782 | dzone->bzone = bzone; |
---|
1413 | 1783 | dmz_get_zone_weight(zmd, bzone); |
---|
1414 | | - list_add_tail(&bzone->link, &zmd->map_rnd_list); |
---|
| 1784 | + if (dmz_is_cache(bzone)) |
---|
| 1785 | + list_add_tail(&bzone->link, &zmd->map_cache_list); |
---|
| 1786 | + else |
---|
| 1787 | + list_add_tail(&bzone->link, &bzone->dev->map_rnd_list); |
---|
1415 | 1788 | next: |
---|
1416 | 1789 | chunk++; |
---|
1417 | 1790 | e++; |
---|
.. | .. |
---|
1424 | 1797 | * fully initialized. All remaining zones are unmapped data |
---|
1425 | 1798 | * zones. Finish initializing those here. |
---|
1426 | 1799 | */ |
---|
1427 | | - for (i = 0; i < dev->nr_zones; i++) { |
---|
| 1800 | + for (i = 0; i < zmd->nr_zones; i++) { |
---|
1428 | 1801 | dzone = dmz_get(zmd, i); |
---|
| 1802 | + if (!dzone) |
---|
| 1803 | + continue; |
---|
1429 | 1804 | if (dmz_is_meta(dzone)) |
---|
1430 | 1805 | continue; |
---|
| 1806 | + if (dmz_is_offline(dzone)) |
---|
| 1807 | + continue; |
---|
1431 | 1808 | |
---|
1432 | | - if (dmz_is_rnd(dzone)) |
---|
1433 | | - zmd->nr_rnd++; |
---|
| 1809 | + if (dmz_is_cache(dzone)) |
---|
| 1810 | + zmd->nr_cache++; |
---|
| 1811 | + else if (dmz_is_rnd(dzone)) |
---|
| 1812 | + dzone->dev->nr_rnd++; |
---|
1434 | 1813 | else |
---|
1435 | | - zmd->nr_seq++; |
---|
| 1814 | + dzone->dev->nr_seq++; |
---|
1436 | 1815 | |
---|
1437 | 1816 | if (dmz_is_data(dzone)) { |
---|
1438 | 1817 | /* Already initialized */ |
---|
.. | .. |
---|
1442 | 1821 | /* Unmapped data zone */ |
---|
1443 | 1822 | set_bit(DMZ_DATA, &dzone->flags); |
---|
1444 | 1823 | dzone->chunk = DMZ_MAP_UNMAPPED; |
---|
1445 | | - if (dmz_is_rnd(dzone)) { |
---|
1446 | | - list_add_tail(&dzone->link, &zmd->unmap_rnd_list); |
---|
1447 | | - atomic_inc(&zmd->unmap_nr_rnd); |
---|
| 1824 | + if (dmz_is_cache(dzone)) { |
---|
| 1825 | + list_add_tail(&dzone->link, &zmd->unmap_cache_list); |
---|
| 1826 | + atomic_inc(&zmd->unmap_nr_cache); |
---|
| 1827 | + } else if (dmz_is_rnd(dzone)) { |
---|
| 1828 | + list_add_tail(&dzone->link, |
---|
| 1829 | + &dzone->dev->unmap_rnd_list); |
---|
| 1830 | + atomic_inc(&dzone->dev->unmap_nr_rnd); |
---|
1448 | 1831 | } else if (atomic_read(&zmd->nr_reserved_seq_zones) < zmd->nr_reserved_seq) { |
---|
1449 | 1832 | list_add_tail(&dzone->link, &zmd->reserved_seq_zones_list); |
---|
| 1833 | + set_bit(DMZ_RESERVED, &dzone->flags); |
---|
1450 | 1834 | atomic_inc(&zmd->nr_reserved_seq_zones); |
---|
1451 | | - zmd->nr_seq--; |
---|
| 1835 | + dzone->dev->nr_seq--; |
---|
1452 | 1836 | } else { |
---|
1453 | | - list_add_tail(&dzone->link, &zmd->unmap_seq_list); |
---|
1454 | | - atomic_inc(&zmd->unmap_nr_seq); |
---|
| 1837 | + list_add_tail(&dzone->link, |
---|
| 1838 | + &dzone->dev->unmap_seq_list); |
---|
| 1839 | + atomic_inc(&dzone->dev->unmap_nr_seq); |
---|
1455 | 1840 | } |
---|
1456 | 1841 | } |
---|
1457 | 1842 | |
---|
.. | .. |
---|
1485 | 1870 | list_del_init(&zone->link); |
---|
1486 | 1871 | if (dmz_is_seq(zone)) { |
---|
1487 | 1872 | /* LRU rotate sequential zone */ |
---|
1488 | | - list_add_tail(&zone->link, &zmd->map_seq_list); |
---|
| 1873 | + list_add_tail(&zone->link, &zone->dev->map_seq_list); |
---|
| 1874 | + } else if (dmz_is_cache(zone)) { |
---|
| 1875 | + /* LRU rotate cache zone */ |
---|
| 1876 | + list_add_tail(&zone->link, &zmd->map_cache_list); |
---|
1489 | 1877 | } else { |
---|
1490 | 1878 | /* LRU rotate random zone */ |
---|
1491 | | - list_add_tail(&zone->link, &zmd->map_rnd_list); |
---|
| 1879 | + list_add_tail(&zone->link, &zone->dev->map_rnd_list); |
---|
1492 | 1880 | } |
---|
1493 | 1881 | } |
---|
1494 | 1882 | |
---|
.. | .. |
---|
1555 | 1943 | { |
---|
1556 | 1944 | dmz_unlock_map(zmd); |
---|
1557 | 1945 | dmz_unlock_metadata(zmd); |
---|
| 1946 | + set_bit(DMZ_RECLAIM_TERMINATE, &zone->flags); |
---|
1558 | 1947 | wait_on_bit_timeout(&zone->flags, DMZ_RECLAIM, TASK_UNINTERRUPTIBLE, HZ); |
---|
| 1948 | + clear_bit(DMZ_RECLAIM_TERMINATE, &zone->flags); |
---|
1559 | 1949 | dmz_lock_metadata(zmd); |
---|
1560 | 1950 | dmz_lock_map(zmd); |
---|
1561 | 1951 | } |
---|
1562 | 1952 | |
---|
1563 | 1953 | /* |
---|
1564 | | - * Select a random write zone for reclaim. |
---|
| 1954 | + * Select a cache or random write zone for reclaim. |
---|
1565 | 1955 | */ |
---|
1566 | | -static struct dm_zone *dmz_get_rnd_zone_for_reclaim(struct dmz_metadata *zmd) |
---|
| 1956 | +static struct dm_zone *dmz_get_rnd_zone_for_reclaim(struct dmz_metadata *zmd, |
---|
| 1957 | + unsigned int idx, bool idle) |
---|
1567 | 1958 | { |
---|
1568 | 1959 | struct dm_zone *dzone = NULL; |
---|
1569 | | - struct dm_zone *zone; |
---|
| 1960 | + struct dm_zone *zone, *maxw_z = NULL; |
---|
| 1961 | + struct list_head *zone_list; |
---|
1570 | 1962 | |
---|
1571 | | - if (list_empty(&zmd->map_rnd_list)) |
---|
1572 | | - return ERR_PTR(-EBUSY); |
---|
| 1963 | + /* If we have cache zones select from the cache zone list */ |
---|
| 1964 | + if (zmd->nr_cache) { |
---|
| 1965 | + zone_list = &zmd->map_cache_list; |
---|
| 1966 | + /* Try to relaim random zones, too, when idle */ |
---|
| 1967 | + if (idle && list_empty(zone_list)) |
---|
| 1968 | + zone_list = &zmd->dev[idx].map_rnd_list; |
---|
| 1969 | + } else |
---|
| 1970 | + zone_list = &zmd->dev[idx].map_rnd_list; |
---|
1573 | 1971 | |
---|
1574 | | - list_for_each_entry(zone, &zmd->map_rnd_list, link) { |
---|
1575 | | - if (dmz_is_buf(zone)) |
---|
| 1972 | + /* |
---|
| 1973 | + * Find the buffer zone with the heaviest weight or the first (oldest) |
---|
| 1974 | + * data zone that can be reclaimed. |
---|
| 1975 | + */ |
---|
| 1976 | + list_for_each_entry(zone, zone_list, link) { |
---|
| 1977 | + if (dmz_is_buf(zone)) { |
---|
1576 | 1978 | dzone = zone->bzone; |
---|
1577 | | - else |
---|
| 1979 | + if (dmz_is_rnd(dzone) && dzone->dev->dev_idx != idx) |
---|
| 1980 | + continue; |
---|
| 1981 | + if (!maxw_z || maxw_z->weight < dzone->weight) |
---|
| 1982 | + maxw_z = dzone; |
---|
| 1983 | + } else { |
---|
| 1984 | + dzone = zone; |
---|
| 1985 | + if (dmz_lock_zone_reclaim(dzone)) |
---|
| 1986 | + return dzone; |
---|
| 1987 | + } |
---|
| 1988 | + } |
---|
| 1989 | + |
---|
| 1990 | + if (maxw_z && dmz_lock_zone_reclaim(maxw_z)) |
---|
| 1991 | + return maxw_z; |
---|
| 1992 | + |
---|
| 1993 | + /* |
---|
| 1994 | + * If we come here, none of the zones inspected could be locked for |
---|
| 1995 | + * reclaim. Try again, being more aggressive, that is, find the |
---|
| 1996 | + * first zone that can be reclaimed regardless of its weitght. |
---|
| 1997 | + */ |
---|
| 1998 | + list_for_each_entry(zone, zone_list, link) { |
---|
| 1999 | + if (dmz_is_buf(zone)) { |
---|
| 2000 | + dzone = zone->bzone; |
---|
| 2001 | + if (dmz_is_rnd(dzone) && dzone->dev->dev_idx != idx) |
---|
| 2002 | + continue; |
---|
| 2003 | + } else |
---|
1578 | 2004 | dzone = zone; |
---|
1579 | 2005 | if (dmz_lock_zone_reclaim(dzone)) |
---|
1580 | 2006 | return dzone; |
---|
.. | .. |
---|
1586 | 2012 | /* |
---|
1587 | 2013 | * Select a buffered sequential zone for reclaim. |
---|
1588 | 2014 | */ |
---|
1589 | | -static struct dm_zone *dmz_get_seq_zone_for_reclaim(struct dmz_metadata *zmd) |
---|
| 2015 | +static struct dm_zone *dmz_get_seq_zone_for_reclaim(struct dmz_metadata *zmd, |
---|
| 2016 | + unsigned int idx) |
---|
1590 | 2017 | { |
---|
1591 | 2018 | struct dm_zone *zone; |
---|
1592 | 2019 | |
---|
1593 | | - if (list_empty(&zmd->map_seq_list)) |
---|
1594 | | - return ERR_PTR(-EBUSY); |
---|
1595 | | - |
---|
1596 | | - list_for_each_entry(zone, &zmd->map_seq_list, link) { |
---|
| 2020 | + list_for_each_entry(zone, &zmd->dev[idx].map_seq_list, link) { |
---|
1597 | 2021 | if (!zone->bzone) |
---|
1598 | 2022 | continue; |
---|
1599 | 2023 | if (dmz_lock_zone_reclaim(zone)) |
---|
.. | .. |
---|
1606 | 2030 | /* |
---|
1607 | 2031 | * Select a zone for reclaim. |
---|
1608 | 2032 | */ |
---|
1609 | | -struct dm_zone *dmz_get_zone_for_reclaim(struct dmz_metadata *zmd) |
---|
| 2033 | +struct dm_zone *dmz_get_zone_for_reclaim(struct dmz_metadata *zmd, |
---|
| 2034 | + unsigned int dev_idx, bool idle) |
---|
1610 | 2035 | { |
---|
1611 | | - struct dm_zone *zone; |
---|
| 2036 | + struct dm_zone *zone = NULL; |
---|
1612 | 2037 | |
---|
1613 | 2038 | /* |
---|
1614 | 2039 | * Search for a zone candidate to reclaim: 2 cases are possible. |
---|
.. | .. |
---|
1620 | 2045 | */ |
---|
1621 | 2046 | dmz_lock_map(zmd); |
---|
1622 | 2047 | if (list_empty(&zmd->reserved_seq_zones_list)) |
---|
1623 | | - zone = dmz_get_seq_zone_for_reclaim(zmd); |
---|
1624 | | - else |
---|
1625 | | - zone = dmz_get_rnd_zone_for_reclaim(zmd); |
---|
| 2048 | + zone = dmz_get_seq_zone_for_reclaim(zmd, dev_idx); |
---|
| 2049 | + if (!zone) |
---|
| 2050 | + zone = dmz_get_rnd_zone_for_reclaim(zmd, dev_idx, idle); |
---|
1626 | 2051 | dmz_unlock_map(zmd); |
---|
1627 | 2052 | |
---|
1628 | 2053 | return zone; |
---|
.. | .. |
---|
1642 | 2067 | unsigned int dzone_id; |
---|
1643 | 2068 | struct dm_zone *dzone = NULL; |
---|
1644 | 2069 | int ret = 0; |
---|
| 2070 | + int alloc_flags = zmd->nr_cache ? DMZ_ALLOC_CACHE : DMZ_ALLOC_RND; |
---|
1645 | 2071 | |
---|
1646 | 2072 | dmz_lock_map(zmd); |
---|
1647 | 2073 | again: |
---|
.. | .. |
---|
1655 | 2081 | if (op != REQ_OP_WRITE) |
---|
1656 | 2082 | goto out; |
---|
1657 | 2083 | |
---|
1658 | | - /* Alloate a random zone */ |
---|
1659 | | - dzone = dmz_alloc_zone(zmd, DMZ_ALLOC_RND); |
---|
| 2084 | + /* Allocate a random zone */ |
---|
| 2085 | + dzone = dmz_alloc_zone(zmd, 0, alloc_flags); |
---|
1660 | 2086 | if (!dzone) { |
---|
1661 | | - if (dmz_bdev_is_dying(zmd->dev)) { |
---|
| 2087 | + if (dmz_dev_is_dying(zmd)) { |
---|
1662 | 2088 | dzone = ERR_PTR(-EIO); |
---|
1663 | 2089 | goto out; |
---|
1664 | 2090 | } |
---|
.. | .. |
---|
1671 | 2097 | } else { |
---|
1672 | 2098 | /* The chunk is already mapped: get the mapping zone */ |
---|
1673 | 2099 | dzone = dmz_get(zmd, dzone_id); |
---|
| 2100 | + if (!dzone) { |
---|
| 2101 | + dzone = ERR_PTR(-EIO); |
---|
| 2102 | + goto out; |
---|
| 2103 | + } |
---|
1674 | 2104 | if (dzone->chunk != chunk) { |
---|
1675 | 2105 | dzone = ERR_PTR(-EIO); |
---|
1676 | 2106 | goto out; |
---|
.. | .. |
---|
1749 | 2179 | struct dm_zone *dzone) |
---|
1750 | 2180 | { |
---|
1751 | 2181 | struct dm_zone *bzone; |
---|
| 2182 | + int alloc_flags = zmd->nr_cache ? DMZ_ALLOC_CACHE : DMZ_ALLOC_RND; |
---|
1752 | 2183 | |
---|
1753 | 2184 | dmz_lock_map(zmd); |
---|
1754 | 2185 | again: |
---|
.. | .. |
---|
1756 | 2187 | if (bzone) |
---|
1757 | 2188 | goto out; |
---|
1758 | 2189 | |
---|
1759 | | - /* Alloate a random zone */ |
---|
1760 | | - bzone = dmz_alloc_zone(zmd, DMZ_ALLOC_RND); |
---|
| 2190 | + /* Allocate a random zone */ |
---|
| 2191 | + bzone = dmz_alloc_zone(zmd, 0, alloc_flags); |
---|
1761 | 2192 | if (!bzone) { |
---|
1762 | | - if (dmz_bdev_is_dying(zmd->dev)) { |
---|
| 2193 | + if (dmz_dev_is_dying(zmd)) { |
---|
1763 | 2194 | bzone = ERR_PTR(-EIO); |
---|
1764 | 2195 | goto out; |
---|
1765 | 2196 | } |
---|
.. | .. |
---|
1768 | 2199 | } |
---|
1769 | 2200 | |
---|
1770 | 2201 | /* Update the chunk mapping */ |
---|
1771 | | - dmz_set_chunk_mapping(zmd, dzone->chunk, dmz_id(zmd, dzone), |
---|
1772 | | - dmz_id(zmd, bzone)); |
---|
| 2202 | + dmz_set_chunk_mapping(zmd, dzone->chunk, dzone->id, bzone->id); |
---|
1773 | 2203 | |
---|
1774 | 2204 | set_bit(DMZ_BUF, &bzone->flags); |
---|
1775 | 2205 | bzone->chunk = dzone->chunk; |
---|
1776 | 2206 | bzone->bzone = dzone; |
---|
1777 | 2207 | dzone->bzone = bzone; |
---|
1778 | | - list_add_tail(&bzone->link, &zmd->map_rnd_list); |
---|
| 2208 | + if (dmz_is_cache(bzone)) |
---|
| 2209 | + list_add_tail(&bzone->link, &zmd->map_cache_list); |
---|
| 2210 | + else |
---|
| 2211 | + list_add_tail(&bzone->link, &bzone->dev->map_rnd_list); |
---|
1779 | 2212 | out: |
---|
1780 | 2213 | dmz_unlock_map(zmd); |
---|
1781 | 2214 | |
---|
.. | .. |
---|
1786 | 2219 | * Get an unmapped (free) zone. |
---|
1787 | 2220 | * This must be called with the mapping lock held. |
---|
1788 | 2221 | */ |
---|
1789 | | -struct dm_zone *dmz_alloc_zone(struct dmz_metadata *zmd, unsigned long flags) |
---|
| 2222 | +struct dm_zone *dmz_alloc_zone(struct dmz_metadata *zmd, unsigned int dev_idx, |
---|
| 2223 | + unsigned long flags) |
---|
1790 | 2224 | { |
---|
1791 | 2225 | struct list_head *list; |
---|
1792 | 2226 | struct dm_zone *zone; |
---|
| 2227 | + int i; |
---|
1793 | 2228 | |
---|
1794 | | - if (flags & DMZ_ALLOC_RND) |
---|
1795 | | - list = &zmd->unmap_rnd_list; |
---|
1796 | | - else |
---|
1797 | | - list = &zmd->unmap_seq_list; |
---|
| 2229 | + /* Schedule reclaim to ensure free zones are available */ |
---|
| 2230 | + if (!(flags & DMZ_ALLOC_RECLAIM)) { |
---|
| 2231 | + for (i = 0; i < zmd->nr_devs; i++) |
---|
| 2232 | + dmz_schedule_reclaim(zmd->dev[i].reclaim); |
---|
| 2233 | + } |
---|
| 2234 | + |
---|
| 2235 | + i = 0; |
---|
1798 | 2236 | again: |
---|
| 2237 | + if (flags & DMZ_ALLOC_CACHE) |
---|
| 2238 | + list = &zmd->unmap_cache_list; |
---|
| 2239 | + else if (flags & DMZ_ALLOC_RND) |
---|
| 2240 | + list = &zmd->dev[dev_idx].unmap_rnd_list; |
---|
| 2241 | + else |
---|
| 2242 | + list = &zmd->dev[dev_idx].unmap_seq_list; |
---|
| 2243 | + |
---|
1799 | 2244 | if (list_empty(list)) { |
---|
1800 | 2245 | /* |
---|
1801 | | - * No free zone: if this is for reclaim, allow using the |
---|
1802 | | - * reserved sequential zones. |
---|
| 2246 | + * No free zone: return NULL if this is for not reclaim. |
---|
1803 | 2247 | */ |
---|
1804 | | - if (!(flags & DMZ_ALLOC_RECLAIM) || |
---|
1805 | | - list_empty(&zmd->reserved_seq_zones_list)) |
---|
| 2248 | + if (!(flags & DMZ_ALLOC_RECLAIM)) |
---|
1806 | 2249 | return NULL; |
---|
| 2250 | + /* |
---|
| 2251 | + * Try to allocate from other devices |
---|
| 2252 | + */ |
---|
| 2253 | + if (i < zmd->nr_devs) { |
---|
| 2254 | + dev_idx = (dev_idx + 1) % zmd->nr_devs; |
---|
| 2255 | + i++; |
---|
| 2256 | + goto again; |
---|
| 2257 | + } |
---|
1807 | 2258 | |
---|
1808 | | - zone = list_first_entry(&zmd->reserved_seq_zones_list, |
---|
1809 | | - struct dm_zone, link); |
---|
1810 | | - list_del_init(&zone->link); |
---|
1811 | | - atomic_dec(&zmd->nr_reserved_seq_zones); |
---|
| 2259 | + /* |
---|
| 2260 | + * Fallback to the reserved sequential zones |
---|
| 2261 | + */ |
---|
| 2262 | + zone = list_first_entry_or_null(&zmd->reserved_seq_zones_list, |
---|
| 2263 | + struct dm_zone, link); |
---|
| 2264 | + if (zone) { |
---|
| 2265 | + list_del_init(&zone->link); |
---|
| 2266 | + atomic_dec(&zmd->nr_reserved_seq_zones); |
---|
| 2267 | + } |
---|
1812 | 2268 | return zone; |
---|
1813 | 2269 | } |
---|
1814 | 2270 | |
---|
1815 | 2271 | zone = list_first_entry(list, struct dm_zone, link); |
---|
1816 | 2272 | list_del_init(&zone->link); |
---|
1817 | 2273 | |
---|
1818 | | - if (dmz_is_rnd(zone)) |
---|
1819 | | - atomic_dec(&zmd->unmap_nr_rnd); |
---|
| 2274 | + if (dmz_is_cache(zone)) |
---|
| 2275 | + atomic_dec(&zmd->unmap_nr_cache); |
---|
| 2276 | + else if (dmz_is_rnd(zone)) |
---|
| 2277 | + atomic_dec(&zone->dev->unmap_nr_rnd); |
---|
1820 | 2278 | else |
---|
1821 | | - atomic_dec(&zmd->unmap_nr_seq); |
---|
| 2279 | + atomic_dec(&zone->dev->unmap_nr_seq); |
---|
1822 | 2280 | |
---|
1823 | 2281 | if (dmz_is_offline(zone)) { |
---|
1824 | | - dmz_dev_warn(zmd->dev, "Zone %u is offline", dmz_id(zmd, zone)); |
---|
| 2282 | + dmz_zmd_warn(zmd, "Zone %u is offline", zone->id); |
---|
1825 | 2283 | zone = NULL; |
---|
1826 | 2284 | goto again; |
---|
1827 | 2285 | } |
---|
1828 | | - |
---|
| 2286 | + if (dmz_is_meta(zone)) { |
---|
| 2287 | + dmz_zmd_warn(zmd, "Zone %u has metadata", zone->id); |
---|
| 2288 | + zone = NULL; |
---|
| 2289 | + goto again; |
---|
| 2290 | + } |
---|
1829 | 2291 | return zone; |
---|
1830 | 2292 | } |
---|
1831 | 2293 | |
---|
.. | .. |
---|
1840 | 2302 | dmz_reset_zone(zmd, zone); |
---|
1841 | 2303 | |
---|
1842 | 2304 | /* Return the zone to its type unmap list */ |
---|
1843 | | - if (dmz_is_rnd(zone)) { |
---|
1844 | | - list_add_tail(&zone->link, &zmd->unmap_rnd_list); |
---|
1845 | | - atomic_inc(&zmd->unmap_nr_rnd); |
---|
1846 | | - } else if (atomic_read(&zmd->nr_reserved_seq_zones) < |
---|
1847 | | - zmd->nr_reserved_seq) { |
---|
| 2305 | + if (dmz_is_cache(zone)) { |
---|
| 2306 | + list_add_tail(&zone->link, &zmd->unmap_cache_list); |
---|
| 2307 | + atomic_inc(&zmd->unmap_nr_cache); |
---|
| 2308 | + } else if (dmz_is_rnd(zone)) { |
---|
| 2309 | + list_add_tail(&zone->link, &zone->dev->unmap_rnd_list); |
---|
| 2310 | + atomic_inc(&zone->dev->unmap_nr_rnd); |
---|
| 2311 | + } else if (dmz_is_reserved(zone)) { |
---|
1848 | 2312 | list_add_tail(&zone->link, &zmd->reserved_seq_zones_list); |
---|
1849 | 2313 | atomic_inc(&zmd->nr_reserved_seq_zones); |
---|
1850 | 2314 | } else { |
---|
1851 | | - list_add_tail(&zone->link, &zmd->unmap_seq_list); |
---|
1852 | | - atomic_inc(&zmd->unmap_nr_seq); |
---|
| 2315 | + list_add_tail(&zone->link, &zone->dev->unmap_seq_list); |
---|
| 2316 | + atomic_inc(&zone->dev->unmap_nr_seq); |
---|
1853 | 2317 | } |
---|
1854 | 2318 | |
---|
1855 | 2319 | wake_up_all(&zmd->free_wq); |
---|
.. | .. |
---|
1863 | 2327 | unsigned int chunk) |
---|
1864 | 2328 | { |
---|
1865 | 2329 | /* Set the chunk mapping */ |
---|
1866 | | - dmz_set_chunk_mapping(zmd, chunk, dmz_id(zmd, dzone), |
---|
| 2330 | + dmz_set_chunk_mapping(zmd, chunk, dzone->id, |
---|
1867 | 2331 | DMZ_MAP_UNMAPPED); |
---|
1868 | 2332 | dzone->chunk = chunk; |
---|
1869 | | - if (dmz_is_rnd(dzone)) |
---|
1870 | | - list_add_tail(&dzone->link, &zmd->map_rnd_list); |
---|
| 2333 | + if (dmz_is_cache(dzone)) |
---|
| 2334 | + list_add_tail(&dzone->link, &zmd->map_cache_list); |
---|
| 2335 | + else if (dmz_is_rnd(dzone)) |
---|
| 2336 | + list_add_tail(&dzone->link, &dzone->dev->map_rnd_list); |
---|
1871 | 2337 | else |
---|
1872 | | - list_add_tail(&dzone->link, &zmd->map_seq_list); |
---|
| 2338 | + list_add_tail(&dzone->link, &dzone->dev->map_seq_list); |
---|
1873 | 2339 | } |
---|
1874 | 2340 | |
---|
1875 | 2341 | /* |
---|
.. | .. |
---|
1891 | 2357 | * Unmapping the chunk buffer zone: clear only |
---|
1892 | 2358 | * the chunk buffer mapping |
---|
1893 | 2359 | */ |
---|
1894 | | - dzone_id = dmz_id(zmd, zone->bzone); |
---|
| 2360 | + dzone_id = zone->bzone->id; |
---|
1895 | 2361 | zone->bzone->bzone = NULL; |
---|
1896 | 2362 | zone->bzone = NULL; |
---|
1897 | 2363 | |
---|
.. | .. |
---|
1953 | 2419 | sector_t chunk_block) |
---|
1954 | 2420 | { |
---|
1955 | 2421 | sector_t bitmap_block = 1 + zmd->nr_map_blocks + |
---|
1956 | | - (sector_t)(dmz_id(zmd, zone) * zmd->zone_nr_bitmap_blocks) + |
---|
| 2422 | + (sector_t)(zone->id * zmd->zone_nr_bitmap_blocks) + |
---|
1957 | 2423 | (chunk_block >> DMZ_BLOCK_SHIFT_BITS); |
---|
1958 | 2424 | |
---|
1959 | 2425 | return dmz_get_mblock(zmd, bitmap_block); |
---|
.. | .. |
---|
1969 | 2435 | sector_t chunk_block = 0; |
---|
1970 | 2436 | |
---|
1971 | 2437 | /* Get the zones bitmap blocks */ |
---|
1972 | | - while (chunk_block < zmd->dev->zone_nr_blocks) { |
---|
| 2438 | + while (chunk_block < zmd->zone_nr_blocks) { |
---|
1973 | 2439 | from_mblk = dmz_get_bitmap(zmd, from_zone, chunk_block); |
---|
1974 | 2440 | if (IS_ERR(from_mblk)) |
---|
1975 | 2441 | return PTR_ERR(from_mblk); |
---|
.. | .. |
---|
2004 | 2470 | int ret; |
---|
2005 | 2471 | |
---|
2006 | 2472 | /* Get the zones bitmap blocks */ |
---|
2007 | | - while (chunk_block < zmd->dev->zone_nr_blocks) { |
---|
| 2473 | + while (chunk_block < zmd->zone_nr_blocks) { |
---|
2008 | 2474 | /* Get a valid region from the source zone */ |
---|
2009 | 2475 | ret = dmz_first_valid_block(zmd, from_zone, &chunk_block); |
---|
2010 | 2476 | if (ret <= 0) |
---|
.. | .. |
---|
2028 | 2494 | sector_t chunk_block, unsigned int nr_blocks) |
---|
2029 | 2495 | { |
---|
2030 | 2496 | unsigned int count, bit, nr_bits; |
---|
2031 | | - unsigned int zone_nr_blocks = zmd->dev->zone_nr_blocks; |
---|
| 2497 | + unsigned int zone_nr_blocks = zmd->zone_nr_blocks; |
---|
2032 | 2498 | struct dmz_mblock *mblk; |
---|
2033 | 2499 | unsigned int n = 0; |
---|
2034 | 2500 | |
---|
2035 | | - dmz_dev_debug(zmd->dev, "=> VALIDATE zone %u, block %llu, %u blocks", |
---|
2036 | | - dmz_id(zmd, zone), (unsigned long long)chunk_block, |
---|
| 2501 | + dmz_zmd_debug(zmd, "=> VALIDATE zone %u, block %llu, %u blocks", |
---|
| 2502 | + zone->id, (unsigned long long)chunk_block, |
---|
2037 | 2503 | nr_blocks); |
---|
2038 | 2504 | |
---|
2039 | 2505 | WARN_ON(chunk_block + nr_blocks > zone_nr_blocks); |
---|
.. | .. |
---|
2062 | 2528 | if (likely(zone->weight + n <= zone_nr_blocks)) |
---|
2063 | 2529 | zone->weight += n; |
---|
2064 | 2530 | else { |
---|
2065 | | - dmz_dev_warn(zmd->dev, "Zone %u: weight %u should be <= %u", |
---|
2066 | | - dmz_id(zmd, zone), zone->weight, |
---|
| 2531 | + dmz_zmd_warn(zmd, "Zone %u: weight %u should be <= %u", |
---|
| 2532 | + zone->id, zone->weight, |
---|
2067 | 2533 | zone_nr_blocks - n); |
---|
2068 | 2534 | zone->weight = zone_nr_blocks; |
---|
2069 | 2535 | } |
---|
.. | .. |
---|
2112 | 2578 | struct dmz_mblock *mblk; |
---|
2113 | 2579 | unsigned int n = 0; |
---|
2114 | 2580 | |
---|
2115 | | - dmz_dev_debug(zmd->dev, "=> INVALIDATE zone %u, block %llu, %u blocks", |
---|
2116 | | - dmz_id(zmd, zone), (u64)chunk_block, nr_blocks); |
---|
| 2581 | + dmz_zmd_debug(zmd, "=> INVALIDATE zone %u, block %llu, %u blocks", |
---|
| 2582 | + zone->id, (u64)chunk_block, nr_blocks); |
---|
2117 | 2583 | |
---|
2118 | | - WARN_ON(chunk_block + nr_blocks > zmd->dev->zone_nr_blocks); |
---|
| 2584 | + WARN_ON(chunk_block + nr_blocks > zmd->zone_nr_blocks); |
---|
2119 | 2585 | |
---|
2120 | 2586 | while (nr_blocks) { |
---|
2121 | 2587 | /* Get bitmap block */ |
---|
.. | .. |
---|
2142 | 2608 | if (zone->weight >= n) |
---|
2143 | 2609 | zone->weight -= n; |
---|
2144 | 2610 | else { |
---|
2145 | | - dmz_dev_warn(zmd->dev, "Zone %u: weight %u should be >= %u", |
---|
2146 | | - dmz_id(zmd, zone), zone->weight, n); |
---|
| 2611 | + dmz_zmd_warn(zmd, "Zone %u: weight %u should be >= %u", |
---|
| 2612 | + zone->id, zone->weight, n); |
---|
2147 | 2613 | zone->weight = 0; |
---|
2148 | 2614 | } |
---|
2149 | 2615 | |
---|
.. | .. |
---|
2159 | 2625 | struct dmz_mblock *mblk; |
---|
2160 | 2626 | int ret; |
---|
2161 | 2627 | |
---|
2162 | | - WARN_ON(chunk_block >= zmd->dev->zone_nr_blocks); |
---|
| 2628 | + WARN_ON(chunk_block >= zmd->zone_nr_blocks); |
---|
2163 | 2629 | |
---|
2164 | 2630 | /* Get bitmap block */ |
---|
2165 | 2631 | mblk = dmz_get_bitmap(zmd, zone, chunk_block); |
---|
.. | .. |
---|
2189 | 2655 | unsigned long *bitmap; |
---|
2190 | 2656 | int n = 0; |
---|
2191 | 2657 | |
---|
2192 | | - WARN_ON(chunk_block + nr_blocks > zmd->dev->zone_nr_blocks); |
---|
| 2658 | + WARN_ON(chunk_block + nr_blocks > zmd->zone_nr_blocks); |
---|
2193 | 2659 | |
---|
2194 | 2660 | while (nr_blocks) { |
---|
2195 | 2661 | /* Get bitmap block */ |
---|
.. | .. |
---|
2233 | 2699 | |
---|
2234 | 2700 | /* The block is valid: get the number of valid blocks from block */ |
---|
2235 | 2701 | return dmz_to_next_set_block(zmd, zone, chunk_block, |
---|
2236 | | - zmd->dev->zone_nr_blocks - chunk_block, 0); |
---|
| 2702 | + zmd->zone_nr_blocks - chunk_block, 0); |
---|
2237 | 2703 | } |
---|
2238 | 2704 | |
---|
2239 | 2705 | /* |
---|
.. | .. |
---|
2249 | 2715 | int ret; |
---|
2250 | 2716 | |
---|
2251 | 2717 | ret = dmz_to_next_set_block(zmd, zone, start_block, |
---|
2252 | | - zmd->dev->zone_nr_blocks - start_block, 1); |
---|
| 2718 | + zmd->zone_nr_blocks - start_block, 1); |
---|
2253 | 2719 | if (ret < 0) |
---|
2254 | 2720 | return ret; |
---|
2255 | 2721 | |
---|
.. | .. |
---|
2257 | 2723 | *chunk_block = start_block; |
---|
2258 | 2724 | |
---|
2259 | 2725 | return dmz_to_next_set_block(zmd, zone, start_block, |
---|
2260 | | - zmd->dev->zone_nr_blocks - start_block, 0); |
---|
| 2726 | + zmd->zone_nr_blocks - start_block, 0); |
---|
2261 | 2727 | } |
---|
2262 | 2728 | |
---|
2263 | 2729 | /* |
---|
.. | .. |
---|
2296 | 2762 | struct dmz_mblock *mblk; |
---|
2297 | 2763 | sector_t chunk_block = 0; |
---|
2298 | 2764 | unsigned int bit, nr_bits; |
---|
2299 | | - unsigned int nr_blocks = zmd->dev->zone_nr_blocks; |
---|
| 2765 | + unsigned int nr_blocks = zmd->zone_nr_blocks; |
---|
2300 | 2766 | void *bitmap; |
---|
2301 | 2767 | int n = 0; |
---|
2302 | 2768 | |
---|
.. | .. |
---|
2352 | 2818 | while (!list_empty(&zmd->mblk_dirty_list)) { |
---|
2353 | 2819 | mblk = list_first_entry(&zmd->mblk_dirty_list, |
---|
2354 | 2820 | struct dmz_mblock, link); |
---|
2355 | | - dmz_dev_warn(zmd->dev, "mblock %llu still in dirty list (ref %u)", |
---|
| 2821 | + dmz_zmd_warn(zmd, "mblock %llu still in dirty list (ref %u)", |
---|
2356 | 2822 | (u64)mblk->no, mblk->ref); |
---|
2357 | 2823 | list_del_init(&mblk->link); |
---|
2358 | 2824 | rb_erase(&mblk->node, &zmd->mblk_rbtree); |
---|
.. | .. |
---|
2370 | 2836 | /* Sanity checks: the mblock rbtree should now be empty */ |
---|
2371 | 2837 | root = &zmd->mblk_rbtree; |
---|
2372 | 2838 | rbtree_postorder_for_each_entry_safe(mblk, next, root, node) { |
---|
2373 | | - dmz_dev_warn(zmd->dev, "mblock %llu ref %u still in rbtree", |
---|
| 2839 | + dmz_zmd_warn(zmd, "mblock %llu ref %u still in rbtree", |
---|
2374 | 2840 | (u64)mblk->no, mblk->ref); |
---|
2375 | 2841 | mblk->ref = 0; |
---|
2376 | 2842 | dmz_free_mblock(zmd, mblk); |
---|
.. | .. |
---|
2383 | 2849 | mutex_destroy(&zmd->map_lock); |
---|
2384 | 2850 | } |
---|
2385 | 2851 | |
---|
| 2852 | +static void dmz_print_dev(struct dmz_metadata *zmd, int num) |
---|
| 2853 | +{ |
---|
| 2854 | + struct dmz_dev *dev = &zmd->dev[num]; |
---|
| 2855 | + |
---|
| 2856 | + if (bdev_zoned_model(dev->bdev) == BLK_ZONED_NONE) |
---|
| 2857 | + dmz_dev_info(dev, "Regular block device"); |
---|
| 2858 | + else |
---|
| 2859 | + dmz_dev_info(dev, "Host-%s zoned block device", |
---|
| 2860 | + bdev_zoned_model(dev->bdev) == BLK_ZONED_HA ? |
---|
| 2861 | + "aware" : "managed"); |
---|
| 2862 | + if (zmd->sb_version > 1) { |
---|
| 2863 | + sector_t sector_offset = |
---|
| 2864 | + dev->zone_offset << zmd->zone_nr_sectors_shift; |
---|
| 2865 | + |
---|
| 2866 | + dmz_dev_info(dev, " %llu 512-byte logical sectors (offset %llu)", |
---|
| 2867 | + (u64)dev->capacity, (u64)sector_offset); |
---|
| 2868 | + dmz_dev_info(dev, " %u zones of %llu 512-byte logical sectors (offset %llu)", |
---|
| 2869 | + dev->nr_zones, (u64)zmd->zone_nr_sectors, |
---|
| 2870 | + (u64)dev->zone_offset); |
---|
| 2871 | + } else { |
---|
| 2872 | + dmz_dev_info(dev, " %llu 512-byte logical sectors", |
---|
| 2873 | + (u64)dev->capacity); |
---|
| 2874 | + dmz_dev_info(dev, " %u zones of %llu 512-byte logical sectors", |
---|
| 2875 | + dev->nr_zones, (u64)zmd->zone_nr_sectors); |
---|
| 2876 | + } |
---|
| 2877 | +} |
---|
| 2878 | + |
---|
2386 | 2879 | /* |
---|
2387 | 2880 | * Initialize the zoned metadata. |
---|
2388 | 2881 | */ |
---|
2389 | | -int dmz_ctr_metadata(struct dmz_dev *dev, struct dmz_metadata **metadata) |
---|
| 2882 | +int dmz_ctr_metadata(struct dmz_dev *dev, int num_dev, |
---|
| 2883 | + struct dmz_metadata **metadata, |
---|
| 2884 | + const char *devname) |
---|
2390 | 2885 | { |
---|
2391 | 2886 | struct dmz_metadata *zmd; |
---|
2392 | | - unsigned int i, zid; |
---|
| 2887 | + unsigned int i; |
---|
2393 | 2888 | struct dm_zone *zone; |
---|
2394 | 2889 | int ret; |
---|
2395 | 2890 | |
---|
.. | .. |
---|
2397 | 2892 | if (!zmd) |
---|
2398 | 2893 | return -ENOMEM; |
---|
2399 | 2894 | |
---|
| 2895 | + strcpy(zmd->devname, devname); |
---|
2400 | 2896 | zmd->dev = dev; |
---|
| 2897 | + zmd->nr_devs = num_dev; |
---|
2401 | 2898 | zmd->mblk_rbtree = RB_ROOT; |
---|
2402 | 2899 | init_rwsem(&zmd->mblk_sem); |
---|
2403 | 2900 | mutex_init(&zmd->mblk_flush_lock); |
---|
.. | .. |
---|
2406 | 2903 | INIT_LIST_HEAD(&zmd->mblk_dirty_list); |
---|
2407 | 2904 | |
---|
2408 | 2905 | mutex_init(&zmd->map_lock); |
---|
2409 | | - atomic_set(&zmd->unmap_nr_rnd, 0); |
---|
2410 | | - INIT_LIST_HEAD(&zmd->unmap_rnd_list); |
---|
2411 | | - INIT_LIST_HEAD(&zmd->map_rnd_list); |
---|
2412 | 2906 | |
---|
2413 | | - atomic_set(&zmd->unmap_nr_seq, 0); |
---|
2414 | | - INIT_LIST_HEAD(&zmd->unmap_seq_list); |
---|
2415 | | - INIT_LIST_HEAD(&zmd->map_seq_list); |
---|
| 2907 | + atomic_set(&zmd->unmap_nr_cache, 0); |
---|
| 2908 | + INIT_LIST_HEAD(&zmd->unmap_cache_list); |
---|
| 2909 | + INIT_LIST_HEAD(&zmd->map_cache_list); |
---|
2416 | 2910 | |
---|
2417 | 2911 | atomic_set(&zmd->nr_reserved_seq_zones, 0); |
---|
2418 | 2912 | INIT_LIST_HEAD(&zmd->reserved_seq_zones_list); |
---|
.. | .. |
---|
2430 | 2924 | goto err; |
---|
2431 | 2925 | |
---|
2432 | 2926 | /* Set metadata zones starting from sb_zone */ |
---|
2433 | | - zid = dmz_id(zmd, zmd->sb_zone); |
---|
2434 | 2927 | for (i = 0; i < zmd->nr_meta_zones << 1; i++) { |
---|
2435 | | - zone = dmz_get(zmd, zid + i); |
---|
2436 | | - if (!dmz_is_rnd(zone)) |
---|
| 2928 | + zone = dmz_get(zmd, zmd->sb[0].zone->id + i); |
---|
| 2929 | + if (!zone) { |
---|
| 2930 | + dmz_zmd_err(zmd, |
---|
| 2931 | + "metadata zone %u not present", i); |
---|
| 2932 | + ret = -ENXIO; |
---|
2437 | 2933 | goto err; |
---|
| 2934 | + } |
---|
| 2935 | + if (!dmz_is_rnd(zone) && !dmz_is_cache(zone)) { |
---|
| 2936 | + dmz_zmd_err(zmd, |
---|
| 2937 | + "metadata zone %d is not random", i); |
---|
| 2938 | + ret = -ENXIO; |
---|
| 2939 | + goto err; |
---|
| 2940 | + } |
---|
2438 | 2941 | set_bit(DMZ_META, &zone->flags); |
---|
2439 | 2942 | } |
---|
2440 | | - |
---|
2441 | 2943 | /* Load mapping table */ |
---|
2442 | 2944 | ret = dmz_load_mapping(zmd); |
---|
2443 | 2945 | if (ret) |
---|
.. | .. |
---|
2458 | 2960 | /* Metadata cache shrinker */ |
---|
2459 | 2961 | ret = register_shrinker(&zmd->mblk_shrinker); |
---|
2460 | 2962 | if (ret) { |
---|
2461 | | - dmz_dev_err(dev, "Register metadata cache shrinker failed"); |
---|
| 2963 | + dmz_zmd_err(zmd, "Register metadata cache shrinker failed"); |
---|
2462 | 2964 | goto err; |
---|
2463 | 2965 | } |
---|
2464 | 2966 | |
---|
2465 | | - dmz_dev_info(dev, "Host-%s zoned block device", |
---|
2466 | | - bdev_zoned_model(dev->bdev) == BLK_ZONED_HA ? |
---|
2467 | | - "aware" : "managed"); |
---|
2468 | | - dmz_dev_info(dev, " %llu 512-byte logical sectors", |
---|
2469 | | - (u64)dev->capacity); |
---|
2470 | | - dmz_dev_info(dev, " %u zones of %llu 512-byte logical sectors", |
---|
2471 | | - dev->nr_zones, (u64)dev->zone_nr_sectors); |
---|
2472 | | - dmz_dev_info(dev, " %u metadata zones", |
---|
2473 | | - zmd->nr_meta_zones * 2); |
---|
2474 | | - dmz_dev_info(dev, " %u data zones for %u chunks", |
---|
2475 | | - zmd->nr_data_zones, zmd->nr_chunks); |
---|
2476 | | - dmz_dev_info(dev, " %u random zones (%u unmapped)", |
---|
2477 | | - zmd->nr_rnd, atomic_read(&zmd->unmap_nr_rnd)); |
---|
2478 | | - dmz_dev_info(dev, " %u sequential zones (%u unmapped)", |
---|
2479 | | - zmd->nr_seq, atomic_read(&zmd->unmap_nr_seq)); |
---|
2480 | | - dmz_dev_info(dev, " %u reserved sequential data zones", |
---|
2481 | | - zmd->nr_reserved_seq); |
---|
| 2967 | + dmz_zmd_info(zmd, "DM-Zoned metadata version %d", zmd->sb_version); |
---|
| 2968 | + for (i = 0; i < zmd->nr_devs; i++) |
---|
| 2969 | + dmz_print_dev(zmd, i); |
---|
2482 | 2970 | |
---|
2483 | | - dmz_dev_debug(dev, "Format:"); |
---|
2484 | | - dmz_dev_debug(dev, "%u metadata blocks per set (%u max cache)", |
---|
| 2971 | + dmz_zmd_info(zmd, " %u zones of %llu 512-byte logical sectors", |
---|
| 2972 | + zmd->nr_zones, (u64)zmd->zone_nr_sectors); |
---|
| 2973 | + dmz_zmd_debug(zmd, " %u metadata zones", |
---|
| 2974 | + zmd->nr_meta_zones * 2); |
---|
| 2975 | + dmz_zmd_debug(zmd, " %u data zones for %u chunks", |
---|
| 2976 | + zmd->nr_data_zones, zmd->nr_chunks); |
---|
| 2977 | + dmz_zmd_debug(zmd, " %u cache zones (%u unmapped)", |
---|
| 2978 | + zmd->nr_cache, atomic_read(&zmd->unmap_nr_cache)); |
---|
| 2979 | + for (i = 0; i < zmd->nr_devs; i++) { |
---|
| 2980 | + dmz_zmd_debug(zmd, " %u random zones (%u unmapped)", |
---|
| 2981 | + dmz_nr_rnd_zones(zmd, i), |
---|
| 2982 | + dmz_nr_unmap_rnd_zones(zmd, i)); |
---|
| 2983 | + dmz_zmd_debug(zmd, " %u sequential zones (%u unmapped)", |
---|
| 2984 | + dmz_nr_seq_zones(zmd, i), |
---|
| 2985 | + dmz_nr_unmap_seq_zones(zmd, i)); |
---|
| 2986 | + } |
---|
| 2987 | + dmz_zmd_debug(zmd, " %u reserved sequential data zones", |
---|
| 2988 | + zmd->nr_reserved_seq); |
---|
| 2989 | + dmz_zmd_debug(zmd, "Format:"); |
---|
| 2990 | + dmz_zmd_debug(zmd, "%u metadata blocks per set (%u max cache)", |
---|
2485 | 2991 | zmd->nr_meta_blocks, zmd->max_nr_mblks); |
---|
2486 | | - dmz_dev_debug(dev, " %u data zone mapping blocks", |
---|
| 2992 | + dmz_zmd_debug(zmd, " %u data zone mapping blocks", |
---|
2487 | 2993 | zmd->nr_map_blocks); |
---|
2488 | | - dmz_dev_debug(dev, " %u bitmap blocks", |
---|
| 2994 | + dmz_zmd_debug(zmd, " %u bitmap blocks", |
---|
2489 | 2995 | zmd->nr_bitmap_blocks); |
---|
2490 | 2996 | |
---|
2491 | 2997 | *metadata = zmd; |
---|
.. | .. |
---|
2514 | 3020 | */ |
---|
2515 | 3021 | int dmz_resume_metadata(struct dmz_metadata *zmd) |
---|
2516 | 3022 | { |
---|
2517 | | - struct dmz_dev *dev = zmd->dev; |
---|
2518 | 3023 | struct dm_zone *zone; |
---|
2519 | 3024 | sector_t wp_block; |
---|
2520 | 3025 | unsigned int i; |
---|
2521 | 3026 | int ret; |
---|
2522 | 3027 | |
---|
2523 | 3028 | /* Check zones */ |
---|
2524 | | - for (i = 0; i < dev->nr_zones; i++) { |
---|
| 3029 | + for (i = 0; i < zmd->nr_zones; i++) { |
---|
2525 | 3030 | zone = dmz_get(zmd, i); |
---|
2526 | 3031 | if (!zone) { |
---|
2527 | | - dmz_dev_err(dev, "Unable to get zone %u", i); |
---|
| 3032 | + dmz_zmd_err(zmd, "Unable to get zone %u", i); |
---|
2528 | 3033 | return -EIO; |
---|
2529 | 3034 | } |
---|
2530 | | - |
---|
2531 | 3035 | wp_block = zone->wp_block; |
---|
2532 | 3036 | |
---|
2533 | 3037 | ret = dmz_update_zone(zmd, zone); |
---|
2534 | 3038 | if (ret) { |
---|
2535 | | - dmz_dev_err(dev, "Broken zone %u", i); |
---|
| 3039 | + dmz_zmd_err(zmd, "Broken zone %u", i); |
---|
2536 | 3040 | return ret; |
---|
2537 | 3041 | } |
---|
2538 | 3042 | |
---|
2539 | 3043 | if (dmz_is_offline(zone)) { |
---|
2540 | | - dmz_dev_warn(dev, "Zone %u is offline", i); |
---|
| 3044 | + dmz_zmd_warn(zmd, "Zone %u is offline", i); |
---|
2541 | 3045 | continue; |
---|
2542 | 3046 | } |
---|
2543 | 3047 | |
---|
.. | .. |
---|
2545 | 3049 | if (!dmz_is_seq(zone)) |
---|
2546 | 3050 | zone->wp_block = 0; |
---|
2547 | 3051 | else if (zone->wp_block != wp_block) { |
---|
2548 | | - dmz_dev_err(dev, "Zone %u: Invalid wp (%llu / %llu)", |
---|
| 3052 | + dmz_zmd_err(zmd, "Zone %u: Invalid wp (%llu / %llu)", |
---|
2549 | 3053 | i, (u64)zone->wp_block, (u64)wp_block); |
---|
2550 | 3054 | zone->wp_block = wp_block; |
---|
2551 | 3055 | dmz_invalidate_blocks(zmd, zone, zone->wp_block, |
---|
2552 | | - dev->zone_nr_blocks - zone->wp_block); |
---|
| 3056 | + zmd->zone_nr_blocks - zone->wp_block); |
---|
2553 | 3057 | } |
---|
2554 | 3058 | } |
---|
2555 | 3059 | |
---|