linux/drivers/md/dm-zoned.h
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2017 Western Digital Corporation or its affiliates.
   3 *
   4 * This file is released under the GPL.
   5 */
   6
   7#ifndef DM_ZONED_H
   8#define DM_ZONED_H
   9
  10#include <linux/types.h>
  11#include <linux/blkdev.h>
  12#include <linux/device-mapper.h>
  13#include <linux/dm-kcopyd.h>
  14#include <linux/list.h>
  15#include <linux/spinlock.h>
  16#include <linux/mutex.h>
  17#include <linux/workqueue.h>
  18#include <linux/rwsem.h>
  19#include <linux/rbtree.h>
  20#include <linux/radix-tree.h>
  21#include <linux/shrinker.h>
  22
  23/*
  24 * dm-zoned creates block devices with 4KB blocks, always.
  25 */
  26#define DMZ_BLOCK_SHIFT         12
  27#define DMZ_BLOCK_SIZE          (1 << DMZ_BLOCK_SHIFT)
  28#define DMZ_BLOCK_MASK          (DMZ_BLOCK_SIZE - 1)
  29
  30#define DMZ_BLOCK_SHIFT_BITS    (DMZ_BLOCK_SHIFT + 3)
  31#define DMZ_BLOCK_SIZE_BITS     (1 << DMZ_BLOCK_SHIFT_BITS)
  32#define DMZ_BLOCK_MASK_BITS     (DMZ_BLOCK_SIZE_BITS - 1)
  33
  34#define DMZ_BLOCK_SECTORS_SHIFT (DMZ_BLOCK_SHIFT - SECTOR_SHIFT)
  35#define DMZ_BLOCK_SECTORS       (DMZ_BLOCK_SIZE >> SECTOR_SHIFT)
  36#define DMZ_BLOCK_SECTORS_MASK  (DMZ_BLOCK_SECTORS - 1)
  37
  38/*
  39 * 4KB block <-> 512B sector conversion.
  40 */
  41#define dmz_blk2sect(b)         ((sector_t)(b) << DMZ_BLOCK_SECTORS_SHIFT)
  42#define dmz_sect2blk(s)         ((sector_t)(s) >> DMZ_BLOCK_SECTORS_SHIFT)
  43
  44#define dmz_bio_block(bio)      dmz_sect2blk((bio)->bi_iter.bi_sector)
  45#define dmz_bio_blocks(bio)     dmz_sect2blk(bio_sectors(bio))
  46
  47/*
  48 * Zoned block device information.
  49 */
  50struct dmz_dev {
  51        struct block_device     *bdev;
  52
  53        char                    name[BDEVNAME_SIZE];
  54
  55        sector_t                capacity;
  56
  57        unsigned int            nr_zones;
  58
  59        sector_t                zone_nr_sectors;
  60        unsigned int            zone_nr_sectors_shift;
  61
  62        sector_t                zone_nr_blocks;
  63        sector_t                zone_nr_blocks_shift;
  64};
  65
  66#define dmz_bio_chunk(dev, bio) ((bio)->bi_iter.bi_sector >> \
  67                                 (dev)->zone_nr_sectors_shift)
  68#define dmz_chunk_block(dev, b) ((b) & ((dev)->zone_nr_blocks - 1))
  69
  70/*
  71 * Zone descriptor.
  72 */
  73struct dm_zone {
  74        /* For listing the zone depending on its state */
  75        struct list_head        link;
  76
  77        /* Zone type and state */
  78        unsigned long           flags;
  79
  80        /* Zone activation reference count */
  81        atomic_t                refcount;
  82
  83        /* Zone write pointer block (relative to the zone start block) */
  84        unsigned int            wp_block;
  85
  86        /* Zone weight (number of valid blocks in the zone) */
  87        unsigned int            weight;
  88
  89        /* The chunk that the zone maps */
  90        unsigned int            chunk;
  91
  92        /*
  93         * For a sequential data zone, pointer to the random zone
  94         * used as a buffer for processing unaligned writes.
  95         * For a buffer zone, this points back to the data zone.
  96         */
  97        struct dm_zone          *bzone;
  98};
  99
 100/*
 101 * Zone flags.
 102 */
 103enum {
 104        /* Zone write type */
 105        DMZ_RND,
 106        DMZ_SEQ,
 107
 108        /* Zone critical condition */
 109        DMZ_OFFLINE,
 110        DMZ_READ_ONLY,
 111
 112        /* How the zone is being used */
 113        DMZ_META,
 114        DMZ_DATA,
 115        DMZ_BUF,
 116
 117        /* Zone internal state */
 118        DMZ_ACTIVE,
 119        DMZ_RECLAIM,
 120        DMZ_SEQ_WRITE_ERR,
 121};
 122
 123/*
 124 * Zone data accessors.
 125 */
 126#define dmz_is_rnd(z)           test_bit(DMZ_RND, &(z)->flags)
 127#define dmz_is_seq(z)           test_bit(DMZ_SEQ, &(z)->flags)
 128#define dmz_is_empty(z)         ((z)->wp_block == 0)
 129#define dmz_is_offline(z)       test_bit(DMZ_OFFLINE, &(z)->flags)
 130#define dmz_is_readonly(z)      test_bit(DMZ_READ_ONLY, &(z)->flags)
 131#define dmz_is_active(z)        test_bit(DMZ_ACTIVE, &(z)->flags)
 132#define dmz_in_reclaim(z)       test_bit(DMZ_RECLAIM, &(z)->flags)
 133#define dmz_seq_write_err(z)    test_bit(DMZ_SEQ_WRITE_ERR, &(z)->flags)
 134
 135#define dmz_is_meta(z)          test_bit(DMZ_META, &(z)->flags)
 136#define dmz_is_buf(z)           test_bit(DMZ_BUF, &(z)->flags)
 137#define dmz_is_data(z)          test_bit(DMZ_DATA, &(z)->flags)
 138
 139#define dmz_weight(z)           ((z)->weight)
 140
 141/*
 142 * Message functions.
 143 */
 144#define dmz_dev_info(dev, format, args...)      \
 145        DMINFO("(%s): " format, (dev)->name, ## args)
 146
 147#define dmz_dev_err(dev, format, args...)       \
 148        DMERR("(%s): " format, (dev)->name, ## args)
 149
 150#define dmz_dev_warn(dev, format, args...)      \
 151        DMWARN("(%s): " format, (dev)->name, ## args)
 152
 153#define dmz_dev_debug(dev, format, args...)     \
 154        DMDEBUG("(%s): " format, (dev)->name, ## args)
 155
 156struct dmz_metadata;
 157struct dmz_reclaim;
 158
 159/*
 160 * Functions defined in dm-zoned-metadata.c
 161 */
 162int dmz_ctr_metadata(struct dmz_dev *dev, struct dmz_metadata **zmd);
 163void dmz_dtr_metadata(struct dmz_metadata *zmd);
 164int dmz_resume_metadata(struct dmz_metadata *zmd);
 165
 166void dmz_lock_map(struct dmz_metadata *zmd);
 167void dmz_unlock_map(struct dmz_metadata *zmd);
 168void dmz_lock_metadata(struct dmz_metadata *zmd);
 169void dmz_unlock_metadata(struct dmz_metadata *zmd);
 170void dmz_lock_flush(struct dmz_metadata *zmd);
 171void dmz_unlock_flush(struct dmz_metadata *zmd);
 172int dmz_flush_metadata(struct dmz_metadata *zmd);
 173
 174unsigned int dmz_id(struct dmz_metadata *zmd, struct dm_zone *zone);
 175sector_t dmz_start_sect(struct dmz_metadata *zmd, struct dm_zone *zone);
 176sector_t dmz_start_block(struct dmz_metadata *zmd, struct dm_zone *zone);
 177unsigned int dmz_nr_chunks(struct dmz_metadata *zmd);
 178
 179#define DMZ_ALLOC_RND           0x01
 180#define DMZ_ALLOC_RECLAIM       0x02
 181
 182struct dm_zone *dmz_alloc_zone(struct dmz_metadata *zmd, unsigned long flags);
 183void dmz_free_zone(struct dmz_metadata *zmd, struct dm_zone *zone);
 184
 185void dmz_map_zone(struct dmz_metadata *zmd, struct dm_zone *zone,
 186                  unsigned int chunk);
 187void dmz_unmap_zone(struct dmz_metadata *zmd, struct dm_zone *zone);
 188unsigned int dmz_nr_rnd_zones(struct dmz_metadata *zmd);
 189unsigned int dmz_nr_unmap_rnd_zones(struct dmz_metadata *zmd);
 190
 191void dmz_activate_zone(struct dm_zone *zone);
 192void dmz_deactivate_zone(struct dm_zone *zone);
 193
 194int dmz_lock_zone_reclaim(struct dm_zone *zone);
 195void dmz_unlock_zone_reclaim(struct dm_zone *zone);
 196struct dm_zone *dmz_get_zone_for_reclaim(struct dmz_metadata *zmd);
 197
 198struct dm_zone *dmz_get_chunk_mapping(struct dmz_metadata *zmd,
 199                                      unsigned int chunk, int op);
 200void dmz_put_chunk_mapping(struct dmz_metadata *zmd, struct dm_zone *zone);
 201struct dm_zone *dmz_get_chunk_buffer(struct dmz_metadata *zmd,
 202                                     struct dm_zone *dzone);
 203
 204int dmz_validate_blocks(struct dmz_metadata *zmd, struct dm_zone *zone,
 205                        sector_t chunk_block, unsigned int nr_blocks);
 206int dmz_invalidate_blocks(struct dmz_metadata *zmd, struct dm_zone *zone,
 207                          sector_t chunk_block, unsigned int nr_blocks);
 208int dmz_block_valid(struct dmz_metadata *zmd, struct dm_zone *zone,
 209                    sector_t chunk_block);
 210int dmz_first_valid_block(struct dmz_metadata *zmd, struct dm_zone *zone,
 211                          sector_t *chunk_block);
 212int dmz_copy_valid_blocks(struct dmz_metadata *zmd, struct dm_zone *from_zone,
 213                          struct dm_zone *to_zone);
 214int dmz_merge_valid_blocks(struct dmz_metadata *zmd, struct dm_zone *from_zone,
 215                           struct dm_zone *to_zone, sector_t chunk_block);
 216
 217/*
 218 * Functions defined in dm-zoned-reclaim.c
 219 */
 220int dmz_ctr_reclaim(struct dmz_dev *dev, struct dmz_metadata *zmd,
 221                    struct dmz_reclaim **zrc);
 222void dmz_dtr_reclaim(struct dmz_reclaim *zrc);
 223void dmz_suspend_reclaim(struct dmz_reclaim *zrc);
 224void dmz_resume_reclaim(struct dmz_reclaim *zrc);
 225void dmz_reclaim_bio_acc(struct dmz_reclaim *zrc);
 226void dmz_schedule_reclaim(struct dmz_reclaim *zrc);
 227
 228#endif /* DM_ZONED_H */
 229