Commit 50f1cff3 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by David Sterba
Browse files

btrfs: fix and document the zoned device choice in alloc_new_bio



Zone Append bios only need a valid block device in struct bio, but
not the device in the btrfs_bio.  Use the information from
btrfs_zoned_get_device to set up bi_bdev and fix zoned writes on
multi-device file system with non-homogeneous capabilities and remove
the pointless btrfs_bio.device assignment.

Add big fat comments explaining what is going on here.

Reviewed-by: default avatarJohannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: default avatarNaohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 50ff5788
Loading
Loading
Loading
Loading
+28 −15
Original line number Diff line number Diff line
@@ -3334,24 +3334,37 @@ static int alloc_new_bio(struct btrfs_inode *inode,
	ret = calc_bio_boundaries(bio_ctrl, inode, file_offset);
	if (ret < 0)
		goto error;
	if (wbc) {
		struct block_device *bdev;

		bdev = fs_info->fs_devices->latest_dev->bdev;
		bio_set_dev(bio, bdev);
		wbc_init_bio(wbc, bio);
	}
	if (wbc) {
		/*
		 * For Zone append we need the correct block_device that we are
		 * going to write to set in the bio to be able to respect the
		 * hardware limitation.  Look it up here:
		 */
		if (bio_op(bio) == REQ_OP_ZONE_APPEND) {
		struct btrfs_device *device;
			struct btrfs_device *dev;

		device = btrfs_zoned_get_device(fs_info, disk_bytenr,
			dev = btrfs_zoned_get_device(fs_info, disk_bytenr,
						     fs_info->sectorsize);
		if (IS_ERR(device)) {
			ret = PTR_ERR(device);
			if (IS_ERR(dev)) {
				ret = PTR_ERR(dev);
				goto error;
			}

		btrfs_bio(bio)->device = device;
			bio_set_dev(bio, dev->bdev);
		} else {
			/*
			 * Otherwise pick the last added device to support
			 * cgroup writeback.  For multi-device file systems this
			 * means blk-cgroup policies have to always be set on the
			 * last added/replaced device.  This is a bit odd but has
			 * been like that for a long time.
			 */
			bio_set_dev(bio, fs_info->fs_devices->latest_dev->bdev);
		}
		wbc_init_bio(wbc, bio);
	} else {
		ASSERT(bio_op(bio) != REQ_OP_ZONE_APPEND);
	}
	return 0;
error: