Unverified Commit 295749b6 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!11044 ext4: some bugfixs for large iomap&folio

Merge Pull Request from: @ci-robot 
 
PR sync from: Zhihao Cheng <chengzhihao@huaweicloud.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/F7X7LQ5WAYBJWYPEXWIQ324QJSVCDYDS/ 
Darrick J. Wong (1):
  xfs: hoist multi-fsb allocation unit detection to a helper

Zhang Yi (4):
  xfs: reserve blocks for truncating large realtime inode
  iomap: don't mark blocks uptodate after partial zeroing
  iomap: reduce unnecessary state_lock when setting ifs uptodate and
    dirty bits
  iomap: optimize setting uptodate bit

Zhihao Cheng (2):
  ext4: ext4_iomap_map_blocks: Fix null pointer deference in nojournal
  iomap: improve iomap_folio_mkwrite_iter and ifs_clear_range_dirty


-- 
2.31.1
 
https://gitee.com/openeuler/kernel/issues/I9DN5Z 
 
Link:https://gitee.com/openeuler/kernel/pulls/11044

 

Reviewed-by: default avatarzhangyi (F) <yi.zhang@huawei.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents da3d113d 9c471105
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3878,7 +3878,7 @@ static int ext4_iomap_map_blocks(struct iomap_writepage_ctx *wpc,
		 * ext4_count_free_blocks() is non-zero, a commit
		 * should free up blocks.
		 */
		if (ret == -ENOSPC && ext4_count_free_clusters(sb)) {
		if (ret == -ENOSPC && journal && ext4_count_free_clusters(sb)) {
			jbd2_journal_force_commit_nested(journal);
			goto retry;
		}
+44 −6
Original line number Diff line number Diff line
@@ -136,7 +136,8 @@ static void ifs_clear_range_dirty(struct folio *folio,
{
	struct inode *inode = folio->mapping->host;
	unsigned int blks_per_folio = i_blocks_per_folio(inode, folio);
	unsigned int first_blk = DIV_ROUND_UP(off, i_blocksize(inode));
	unsigned int first_blk = round_up(off, i_blocksize(inode)) >>
				 inode->i_blkbits;
	unsigned int last_blk = (off + len) >> inode->i_blkbits;
	unsigned int nr_blks = last_blk - first_blk;
	unsigned long flags;
@@ -211,6 +212,37 @@ bool iomap_is_fully_dirty(struct folio *folio, size_t from, size_t count)
}
EXPORT_SYMBOL_GPL(iomap_is_fully_dirty);

static void ifs_set_range_dirty_uptodate(struct folio *folio,
		struct iomap_folio_state *ifs, size_t off, size_t len)
{
	struct inode *inode = folio->mapping->host;
	unsigned int blks_per_folio = i_blocks_per_folio(inode, folio);
	unsigned int first_blk = (off >> inode->i_blkbits);
	unsigned int last_blk = (off + len - 1) >> inode->i_blkbits;
	unsigned int nr_blks = last_blk - first_blk + 1;
	unsigned long flags;

	spin_lock_irqsave(&ifs->state_lock, flags);
	bitmap_set(ifs->state, first_blk, nr_blks);
	if (ifs_is_fully_uptodate(folio, ifs))
		folio_mark_uptodate(folio);
	bitmap_set(ifs->state, first_blk + blks_per_folio, nr_blks);
	spin_unlock_irqrestore(&ifs->state_lock, flags);
}

static void iomap_set_range_dirty_uptodate(struct folio *folio,
		size_t off, size_t len)
{
	struct iomap_folio_state *ifs = folio->private;

	if (ifs)
		ifs_set_range_dirty_uptodate(folio, ifs, off, len);
	else
		folio_mark_uptodate(folio);

	filemap_dirty_folio(folio->mapping, folio);
}

static struct iomap_folio_state *ifs_alloc(struct inode *inode,
		struct folio *folio, unsigned int flags)
{
@@ -761,7 +793,6 @@ int __iomap_write_begin(const struct iomap_iter *iter, loff_t pos,
			if (status)
				return status;
		}
		iomap_set_range_uptodate(folio, poff, plen);
	} while ((block_start += plen) < block_end);

	return 0;
@@ -868,6 +899,8 @@ static int iomap_write_begin(struct iomap_iter *iter, loff_t pos,
bool __iomap_write_end(struct inode *inode, loff_t pos, size_t len,
		size_t copied, struct folio *folio)
{
	size_t from = offset_in_folio(folio, pos);

	flush_dcache_folio(folio);

	/*
@@ -883,9 +916,13 @@ bool __iomap_write_end(struct inode *inode, loff_t pos, size_t len,
	 */
	if (unlikely(copied < len && !folio_test_uptodate(folio)))
		return false;
	iomap_set_range_uptodate(folio, offset_in_folio(folio, pos), len);
	iomap_set_range_dirty(folio, offset_in_folio(folio, pos), copied);
	filemap_dirty_folio(inode->i_mapping, folio);

	if (folio_test_uptodate(folio)) {
		iomap_set_range_dirty(folio, from, copied);
		filemap_dirty_folio(folio->mapping, folio);
	} else {
		iomap_set_range_dirty_uptodate(folio, from, copied);
	}
	return true;
}
EXPORT_SYMBOL_GPL(__iomap_write_end);
@@ -1523,7 +1560,6 @@ static loff_t iomap_folio_mkwrite_iter(struct iomap_iter *iter,

		ifs_alloc(iter->inode, folio, 0);
		iomap_set_range_dirty(folio, 0, length);
		filemap_dirty_folio(iter->inode->i_mapping, folio);
	}

	return length;
@@ -1547,6 +1583,8 @@ vm_fault_t iomap_page_mkwrite(struct vm_fault *vmf, const struct iomap_ops *ops)
	while ((ret = iomap_iter(&iter, ops)) > 0)
		iter.processed = iomap_folio_mkwrite_iter(&iter, folio);

	if (iter.pos > folio_pos(folio))
		filemap_dirty_folio(folio->mapping, folio);
	if (ret < 0)
		goto out_unlock;
	folio_wait_stable(folio);
+2 −2
Original line number Diff line number Diff line
@@ -689,7 +689,7 @@ xfs_can_free_eofblocks(
	 * forever.
	 */
	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_ISIZE(ip));
	if (XFS_IS_REALTIME_INODE(ip) && mp->m_sb.sb_rextsize > 1)
	if (xfs_inode_has_bigrtalloc(ip))
		end_fsb = roundup_64(end_fsb, mp->m_sb.sb_rextsize);
	last_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
	if (last_fsb <= end_fsb)
@@ -990,7 +990,7 @@ xfs_free_file_space(
	endoffset_fsb = XFS_B_TO_FSBT(mp, offset + len);

	/* We can only free complete realtime extents. */
	if (XFS_IS_REALTIME_INODE(ip) && mp->m_sb.sb_rextsize > 1) {
	if (xfs_inode_has_bigrtalloc(ip)) {
		startoffset_fsb = roundup_64(startoffset_fsb,
					     mp->m_sb.sb_rextsize);
		endoffset_fsb = rounddown_64(endoffset_fsb,
+9 −0
Original line number Diff line number Diff line
@@ -305,6 +305,15 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip)
	return ip->i_diflags2 & XFS_DIFLAG2_NREXT64;
}

/*
 * Decide if this file is a realtime file whose data allocation unit is larger
 * than a single filesystem block.
 */
static inline bool xfs_inode_has_bigrtalloc(struct xfs_inode *ip)
{
	return XFS_IS_REALTIME_INODE(ip) && ip->i_mount->m_sb.sb_rextsize > 1;
}

/*
 * Return the buftarg used for data allocations on a given inode.
 */
+14 −1
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
#include "xfs_da_btree.h"
#include "xfs_attr.h"
#include "xfs_trans.h"
#include "xfs_trans_space.h"
#include "xfs_bmap_btree.h"
#include "xfs_trace.h"
#include "xfs_icache.h"
#include "xfs_symlink.h"
@@ -794,6 +796,7 @@ xfs_setattr_size(
	struct xfs_trans	*tp;
	int			error;
	uint			lock_flags = 0;
	uint			resblks = 0;
	bool			did_zeroing = false;

	ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
@@ -901,7 +904,17 @@ xfs_setattr_size(
			return error;
	}

	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
	/*
	 * For realtime inode with more than one block rtextsize, we need the
	 * block reservation for bmap btree block allocations/splits that can
	 * happen since it could split the tail written extent and convert the
	 * right beyond EOF one to unwritten.
	 */
	if (xfs_inode_has_bigrtalloc(ip))
		resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);

	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, resblks,
				0, 0, &tp);
	if (error)
		return error;