xref: /openbmc/linux/fs/btrfs/zoned.h (revision 18bb8bbf13c1839b43c9e09e76d397b753989af2)
15b316468SNaohiro Aota /* SPDX-License-Identifier: GPL-2.0 */
25b316468SNaohiro Aota 
35b316468SNaohiro Aota #ifndef BTRFS_ZONED_H
45b316468SNaohiro Aota #define BTRFS_ZONED_H
55b316468SNaohiro Aota 
65b316468SNaohiro Aota #include <linux/types.h>
7b70f5097SNaohiro Aota #include <linux/blkdev.h>
812659251SNaohiro Aota #include "volumes.h"
912659251SNaohiro Aota #include "disk-io.h"
1040ab3be1SNaohiro Aota #include "block-group.h"
115b316468SNaohiro Aota 
12*18bb8bbfSJohannes Thumshirn /*
13*18bb8bbfSJohannes Thumshirn  * Block groups with more than this value (percents) of unusable space will be
14*18bb8bbfSJohannes Thumshirn  * scheduled for background reclaim.
15*18bb8bbfSJohannes Thumshirn  */
16*18bb8bbfSJohannes Thumshirn #define BTRFS_DEFAULT_RECLAIM_THRESH		75
17*18bb8bbfSJohannes Thumshirn 
185b316468SNaohiro Aota struct btrfs_zoned_device_info {
195b316468SNaohiro Aota 	/*
205b316468SNaohiro Aota 	 * Number of zones, zone size and types of zones if bdev is a
215b316468SNaohiro Aota 	 * zoned block device.
225b316468SNaohiro Aota 	 */
235b316468SNaohiro Aota 	u64 zone_size;
245b316468SNaohiro Aota 	u8  zone_size_shift;
25862931c7SNaohiro Aota 	u64 max_zone_append_size;
265b316468SNaohiro Aota 	u32 nr_zones;
275b316468SNaohiro Aota 	unsigned long *seq_zones;
285b316468SNaohiro Aota 	unsigned long *empty_zones;
2912659251SNaohiro Aota 	struct blk_zone sb_zones[2 * BTRFS_SUPER_MIRROR_MAX];
305b316468SNaohiro Aota };
315b316468SNaohiro Aota 
325b316468SNaohiro Aota #ifdef CONFIG_BLK_DEV_ZONED
335b316468SNaohiro Aota int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos,
345b316468SNaohiro Aota 		       struct blk_zone *zone);
3573651042SNaohiro Aota int btrfs_get_dev_zone_info_all_devices(struct btrfs_fs_info *fs_info);
365b316468SNaohiro Aota int btrfs_get_dev_zone_info(struct btrfs_device *device);
375b316468SNaohiro Aota void btrfs_destroy_dev_zone_info(struct btrfs_device *device);
38b70f5097SNaohiro Aota int btrfs_check_zoned_mode(struct btrfs_fs_info *fs_info);
395d1ab66cSNaohiro Aota int btrfs_check_mountopts_zoned(struct btrfs_fs_info *info);
4012659251SNaohiro Aota int btrfs_sb_log_location_bdev(struct block_device *bdev, int mirror, int rw,
4112659251SNaohiro Aota 			       u64 *bytenr_ret);
4212659251SNaohiro Aota int btrfs_sb_log_location(struct btrfs_device *device, int mirror, int rw,
4312659251SNaohiro Aota 			  u64 *bytenr_ret);
4412659251SNaohiro Aota void btrfs_advance_sb_log(struct btrfs_device *device, int mirror);
4512659251SNaohiro Aota int btrfs_reset_sb_log_zones(struct block_device *bdev, int mirror);
461cd6121fSNaohiro Aota u64 btrfs_find_allocatable_zones(struct btrfs_device *device, u64 hole_start,
471cd6121fSNaohiro Aota 				 u64 hole_end, u64 num_bytes);
481cd6121fSNaohiro Aota int btrfs_reset_device_zone(struct btrfs_device *device, u64 physical,
491cd6121fSNaohiro Aota 			    u64 length, u64 *bytes);
501cd6121fSNaohiro Aota int btrfs_ensure_empty_zones(struct btrfs_device *device, u64 start, u64 size);
51a94794d5SNaohiro Aota int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new);
52169e0da9SNaohiro Aota void btrfs_calc_zone_unusable(struct btrfs_block_group *cache);
53d3575156SNaohiro Aota void btrfs_redirty_list_add(struct btrfs_transaction *trans,
54d3575156SNaohiro Aota 			    struct extent_buffer *eb);
55d3575156SNaohiro Aota void btrfs_free_redirty_list(struct btrfs_transaction *trans);
5608f45559SJohannes Thumshirn bool btrfs_use_zone_append(struct btrfs_inode *inode, struct extent_map *em);
57d8e3fb10SNaohiro Aota void btrfs_record_physical_zoned(struct inode *inode, u64 file_offset,
58d8e3fb10SNaohiro Aota 				 struct bio *bio);
59d8e3fb10SNaohiro Aota void btrfs_rewrite_logical_zoned(struct btrfs_ordered_extent *ordered);
600bc09ca1SNaohiro Aota bool btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
610bc09ca1SNaohiro Aota 				    struct extent_buffer *eb,
620bc09ca1SNaohiro Aota 				    struct btrfs_block_group **cache_ret);
630bc09ca1SNaohiro Aota void btrfs_revert_meta_write_pointer(struct btrfs_block_group *cache,
640bc09ca1SNaohiro Aota 				     struct extent_buffer *eb);
65de17addcSNaohiro Aota int btrfs_zoned_issue_zeroout(struct btrfs_device *device, u64 physical, u64 length);
667db1c5d1SNaohiro Aota int btrfs_sync_zone_write_pointer(struct btrfs_device *tgt_dev, u64 logical,
677db1c5d1SNaohiro Aota 				  u64 physical_start, u64 physical_pos);
685b316468SNaohiro Aota #else /* CONFIG_BLK_DEV_ZONED */
695b316468SNaohiro Aota static inline int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos,
705b316468SNaohiro Aota 				     struct blk_zone *zone)
715b316468SNaohiro Aota {
725b316468SNaohiro Aota 	return 0;
735b316468SNaohiro Aota }
745b316468SNaohiro Aota 
7573651042SNaohiro Aota static inline int btrfs_get_dev_zone_info_all_devices(struct btrfs_fs_info *fs_info)
7673651042SNaohiro Aota {
7773651042SNaohiro Aota 	return 0;
7873651042SNaohiro Aota }
7973651042SNaohiro Aota 
805b316468SNaohiro Aota static inline int btrfs_get_dev_zone_info(struct btrfs_device *device)
815b316468SNaohiro Aota {
825b316468SNaohiro Aota 	return 0;
835b316468SNaohiro Aota }
845b316468SNaohiro Aota 
855b316468SNaohiro Aota static inline void btrfs_destroy_dev_zone_info(struct btrfs_device *device) { }
865b316468SNaohiro Aota 
87b70f5097SNaohiro Aota static inline int btrfs_check_zoned_mode(const struct btrfs_fs_info *fs_info)
88b70f5097SNaohiro Aota {
89b70f5097SNaohiro Aota 	if (!btrfs_is_zoned(fs_info))
90b70f5097SNaohiro Aota 		return 0;
91b70f5097SNaohiro Aota 
92b70f5097SNaohiro Aota 	btrfs_err(fs_info, "zoned block devices support is not enabled");
93b70f5097SNaohiro Aota 	return -EOPNOTSUPP;
94b70f5097SNaohiro Aota }
95b70f5097SNaohiro Aota 
965d1ab66cSNaohiro Aota static inline int btrfs_check_mountopts_zoned(struct btrfs_fs_info *info)
975d1ab66cSNaohiro Aota {
985d1ab66cSNaohiro Aota 	return 0;
995d1ab66cSNaohiro Aota }
1005d1ab66cSNaohiro Aota 
10112659251SNaohiro Aota static inline int btrfs_sb_log_location_bdev(struct block_device *bdev,
10212659251SNaohiro Aota 					     int mirror, int rw, u64 *bytenr_ret)
10312659251SNaohiro Aota {
10412659251SNaohiro Aota 	*bytenr_ret = btrfs_sb_offset(mirror);
10512659251SNaohiro Aota 	return 0;
10612659251SNaohiro Aota }
10712659251SNaohiro Aota 
10812659251SNaohiro Aota static inline int btrfs_sb_log_location(struct btrfs_device *device, int mirror,
10912659251SNaohiro Aota 					int rw, u64 *bytenr_ret)
11012659251SNaohiro Aota {
11112659251SNaohiro Aota 	*bytenr_ret = btrfs_sb_offset(mirror);
11212659251SNaohiro Aota 	return 0;
11312659251SNaohiro Aota }
11412659251SNaohiro Aota 
11512659251SNaohiro Aota static inline void btrfs_advance_sb_log(struct btrfs_device *device, int mirror)
11612659251SNaohiro Aota { }
11712659251SNaohiro Aota 
11812659251SNaohiro Aota static inline int btrfs_reset_sb_log_zones(struct block_device *bdev, int mirror)
11912659251SNaohiro Aota {
12012659251SNaohiro Aota 	return 0;
12112659251SNaohiro Aota }
12212659251SNaohiro Aota 
1231cd6121fSNaohiro Aota static inline u64 btrfs_find_allocatable_zones(struct btrfs_device *device,
1241cd6121fSNaohiro Aota 					       u64 hole_start, u64 hole_end,
1251cd6121fSNaohiro Aota 					       u64 num_bytes)
1261cd6121fSNaohiro Aota {
1271cd6121fSNaohiro Aota 	return hole_start;
1281cd6121fSNaohiro Aota }
1291cd6121fSNaohiro Aota 
1301cd6121fSNaohiro Aota static inline int btrfs_reset_device_zone(struct btrfs_device *device,
1311cd6121fSNaohiro Aota 					  u64 physical, u64 length, u64 *bytes)
1321cd6121fSNaohiro Aota {
1331cd6121fSNaohiro Aota 	*bytes = 0;
1341cd6121fSNaohiro Aota 	return 0;
1351cd6121fSNaohiro Aota }
1361cd6121fSNaohiro Aota 
1371cd6121fSNaohiro Aota static inline int btrfs_ensure_empty_zones(struct btrfs_device *device,
1381cd6121fSNaohiro Aota 					   u64 start, u64 size)
1391cd6121fSNaohiro Aota {
1401cd6121fSNaohiro Aota 	return 0;
1411cd6121fSNaohiro Aota }
1421cd6121fSNaohiro Aota 
14308e11a3dSNaohiro Aota static inline int btrfs_load_block_group_zone_info(
144a94794d5SNaohiro Aota 		struct btrfs_block_group *cache, bool new)
14508e11a3dSNaohiro Aota {
14608e11a3dSNaohiro Aota 	return 0;
14708e11a3dSNaohiro Aota }
14808e11a3dSNaohiro Aota 
149169e0da9SNaohiro Aota static inline void btrfs_calc_zone_unusable(struct btrfs_block_group *cache) { }
150169e0da9SNaohiro Aota 
151d3575156SNaohiro Aota static inline void btrfs_redirty_list_add(struct btrfs_transaction *trans,
152d3575156SNaohiro Aota 					  struct extent_buffer *eb) { }
153d3575156SNaohiro Aota static inline void btrfs_free_redirty_list(struct btrfs_transaction *trans) { }
154d3575156SNaohiro Aota 
15508f45559SJohannes Thumshirn static inline bool btrfs_use_zone_append(struct btrfs_inode *inode,
15608f45559SJohannes Thumshirn 					 struct extent_map *em)
15708f45559SJohannes Thumshirn {
15808f45559SJohannes Thumshirn 	return false;
15908f45559SJohannes Thumshirn }
160d8e3fb10SNaohiro Aota 
161d8e3fb10SNaohiro Aota static inline void btrfs_record_physical_zoned(struct inode *inode,
162d8e3fb10SNaohiro Aota 					       u64 file_offset, struct bio *bio)
163d8e3fb10SNaohiro Aota {
164d8e3fb10SNaohiro Aota }
165d8e3fb10SNaohiro Aota 
166d8e3fb10SNaohiro Aota static inline void btrfs_rewrite_logical_zoned(
167d8e3fb10SNaohiro Aota 				struct btrfs_ordered_extent *ordered) { }
168d8e3fb10SNaohiro Aota 
1690bc09ca1SNaohiro Aota static inline bool btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
1700bc09ca1SNaohiro Aota 			       struct extent_buffer *eb,
1710bc09ca1SNaohiro Aota 			       struct btrfs_block_group **cache_ret)
1720bc09ca1SNaohiro Aota {
1730bc09ca1SNaohiro Aota 	return true;
1740bc09ca1SNaohiro Aota }
1750bc09ca1SNaohiro Aota 
1760bc09ca1SNaohiro Aota static inline void btrfs_revert_meta_write_pointer(
1770bc09ca1SNaohiro Aota 						struct btrfs_block_group *cache,
1780bc09ca1SNaohiro Aota 						struct extent_buffer *eb)
1790bc09ca1SNaohiro Aota {
1800bc09ca1SNaohiro Aota }
1810bc09ca1SNaohiro Aota 
182de17addcSNaohiro Aota static inline int btrfs_zoned_issue_zeroout(struct btrfs_device *device,
183de17addcSNaohiro Aota 					    u64 physical, u64 length)
184de17addcSNaohiro Aota {
185de17addcSNaohiro Aota 	return -EOPNOTSUPP;
186de17addcSNaohiro Aota }
187de17addcSNaohiro Aota 
1887db1c5d1SNaohiro Aota static inline int btrfs_sync_zone_write_pointer(struct btrfs_device *tgt_dev,
1897db1c5d1SNaohiro Aota 						u64 logical, u64 physical_start,
1907db1c5d1SNaohiro Aota 						u64 physical_pos)
1917db1c5d1SNaohiro Aota {
1927db1c5d1SNaohiro Aota 	return -EOPNOTSUPP;
1937db1c5d1SNaohiro Aota }
1947db1c5d1SNaohiro Aota 
1955b316468SNaohiro Aota #endif
1965b316468SNaohiro Aota 
1975b316468SNaohiro Aota static inline bool btrfs_dev_is_sequential(struct btrfs_device *device, u64 pos)
1985b316468SNaohiro Aota {
1995b316468SNaohiro Aota 	struct btrfs_zoned_device_info *zone_info = device->zone_info;
2005b316468SNaohiro Aota 
2015b316468SNaohiro Aota 	if (!zone_info)
2025b316468SNaohiro Aota 		return false;
2035b316468SNaohiro Aota 
2045b316468SNaohiro Aota 	return test_bit(pos >> zone_info->zone_size_shift, zone_info->seq_zones);
2055b316468SNaohiro Aota }
2065b316468SNaohiro Aota 
2075b316468SNaohiro Aota static inline bool btrfs_dev_is_empty_zone(struct btrfs_device *device, u64 pos)
2085b316468SNaohiro Aota {
2095b316468SNaohiro Aota 	struct btrfs_zoned_device_info *zone_info = device->zone_info;
2105b316468SNaohiro Aota 
2115b316468SNaohiro Aota 	if (!zone_info)
2125b316468SNaohiro Aota 		return true;
2135b316468SNaohiro Aota 
2145b316468SNaohiro Aota 	return test_bit(pos >> zone_info->zone_size_shift, zone_info->empty_zones);
2155b316468SNaohiro Aota }
2165b316468SNaohiro Aota 
2175b316468SNaohiro Aota static inline void btrfs_dev_set_empty_zone_bit(struct btrfs_device *device,
2185b316468SNaohiro Aota 						u64 pos, bool set)
2195b316468SNaohiro Aota {
2205b316468SNaohiro Aota 	struct btrfs_zoned_device_info *zone_info = device->zone_info;
2215b316468SNaohiro Aota 	unsigned int zno;
2225b316468SNaohiro Aota 
2235b316468SNaohiro Aota 	if (!zone_info)
2245b316468SNaohiro Aota 		return;
2255b316468SNaohiro Aota 
2265b316468SNaohiro Aota 	zno = pos >> zone_info->zone_size_shift;
2275b316468SNaohiro Aota 	if (set)
2285b316468SNaohiro Aota 		set_bit(zno, zone_info->empty_zones);
2295b316468SNaohiro Aota 	else
2305b316468SNaohiro Aota 		clear_bit(zno, zone_info->empty_zones);
2315b316468SNaohiro Aota }
2325b316468SNaohiro Aota 
2335b316468SNaohiro Aota static inline void btrfs_dev_set_zone_empty(struct btrfs_device *device, u64 pos)
2345b316468SNaohiro Aota {
2355b316468SNaohiro Aota 	btrfs_dev_set_empty_zone_bit(device, pos, true);
2365b316468SNaohiro Aota }
2375b316468SNaohiro Aota 
2385b316468SNaohiro Aota static inline void btrfs_dev_clear_zone_empty(struct btrfs_device *device, u64 pos)
2395b316468SNaohiro Aota {
2405b316468SNaohiro Aota 	btrfs_dev_set_empty_zone_bit(device, pos, false);
2415b316468SNaohiro Aota }
2425b316468SNaohiro Aota 
243b70f5097SNaohiro Aota static inline bool btrfs_check_device_zone_type(const struct btrfs_fs_info *fs_info,
244b70f5097SNaohiro Aota 						struct block_device *bdev)
245b70f5097SNaohiro Aota {
246b70f5097SNaohiro Aota 	if (btrfs_is_zoned(fs_info)) {
2473c9daa09SJohannes Thumshirn 		/*
2483c9daa09SJohannes Thumshirn 		 * We can allow a regular device on a zoned filesystem, because
2493c9daa09SJohannes Thumshirn 		 * we will emulate the zoned capabilities.
2503c9daa09SJohannes Thumshirn 		 */
2513c9daa09SJohannes Thumshirn 		if (!bdev_is_zoned(bdev))
2523c9daa09SJohannes Thumshirn 			return true;
2533c9daa09SJohannes Thumshirn 
2543c9daa09SJohannes Thumshirn 		return fs_info->zone_size ==
2553c9daa09SJohannes Thumshirn 			(bdev_zone_sectors(bdev) << SECTOR_SHIFT);
256b70f5097SNaohiro Aota 	}
257b70f5097SNaohiro Aota 
258b70f5097SNaohiro Aota 	/* Do not allow Host Manged zoned device */
259b70f5097SNaohiro Aota 	return bdev_zoned_model(bdev) != BLK_ZONED_HM;
260b70f5097SNaohiro Aota }
261b70f5097SNaohiro Aota 
26212659251SNaohiro Aota static inline bool btrfs_check_super_location(struct btrfs_device *device, u64 pos)
26312659251SNaohiro Aota {
26412659251SNaohiro Aota 	/*
26512659251SNaohiro Aota 	 * On a non-zoned device, any address is OK. On a zoned device,
26612659251SNaohiro Aota 	 * non-SEQUENTIAL WRITE REQUIRED zones are capable.
26712659251SNaohiro Aota 	 */
26812659251SNaohiro Aota 	return device->zone_info == NULL || !btrfs_dev_is_sequential(device, pos);
26912659251SNaohiro Aota }
27012659251SNaohiro Aota 
271dcba6e48SNaohiro Aota static inline bool btrfs_can_zone_reset(struct btrfs_device *device,
272dcba6e48SNaohiro Aota 					u64 physical, u64 length)
273dcba6e48SNaohiro Aota {
274dcba6e48SNaohiro Aota 	u64 zone_size;
275dcba6e48SNaohiro Aota 
276dcba6e48SNaohiro Aota 	if (!btrfs_dev_is_sequential(device, physical))
277dcba6e48SNaohiro Aota 		return false;
278dcba6e48SNaohiro Aota 
279dcba6e48SNaohiro Aota 	zone_size = device->zone_info->zone_size;
280dcba6e48SNaohiro Aota 	if (!IS_ALIGNED(physical, zone_size) || !IS_ALIGNED(length, zone_size))
281dcba6e48SNaohiro Aota 		return false;
282dcba6e48SNaohiro Aota 
283dcba6e48SNaohiro Aota 	return true;
284dcba6e48SNaohiro Aota }
285dcba6e48SNaohiro Aota 
2860bc09ca1SNaohiro Aota static inline void btrfs_zoned_meta_io_lock(struct btrfs_fs_info *fs_info)
2870bc09ca1SNaohiro Aota {
2880bc09ca1SNaohiro Aota 	if (!btrfs_is_zoned(fs_info))
2890bc09ca1SNaohiro Aota 		return;
2900bc09ca1SNaohiro Aota 	mutex_lock(&fs_info->zoned_meta_io_lock);
2910bc09ca1SNaohiro Aota }
2920bc09ca1SNaohiro Aota 
2930bc09ca1SNaohiro Aota static inline void btrfs_zoned_meta_io_unlock(struct btrfs_fs_info *fs_info)
2940bc09ca1SNaohiro Aota {
2950bc09ca1SNaohiro Aota 	if (!btrfs_is_zoned(fs_info))
2960bc09ca1SNaohiro Aota 		return;
2970bc09ca1SNaohiro Aota 	mutex_unlock(&fs_info->zoned_meta_io_lock);
2980bc09ca1SNaohiro Aota }
2990bc09ca1SNaohiro Aota 
30040ab3be1SNaohiro Aota static inline void btrfs_clear_treelog_bg(struct btrfs_block_group *bg)
30140ab3be1SNaohiro Aota {
30240ab3be1SNaohiro Aota 	struct btrfs_fs_info *fs_info = bg->fs_info;
30340ab3be1SNaohiro Aota 
30440ab3be1SNaohiro Aota 	if (!btrfs_is_zoned(fs_info))
30540ab3be1SNaohiro Aota 		return;
30640ab3be1SNaohiro Aota 
30740ab3be1SNaohiro Aota 	spin_lock(&fs_info->treelog_bg_lock);
30840ab3be1SNaohiro Aota 	if (fs_info->treelog_bg == bg->start)
30940ab3be1SNaohiro Aota 		fs_info->treelog_bg = 0;
31040ab3be1SNaohiro Aota 	spin_unlock(&fs_info->treelog_bg_lock);
31140ab3be1SNaohiro Aota }
31240ab3be1SNaohiro Aota 
3135b316468SNaohiro Aota #endif
314