xref: /openbmc/linux/fs/btrfs/zoned.h (revision 36fe4655)
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