Commit fd574a2f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:

 - direct IO fixes:

      - restore passing file offset to correctly calculate checksums
        when repairing on read and bio split happens

      - use correct bio when sumitting IO on zoned filesystem

 - zoned mode fixes:

      - fix selection of device to correctly calculate device
        capabilities when allocating a new bio

      - use a dedicated lock for exclusion during relocation

      - fix leaked plug after failure syncing log

 - fix assertion during scrub and relocation

* tag 'for-5.18-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: zoned: use dedicated lock for data relocation
  btrfs: fix assertion failure during scrub due to block group reallocation
  btrfs: fix direct I/O writes for split bios on zoned devices
  btrfs: fix direct I/O read repair for split bios
  btrfs: fix and document the zoned device choice in alloc_new_bio
  btrfs: fix leaked plug after failure syncing log on zoned filesystems
parents d615b541 5f0addf7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1060,6 +1060,7 @@ struct btrfs_fs_info {
	 */
	spinlock_t relocation_bg_lock;
	u64 data_reloc_bg;
	struct mutex zoned_data_reloc_io_lock;

	u64 nr_global_roots;

+6 −1
Original line number Diff line number Diff line
@@ -734,7 +734,12 @@ static int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,

	btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);

	/* Commit dev_replace state and reserve 1 item for it. */
	/*
	 * Commit dev_replace state and reserve 1 item for it.
	 * This is crucial to ensure we won't miss copying extents for new block
	 * groups that are allocated after we started the device replace, and
	 * must be done after setting up the device replace state.
	 */
	trans = btrfs_start_transaction(root, 1);
	if (IS_ERR(trans)) {
		ret = PTR_ERR(trans);
+1 −0
Original line number Diff line number Diff line
@@ -3157,6 +3157,7 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
	mutex_init(&fs_info->reloc_mutex);
	mutex_init(&fs_info->delalloc_root_mutex);
	mutex_init(&fs_info->zoned_meta_io_lock);
	mutex_init(&fs_info->zoned_data_reloc_io_lock);
	seqlock_init(&fs_info->profiles_lock);

	INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots);
+29 −15
Original line number Diff line number Diff line
@@ -2658,6 +2658,7 @@ int btrfs_repair_one_sector(struct inode *inode,

	repair_bio = btrfs_bio_alloc(1);
	repair_bbio = btrfs_bio(repair_bio);
	repair_bbio->file_offset = start;
	repair_bio->bi_opf = REQ_OP_READ;
	repair_bio->bi_end_io = failed_bio->bi_end_io;
	repair_bio->bi_iter.bi_sector = failrec->logical >> 9;
@@ -3333,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:
+8 −10
Original line number Diff line number Diff line
@@ -7810,8 +7810,6 @@ static blk_status_t btrfs_check_read_dio_bio(struct btrfs_dio_private *dip,
	const bool csum = !(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM);
	struct bio_vec bvec;
	struct bvec_iter iter;
	const u64 orig_file_offset = dip->file_offset;
	u64 start = orig_file_offset;
	u32 bio_offset = 0;
	blk_status_t err = BLK_STS_OK;

@@ -7821,6 +7819,8 @@ static blk_status_t btrfs_check_read_dio_bio(struct btrfs_dio_private *dip,
		nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info, bvec.bv_len);
		pgoff = bvec.bv_offset;
		for (i = 0; i < nr_sectors; i++) {
			u64 start = bbio->file_offset + bio_offset;

			ASSERT(pgoff < PAGE_SIZE);
			if (uptodate &&
			    (!csum || !check_data_csum(inode, bbio,
@@ -7833,17 +7833,13 @@ static blk_status_t btrfs_check_read_dio_bio(struct btrfs_dio_private *dip,
			} else {
				int ret;

				ASSERT((start - orig_file_offset) < UINT_MAX);
				ret = btrfs_repair_one_sector(inode,
						&bbio->bio,
						start - orig_file_offset,
						bvec.bv_page, pgoff,
				ret = btrfs_repair_one_sector(inode, &bbio->bio,
						bio_offset, bvec.bv_page, pgoff,
						start, bbio->mirror_num,
						submit_dio_repair_bio);
				if (ret)
					err = errno_to_blk_status(ret);
			}
			start += sectorsize;
			ASSERT(bio_offset + sectorsize > bio_offset);
			bio_offset += sectorsize;
			pgoff += sectorsize;
@@ -7870,6 +7866,7 @@ static blk_status_t btrfs_submit_bio_start_direct_io(struct inode *inode,
static void btrfs_end_dio_bio(struct bio *bio)
{
	struct btrfs_dio_private *dip = bio->bi_private;
	struct btrfs_bio *bbio = btrfs_bio(bio);
	blk_status_t err = bio->bi_status;

	if (err)
@@ -7880,12 +7877,12 @@ static void btrfs_end_dio_bio(struct bio *bio)
			   bio->bi_iter.bi_size, err);

	if (bio_op(bio) == REQ_OP_READ)
		err = btrfs_check_read_dio_bio(dip, btrfs_bio(bio), !err);
		err = btrfs_check_read_dio_bio(dip, bbio, !err);

	if (err)
		dip->dio_bio->bi_status = err;

	btrfs_record_physical_zoned(dip->inode, dip->file_offset, bio);
	btrfs_record_physical_zoned(dip->inode, bbio->file_offset, bio);

	bio_put(bio);
	btrfs_dio_private_put(dip);
@@ -8046,6 +8043,7 @@ static void btrfs_submit_direct(const struct iomap_iter *iter,
		bio = btrfs_bio_clone_partial(dio_bio, clone_offset, clone_len);
		bio->bi_private = dip;
		bio->bi_end_io = btrfs_end_dio_bio;
		btrfs_bio(bio)->file_offset = file_offset;

		if (bio_op(bio) == REQ_OP_ZONE_APPEND) {
			status = extract_ordered_extent(BTRFS_I(inode), bio,
Loading