Commit 7d900724 authored by Linus Torvalds's avatar Linus Torvalds

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
parents add6b926 53b74fa9
...@@ -21,9 +21,30 @@ ...@@ -21,9 +21,30 @@
/* Pseudo write pointer value for conventional zone */ /* Pseudo write pointer value for conventional zone */
#define WP_CONVENTIONAL ((u64)-2) #define WP_CONVENTIONAL ((u64)-2)
/*
* Location of the first zone of superblock logging zone pairs.
*
* - primary superblock: 0B (zone 0)
* - first copy: 512G (zone starting at that offset)
* - second copy: 4T (zone starting at that offset)
*/
#define BTRFS_SB_LOG_PRIMARY_OFFSET (0ULL)
#define BTRFS_SB_LOG_FIRST_OFFSET (512ULL * SZ_1G)
#define BTRFS_SB_LOG_SECOND_OFFSET (4096ULL * SZ_1G)
#define BTRFS_SB_LOG_FIRST_SHIFT const_ilog2(BTRFS_SB_LOG_FIRST_OFFSET)
#define BTRFS_SB_LOG_SECOND_SHIFT const_ilog2(BTRFS_SB_LOG_SECOND_OFFSET)
/* Number of superblock log zones */ /* Number of superblock log zones */
#define BTRFS_NR_SB_LOG_ZONES 2 #define BTRFS_NR_SB_LOG_ZONES 2
/*
* Maximum supported zone size. Currently, SMR disks have a zone size of
* 256MiB, and we are expecting ZNS drives to be in the 1-4GiB range. We do not
* expect the zone size to become larger than 8GiB in the near future.
*/
#define BTRFS_MAX_ZONE_SIZE SZ_8G
static int copy_zone_info_cb(struct blk_zone *zone, unsigned int idx, void *data) static int copy_zone_info_cb(struct blk_zone *zone, unsigned int idx, void *data)
{ {
struct blk_zone *zones = data; struct blk_zone *zones = data;
...@@ -111,23 +132,22 @@ static int sb_write_pointer(struct block_device *bdev, struct blk_zone *zones, ...@@ -111,23 +132,22 @@ static int sb_write_pointer(struct block_device *bdev, struct blk_zone *zones,
} }
/* /*
* The following zones are reserved as the circular buffer on ZONED btrfs. * Get the first zone number of the superblock mirror
* - The primary superblock: zones 0 and 1
* - The first copy: zones 16 and 17
* - The second copy: zones 1024 or zone at 256GB which is minimum, and
* the following one
*/ */
static inline u32 sb_zone_number(int shift, int mirror) static inline u32 sb_zone_number(int shift, int mirror)
{ {
ASSERT(mirror < BTRFS_SUPER_MIRROR_MAX); u64 zone;
ASSERT(mirror < BTRFS_SUPER_MIRROR_MAX);
switch (mirror) { switch (mirror) {
case 0: return 0; case 0: zone = 0; break;
case 1: return 16; case 1: zone = 1ULL << (BTRFS_SB_LOG_FIRST_SHIFT - shift); break;
case 2: return min_t(u64, btrfs_sb_offset(mirror) >> shift, 1024); case 2: zone = 1ULL << (BTRFS_SB_LOG_SECOND_SHIFT - shift); break;
} }
return 0; ASSERT(zone <= U32_MAX);
return (u32)zone;
} }
/* /*
...@@ -300,10 +320,21 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device) ...@@ -300,10 +320,21 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device)
zone_sectors = bdev_zone_sectors(bdev); zone_sectors = bdev_zone_sectors(bdev);
} }
nr_sectors = bdev_nr_sectors(bdev);
/* Check if it's power of 2 (see is_power_of_2) */ /* Check if it's power of 2 (see is_power_of_2) */
ASSERT(zone_sectors != 0 && (zone_sectors & (zone_sectors - 1)) == 0); ASSERT(zone_sectors != 0 && (zone_sectors & (zone_sectors - 1)) == 0);
zone_info->zone_size = zone_sectors << SECTOR_SHIFT; zone_info->zone_size = zone_sectors << SECTOR_SHIFT;
/* We reject devices with a zone size larger than 8GB */
if (zone_info->zone_size > BTRFS_MAX_ZONE_SIZE) {
btrfs_err_in_rcu(fs_info,
"zoned: %s: zone size %llu larger than supported maximum %llu",
rcu_str_deref(device->name),
zone_info->zone_size, BTRFS_MAX_ZONE_SIZE);
ret = -EINVAL;
goto out;
}
nr_sectors = bdev_nr_sectors(bdev);
zone_info->zone_size_shift = ilog2(zone_info->zone_size); zone_info->zone_size_shift = ilog2(zone_info->zone_size);
zone_info->max_zone_append_size = zone_info->max_zone_append_size =
(u64)queue_max_zone_append_sectors(queue) << SECTOR_SHIFT; (u64)queue_max_zone_append_sectors(queue) << SECTOR_SHIFT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment