linux/drivers/md/dm-zoned.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * Copyright (C) 2017 Western Digital Corporation or its affiliates.
   4 *
   5 * This file is released under the GPL.
   6 */
   7
   8#ifndef DM_ZONED_H
   9#define DM_ZONED_H
  10
  11#include <linux/types.h>
  12#include <linux/blkdev.h>
  13#include <linux/device-mapper.h>
  14#include <linux/dm-kcopyd.h>
  15#include <linux/list.h>
  16#include <linux/spinlock.h>
  17#include <linux/mutex.h>
  18#include <linux/workqueue.h>
  19#include <linux/rwsem.h>
  20#include <linux/rbtree.h>
  21#include <linux/radix-tree.h>
  22#include <linux/shrinker.h>
  23
  24/*
  25 * dm-zoned creates block devices with 4KB blocks, always.
  26 */
  27#define DMZ_BLOCK_SHIFT         12
  28#define DMZ_BLOCK_SIZE          (1 << DMZ_BLOCK_SHIFT)
  29#define DMZ_BLOCK_MASK          (DMZ_BLOCK_SIZE - 1)
  30
  31#define DMZ_BLOCK_SHIFT_BITS    (DMZ_BLOCK_SHIFT + 3)
  32#define DMZ_BLOCK_SIZE_BITS     (1 << DMZ_BLOCK_SHIFT_BITS)
  33#define DMZ_BLOCK_MASK_BITS     (DMZ_BLOCK_SIZE_BITS - 1)
  34
  35#define DMZ_BLOCK_SECTORS_SHIFT (DMZ_BLOCK_SHIFT - SECTOR_SHIFT)
  36#define DMZ_BLOCK_SECTORS       (DMZ_BLOCK_SIZE >> SECTOR_SHIFT)
  37#define DMZ_BLOCK_SECTORS_MASK  (DMZ_BLOCK_SECTORS - 1)
  38
  39/*
  40 * 4KB block <-> 512B sector conversion.
  41 */
  42#define dmz_blk2sect(b)         ((sector_t)(b) << DMZ_BLOCK_SECTORS_SHIFT)
  43#define dmz_sect2blk(s)         ((sector_t)(s) >> DMZ_BLOCK_SECTORS_SHIFT)
  44
  45#define dmz_bio_block(bio)      dmz_sect2blk((bio)->bi_iter.bi_sector)
  46#define dmz_bio_blocks(bio)     dmz_sect2blk(bio_sectors(bio))
  47
  48struct dmz_metadata;
  49struct dmz_reclaim;
  50
  51/*
  52 * Zoned block device information.
  53 */
  54struct dmz_dev {
  55        struct block_device     *bdev;
  56        struct dmz_metadata     *metadata;
  57        struct dmz_reclaim      *reclaim;
  58
  59        char                    name[BDEVNAME_SIZE];
  60        uuid_t                  uuid;
  61
  62        sector_t                capacity;
  63
  64        unsigned int            dev_idx;
  65
  66        unsigned int            nr_zones;
  67        unsigned int            zone_offset;
  68
  69        unsigned int            flags;
  70
  71        sector_t                zone_nr_sectors;
  72
  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;
  82};
  83
  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))
  87
  88/* Device flags. */
  89#define DMZ_BDEV_DYING          (1 << 0)
  90#define DMZ_CHECK_BDEV          (2 << 0)
  91#define DMZ_BDEV_REGULAR        (4 << 0)
  92
  93/*
  94 * Zone descriptor.
  95 */
  96struct dm_zone {
  97        /* For listing the zone depending on its state */
  98        struct list_head        link;
  99
 100        /* Device containing this zone */
 101        struct dmz_dev          *dev;
 102
 103        /* Zone type and state */
 104        unsigned long           flags;
 105
 106        /* Zone activation reference count */
 107        atomic_t                refcount;
 108
 109        /* Zone id */
 110        unsigned int            id;
 111
 112        /* Zone write pointer block (relative to the zone start block) */
 113        unsigned int            wp_block;
 114
 115        /* Zone weight (number of valid blocks in the zone) */
 116        unsigned int            weight;
 117
 118        /* The chunk that the zone maps */
 119        unsigned int            chunk;
 120
 121        /*
 122         * For a sequential data zone, pointer to the random zone
 123         * used as a buffer for processing unaligned writes.
 124         * For a buffer zone, this points back to the data zone.
 125         */
 126        struct dm_zone          *bzone;
 127};
 128
 129/*
 130 * Zone flags.
 131 */
 132enum {
 133        /* Zone write type */
 134        DMZ_CACHE,
 135        DMZ_RND,
 136        DMZ_SEQ,
 137
 138        /* Zone critical condition */
 139        DMZ_OFFLINE,
 140        DMZ_READ_ONLY,
 141
 142        /* How the zone is being used */
 143        DMZ_META,
 144        DMZ_DATA,
 145        DMZ_BUF,
 146        DMZ_RESERVED,
 147
 148        /* Zone internal state */
 149        DMZ_RECLAIM,
 150        DMZ_SEQ_WRITE_ERR,
 151        DMZ_RECLAIM_TERMINATE,
 152};
 153
 154/*
 155 * Zone data accessors.
 156 */
 157#define dmz_is_cache(z)         test_bit(DMZ_CACHE, &(z)->flags)
 158#define dmz_is_rnd(z)           test_bit(DMZ_RND, &(z)->flags)
 159#define dmz_is_seq(z)           test_bit(DMZ_SEQ, &(z)->flags)
 160#define dmz_is_empty(z)         ((z)->wp_block == 0)
 161#define dmz_is_offline(z)       test_bit(DMZ_OFFLINE, &(z)->flags)
 162#define dmz_is_readonly(z)      test_bit(DMZ_READ_ONLY, &(z)->flags)
 163#define dmz_in_reclaim(z)       test_bit(DMZ_RECLAIM, &(z)->flags)
 164#define dmz_is_reserved(z)      test_bit(DMZ_RESERVED, &(z)->flags)
 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)
 168
 169#define dmz_is_meta(z)          test_bit(DMZ_META, &(z)->flags)
 170#define dmz_is_buf(z)           test_bit(DMZ_BUF, &(z)->flags)
 171#define dmz_is_data(z)          test_bit(DMZ_DATA, &(z)->flags)
 172
 173#define dmz_weight(z)           ((z)->weight)
 174
 175/*
 176 * Message functions.
 177 */
 178#define dmz_dev_info(dev, format, args...)      \
 179        DMINFO("(%s): " format, (dev)->name, ## args)
 180
 181#define dmz_dev_err(dev, format, args...)       \
 182        DMERR("(%s): " format, (dev)->name, ## args)
 183
 184#define dmz_dev_warn(dev, format, args...)      \
 185        DMWARN("(%s): " format, (dev)->name, ## args)
 186
 187#define dmz_dev_debug(dev, format, args...)     \
 188        DMDEBUG("(%s): " format, (dev)->name, ## args)
 189
 190/*
 191 * Functions defined in dm-zoned-metadata.c
 192 */
 193int dmz_ctr_metadata(struct dmz_dev *dev, int num_dev,
 194                     struct dmz_metadata **zmd, const char *devname);
 195void dmz_dtr_metadata(struct dmz_metadata *zmd);
 196int dmz_resume_metadata(struct dmz_metadata *zmd);
 197
 198void dmz_lock_map(struct dmz_metadata *zmd);
 199void dmz_unlock_map(struct dmz_metadata *zmd);
 200void dmz_lock_metadata(struct dmz_metadata *zmd);
 201void dmz_unlock_metadata(struct dmz_metadata *zmd);
 202void dmz_lock_flush(struct dmz_metadata *zmd);
 203void dmz_unlock_flush(struct dmz_metadata *zmd);
 204int dmz_flush_metadata(struct dmz_metadata *zmd);
 205const char *dmz_metadata_label(struct dmz_metadata *zmd);
 206
 207sector_t dmz_start_sect(struct dmz_metadata *zmd, struct dm_zone *zone);
 208sector_t dmz_start_block(struct dmz_metadata *zmd, struct dm_zone *zone);
 209unsigned int dmz_nr_chunks(struct dmz_metadata *zmd);
 210
 211bool dmz_check_dev(struct dmz_metadata *zmd);
 212bool dmz_dev_is_dying(struct dmz_metadata *zmd);
 213
 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
 219struct dm_zone *dmz_alloc_zone(struct dmz_metadata *zmd,
 220                               unsigned int dev_idx, unsigned long flags);
 221void dmz_free_zone(struct dmz_metadata *zmd, struct dm_zone *zone);
 222
 223void dmz_map_zone(struct dmz_metadata *zmd, struct dm_zone *zone,
 224                  unsigned int chunk);
 225void dmz_unmap_zone(struct dmz_metadata *zmd, struct dm_zone *zone);
 226unsigned int dmz_nr_zones(struct dmz_metadata *zmd);
 227unsigned int dmz_nr_cache_zones(struct dmz_metadata *zmd);
 228unsigned int dmz_nr_unmap_cache_zones(struct dmz_metadata *zmd);
 229unsigned int dmz_nr_rnd_zones(struct dmz_metadata *zmd, int idx);
 230unsigned int dmz_nr_unmap_rnd_zones(struct dmz_metadata *zmd, int idx);
 231unsigned int dmz_nr_seq_zones(struct dmz_metadata *zmd, int idx);
 232unsigned int dmz_nr_unmap_seq_zones(struct dmz_metadata *zmd, int idx);
 233unsigned int dmz_zone_nr_blocks(struct dmz_metadata *zmd);
 234unsigned int dmz_zone_nr_blocks_shift(struct dmz_metadata *zmd);
 235unsigned int dmz_zone_nr_sectors(struct dmz_metadata *zmd);
 236unsigned int dmz_zone_nr_sectors_shift(struct dmz_metadata *zmd);
 237
 238/*
 239 * Activate a zone (increment its reference count).
 240 */
 241static inline void dmz_activate_zone(struct dm_zone *zone)
 242{
 243        atomic_inc(&zone->refcount);
 244}
 245
 246int dmz_lock_zone_reclaim(struct dm_zone *zone);
 247void dmz_unlock_zone_reclaim(struct dm_zone *zone);
 248struct dm_zone *dmz_get_zone_for_reclaim(struct dmz_metadata *zmd,
 249                                         unsigned int dev_idx, bool idle);
 250
 251struct dm_zone *dmz_get_chunk_mapping(struct dmz_metadata *zmd,
 252                                      unsigned int chunk, int op);
 253void dmz_put_chunk_mapping(struct dmz_metadata *zmd, struct dm_zone *zone);
 254struct dm_zone *dmz_get_chunk_buffer(struct dmz_metadata *zmd,
 255                                     struct dm_zone *dzone);
 256
 257int dmz_validate_blocks(struct dmz_metadata *zmd, struct dm_zone *zone,
 258                        sector_t chunk_block, unsigned int nr_blocks);
 259int dmz_invalidate_blocks(struct dmz_metadata *zmd, struct dm_zone *zone,
 260                          sector_t chunk_block, unsigned int nr_blocks);
 261int dmz_block_valid(struct dmz_metadata *zmd, struct dm_zone *zone,
 262                    sector_t chunk_block);
 263int dmz_first_valid_block(struct dmz_metadata *zmd, struct dm_zone *zone,
 264                          sector_t *chunk_block);
 265int dmz_copy_valid_blocks(struct dmz_metadata *zmd, struct dm_zone *from_zone,
 266                          struct dm_zone *to_zone);
 267int dmz_merge_valid_blocks(struct dmz_metadata *zmd, struct dm_zone *from_zone,
 268                           struct dm_zone *to_zone, sector_t chunk_block);
 269
 270/*
 271 * Functions defined in dm-zoned-reclaim.c
 272 */
 273int dmz_ctr_reclaim(struct dmz_metadata *zmd, struct dmz_reclaim **zrc, int idx);
 274void dmz_dtr_reclaim(struct dmz_reclaim *zrc);
 275void dmz_suspend_reclaim(struct dmz_reclaim *zrc);
 276void dmz_resume_reclaim(struct dmz_reclaim *zrc);
 277void dmz_reclaim_bio_acc(struct dmz_reclaim *zrc);
 278void dmz_schedule_reclaim(struct dmz_reclaim *zrc);
 279
 280/*
 281 * Functions defined in dm-zoned-target.c
 282 */
 283bool dmz_bdev_is_dying(struct dmz_dev *dmz_dev);
 284bool dmz_check_bdev(struct dmz_dev *dmz_dev);
 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 */
 290static 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 */
 299static inline bool dmz_is_active(struct dm_zone *zone)
 300{
 301        return atomic_read(&zone->refcount);
 302}
 303
 304#endif /* DM_ZONED_H */
 305