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 11 struct 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 26 int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos, 27 struct blk_zone *zone); 28 int btrfs_get_dev_zone_info(struct btrfs_device *device); 29 void btrfs_destroy_dev_zone_info(struct btrfs_device *device); 30 int btrfs_check_zoned_mode(struct btrfs_fs_info *fs_info); 31 int btrfs_check_mountopts_zoned(struct btrfs_fs_info *info); 32 int btrfs_sb_log_location_bdev(struct block_device *bdev, int mirror, int rw, 33 u64 *bytenr_ret); 34 int btrfs_sb_log_location(struct btrfs_device *device, int mirror, int rw, 35 u64 *bytenr_ret); 36 void btrfs_advance_sb_log(struct btrfs_device *device, int mirror); 37 int btrfs_reset_sb_log_zones(struct block_device *bdev, int mirror); 38 #else /* CONFIG_BLK_DEV_ZONED */ 39 static inline int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos, 40 struct blk_zone *zone) 41 { 42 return 0; 43 } 44 45 static inline int btrfs_get_dev_zone_info(struct btrfs_device *device) 46 { 47 return 0; 48 } 49 50 static inline void btrfs_destroy_dev_zone_info(struct btrfs_device *device) { } 51 52 static 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 61 static inline int btrfs_check_mountopts_zoned(struct btrfs_fs_info *info) 62 { 63 return 0; 64 } 65 66 static 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 73 static 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 80 static inline void btrfs_advance_sb_log(struct btrfs_device *device, int mirror) 81 { } 82 83 static inline int btrfs_reset_sb_log_zones(struct block_device *bdev, int mirror) 84 { 85 return 0; 86 } 87 88 #endif 89 90 static 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 100 static 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 110 static 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 126 static 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 131 static 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 136 static 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 151 static 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