linux/fs/btrfs/zoned.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2
   3#ifndef BTRFS_ZONED_H
   4#define BTRFS_ZONED_H
   5
   6#include <linux/types.h>
   7#include <linux/blkdev.h>
   8#include "volumes.h"
   9#include "disk-io.h"
  10
  11struct btrfs_zoned_device_info {
  12        /*
  13         * Number of zones, zone size and types of zones if bdev is a
  14         * zoned block device.
  15         */
  16        u64 zone_size;
  17        u8  zone_size_shift;
  18        u64 max_zone_append_size;
  19        u32 nr_zones;
  20        unsigned long *seq_zones;
  21        unsigned long *empty_zones;
  22        struct blk_zone sb_zones[2 * BTRFS_SUPER_MIRROR_MAX];
  23};
  24
  25#ifdef CONFIG_BLK_DEV_ZONED
  26int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos,
  27                       struct blk_zone *zone);
  28int btrfs_get_dev_zone_info(struct btrfs_device *device);
  29void btrfs_destroy_dev_zone_info(struct btrfs_device *device);
  30int btrfs_check_zoned_mode(struct btrfs_fs_info *fs_info);
  31int btrfs_check_mountopts_zoned(struct btrfs_fs_info *info);
  32int btrfs_sb_log_location_bdev(struct block_device *bdev, int mirror, int rw,
  33                               u64 *bytenr_ret);
  34int btrfs_sb_log_location(struct btrfs_device *device, int mirror, int rw,
  35                          u64 *bytenr_ret);
  36void btrfs_advance_sb_log(struct btrfs_device *device, int mirror);
  37int btrfs_reset_sb_log_zones(struct block_device *bdev, int mirror);
  38#else /* CONFIG_BLK_DEV_ZONED */
  39static inline int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos,
  40                                     struct blk_zone *zone)
  41{
  42        return 0;
  43}
  44
  45static inline int btrfs_get_dev_zone_info(struct btrfs_device *device)
  46{
  47        return 0;
  48}
  49
  50static inline void btrfs_destroy_dev_zone_info(struct btrfs_device *device) { }
  51
  52static inline int btrfs_check_zoned_mode(const struct btrfs_fs_info *fs_info)
  53{
  54        if (!btrfs_is_zoned(fs_info))
  55                return 0;
  56
  57        btrfs_err(fs_info, "zoned block devices support is not enabled");
  58        return -EOPNOTSUPP;
  59}
  60
  61static inline int btrfs_check_mountopts_zoned(struct btrfs_fs_info *info)
  62{
  63        return 0;
  64}
  65
  66static inline int btrfs_sb_log_location_bdev(struct block_device *bdev,
  67                                             int mirror, int rw, u64 *bytenr_ret)
  68{
  69        *bytenr_ret = btrfs_sb_offset(mirror);
  70        return 0;
  71}
  72
  73static inline int btrfs_sb_log_location(struct btrfs_device *device, int mirror,
  74                                        int rw, u64 *bytenr_ret)
  75{
  76        *bytenr_ret = btrfs_sb_offset(mirror);
  77        return 0;
  78}
  79
  80static inline void btrfs_advance_sb_log(struct btrfs_device *device, int mirror)
  81{ }
  82
  83static inline int btrfs_reset_sb_log_zones(struct block_device *bdev, int mirror)
  84{
  85        return 0;
  86}
  87
  88#endif
  89
  90static inline bool btrfs_dev_is_sequential(struct btrfs_device *device, u64 pos)
  91{
  92        struct btrfs_zoned_device_info *zone_info = device->zone_info;
  93
  94        if (!zone_info)
  95                return false;
  96
  97        return test_bit(pos >> zone_info->zone_size_shift, zone_info->seq_zones);
  98}
  99
 100static inline bool btrfs_dev_is_empty_zone(struct btrfs_device *device, u64 pos)
 101{
 102        struct btrfs_zoned_device_info *zone_info = device->zone_info;
 103
 104        if (!zone_info)
 105                return true;
 106
 107        return test_bit(pos >> zone_info->zone_size_shift, zone_info->empty_zones);
 108}
 109
 110static inline void btrfs_dev_set_empty_zone_bit(struct btrfs_device *device,
 111                                                u64 pos, bool set)
 112{
 113        struct btrfs_zoned_device_info *zone_info = device->zone_info;
 114        unsigned int zno;
 115
 116        if (!zone_info)
 117                return;
 118
 119        zno = pos >> zone_info->zone_size_shift;
 120        if (set)
 121                set_bit(zno, zone_info->empty_zones);
 122        else
 123                clear_bit(zno, zone_info->empty_zones);
 124}
 125
 126static inline void btrfs_dev_set_zone_empty(struct btrfs_device *device, u64 pos)
 127{
 128        btrfs_dev_set_empty_zone_bit(device, pos, true);
 129}
 130
 131static inline void btrfs_dev_clear_zone_empty(struct btrfs_device *device, u64 pos)
 132{
 133        btrfs_dev_set_empty_zone_bit(device, pos, false);
 134}
 135
 136static inline bool btrfs_check_device_zone_type(const struct btrfs_fs_info *fs_info,
 137                                                struct block_device *bdev)
 138{
 139        u64 zone_size;
 140
 141        if (btrfs_is_zoned(fs_info)) {
 142                zone_size = bdev_zone_sectors(bdev) << SECTOR_SHIFT;
 143                /* Do not allow non-zoned device */
 144                return bdev_is_zoned(bdev) && fs_info->zone_size == zone_size;
 145        }
 146
 147        /* Do not allow Host Manged zoned device */
 148        return bdev_zoned_model(bdev) != BLK_ZONED_HM;
 149}
 150
 151static inline bool btrfs_check_super_location(struct btrfs_device *device, u64 pos)
 152{
 153        /*
 154         * On a non-zoned device, any address is OK. On a zoned device,
 155         * non-SEQUENTIAL WRITE REQUIRED zones are capable.
 156         */
 157        return device->zone_info == NULL || !btrfs_dev_is_sequential(device, pos);
 158}
 159
 160#endif
 161