Commit 54162b06 authored by Zhang Yi's avatar Zhang Yi
Browse files

iomap: advance the ifs allocation if we have more than one blocks per folio

hulk inclusion
category: perf
bugzilla: https://gitee.com/openeuler/kernel/issues/IACNS4


CVE: NA

--------------------------------

Now we allocate ifs if i_blocks_per_folio is larger than one when
writing back dirty folios in iomap_writepage_map(), so we don't attach
an ifs after buffer write to an entire folio until it starts writing
back, if we partial truncate that folio, iomap_invalidate_folio() can't
clear counterpart block's dirty bit as expected. Fix this by advance the
ifs allocation to __iomap_write_begin().

Signed-off-by: default avatarZhang Yi <yi.zhang@huawei.com>
parent 71be4d0f
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -682,6 +682,12 @@ int __iomap_write_begin(const struct iomap_iter *iter, loff_t pos,
	size_t from = offset_in_folio(folio, pos), to = from + len;
	size_t poff, plen;

	if (nr_blocks > 1) {
		ifs = ifs_alloc(iter->inode, folio, iter->flags);
		if ((iter->flags & IOMAP_NOWAIT) && !ifs)
			return -EAGAIN;
	}

	/*
	 * If the write or zeroing completely overlaps the current folio, then
	 * entire folio will be dirtied so there is no need for
@@ -693,10 +699,6 @@ int __iomap_write_begin(const struct iomap_iter *iter, loff_t pos,
	    pos + len >= folio_pos(folio) + folio_size(folio))
		return 0;

	ifs = ifs_alloc(iter->inode, folio, iter->flags);
	if ((iter->flags & IOMAP_NOWAIT) && !ifs && nr_blocks > 1)
		return -EAGAIN;

	if (folio_test_uptodate(folio))
		return 0;
	folio_clear_error(folio);
@@ -1925,7 +1927,12 @@ static int iomap_writepage_map(struct iomap_writepage_ctx *wpc,
	WARN_ON_ONCE(end_pos <= pos);

	if (i_blocks_per_folio(inode, folio) > 1) {
		if (!ifs) {
		/*
		 * This should not happen since we always allocate ifs in
		 * iomap_folio_mkwrite_iter() and there is more than one
		 * blocks per folio in __iomap_write_begin().
		 */
		if (WARN_ON_ONCE(!ifs)) {
			ifs = ifs_alloc(inode, folio, 0);
			iomap_set_range_dirty(folio, 0, end_pos - pos);
		}