Skip to content

Commit 7d90072

Browse files
committed
Merge tag 'for-5.12-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fix from David Sterba: "One more patch that we'd like to get to 5.12 before release. It's changing where and how the superblock is stored in the zoned mode. It is an on-disk format change but so far there are no implications for users as the proper mkfs support hasn't been merged and is waiting for the kernel side to settle. Until now, the superblocks were derived from the zone index, but zone size can differ per device. This is changed to be based on fixed offset values, to make it independent of the device zone size. The work on that got a bit delayed, we discussed the exact locations to support potential device sizes and usecases. (Partially delayed also due to my vacation.) Having that in the same release where the zoned mode is declared usable is highly desired, there are userspace projects that need to be updated to recognize the feature. Pushing that to the next release would make things harder to test" * tag 'for-5.12-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: zoned: move superblock logging zone location
2 parents add6b92 + 53b74fa commit 7d90072

File tree

1 file changed

+42
-11
lines changed

1 file changed

+42
-11
lines changed

fs/btrfs/zoned.c

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,30 @@
2121
/* Pseudo write pointer value for conventional zone */
2222
#define WP_CONVENTIONAL ((u64)-2)
2323

24+
/*
25+
* Location of the first zone of superblock logging zone pairs.
26+
*
27+
* - primary superblock: 0B (zone 0)
28+
* - first copy: 512G (zone starting at that offset)
29+
* - second copy: 4T (zone starting at that offset)
30+
*/
31+
#define BTRFS_SB_LOG_PRIMARY_OFFSET (0ULL)
32+
#define BTRFS_SB_LOG_FIRST_OFFSET (512ULL * SZ_1G)
33+
#define BTRFS_SB_LOG_SECOND_OFFSET (4096ULL * SZ_1G)
34+
35+
#define BTRFS_SB_LOG_FIRST_SHIFT const_ilog2(BTRFS_SB_LOG_FIRST_OFFSET)
36+
#define BTRFS_SB_LOG_SECOND_SHIFT const_ilog2(BTRFS_SB_LOG_SECOND_OFFSET)
37+
2438
/* Number of superblock log zones */
2539
#define BTRFS_NR_SB_LOG_ZONES 2
2640

41+
/*
42+
* Maximum supported zone size. Currently, SMR disks have a zone size of
43+
* 256MiB, and we are expecting ZNS drives to be in the 1-4GiB range. We do not
44+
* expect the zone size to become larger than 8GiB in the near future.
45+
*/
46+
#define BTRFS_MAX_ZONE_SIZE SZ_8G
47+
2748
static int copy_zone_info_cb(struct blk_zone *zone, unsigned int idx, void *data)
2849
{
2950
struct blk_zone *zones = data;
@@ -111,23 +132,22 @@ static int sb_write_pointer(struct block_device *bdev, struct blk_zone *zones,
111132
}
112133

113134
/*
114-
* The following zones are reserved as the circular buffer on ZONED btrfs.
115-
* - The primary superblock: zones 0 and 1
116-
* - The first copy: zones 16 and 17
117-
* - The second copy: zones 1024 or zone at 256GB which is minimum, and
118-
* the following one
135+
* Get the first zone number of the superblock mirror
119136
*/
120137
static inline u32 sb_zone_number(int shift, int mirror)
121138
{
122-
ASSERT(mirror < BTRFS_SUPER_MIRROR_MAX);
139+
u64 zone;
123140

141+
ASSERT(mirror < BTRFS_SUPER_MIRROR_MAX);
124142
switch (mirror) {
125-
case 0: return 0;
126-
case 1: return 16;
127-
case 2: return min_t(u64, btrfs_sb_offset(mirror) >> shift, 1024);
143+
case 0: zone = 0; break;
144+
case 1: zone = 1ULL << (BTRFS_SB_LOG_FIRST_SHIFT - shift); break;
145+
case 2: zone = 1ULL << (BTRFS_SB_LOG_SECOND_SHIFT - shift); break;
128146
}
129147

130-
return 0;
148+
ASSERT(zone <= U32_MAX);
149+
150+
return (u32)zone;
131151
}
132152

133153
/*
@@ -300,10 +320,21 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device)
300320
zone_sectors = bdev_zone_sectors(bdev);
301321
}
302322

303-
nr_sectors = bdev_nr_sectors(bdev);
304323
/* Check if it's power of 2 (see is_power_of_2) */
305324
ASSERT(zone_sectors != 0 && (zone_sectors & (zone_sectors - 1)) == 0);
306325
zone_info->zone_size = zone_sectors << SECTOR_SHIFT;
326+
327+
/* We reject devices with a zone size larger than 8GB */
328+
if (zone_info->zone_size > BTRFS_MAX_ZONE_SIZE) {
329+
btrfs_err_in_rcu(fs_info,
330+
"zoned: %s: zone size %llu larger than supported maximum %llu",
331+
rcu_str_deref(device->name),
332+
zone_info->zone_size, BTRFS_MAX_ZONE_SIZE);
333+
ret = -EINVAL;
334+
goto out;
335+
}
336+
337+
nr_sectors = bdev_nr_sectors(bdev);
307338
zone_info->zone_size_shift = ilog2(zone_info->zone_size);
308339
zone_info->max_zone_append_size =
309340
(u64)queue_max_zone_append_sectors(queue) << SECTOR_SHIFT;

0 commit comments

Comments
 (0)