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

 - fix regression in extent map rework when handling insertion of
   overlapping compressed extent

 - fix unexpected file length when appending to a file using direct io
   and buffer not faulted in

 - in zoned mode, fix accounting of unusable space when flipping
   read-only block group back to read-write

 - fix page locking when COWing an inline range, assertion failure found
   by syzbot

 - fix calculation of space info in debugging print

 - tree-checker, add validation of data reference item

 - fix a few -Wmaybe-uninitialized build warnings

* tag 'for-6.11-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: initialize location to fix -Wmaybe-uninitialized in btrfs_lookup_dentry()
  btrfs: fix corruption after buffer fault in during direct IO append write
  btrfs: zoned: fix zone_unusable accounting on making block group read-write again
  btrfs: do not subtract delalloc from avail bytes
  btrfs: make cow_file_range_inline() honor locked_page on error
  btrfs: fix corrupt read due to bad offset of a compressed extent map
  btrfs: tree-checker: validate dref root and objectid
parents e254e0c5 b8e947e9
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -1223,8 +1223,8 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
	block_group->space_info->total_bytes -= block_group->length;
	block_group->space_info->bytes_readonly -=
		(block_group->length - block_group->zone_unusable);
	block_group->space_info->bytes_zone_unusable -=
		block_group->zone_unusable;
	btrfs_space_info_update_bytes_zone_unusable(fs_info, block_group->space_info,
						    -block_group->zone_unusable);
	block_group->space_info->disk_total -= block_group->length * factor;

	spin_unlock(&block_group->space_info->lock);
@@ -1396,7 +1396,8 @@ static int inc_block_group_ro(struct btrfs_block_group *cache, int force)
		if (btrfs_is_zoned(cache->fs_info)) {
			/* Migrate zone_unusable bytes to readonly */
			sinfo->bytes_readonly += cache->zone_unusable;
			sinfo->bytes_zone_unusable -= cache->zone_unusable;
			btrfs_space_info_update_bytes_zone_unusable(cache->fs_info, sinfo,
								    -cache->zone_unusable);
			cache->zone_unusable = 0;
		}
		cache->ro++;
@@ -3056,9 +3057,11 @@ void btrfs_dec_block_group_ro(struct btrfs_block_group *cache)
		if (btrfs_is_zoned(cache->fs_info)) {
			/* Migrate zone_unusable bytes back */
			cache->zone_unusable =
				(cache->alloc_offset - cache->used) +
				(cache->alloc_offset - cache->used - cache->pinned -
				 cache->reserved) +
				(cache->length - cache->zone_capacity);
			sinfo->bytes_zone_unusable += cache->zone_unusable;
			btrfs_space_info_update_bytes_zone_unusable(cache->fs_info, sinfo,
								    cache->zone_unusable);
			sinfo->bytes_readonly -= cache->zone_unusable;
		}
		num_bytes = cache->length - cache->reserved -
+1 −0
Original line number Diff line number Diff line
@@ -459,6 +459,7 @@ struct btrfs_file_private {
	void *filldir_buf;
	u64 last_index;
	struct extent_state *llseek_cached_state;
	bool fsync_skip_inode_lock;
};

static inline u32 BTRFS_LEAF_DATA_SIZE(const struct btrfs_fs_info *info)
+28 −10
Original line number Diff line number Diff line
@@ -856,21 +856,37 @@ ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from)
	 * So here we disable page faults in the iov_iter and then retry if we
	 * got -EFAULT, faulting in the pages before the retry.
	 */
again:
	from->nofault = true;
	dio = btrfs_dio_write(iocb, from, written);
	from->nofault = false;

	if (IS_ERR_OR_NULL(dio)) {
		ret = PTR_ERR_OR_ZERO(dio);
	} else {
		struct btrfs_file_private stack_private = { 0 };
		struct btrfs_file_private *private;
		const bool have_private = (file->private_data != NULL);

		if (!have_private)
			file->private_data = &stack_private;

		/*
	 * iomap_dio_complete() will call btrfs_sync_file() if we have a dsync
	 * iocb, and that needs to lock the inode. So unlock it before calling
	 * iomap_dio_complete() to avoid a deadlock.
		 * If we have a synchronous write, we must make sure the fsync
		 * triggered by the iomap_dio_complete() call below doesn't
		 * deadlock on the inode lock - we are already holding it and we
		 * can't call it after unlocking because we may need to complete
		 * partial writes due to the input buffer (or parts of it) not
		 * being already faulted in.
		 */
	btrfs_inode_unlock(BTRFS_I(inode), ilock_flags);

	if (IS_ERR_OR_NULL(dio))
		ret = PTR_ERR_OR_ZERO(dio);
	else
		private = file->private_data;
		private->fsync_skip_inode_lock = true;
		ret = iomap_dio_complete(dio);
		private->fsync_skip_inode_lock = false;

		if (!have_private)
			file->private_data = NULL;
	}

	/* No increment (+=) because iomap returns a cumulative value. */
	if (ret > 0)
@@ -897,10 +913,12 @@ ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from)
		} else {
			fault_in_iov_iter_readable(from, left);
			prev_left = left;
			goto relock;
			goto again;
		}
	}

	btrfs_inode_unlock(BTRFS_I(inode), ilock_flags);

	/*
	 * If 'ret' is -ENOTBLK or we have not written all data, then it means
	 * we must fallback to buffered IO.
+2 −1
Original line number Diff line number Diff line
@@ -2793,7 +2793,8 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info,
			readonly = true;
		} else if (btrfs_is_zoned(fs_info)) {
			/* Need reset before reusing in a zoned block group */
			space_info->bytes_zone_unusable += len;
			btrfs_space_info_update_bytes_zone_unusable(fs_info, space_info,
								    len);
			readonly = true;
		}
		spin_unlock(&cache->lock);
+1 −1
Original line number Diff line number Diff line
@@ -664,7 +664,7 @@ static noinline int merge_extent_mapping(struct btrfs_inode *inode,
	start_diff = start - em->start;
	em->start = start;
	em->len = end - start;
	if (em->disk_bytenr < EXTENT_MAP_LAST_BYTE && !extent_map_is_compressed(em))
	if (em->disk_bytenr < EXTENT_MAP_LAST_BYTE)
		em->offset += start_diff;
	return add_extent_mapping(inode, em, 0);
}
Loading