Subject: linux-next: manual merge of the btrfs tree with the btrfs-fixes tree

From: Mark Brown <[email-masked]>
Date: Tue, 2 Jun 2026 13:41:52 +0100

Hi all,

Today's linux-next merge of the btrfs tree got a conflict in:

  fs/btrfs/zoned.c

between commits:

  c4dbdc9e2c61b ("btrfs: protect sb_write_pointer() with invalidate lock")
  e67ae2bce5703 ("btrfs: use mapping shared locking for reading super block")

from the btrfs tree and commit:

  6cfd0b77103ae ("btrfs: protect sb_write_pointer() with invalidate lock")

from the btrfs-fixes tree - there's a commit that's been duplicated in
the two trees there.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

diff --combined fs/btrfs/zoned.c
index 5f75cf0e14b95,0f87701e38e34..0000000000000
--- a/fs/btrfs/zoned.c
+++ b/fs/btrfs/zoned.c
@@@ -131,10 -131,10 +131,10 @@@ static int sb_write_pointer(struct bloc
  			u64 bytenr = ALIGN_DOWN(zone_end, BTRFS_SUPER_INFO_SIZE) -
  						BTRFS_SUPER_INFO_SIZE;
  
- 			filemap_invalidate_lock(mapping);
+ 			filemap_invalidate_lock_shared(mapping);
  			page[i] = read_cache_page_gfp(mapping,
  					bytenr >> PAGE_SHIFT, GFP_NOFS);
- 			filemap_invalidate_unlock(mapping);
+ 			filemap_invalidate_unlock_shared(mapping);
  			if (IS_ERR(page[i])) {
  				if (i == 1)
  					btrfs_release_disk_super(super[0]);
@@@ -356,12 -356,33 +356,33 @@@ int btrfs_get_dev_zone_info_all_devices
  	return ret;
  }
  
+ static int btrfs_get_max_active_zones(struct btrfs_device *device,
+ 				      struct btrfs_zoned_device_info *zone_info)
+ {
+ 	struct block_device *bdev = device->bdev;
+ 	int max_active_zones;
+ 
+ 	if (unlikely(zone_info->nr_zones < BTRFS_MIN_ACTIVE_ZONES)) {
+ 		btrfs_err(device->fs_info, "zoned: not enough zones to mount filesystem: %u < %d",
+ 			  zone_info->nr_zones, BTRFS_MIN_ACTIVE_ZONES);
+ 		return -EINVAL;
+ 	}
+ 
+ 	max_active_zones = min_not_zero(bdev_max_active_zones(bdev),
+ 					bdev_max_open_zones(bdev));
+ 	if (max_active_zones == 0)
+ 		max_active_zones = min(zone_info->nr_zones / 4,
+ 				       BTRFS_DEFAULT_MAX_ACTIVE_ZONES);
+ 
+ 	zone_info->max_active_zones = max(max_active_zones, BTRFS_MIN_ACTIVE_ZONES);
+ 	return 0;
+ }
+ 
  int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
  {
  	struct btrfs_fs_info *fs_info = device->fs_info;
  	struct btrfs_zoned_device_info *zone_info = NULL;
  	struct block_device *bdev = device->bdev;
- 	unsigned int max_active_zones;
  	unsigned int nactive;
  	sector_t nr_sectors;
  	sector_t sector = 0;
@@@ -426,19 -447,9 +447,9 @@@
  	if (!IS_ALIGNED(nr_sectors, zone_sectors))
  		zone_info->nr_zones++;
  
- 	max_active_zones = min_not_zero(bdev_max_active_zones(bdev),
- 					bdev_max_open_zones(bdev));
- 	if (!max_active_zones && zone_info->nr_zones > BTRFS_DEFAULT_MAX_ACTIVE_ZONES)
- 		max_active_zones = BTRFS_DEFAULT_MAX_ACTIVE_ZONES;
- 	if (max_active_zones && max_active_zones < BTRFS_MIN_ACTIVE_ZONES) {
- 		btrfs_err(fs_info,
- "zoned: %s: max active zones %u is too small, need at least %u active zones",
- 				 rcu_dereference(device->name), max_active_zones,
- 				 BTRFS_MIN_ACTIVE_ZONES);
- 		ret = -EINVAL;
+ 	ret = btrfs_get_max_active_zones(device, zone_info);
+ 	if (ret)
  		goto out;
- 	}
- 	zone_info->max_active_zones = max_active_zones;
  
  	zone_info->seq_zones = bitmap_zalloc(zone_info->nr_zones, GFP_KERNEL);
  	if (!zone_info->seq_zones) {
@@@ -519,26 -530,29 +530,29 @@@
  		goto out;
  	}
  
- 	if (max_active_zones) {
- 		if (unlikely(nactive > max_active_zones)) {
- 			if (bdev_max_active_zones(bdev) == 0) {
- 				max_active_zones = 0;
- 				zone_info->max_active_zones = 0;
- 				goto validate;
- 			}
+ 	if (unlikely(nactive > zone_info->max_active_zones)) {
+ 		if (bdev_max_active_zones(bdev) > 0) {
  			btrfs_err(device->fs_info,
- 			"zoned: %u active zones on %s exceeds max_active_zones %u",
- 					 nactive, rcu_dereference(device->name),
- 					 max_active_zones);
+ 					"zoned: %u active zones on %s exceeds max_active_zones %u",
+ 					nactive, rcu_dereference(device->name),
+ 					zone_info->max_active_zones);
  			ret = -EIO;
  			goto out;
  		}
+ 
+ 		/*
+ 		 * This is for backward compatibility with old filesystems that
+ 		 * have a lot of active zones because the device doesn't report
+ 		 * a maximum number of zones and we previously didn't care for
+ 		 * the limit.
+ 		 */
+ 		zone_info->max_active_zones = 0;
+ 	} else {
  		atomic_set(&zone_info->active_zones_left,
- 			   max_active_zones - nactive);
+ 				zone_info->max_active_zones - nactive);
  		set_bit(BTRFS_FS_ACTIVE_ZONE_TRACKING, &fs_info->flags);
  	}
  
- validate:
  	/* Validate superblock log */
  	nr_zones = BTRFS_NR_SB_LOG_ZONES;
  	for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
@@@ -1313,7 -1327,7 +1327,7 @@@ static int btrfs_load_zone_info(struct 
  {
  	struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
  	struct btrfs_device *device;
- 	int dev_replace_is_ongoing = 0;
+ 	bool dev_replace_is_ongoing = false;
  	unsigned int nofs_flag;
  	struct blk_zone zone;
  	int ret;
@@@ -2765,7 -2779,6 +2779,6 @@@ void btrfs_zoned_reserve_data_reloc_bg(
  	struct btrfs_block_group *bg;
  	struct list_head *bg_list;
  	u64 alloc_flags;
- 	bool first = true;
  	bool did_chunk_alloc = false;
  	int index;
  	int ret;
@@@ -2782,18 -2795,13 +2795,13 @@@
  	alloc_flags = btrfs_get_alloc_profile(fs_info, space_info->flags);
  	index = btrfs_bg_flags_to_raid_index(alloc_flags);
  
- 	/* Scan the data space_info to find empty block groups. Take the second one. */
  again:
  	bg_list = &space_info->block_groups[index];
  	list_for_each_entry(bg, bg_list, list) {
+ 
  		if (bg->alloc_offset != 0)
  			continue;
  
- 		if (first) {
- 			first = false;
- 			continue;
- 		}
- 
  		if (space_info == data_sinfo) {
  			/* Migrate the block group to the data relocation space_info. */
  			struct btrfs_space_info *reloc_sinfo = data_sinfo->sub_group[0];
@@@ -2851,7 -2859,6 +2859,6 @@@
  		 * We allocated a new block group in the data relocation space_info. We
  		 * can take that one.
  		 */
- 		first = false;
  		did_chunk_alloc = true;
  		goto again;
  	}